DatabaseProcApplicationCreatedLinks
sybsystemprocssp_ddlgen_database  31 Aug 14Defects Dependencies

1     
2     /*
3     ** sp_ddlgen_database
4     **
5     **	Entry-point for generating DDL for a database. Currently all we support
6     **	is the basic create/alter database syntax. Subsequent sp_dboption etc.
7     **	are not [ to be ] supported. The expectation is that the DDLGen tool
8     **	will provide those value-adds.
9     **
10    ** Parameters:
11    **	@dbname		- Name of db to generate DDL for. Supports wild-cards.
12    **	@trace		- Trace options (internal use.)
13    **
14    ** Trace Levels:
15    ** ------------
16    **	1	- Basic tracing of code flow.
17    **	2	- Trace alter db SQL generation.
18    **	1192	- Pretend that this is a 119x server, and ignore the code/data
19    **		  pieces that exist in 12.5.x, or later, but not in 11.9.x.
20    **	120	- Pretend that this is a 120.x server, and ignore the code/data
21    **		  pieces that exist in 12.5.x, or later, but not in 12.0.x.
22    **		  [ By running in this older-server mode, you can test that
23    **		    this sproc will correctly collapse multiple alter dbs into
24    **		    one when possible (ignoring 'crdate'), and will generate
25    **		    the syntax corectly without unit-specifiers. ]
26    {
27    */
28    create procedure sp_ddlgen_database(
29        @dbname varchar(255) = NULL
30        , @trace int = 0
31    ) as
32        begin -- {
33            declare @newline char(1)
34                , @tabchar char(1)
35                , @retval int
36                , @objtype varchar(10)
37                , @objtype_lower varchar(10)
38                , @prev_dbname varchar(30)
39                , @devname varchar(255)
40                , @segment varchar(12) -- of current disk piece
41                , @prev_segment varchar(20) -- of previous disk piece
42                , @lstart int
43                , @size_pages int
44                , @status3 int -- sysdatabases.status3
45                , @devstat int -- sysdevices.status
46                , @devstat2 int -- sysdevices.status2
47                , @size_str varchar(20) -- size as a string.
48                , @size_comments varchar(255) -- size in comments (and other
49                -- diag info if tracing is ON).
50                , @size_mb varchar(10)
51                , @prefix varchar(10)
52    
53                , @create_sql varchar(6)
54                , @alterdb_sql varchar(15)
55                , @override_sql varchar(13)
56                , @local_systempdb_ph varchar(18)
57                , @local_usrtempdb_ph varchar(11)
58                , @global_usrtempdb_ph varchar(18)
59                , @tempdb_ph varchar(30) -- used to point to these above.
60                , @imdb_sql varchar(9)
61                , @imdb_ph varchar(30)
62                , @archive_sql varchar(30)
63                , @durability_no_recovery_sql varchar(13)
64                , @durability_at_shutdown_sql varchar(13)
65                , @durability_full_sql varchar(6)
66                , @dmllogging_minimal_sql varchar(7)
67                , @dmllogging_full_sql varchar(4)
68    
69                , @data_compression_row_sql varchar(3)
70                , @data_compression_page_sql varchar(4)
71                , @data_compression_none_sql varchar(4)
72    
73                , @archivedb tinyint
74                , @usertempdb tinyint -- is it a user-created tempdb.
75                , @templatedbname varchar(30) -- print the template database name
76                , @durability varchar(13)
77                , @dmllogging varchar(9)
78                , @data_compression varchar(4)
79                , @lob_compression int
80                , @inrow_lob_length int
81                , @instancename varchar(30) -- used to print the instance
82                -- of which the current database
83                -- is local system temporary 
84                -- database.
85                , @durability_status int --sysdatabases.durability
86                , @dmllogging_status int --sysdatabases.status4
87                , @durability_no_recovery_status int
88                , @durability_at_shutdown_status int
89                , @durability_full_status int
90                , @dmllogging_minimal_status int
91    
92                , @data_compression_status int --sysdatabases.status4
93                , @data_compression_row_status int
94                , @data_compression_page_status int
95    
96    
97    
98    
99                -- # of dbids for which we didn't generate the right #s of rows 
100               -- in the #temp table when compared to the # of rows that exist
101               -- for that db in sysusages.
102               --
103               , @count_failed_dbids int
104   
105               -- To account for >2k logical page sizes
106               , @numpgsmb float
107   
108   
109               -- Various status bits in catalogs for re-use.
110               , @stat3_tempdb int
111               , @stat3_archivedb int
112               , @stat4_inmem_db int
113               , @stat4_explicit_no_rec int
114   
115               , @inmem_db tinyint
116               , @explicit_no_rec tinyint
117   
118               -- Version sub-string to check against running server.
119               , @ase_1192_str varchar(30)
120               , @ase_120x_str varchar(30)
121               , @ase_150x_str varchar(30)
122               , @ase_155x_str varchar(30)
123               , @ase_157x_str varchar(30)
124   
125               -- Are we running in a 12.5x or later server?
126               , @ase_125x_or_gt tinyint
127               , @ase_150x_or_gt tinyint
128               , @ase_155x_or_gt tinyint
129               , @ase_157x_or_gt tinyint
130   
131               , @sqlstmt varchar(255)
132               , @indent varchar(32)
133               , @archivedb_comm varchar(255)
134   
135               , @comment char(3)
136               , @pages char(6)
137               , @crdate datetime
138               , @prev_crdate datetime -- of previous disk piece
139               , @use_crdate tinyint -- whether server supports this
140               , @override tinyint -- setting of current disk piece
141               , @with_override tinyint -- whether we need to set this
142               -- for this set of disk pieces.
143               , @with_dur_and_dmllog tinyint
144               -- whether we need to set this
145               -- for the database.
146               , @with_dcomp_and_IRL tinyint
147               -- whether we need to set this
148               -- for the database.
149   
150               , @units_ok tinyint -- does server support
151           -- unit specifiers.
152   
153           select @newline = char(10)
154               , @tabchar = char(9)
155               , @comment = "-- "
156               , @pages = " pages"
157               , @objtype = "DATABASE"
158               , @indent = space(@@nestlevel * 2)
159               , @retval = 0
160   
161           select @objtype_lower = lower(@objtype)
162   
163               -- SQL fragments that we will reuse.
164               , @create_sql = "CREATE"
165               , @alterdb_sql = "ALTER DATABASE"
166               , @override_sql = "WITH OVERRIDE"
167               , @imdb_sql = " INMEMORY"
168               , @local_systempdb_ph
169               = " SYSTEM TEMPORARY "
170               , @local_usrtempdb_ph
171               = " TEMPORARY "
172               , @global_usrtempdb_ph
173               = " GLOBAL TEMPORARY "
174               , @archive_sql = " TEMPLATE SQL FOR ARCHIVE "
175   
176               -- Version parsing related variables.
177               , @ase_1192_str = "%Enterprise/11.9%"
178               , @ase_120x_str = "%Enterprise/12.0%"
179               , @ase_150x_str = "%Enterprise/15.0%"
180               , @ase_155x_str = "%Enterprise/15.5%"
181               , @ase_157x_str = "%Enterprise/15.7%"
182   
183               -- Build special-use comment for archive dbs.
184               --
185               , @archivedb_comm = @newline +
186               + "-- This is a template DDL for an archive database. Fill in the logical"
187               + @newline
188               + "-- device names based on the devices existing in your installation,"
189               + @newline
190               + "-- and uncomment the WITH OVERRIDE clause, as necessary."
191   
192               -- 125x was when ASE started support unit-specifiers for
193               -- DB DDL. So assume the server is >= 125x by default so we
194               -- can always generate the new DDL with unit-specifiers.
195               -- Likewise, 12.5 onwards, sysusages.crdate existed.
196               --
197               , @ase_125x_or_gt = 1 -- Assume it's 12.5.x or later till
198               -- we find out otherwise.
199   
200               , @ase_150x_or_gt = 0 -- Assume it's *not* 15.0.x or later
201               -- till we find out otherwise.
202   
203               , @ase_155x_or_gt = 0 -- Assume it's *not* 15.5.x or later
204               -- till we find out otherwise.
205   
206               , @ase_157x_or_gt = 0 -- Assume it's *not* 15.7.x or later
207               -- till we find out otherwise.
208   
209               -- Initialize 'prev' values that are used later for comparing
210               -- whether disk piece info changed across rows.
211               --
212               , @prev_dbname = NULL
213               , @prev_segment = NULL
214               , @prev_crdate = NULL
215   
216               -- Assume server does have this column. (We can't do matching
217               -- based on 'sysusages.crdate', till we are at 12.5x. or later.)
218               --
219               , @use_crdate = 0
220   
221   
222               , @override = 0 -- Assume no WITH OVERRIDE
223               , @usertempdb = 0 -- Assume it's not a user tempdb
224               , @with_override = 0
225               , @with_dur_and_dmllog = 0
226               , @with_dcomp_and_IRL = 0
227   
228               -- From 15.5 or later, the following variables are introduced
229               -- Initialize the following variables
230               --
231               , @templatedbname = NULL
232               , @durability = NULL
233               , @dmllogging = NULL
234               , @durability_no_recovery_sql = "NO_RECOVERY"
235               , @durability_at_shutdown_sql = "AT_SHUTDOWN"
236               , @durability_full_sql = "FULL"
237               , @dmllogging_minimal_sql = "MINIMAL"
238               , @dmllogging_full_sql = "FULL"
239   
240               -- From 15.7 or later, the following variables are introduced
241               -- Initialize the following variables
242               --
243               , @data_compression = NULL
244               , @data_compression_row_sql = "ROW"
245               , @data_compression_page_sql = "PAGE"
246               , @data_compression_none_sql = "NONE"
247   
248   
249               -- Initialize various system catalog status bits
250               , @stat3_archivedb = 4194304
251               , @durability_no_recovery_status = 6
252               , @durability_at_shutdown_status = 5
253               , @durability_full_status = 1
254               , @dmllogging_minimal_status = 256
255               , @stat4_inmem_db = 4096 -- It is an 'inmemory' db
256               , @stat4_explicit_no_rec = 8192 -- Tempdb was created with
257               -- explicit NO_RECOVERY clause.
258               , @inmem_db = 0
259               , @explicit_no_rec = 0 -- Assume all tempdbs were not
260               -- created / altered with 
261               -- explicit NO_RECOVERY option.
262               , @data_compression_row_status = 33554432
263               , @data_compression_page_status = 16777216
264   
265   
266           select @stat3_tempdb = number
267           from master.dbo.spt_values
268           where type = "D3"
269               and name = "TEMPDB STATUS MASK"
270   
271           select @numpgsmb = (1048576. / v.low)
272           from master.dbo.spt_values v
273           where v.number = 1
274               and v.type = "E"
275   
276           if (@objtype IS NULL)
277               select @objtype = "DATABASE"
278   
279           -- Validate that the db exists, first, if only one was requested.
280           if (charindex("%", @dbname) = 0) and (db_id(@dbname) IS NULL)
281           begin
282               raiserror 18322, @dbname
283               return 1
284           end
285   
286           -- Identify the server version we are running on.
287           --
288           if (@@version like @ase_1192_str) or (@@version like @ase_120x_str)
289           begin
290               select @ase_125x_or_gt = 0
291           end
292           else if (@@version like @ase_150x_str)
293           begin
294               select @ase_150x_or_gt = 1
295           end
296           else if (@@version like @ase_155x_str)
297           begin
298               select @ase_155x_or_gt = 1
299           end
300           else if (@@version like @ase_157x_str)
301           begin
302               -- 15.7 subsumes 15.5 DDL syntax, too. So turn ON the
303               -- boolean for that release-checking, too.
304               --
305               select @ase_157x_or_gt = 1
306                   , @ase_155x_or_gt = 1
307           end
308   
309   
310           -- Support masquerading as an older server.
311           --
312           if (@trace in (1192, 120))
313           begin
314               select @ase_125x_or_gt = 0
315                   , @ase_150x_or_gt = 0
316                   , @ase_155x_or_gt = 0
317                   , @ase_157x_or_gt = 0
318           end
319   
320           -- Some features are only usable 12.5.x onwards:
321           -- 	. unit-specifiers 
322           --	. 'sysusages.crdate'
323           --
324           select @units_ok = @ase_125x_or_gt
325               , @use_crdate = @ase_125x_or_gt
326   
327           -- ###################################################################
328           -- Stash away the segment info into a #temp table for processing.
329           --
330           select u.dbid
331               , dbname = d.name
332   
333               -- Remember whether this usages entry is for an archivedb.
334               , archivedb = 0
335               , d.status3
336               , u.lstart
337               , u.segmap
338               , segment = case
339                   WHEN ((u.segmap & 4) = 0) then 'data only'
340                   WHEN (u.segmap = 4) then 'log only'
341                   ELSE 'data and log'
342               end
343               , size = convert(int, u.size)
344               -- , sizeMb = ltrim(rtrim(str(u.size/512.0))) + 'M'
345               , sizeMb = ltrim(rtrim(str(u.size / @numpgsmb))) + 'M'
346               , vdevno = u.vdevno -- use this directly in 15.0 onwards.
347               , override = 0 -- whether this is a shared device that
348               -- needs WITH OVERRIDE clause to be
349               -- generated.
350               , devname = v.name
351               , devstat = v.status
352               , devstat2 = v.status2
353   
354               -- The sysusages entries fabricated from the dump for an
355               -- archive db don't have the original 'crdate' (if exists)
356               -- from the db dump. Fabricate current date, as a placeholder.
357               --
358               , crdate = getdate()
359           into #seginfo
360           from master.dbo.sysusages u
361           , master.dbo.sysdevices v
362           , master.dbo.sysdatabases d
363           where 1 = 1
364               and d.name like @dbname -- support for '%mydb%'
365               and d.dbid = u.dbid
366               and ((d.status3 & @stat3_archivedb) != @stat3_archivedb)
367               -- skip archive dbs for now
368               -- We'll get them a bit later.
369   
370               and u.vdevno = v.vdevno -- Use this for 15.0 onwards.
371   
372               and (((v.status & 2) = 2) -- for physical devices
373                   or ((v.status2 & 8) = 8)) -- for cache devices
374   
375           -- ###################################################################
376           -- Validate that the above SQL captured exactly one row for each
377           -- sysusages entry for a db. If not, we will be generating wrong
378           -- data, as there is some cross-product join happening.
379           -- If the validation fails, error out. [ This came about as during
380           -- testing some wrong WHERE clause was used in 15.0.x from a version
381           -- of this sproc meant for 12.5.x. Add this validation to trap
382           -- future errors.]
383           --
384           select @count_failed_dbids = (select count(1)
385                   from (select dbid, numrows = count(*)
386                       from #seginfo group by dbid) V1
387                   , (select dbid, numrows = count(*)
388                       from master.dbo.sysusages group by dbid) V2
389                   where V1.dbid = V2.dbid
390                       and V1.numrows != V2.numrows
391                   )
392   
393           if (@count_failed_dbids != 0)
394           begin
395               print "Found %1! dbids with wrong number of rows cached in '%2!' v/s the rows in '%3!'"
396                   , @count_failed_dbids
397                   , '#seginfo'
398                   , 'master.dbo.sysusages'
399   
400               -- Display the dbids for which we failed, if tracing is ON.
401               -- RESOLVE: This code will probably not work in 12.0, or
402               -- 11.9.x. Need to maintain a different version of this
403               -- sproc for those codelines.
404               --
405               if (@trace = 1)
406               begin
407                   select V1.dbid
408                       , dbname = db_name(V1.dbid)
409                       , expected_in_sysusages = V2.numrows
410                       , actual_in_#seginfo = V1.numrows
411                       , status = case V1.numrows
412                           when V2.numrows
413                           then "ok"
414                           else "not ok"
415                       end
416                   into #failed_dbids
417                   from (select dbid, numrows = count(*)
418                       from #seginfo group by dbid) V1
419                   , (select dbid, numrows = count(*)
420                       from master.dbo.sysusages group by dbid) V2
421                   where V1.dbid = V2.dbid
422   
423                   -- Skip this clause, so that we can see all rows.
424                   -- and V1.numrows != V2.numrows
425   
426                   -- See the 'not ok' rows at the top.
427                   exec sp_autoformat @fulltabname = #failed_dbids
428                       , @orderby = "order by status asc"
429               end
430   
431               return @count_failed_dbids
432           end
433   
434           -- exec sp_autoformat #seginfo
435   
436           -- ###################################################################
437           -- Of the dbs named by the user by the @dbname argument, if there is
438           -- even one archive db, fork off control to a sub-proc that knows how
439           -- to gather and process sysusages entries for archive dbs.
440           --
441           if exists (select 1 from master.dbo.sysdatabases d
442                   where d.name like @dbname
443                       and ((d.status3 & @stat3_archivedb) = @stat3_archivedb))
444           begin
445               -- Reuse @devname to raise an error message.
446               select @devname = """sp_ddlgen 'database', " + @dbname + '"'
447               raiserror 19475, @devname
448               return 1
449           end
450   
451   
452           -- ###################################################################
453           -- Depending on the version of ASE, we might / not have 'crdate'
454           -- column in sysusages. If we do, copy that into the #temp table,
455           -- using execute immediate. Seems straightforward, but there is an
456           -- issue here if archive dbs are involved. In that case, master..
457           -- sysusages has only a 'stub' entry for the db, whereas the #temp
458           -- table would have been populated with possibly multiple rows from
459           -- ..sysaltusages. In that case, we can't do a row-to-row
460           -- update from master..sysusages.crdate to #seginfo.crdate as there
461           -- won't be matching rows in master..sysusages.
462           --
463           if (@ase_125x_or_gt = 1)
464           begin
465               if (@trace = 1)
466               begin
467                   -- The UPDATE below sometimes fails. Run the query
468                   -- to see what the actual results are like, using
469                   -- data from the temp table.
470                   --
471                   select u.dbid, u.crdate
472                   from master.dbo.sysusages u,
473                       #seginfo t
474                   where u.dbid = t.dbid
475                       and u.lstart = t.lstart
476   
477                   print "%1!---- End Trace update ----%2!"
478                       , @indent, @newline
479                   if (@retval != 0)
480                       return @retval
481               end
482   
483               -- First only update for non-archive db rows.
484               --
485               update #seginfo
486               set crdate = (select u.crdate
487                       from master.dbo.sysusages u
488                       where u.dbid = t.dbid
489                           and u.lstart = t.lstart)
490               from #seginfo t
491               where t.archivedb = 0
492   
493               select @retval = @@error
494   
495               if (@retval != 0)
496               begin
497                   if (@trace = 1)
498                       print "Error updating #seginfo.crdate using sysusages.crdate"
499   
500                   return @retval
501               end
502           end
503   
504           -- ###################################################################
505           -- Go back and check each disk piece to see 
506           -- 1) if it has data fragment created on the device when the device was 
507           --    a log-only device.
508           --				OR
509           -- 2) if it has log fragment created on the device when the device was
510           --    a data-only device.
511           -- If so, the user would have had to create this with WITH OVERRIDE
512           -- clause. Note that here, we will re-gen the DDL accordingly.
513           -- --
514           -- [ NOTE: This will update 'override' to 1 for all usages entries
515           -- for an archive db, as the 'vdevno' is the same for all entries.
516           -- That is ok, here as then we comment out the WITH OVERRIDE clause for
517           -- the DDL for an archive db.
518           -- #####################################################################
519           -- The condition in the following update query  to set @override bit 
520           -- for the current disk piece to 1, is based on the fact that  
521           -- 'with override'clause is needed only when
522           -- 1) The current disk piece is of either 'data only' or 'log only' 
523           --    types.
524           --				AND
525           -- 2) There exists at least one disk piece on the same device as that 
526           --    of the current disk piece such that the other disk piece was 
527           --    created before the current disk piece.
528           --    (We need this condition to ensure that we do *not* generate the
529           --    WITH OVERRIDE clause for the first piece of a db on any device.)
530           --				AND
531           -- 3) There exists no disk piece preceding the current one such that the
532           --    preceding one is of either 'data and log' type or of the same type
533           --    as that of the current diskpiece.
534           --
535           -- . If there exists a prior piece on the same device of type
536           --   "data and log", it means all its subsequent pieces would not
537           --    have needed the WITH OVERRIDE clause.
538           --
539           -- . If there exists a prior piecce on the same device of the
540           --   same type as the current one, it means that prior piece
541           --   would have been created with WITH OVERRIDE clause. Hence,
542           --   all its subsequent pieces of the same segment type will
543           --   not have needed the WITH OVERRIDE clause; hence, we can
544           --   skip generating it here.
545   
546           update #seginfo
547           set override = 1
548           from #seginfo o -- outer table
549           where segment IN ("data only", "log only")
550               and exists (select 1 from #seginfo i1 -- inner table
551                   where i1.lstart < o.lstart
552                       and i1.dbid = o.dbid
553                       and i1.vdevno = o.vdevno)
554               and not exists (select 1 from #seginfo i2 -- inner table
555   
556                   -- ignore this very disk piece from the outer table,
557                   -- and search for other disk pieces with a lower
558                   -- lstart (i.e. the ones that were created -before-
559                   -- the outer disk piece.
560                   --
561                   where i2.lstart < o.lstart
562                       and i2.dbid = o.dbid
563                       and i2.vdevno = o.vdevno
564                       and (i2.segment = "data and log"
565                           or i2.segment = o.segment))
566   
567           declare diskcur cursor for
568           select dbname, devname, segment, size, sizeMb, override, crdate
569               , status3
570               , devstat
571               , devstat2
572               , lstart
573               , archivedb
574           from #seginfo
575           order by dbid, lstart asc
576           for read only
577   
578           select @retval = @@error
579           if (@retval != 0)
580               return @retval
581   
582           open diskcur
583           select @retval = @@error
584           if (@retval != 0)
585               return @retval
586   
587           while (1 = 1)
588           begin -- {
589               fetch diskcur into @dbname
590                   , @devname
591                   , @segment
592                   , @size_pages
593                   , @size_mb
594                   , @override
595                   , @crdate
596                   , @status3
597                   , @devstat
598                   , @devstat2
599                   , @lstart
600                   , @archivedb
601   
602               select @retval = @@error
603               if (@@sqlstatus != 0) OR (@retval != 0)
604                   break
605   
606               -- We are beginning the processing for sysusages entries
607               -- for a new database. Initialize the SQL fragments...
608               --
609               if (@prev_dbname != @dbname)
610               begin -- {
611   
612                   -- If a database previous to the current one existed 
613                   -- (That is, in case of  multiple database input to 
614                   -- ddlgen using wild card)
615                   --
616                   if (@prev_dbname IS NOT NULL)
617                   begin
618                       -- Handle the case that the very last disk 
619                       -- piece of previous database might need this 
620                       -- clause.
621                       --
622                       exec sp_ddlgen_db_print_with_clause
623                           @with_override output
624                           , @with_dur_and_dmllog output
625                           , @with_dcomp_and_IRL output
626                           , @durability
627                           , @dmllogging
628                           , @data_compression
629                           , @lob_compression
630                           , @inrow_lob_length
631                           , @archivedb
632                   end
633   
634                   else if (@prev_dbname IS NULL)
635                   begin
636                       print "USE master%1!go%2!", @newline, @newline
637                   end
638   
639                   -- Reset for every db that we'll process in a loop.
640                   /*
641                   ** If it is a temporary database other than 'tempdb'
642                   ** add the keywords that reflect the type of the
643                   ** database accordingly ([system | global] temporary).
644                   */
645                   if ((@status3 & @stat3_tempdb) != 0)
646                   begin
647                       -- The database is a temporary database; start 
648                       -- with the default phrase (with the TEMPORARY 
649                       -- keyword)
650                       --
651                       select @tempdb_ph = @local_usrtempdb_ph
652   
653                       if (@@clustermode = 'shared disk cluster')
654                       begin
655                           -- In case of sdc, there are a few
656                           -- variations as shown in the switch
657                           -- case.
658                           --
659                           select @tempdb_ph =
660                               case (@status3 & @stat3_tempdb)
661                                   when (select number
662                                       from master.dbo.spt_values
663                                       where name =
664                                           'local system temp db')
665                                   then @local_systempdb_ph
666                                   when (select number
667                                       from master.dbo.spt_values
668                                       where name =
669                                           'global user temp db')
670                                   then @global_usrtempdb_ph
671                                   else @local_usrtempdb_ph
672                               end
673   
674                       end
675                   end
676   
677                   else if ((@status3 & @stat3_archivedb) = @stat3_archivedb)
678                   begin
679                       select @tempdb_ph = @archive_sql
680                   end
681   
682                   else
683                       select @tempdb_ph = ""
684   
685                   /*
686                   ** If it is a inmemory database,
687                   ** add the keywords that reflect the type of the
688                   ** database accordingly (inmemory).
689                   */
690                   if (@ase_155x_or_gt = 1)
691                   begin -- {
692                       if (@@clustermode = 'smp')
693                       begin
694                           select @with_dur_and_dmllog = 1
695                       end
696   
697                       -- Extract the durability from catalogs:
698                       -- First find the durability as we see it in
699                       -- the catalogs. Also note if it's a user
700                       -- created tempdb.
701                       --
702                       select @durability_status = durability
703   
704                           -- Is it a user-created temp db?
705                           , @usertempdb = case (status3
706                           & @stat3_tempdb)
707                               when @stat3_tempdb
708                               then 1
709                               else 0
710                           end
711   
712                           -- Is it a tempdb created with explicit
713                           -- NO_RECOVERY durability?
714                           --
715                           , @explicit_no_rec
716                           = case (status4 & @stat4_explicit_no_rec)
717                               when @stat4_explicit_no_rec
718                               then 1
719                               else 0
720                           end
721   
722                           -- Is it an in-memory db?
723                           , @inmem_db
724                           = case (status4 & @stat4_inmem_db)
725                               when @stat4_inmem_db
726                               then 1
727                               else 0
728                           end
729   
730                       from master.dbo.sysdatabases
731                       where name = @dbname
732   
733                       select @durability =
734                           case (@durability_status)
735                               when @durability_no_recovery_status
736                               then @durability_no_recovery_sql
737                               when @durability_at_shutdown_status
738                               then @durability_at_shutdown_sql
739                               else @durability_full_sql
740                           end
741   
742   
743                       -- Next, for the system tempdb, or for any
744                       -- user-created tempdb, check if the db was
745                       -- created / altered with the explicit
746                       -- NO_RECOVERY durability. If not, reset the
747                       -- durability to NULL. (Do not do this for 
748                       -- in-memory dbs which *need* to be always
749                       -- created with the NO_RECOVERY clause.)
750                       -- This will eventually suppress generating
751                       -- the WITH DURABILITY clause in the DDL.
752                       --
753                       if (((@dbname = 'tempdb')
754                                   or (@usertempdb = 1))
755                               and (@explicit_no_rec = 0)
756                               and (@inmem_db = 0)
757                           )
758                       begin
759                           select @durability = NULL
760                       end
761   
762                       select @dmllogging_status = status4
763                       from master.dbo.sysdatabases
764                       where name = @dbname
765   
766                       select @dmllogging =
767                           case (@dmllogging_status
768                           & @dmllogging_minimal_status)
769                               when @dmllogging_minimal_status
770                               then @dmllogging_minimal_sql
771                               else @dmllogging_full_sql
772                           end
773   
774                       if (@devstat2 & 8 = 8)
775                       begin
776                           select @imdb_ph = @imdb_sql
777   
778                           -- Don't forget to add:
779                           --	'USE dbname AS TEMPLATE'
780                           -- clause for the database if it is an
781                           -- IMDB db. Currently, we don't support
782                           -- template clause
783                           -- for inmemory temp DB
784                           -- 
785                           if ((@status3 & @stat3_tempdb) = 0)
786                           begin
787                               select @templatedbname = def_remote_loc
788                               from master.dbo.sysdatabases
789                               where name = @dbname
790                           end
791                       end
792   
793                       if (@devstat2 & 8 != 8)
794                           select @imdb_ph = NULL
795   
796                       if ((@devstat & 2 = 2)
797                               and (@durability_status
798                                   & @durability_no_recovery_status
799                                   = @durability_no_recovery_status))
800                       begin
801                           select @templatedbname = def_remote_loc
802                           from master.dbo.sysdatabases
803                           where name = @dbname
804                       end
805                   end -- }
806   
807                   if (@ase_157x_or_gt = 1)
808                   begin -- {
809                       select @with_dcomp_and_IRL = 1
810   
811                       select @data_compression_status = status4
812                       from master.dbo.sysdatabases
813                       where name = @dbname
814   
815                       if ((@data_compression_status
816                               & @data_compression_row_status)
817                               = @data_compression_row_status)
818                       begin
819                           select @data_compression
820                               = @data_compression_row_sql
821                       end
822   
823                       else if ((@data_compression_status
824                               & @data_compression_page_status)
825                               = @data_compression_page_status)
826                       begin
827                           select @data_compression
828                               = @data_compression_page_sql
829                       end
830   
831                       else
832                       begin
833                           select @data_compression
834                               = @data_compression_none_sql
835                       end
836   
837                       select @lob_compression = lobcomp_lvl
838                       from master.dbo.sysdatabases
839                       where name = @dbname
840   
841                       select @inrow_lob_length = inrowlen
842                       from master.dbo.sysdatabases
843                       where name = @dbname
844                   end -- }
845   
846                   -- Generate the DROP syntax first.
847                   --
848                   print "%1!PRINT ""<<<< %2!%3!%4!%5! %6!>>>>""%7!go%8!%9!"
849                       , @newline
850                       , @create_sql
851                       , @imdb_ph
852                       , @tempdb_ph
853                       , @objtype
854                       , @dbname
855                       , @newline, @newline, @newline
856   
857                   print "IF EXISTS (SELECT 1 FROM master.dbo.sysdatabases"
858                   print "	   WHERE name = '%1!')", @dbname
859                   print "	DROP %1! %2!", @objtype, @dbname
860                   print "go%1!%2!", @newline, @newline
861   
862                   print "IF (@@error != 0)%1!BEGIN", @newline
863                   print "	PRINT ""Error dropping %1! '%2!'"""
864                       , @objtype_lower, @dbname
865                   print "	SELECT syb_quit()%1!END%2!go%3!%4!"
866                       , @newline, @newline, @newline, @newline
867   
868                   -- Reset loop variables that are only to be used for
869                   -- rows for one db.
870                   --
871                   select @prev_segment = NULL
872                       , @prev_crdate = NULL
873   
874                   -- We don't want to generate CREATE ARCHIVE DATABASE,
875                   -- so reset the phrase, in a way to suppress that.
876                   --
877                   if (@tempdb_ph = @archive_sql)
878                       select @tempdb_ph = " "
879   
880                   -- Display special-case comments for archive db's DDL.
881                   if (@archivedb = 1)
882                   begin
883                       print @archivedb_comm
884                   end
885   
886                   print "%1!%2!%3!%4! %5!"
887                       , @create_sql, @imdb_ph, @tempdb_ph
888                       , @objtype, @dbname
889   
890   
891   
892   
893                   -- Don't forget to add 'USE dbname AS TEMPLATE' clause 
894                   -- for the database if it is an in-memory db.
895                   --
896                   if (@templatedbname IS NOT NULL)
897                   begin
898                       print "%1!    USE %2! AS TEMPLATE"
899                           , @tabchar
900                           , @templatedbname
901                   end
902                   select @templatedbname = NULL
903   
904               end -- }
905   
906   
907   
908               if (@prev_segment IS NULL)
909               begin
910                   select @prefix = @tabchar + "    ON "
911               end
912               else if (@use_crdate = 1) and (@prev_crdate != @crdate)
913               begin -- {
914                   -- State change in segment defn. Move to ALTER DB SQL
915                   exec sp_ddlgen_db_print_alterdb
916                       @dbname
917                       , @archivedb
918                       , @alterdb_sql
919                       , @segment
920                       , @durability
921                       , @dmllogging
922                       , @data_compression
923                       , @lob_compression
924                       , @inrow_lob_length
925                       , @trace
926                       , 'dates are different'
927                       , @with_override output
928                       , @with_dur_and_dmllog output
929                       , @with_dcomp_and_IRL output
930                       , @prefix output
931               end -- }
932   
933               else if (@prev_segment = @segment)
934               begin
935                   select @prefix = @tabchar + "     , "
936               end
937   
938               else if ((@prev_segment != "data and log")
939                       and (@segment = "log only"))
940               begin
941                   select @prefix = @tabchar + "LOG ON "
942               end
943               else
944               begin -- {
945                   -- State change in segment defn. Move to ALTER DB SQL
946                   exec sp_ddlgen_db_print_alterdb
947                       @dbname
948                       , @archivedb
949                       , @alterdb_sql
950                       , @segment
951                       , @durability
952                       , @dmllogging
953                       , @data_compression
954                       , @lob_compression
955                       , @inrow_lob_length
956                       , @trace
957                       , 'segments are different'
958                       , @with_override output
959                       , @with_dur_and_dmllog output
960                       , @with_dcomp_and_IRL output
961                       , @prefix output
962               end -- }
963   
964               -- Depending on whether the server supports unit-specifiers,
965               -- pick the way 'size' is printed. If the server supports
966               -- unit-specifiers, report using units, and report the # of
967               -- pages in comments. Otherwise, do the opposite.
968               --
969               if (@units_ok = 1)
970               begin
971                   select @size_str = "'" + @size_mb + "'"
972                       , @size_comments = @comment
973                       + convert(varchar, @size_pages)
974                       + @pages
975               end
976               else
977               begin
978                   select @size_str = convert(varchar, @size_pages)
979                       , @size_comments = @comment + @size_mb
980               end
981   
982               if (@trace = 1)
983               begin
984                   select @size_comments = @size_comments
985                       + " ["
986                       + @segment
987   
988                       + ",lstart="
989                       + convert(varchar, @lstart)
990   
991                       + ",override="
992                       + convert(varchar, @override)
993   
994                       + ","
995                       + convert(varchar, @crdate)
996                       + "]"
997               end
998   
999               -- In this cursor loop we could be generating the syntax
1000              -- for more than one disk piece, followed by more than
1001              -- one disk piece for the LOG ON phrase. Here, we remember
1002              -- if any one of these would have needed a WITH OVERRIDE
1003              -- clause, which should only be generated at the very end
1004              -- of the block of SQL for all the disk pieces being
1005              -- printed under one ALTER DATABASE statement. Then, we
1006              -- will pass this @with_override to the print routine which
1007              -- will terminate the current ALTER DATABASE SQL chunk with
1008              -- any required WITH OVERRIDE clause, and start a new block
1009              -- of SQL.
1010  
1011              if (@override = 1)
1012                  select @with_override = 1
1013  
1014              print "%1!%2! = %3! %4!"
1015                  , @prefix, @devname, @size_str
1016                  , @size_comments
1017  
1018              -- Store this disk piece's values, for comparison with those
1019              -- of the next piece.
1020              select @prev_segment = @segment
1021                  , @prev_crdate = @crdate
1022                  , @prev_dbname = @dbname
1023  
1024          end -- }
1025          close diskcur
1026          deallocate cursor diskcur
1027  
1028          if (@retval != 0)
1029              return @retval
1030  
1031          -- Handle the case that the very last disk piece might need this clause.
1032          --
1033          exec sp_ddlgen_db_print_with_clause @with_override output
1034              , @with_dur_and_dmllog output
1035              , @with_dcomp_and_IRL output
1036              , @durability
1037              , @dmllogging
1038              , @data_compression
1039              , @lob_compression
1040              , @inrow_lob_length
1041              , @archivedb
1042  
1043          return @retval
1044      end -- }
1045  

