<?xml version="1.0" encoding="ISO-8859-1" ?>
 <!DOCTYPE root [ 
   <!ENTITY nl "&#10;">  
   <!ENTITY nbsp "&#160;">  
   ]>
<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:rf="http://schemas.roadintranet.org/road-faq-1"
    xmlns:rs="http://schemas.roadintranet.org/road-database-schema-1"
    >
    <xsl:output method="text"/>
    <xsl:variable name="topics" select="document('../xml/topics.xml')"/>
    <xsl:variable name="items-sections" select="document('../xml/index.xml')"/>
    <xsl:key name="domains"
        match="rs:domain" use="@id"/>
   
    <!-- =====================================================================
          Functions
    -->
    <xsl:function name="rs:report-error">
        <xsl:param name="message"/>
        <xsl:param name="element"/>
        <xsl:for-each select="$element">
        <xsl:variable name="err-message"   select="
            if (@id) then concat($message, ' for ', @id)
            else if (@item)  then concat($message, ' for ', @item)
            else if (@title)  then concat($message, ' for ', @title)
            else if (@name)  then concat($message, ' for ', @name)
            else $message
            "/>
            <xsl:value-of select="'ERROR', $err-message"/>  
            <xsl:comment>error() requires a QName literal!</xsl:comment>
        </xsl:for-each>
    </xsl:function>
    
    <xsl:function name="rs:table-for-domain">
        <xsl:param name="element"/>
        <xsl:for-each select="$element">
            <xsl:value-of select="
                if (@table) then @table
                else if (@domain) then 
                if (key('domains', @domain)) then rs:table-for-domain(key('domains', @domain))
                else rs:report-error('Undefined domain', .)
                else ''
                "/>
        </xsl:for-each>
        <!-- [bbarber June 06] Can't use xsl:sequence since the recursive call reports "Cannot
            select a node here: the context item is undefined" -->
    </xsl:function> 
    
    
    <xsl:function name="rs:column-for-domain">
        <xsl:param name="element"/>
        <xsl:for-each select="$element">
            <xsl:value-of select="
                if (@column) then @column 
                else if (@domain) then 
                if (key('domains', @domain)) then rs:column-for-domain(key('domains', @domain))
                else rs:report-error('Undefined domain', .)
                else rs:report-error('Missing column attribute for domain table', .)
                "/>
        </xsl:for-each>
    </xsl:function> 
    
   
    <xsl:function name="rs:sql-for-domain">
       <xsl:param name="element"/>
       <xsl:for-each select="$element">
       <xsl:value-of select="
           if (@sql-type) then @sql-type 
             else if (@same-as) then rs:sql-for-domain(key('domains', @same-as)) 
           else if (@domain) then 
           if (key('domains', @domain)) then rs:sql-for-domain(key('domains', @domain))
           else rs:report-error('Undefined domain', .)
           else rs:report-error('Missing sql-type, same-as, or domain', .)
           "/>
       </xsl:for-each>
   </xsl:function> 

    <!-- =====================================================================
        Master template
    -->
    <!-- [bbarber May 2006] Gave up on using Alter Table for automatic migration.   There is
           too little information available to too many restrictions on altering, especially with
           indices, constraints, and existing data.  
    -->
    <xsl:template match="/">