RESULT SETS
sp_ddlgen_database_rset_001

DEFECTS
 QBGB 6 Bad group by : Query requires a 'group by' clause 384
 QJWI 5 Join or Sarg Without Index 389
 QJWI 5 Join or Sarg Without Index 421
 MEST 4 Empty String will be replaced by Single Space 683
 MTYP 4 Assignment type mismatch @templatedbname: varchar(30) = varchar(349) 787
 MTYP 4 Assignment type mismatch @templatedbname: varchar(30) = varchar(349) 801
 MTYP 4 Assignment type mismatch @dbname: varchar(30) = varchar(255) 916
 MTYP 4 Assignment type mismatch @dbname: varchar(30) = varchar(255) 947
 MTYP 4 Assignment type mismatch @prev_dbname: varchar(30) = varchar(255) 1022
 MUSP 4 Unquoted String Parameter sybsystemprocs..sp_autoformat: @fulltabname 427
 QPUI 4 Join or Sarg with Un-Rooted Partial Index Use SARG Candidate index: spt_values.spt_valuesclust clustered
(number, type)
Intersection: {type}
268
 TNOI 4 Table with no index tempdb..V1_D3 tempdb..V1_D3
 TNOI 4 Table with no index tempdb..V2_D4 tempdb..V2_D4
 TNOU 4 Table with no unique index master..spt_values master..spt_values
 MGTP 3 Grant to public master..spt_values  
 MGTP 3 Grant to public master..sysdatabases  
 MGTP 3 Grant to public master..sysdevices  
 MGTP 3 Grant to public master..sysusages  
 MNEJ 3 'Not Equal' join 390
 MNER 3 No Error Check should check @@error after select into 330
 MNER 3 No Error Check should check @@error after select into 407
 MNER 3 No Error Check should check return value of exec 427
 MNER 3 No Error Check should check @@error after update 546
 MNER 3 No Error Check should check return value of exec 622
 MNER 3 No Error Check should check return value of exec 915
 MNER 3 No Error Check should check return value of exec 946
 MNER 3 No Error Check should check return value of exec 1033
 MUCO 3 Useless Code Useless Brackets in create proc 28
 MUCO 3 Useless Code Useless Begin-End Pair 32
 MUCO 3 Useless Code Useless Brackets 271
 MUCO 3 Useless Code Useless Brackets 276
 MUCO 3 Useless Code Useless Brackets 292
 MUCO 3 Useless Code Useless Brackets 296
 MUCO 3 Useless Code Useless Brackets 300
 MUCO 3 Useless Code Useless Brackets 312
 MUCO 3 Useless Code Useless Brackets 339
 MUCO 3 Useless Code Useless Brackets 340
 MUCO 3 Useless Code Useless Brackets 393
 MUCO 3 Useless Code Useless Brackets 405
 MUCO 3 Useless Code Useless Brackets 463
 MUCO 3 Useless Code Useless Brackets 465
 MUCO 3 Useless Code Useless Brackets 479
 MUCO 3 Useless Code Useless Brackets 495
 MUCO 3 Useless Code Useless Brackets 497
 MUCO 3 Useless Code Useless Brackets 579
 MUCO 3 Useless Code Useless Brackets 584
 MUCO 3 Useless Code Useless Brackets 587
 MUCO 3 Useless Code Useless Brackets 609
 MUCO 3 Useless Code Useless Brackets 616
 MUCO 3 Useless Code Useless Brackets 634
 MUCO 3 Useless Code Useless Brackets 645
 MUCO 3 Useless Code Useless Brackets 653
 MUCO 3 Useless Code Useless Brackets 677
 MUCO 3 Useless Code Useless Brackets 690
 MUCO 3 Useless Code Useless Brackets 692
 MUCO 3 Useless Code Useless Brackets 734
 MUCO 3 Useless Code Useless Brackets 753
 MUCO 3 Useless Code Useless Brackets 774
 MUCO 3 Useless Code Useless Brackets 785
 MUCO 3 Useless Code Useless Brackets 793
 MUCO 3 Useless Code Useless Brackets 796
 MUCO 3 Useless Code Useless Brackets 807
 MUCO 3 Useless Code Useless Brackets 815
 MUCO 3 Useless Code Useless Brackets 823
 MUCO 3 Useless Code Useless Brackets 877
 MUCO 3 Useless Code Useless Brackets 881
 MUCO 3 Useless Code Useless Brackets 896
 MUCO 3 Useless Code Useless Brackets 908
 MUCO 3 Useless Code Useless Brackets 933
 MUCO 3 Useless Code Useless Brackets 938
 MUCO 3 Useless Code Useless Brackets 969
 MUCO 3 Useless Code Useless Brackets 982
 MUCO 3 Useless Code Useless Brackets 1011
 MUCO 3 Useless Code Useless Brackets 1028
 QAFM 3 Var Assignment from potentially many rows 266
 QAFM 3 Var Assignment from potentially many rows 271
 QAFM 3 Var Assignment from potentially many rows 384
 QCRS 3 Conditional Result Set 471
 QCTC 3 Conditional Table Creation 407
 QJWT 3 Join or Sarg Without Index on temp table 474
 QJWT 3 Join or Sarg Without Index on temp table 488
 QJWT 3 Join or Sarg Without Index on temp table 551
 QJWT 3 Join or Sarg Without Index on temp table 561
 QNAJ 3 Not using ANSI Inner Join 360
 QNAJ 3 Not using ANSI Inner Join 385
 QNAJ 3 Not using ANSI Inner Join 417
 QNAJ 3 Not using ANSI Inner Join 472
 QPNC 3 No column in condition 363
 QTJ1 3 Table only appears in inner join clause 386
 QTJ1 3 Table only appears in inner join clause 388
 QTJ1 3 Table only appears in inner join clause 473
 VNRD 3 Variable is not read @override_sql 166
 VNRD 3 Variable is not read @durability_full_status 253
 VNRD 3 Variable is not read @ase_150x_or_gt 315
 VNRD 3 Variable is not read @with_override 1033
 VNRD 3 Variable is not read @with_dur_and_dmllog 1034
 VNRD 3 Variable is not read @with_dcomp_and_IRL 1035
 VUNU 3 Variable is not used @instancename 81
 VUNU 3 Variable is not used @sqlstmt 131
 CRDO 2 Read Only Cursor Marker (has for read only clause) 568
 MDRV 2 Derived Table Marker 385
 MDRV 2 Derived Table Marker 387
 MDRV 2 Derived Table Marker 417
 MDRV 2 Derived Table Marker 419
 MRST 2 Result Set Marker 471
 MSUB 2 Subquery Marker 384
 MSUB 2 Subquery Marker 441
 MSUB 2 Subquery Marker 661
 MSUB 2 Subquery Marker 666
 MSUC 2 Correlated Subquery Marker 486
 MSUC 2 Correlated Subquery Marker 550
 MSUC 2 Correlated Subquery Marker 554
 MTR1 2 Metrics: Comments Ratio Comments: 37% 28
 MTR2 2 Metrics: Cyclomatic Complexity Cyclo: 61 = 65dec - 6exi + 2 28
 MTR3 2 Metrics: Query Complexity Complexity: 273 28
 PRED_QUERY_COLLECTION 2 {d=master..sysdatabases, d2=master..sysdevices, u=master..sysusages} 0 330

DEPENDENCIES
PROCS AND TABLES USED
reads table master..sysdevices (1)  
read_writes table tempdb..#seginfo (1) 
calls proc sybsystemprocs..sp_ddlgen_db_print_with_clause  
reads table master..sysusages (1)  
reads table master..sysdatabases (1)  
reads table master..spt_values (1)  
writes table tempdb..#failed_dbids (1) 
calls proc sybsystemprocs..sp_ddlgen_db_print_alterdb  
   calls proc sybsystemprocs..sp_ddlgen_db_print_with_clause  
calls proc sybsystemprocs..sp_autoformat  
   reads table master..systypes (1)  
   reads table tempdb..syscolumns (1)  
   read_writes table tempdb..#colinfo_af (1) 
   calls proc sybsystemprocs..sp_autoformat  
   reads table master..syscolumns (1)  
   reads table tempdb..systypes (1)  
   calls proc sybsystemprocs..sp_namecrack