/******************************
*         Drop Tables by inverse order of creation:   z=import, y=no-dependency, m=foreign-keys, a=no foreign key
        <xsl:for-each-group select="//rs:tables/rf:section/rs:table" group-by="@level">
            <xsl:sort  select="@level" order="descending"/>
            <xsl:sort select="@id"/>
            DROP TABLE 
            <xsl:for-each select="current-group()">
                <xsl:value-of select="@id, 
                  if (position()!=last()) then ','  else ()"/>
            </xsl:for-each>   
        </xsl:for-each-group>
        
******************************
*         Summarize min and max values for each column of each table
    <xsl:for-each select="//rs:tables/rf:section/rs:table">
             <xsl:sort select="@id"/>
            <xsl:variable name="table-id" select="@id"/>
            SELECT '<xsl:value-of select="$table-id"/>' as name, COUNT(*) as Count<xsl:text/>
            <xsl:for-each select="rs:column">
                <xsl:choose>
                    <xsl:when test="rs:sql-for-domain(.) = 'bit' ">
                        <xsl:value-of select="
                            ', SUM(case when',
                           @id,
                            '= 0 then 1 else 0 end) as',
                            concat(@id, '_0'), 
                            ', SUM(case when',
                            @id,
                            '= 1 then 1 else 0 end) as',
                            concat(@id, '_1')
                            "/>  
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="
                            ', MIN(',
                            @id, 
                            concat(') as min_', @id), 
                            ',  MAX(',
                            @id, 
                            concat(') as max_', @id) "/>  
                    </xsl:otherwise>
                </xsl:choose> 
            </xsl:for-each>
            <xsl:value-of select="
                ' FROM',
                $table-id "/>
        </xsl:for-each>

******************************
*        Count each ID values [varchar(100)]

        <!-- Table and column names from Road-database-schema.xml -->
        DROP TABLE domain_values
        CREATE TABLE  domain_values 
        (
            tbl varchar(100),
            col varchar(100),
            val varchar(100),
            cnt int,
        )
        
        <xsl:for-each select="//rs:tables/rf:section/rs:table">
            <xsl:sort select="@id"/>
            <xsl:variable name="table-id" select="@id"/>
            <xsl:for-each select="rs:column">
                <!--  FIXUP: test for name-id-domain -->
                <xsl:if test="rs:sql-for-domain(.) =  'varchar(100)' ">
                    <xsl:value-of separator="" select="
                        'insert into domain_values',
                        ' (tbl, col, val, cnt)',
                        ' select  ''', $table-id, ''', ''', @id, ''', ', @id,  
                        ', count(*)', 
                        ' from ', $table-id, ' group by ', @id
                        " /><xsl:text>&nl;</xsl:text>
                </xsl:if>
            </xsl:for-each>
        </xsl:for-each>
        SELECT col, val, sum(cnt) as count, min(tbl) as min_table, max(tbl) as max_table from domain_values where col > '' group by col, val order by col, val
        
*******************************/&nl;<xsl:text/>
            <xsl:for-each select="//rs:tables/rf:section/rs:table">
                <xsl:sort  select="@level"/>
                <xsl:sort select="@id"/>
                <xsl:variable name="table-id" select="@id"/>
                <xsl:variable name="short-name" select="@short-name"/>
                IF OBJECT_ID ( '<xsl:value-of select="$table-id"/>', 'U') IS NULL
                BEGIN
                CREATE TABLE  <xsl:value-of select="$table-id"/>
                (&nl;<xsl:text/>
                    <xsl:for-each select="rs:column">
                        <!--  Use table foreign key constraints when there are multiple columns -->
                        <xsl:if test="@foreign-columns and not(@foreign-key='no') and rs:table-for-domain(.) != '' and rs:table-for-domain(.) !=$table-id">
                            <xsl:text>                   </xsl:text>
                            <xsl:value-of select="concat(
                                ' CONSTRAINT ', $short-name, '_', @id, '_ref',
                                ' FOREIGN KEY (', @foreign-columns, ')' ,
                                ' REFERENCES ', 
                                rs:table-for-domain(.), ' (', rs:column-for-domain(.), ')' 
                                )"/>
                            <xsl:text>,&nl;</xsl:text>
                         </xsl:if>
                         <xsl:text>                    </xsl:text>
                        <xsl:value-of select="@id, rs:sql-for-domain(.), 
                            if (@identity='yes') then ' IDENTITY' else (),
                            if (@case-sensitive='yes') then ' COLLATE SQL_Latin1_General_CP1_CS_AS' else (),
                            if (not(@null='yes')) then ' NOT NULL' else (), 
                            if (@default) then concat('DEFAULT ',@default) else (),  
                            if (not(@foreign-key='no') and not(@foreign-columns) and rs:table-for-domain(.) != '' and rs:table-for-domain(.) !=$table-id) 
                            then concat(
                               ' CONSTRAINT ', $short-name, '_', @id, '_ref',
                               ' REFERENCES ', 
                               rs:table-for-domain(.), ' (', rs:column-for-domain(.), ')') 
                            else (),
                            if (position()!=last()) then ','  else ()"/>
                        <xsl:text>&nl;</xsl:text>
                    </xsl:for-each>
                <xsl:text>                )&nl;</xsl:text>
                <xsl:for-each select="rs:column[@clustered='yes']">
                    <xsl:call-template name="create-index">
                        <xsl:with-param name="table-id" select="$table-id"/>
                    </xsl:call-template>
                </xsl:for-each>
                <xsl:for-each select="rs:column[ not(@clustered='yes' ) and (@unique or @index or
                    @index-columns) ]">
                    <xsl:call-template name="create-index">
                        <xsl:with-param name="table-id" select="$table-id"/>
                    </xsl:call-template>
                </xsl:for-each>
                <xsl:text/>               END&nl;<xsl:text/>
            </xsl:for-each>
    </xsl:template>
    
    <!-- =====================================================================
        Called templates
    -->
    <xsl:template name="create-index">
        <xsl:param name="table-id"/>
        <xsl:text/>               CREATE <xsl:value-of select="if (@unique='yes') then 'UNIQUE ' else ()"/>
        <xsl:value-of select="if (@clustered='yes') then 'CLUSTERED ' else ()"/>
        <xsl:text/>INDEX <xsl:value-of select="if (@index) then @index else concat(@id, '_index')"/>
        <xsl:text/> ON <xsl:value-of select="$table-id"/>
        <xsl:text/> (<xsl:value-of select="if (@index-columns) then @index-columns else @id"/>)<xsl:text/>
       <xsl:if test="@include-columns">
            <xsl:text/> INCLUDE (<xsl:value-of select="@include-columns"/>)<xsl:text/>
       </xsl:if>
        <xsl:text/>  WITH (<xsl:value-of select="@index-options, 'DROP_EXISTING=OFF'" separator=","/>)&nl;<xsl:text/>
    </xsl:template>
    
</xsl:stylesheet>
