472 lines
20 KiB
HTML
Executable file
472 lines
20 KiB
HTML
Executable file
<?xml version="1.0"?>
|
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
<!--
|
|
C1873 SRU Hospitality
|
|
adl2mssql.xsl
|
|
|
|
(c) 2007 Cygnet Solutions Ltd
|
|
|
|
Convert ADL to MS-SQL
|
|
|
|
$Author: af $
|
|
$Revision: 1.1 $
|
|
-->
|
|
|
|
<xsl:output indent="no" encoding="utf-8" method="text"/>
|
|
|
|
<xsl:template match="application">
|
|
-------------------------------------------------------------------------------------------------
|
|
--
|
|
-- Database for application <xsl:value-of select="@name"/> version <xsl:value-of select="@version"/>
|
|
-- Generated for MS-SQL 2000+ using adl2mssql.xsl $Revision: 1.1 $
|
|
--
|
|
-- Code generator (c) 2007 Cygnet Solutions Ltd
|
|
--
|
|
-------------------------------------------------------------------------------------------------
|
|
|
|
-------------------------------------------------------------------------------------------------
|
|
-- authentication roles
|
|
-------------------------------------------------------------------------------------------------
|
|
<xsl:apply-templates select="group"/>
|
|
|
|
-------------------------------------------------------------------------------------------------
|
|
-- tables, views and permissions
|
|
-------------------------------------------------------------------------------------------------
|
|
<xsl:apply-templates select="entity" mode="table"/>
|
|
|
|
<xsl:apply-templates select="entity" mode="view"/>
|
|
|
|
-------------------------------------------------------------------------------------------------
|
|
-- referential integrity constraints
|
|
-------------------------------------------------------------------------------------------------
|
|
<xsl:for-each select="entity">
|
|
<xsl:variable name="nearside" select="@name"/>
|
|
<xsl:for-each select="property[@type='entity']">
|
|
<xsl:call-template name="referentialintegrity">
|
|
<xsl:with-param name="nearside" select="$nearside"/>
|
|
</xsl:call-template>
|
|
|
|
</xsl:for-each>
|
|
</xsl:for-each>
|
|
|
|
-------------------------------------------------------------------------------------------------
|
|
-- end of file
|
|
-------------------------------------------------------------------------------------------------
|
|
</xsl:template>
|
|
|
|
<xsl:template match="group">
|
|
execute sp_addrole @rolename = '<xsl:value-of select="@name"/>'
|
|
|
|
GO
|
|
</xsl:template>
|
|
|
|
|
|
<xsl:template name="referentialintegrity">
|
|
<xsl:param name="nearside"/>
|
|
<!-- set up referential integrity constraints for primary tables -->
|
|
ALTER TABLE "<xsl:value-of select="$nearside"/>"
|
|
ADD FOREIGN KEY ( "<xsl:value-of select="@name"/>")
|
|
REFERENCES "<xsl:value-of select="@entity"/>" ON DELETE NO ACTION
|
|
|
|
GO
|
|
</xsl:template>
|
|
|
|
|
|
<xsl:template match="entity" mode="table">
|
|
<xsl:variable name="table" select="@name"/>
|
|
|
|
-------------------------------------------------------------------------------------------------
|
|
-- primary table <xsl:value-of select="@name"/>
|
|
-------------------------------------------------------------------------------------------------
|
|
CREATE TABLE "<xsl:value-of select="@name"/>"
|
|
(
|
|
<xsl:apply-templates select="property[@type!='link']"/>
|
|
<xsl:value-of select="@name"/>Id INT IDENTITY( 1, 1) PRIMARY KEY
|
|
)
|
|
|
|
GO
|
|
|
|
---- permissions ------------------------------------------------------------------------------
|
|
<xsl:for-each select="permission">
|
|
<xsl:call-template name="permission">
|
|
<xsl:with-param name="table" select="$table"/>
|
|
</xsl:call-template>
|
|
</xsl:for-each>
|
|
|
|
</xsl:template>
|
|
|
|
<xsl:template match="entity" mode="view">
|
|
<xsl:variable name="table" select="@name"/>
|
|
-------------------------------------------------------------------------------------------------
|
|
-- convenience view VW_DL_<xsl:value-of select="@name"/> for default list
|
|
-------------------------------------------------------------------------------------------------
|
|
|
|
CREATE VIEW "VW_DL_<xsl:value-of select="@name"/>" AS
|
|
SELECT "<xsl:value-of select="@name"/>"."<xsl:value-of select="@name"/>Id",
|
|
<xsl:for-each select="property[@type!='link']">
|
|
<xsl:choose>
|
|
<xsl:when test="@type='entity'">
|
|
<xsl:call-template name="distinctfield">
|
|
<xsl:with-param name="table" select="@entity"/>
|
|
<xsl:with-param name="alias" select="@name"/>
|
|
</xsl:call-template> AS <xsl:value-of select="@name"/></xsl:when>
|
|
<xsl:otherwise>"<xsl:value-of select="$table"/>"."<xsl:value-of select="@name"/>"</xsl:otherwise>
|
|
</xsl:choose><xsl:choose>
|
|
<xsl:when test="position() = last()"></xsl:when>
|
|
<xsl:otherwise>,
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:for-each>
|
|
FROM "<xsl:value-of select="@name"/>" <xsl:for-each
|
|
select="property[@type='entity']">, "<xsl:value-of select="@entity"/>" AS "<xsl:value-of select="@name"/>"</xsl:for-each>
|
|
<xsl:text>
|
|
</xsl:text>
|
|
<xsl:for-each select="property[@type='entity']">
|
|
<xsl:choose>
|
|
<xsl:when test="position() = 1">WHERE </xsl:when>
|
|
<xsl:otherwise>AND </xsl:otherwise>
|
|
</xsl:choose>"<xsl:value-of select="$table"/>"."<xsl:value-of
|
|
select="@name"/>" = "<xsl:value-of select="@name"/>"."<xsl:value-of select="@entity"/>Id"
|
|
</xsl:for-each>
|
|
|
|
GO
|
|
|
|
---- permissions ------------------------------------------------------------------------------
|
|
<xsl:for-each select="permission">
|
|
<xsl:call-template name="viewpermission">
|
|
<xsl:with-param name="table" select="$table"/>
|
|
</xsl:call-template>
|
|
</xsl:for-each>
|
|
|
|
<!-- link tables -->
|
|
<xsl:for-each select="property[@type='link']">
|
|
<xsl:call-template name="linktable">
|
|
<xsl:with-param name="nearside" select="$table"/>
|
|
</xsl:call-template>
|
|
</xsl:for-each>
|
|
|
|
</xsl:template>
|
|
|
|
<xsl:template name="distinctfield">
|
|
<xsl:param name="table"/>
|
|
<xsl:param name="alias"/>
|
|
<!--
|
|
print the names of the distinguishing fields in this table,
|
|
concatenating into a single string.
|
|
-->
|
|
<xsl:for-each select="/application/entity[@name=$table]">
|
|
<xsl:for-each select="property[@distinct='user' or @distinct='all']">
|
|
<xsl:choose>
|
|
<xsl:when test="@type='entity'">
|
|
<xsl:call-template name="distinctfield">
|
|
<xsl:with-param name="table" select="@entity"/>
|
|
<xsl:with-param name="alias" select="concat( $alias, '_', @name)"></xsl:with-param>
|
|
</xsl:call-template>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
"<xsl:value-of select="$alias"/>"."<xsl:value-of
|
|
select="@name"/>"<xsl:if test="position() != last()"> + ' ' + </xsl:if>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
|
|
</xsl:for-each>
|
|
</xsl:for-each>
|
|
</xsl:template>
|
|
|
|
<xsl:template name="permission">
|
|
<xsl:param name="table"/>
|
|
<!-- decode the permissions for a table -->
|
|
<xsl:choose>
|
|
<xsl:when test="@permission='read'">GRANT SELECT ON "<xsl:value-of
|
|
select="$table"/>" TO <xsl:value-of select="@group"/>
|
|
|
|
GO</xsl:when>
|
|
<xsl:when test="@permission='insert'">GRANT INSERT ON "<xsl:value-of
|
|
select="$table"/>" TO <xsl:value-of select="@group"/>
|
|
|
|
GO</xsl:when>
|
|
<xsl:when test="@permission='noedit'">GRANT SELECT, INSERT ON "<xsl:value-of
|
|
select="$table"/>" TO <xsl:value-of select="@group"/>
|
|
|
|
GO</xsl:when>
|
|
<xsl:when test="@permission='edit'">GRANT SELECT, INSERT, UPDATE ON "<xsl:value-of
|
|
select="$table"/>" TO <xsl:value-of select="@group"/>
|
|
|
|
GO</xsl:when>
|
|
<xsl:when test="@permission='all'">GRANT SELECT, INSERT, UPDATE, DELETE ON "<xsl:value-of
|
|
select="$table"/>" TO <xsl:value-of select="@group"/>
|
|
|
|
GO</xsl:when>
|
|
<xsl:otherwise>REVOKE ALL ON "<xsl:value-of
|
|
select="$table"/>" FROM <xsl:value-of select="@group"/>
|
|
|
|
GO</xsl:otherwise>
|
|
</xsl:choose>
|
|
<xsl:text>
|
|
|
|
</xsl:text>
|
|
</xsl:template>
|
|
|
|
<xsl:template name="viewpermission">
|
|
<xsl:param name="table"/>
|
|
<!-- decode the permissions for a convenience view -->
|
|
<xsl:choose>
|
|
<xsl:when test="@permission='none'">REVOKE ALL ON "VW_DL_<xsl:value-of
|
|
select="$table"/>" FROM <xsl:value-of select="@group"/>
|
|
|
|
GO</xsl:when>
|
|
<xsl:when test="@permission='insert'">REVOKE ALL ON "VW_DL_<xsl:value-of
|
|
select="$table"/>" FROM <xsl:value-of select="@group"/>
|
|
|
|
GO</xsl:when>
|
|
<xsl:otherwise>GRANT SELECT ON "VW_DL_<xsl:value-of
|
|
select="$table"/>" TO <xsl:value-of select="@group"/>
|
|
|
|
GO</xsl:otherwise>
|
|
</xsl:choose>
|
|
<xsl:text>
|
|
|
|
</xsl:text>
|
|
</xsl:template>
|
|
|
|
|
|
<xsl:template name="linktable">
|
|
<xsl:param name="nearside"/>
|
|
<!-- This is tricky. For any many-to-many relationship between two
|
|
entities, we only want to create one link table, even if (as should be)
|
|
a property of type 'link' has been declared at both ends -->
|
|
<xsl:variable name="farside">
|
|
<xsl:choose>
|
|
<xsl:when test="@entity = $nearside">
|
|
<xsl:value-of select="concat( @entity, '_1')"/>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:value-of select="@entity"/>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:variable>
|
|
<xsl:variable name="comparison">
|
|
<xsl:call-template name="stringcompare">
|
|
<xsl:with-param name="node1" select="$nearside"/>
|
|
<xsl:with-param name="node2" select="@entity"/>
|
|
</xsl:call-template>
|
|
</xsl:variable>
|
|
<xsl:variable name="farentity" select="/application/entity[@name=$farside]"/>
|
|
|
|
-- Problems with responsibility for generating link tables:
|
|
-- @entity = <xsl:value-of select="@entity"/>
|
|
-- $nearside = <xsl:value-of select="$nearside"/>
|
|
-- $farside = <xsl:value-of select="$farside"/>
|
|
-- $farentity = <xsl:value-of select="count( $farentity/property)"/>
|
|
-- farlink = <xsl:value-of select="$farentity/property[@type='link' and @entity=$nearside]/@name"/>
|
|
-- comparison = '<xsl:value-of select="$comparison"/>'
|
|
|
|
<xsl:variable name="myresponsibility">
|
|
<xsl:choose>
|
|
<!-- if we could use the compare( string, string) function this would be a lot simpler, but
|
|
unfortunately that's in XSL 2.0, and neither NAnt nor Visual Studio can manage that -->
|
|
<!-- if the link is back to me, then obviously I'm responsible -->
|
|
<xsl:when test="$comparison = 0">true</xsl:when>
|
|
<!-- generally, the entity whose name is later in the default collating sequence
|
|
shall not be responsible. -->
|
|
<xsl:when test="$comparison = -1">true</xsl:when>
|
|
<!-- However if the one that is earlier doesn't have a 'link'
|
|
property for this join, however, then later end will have to do it -->
|
|
<xsl:when test="$comparison = 1">
|
|
<xsl:choose>
|
|
<!-- the far side is doing it... -->
|
|
<xsl:when test="$farentity/property[@type='link' and @entity=$nearside]">false</xsl:when>
|
|
<xsl:otherwise>true</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:when>
|
|
<xsl:otherwise>false</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:variable>
|
|
<xsl:variable name="tablename">
|
|
<xsl:choose>
|
|
<xsl:when test="$comparison =-1">
|
|
<xsl:value-of select="concat( 'ln_', $nearside, '_', @entity)"/>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:value-of select="concat( 'ln_', @entity, '_', $nearside)"/>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:variable>
|
|
-- Responsibility = '<xsl:value-of select="$myresponsibility"/>'
|
|
<xsl:choose>
|
|
<xsl:when test="$myresponsibility='true'">
|
|
<!-- create a linking table -->
|
|
|
|
-------------------------------------------------------------------------------------------------
|
|
-- link table joining <xsl:value-of select="$nearside"/> with <xsl:value-of select="@entity"/>
|
|
-------------------------------------------------------------------------------------------------
|
|
CREATE TABLE "<xsl:value-of select="$tablename"/>"
|
|
(
|
|
"<xsl:value-of select="$nearside"/>Id" INT NOT NULL,
|
|
"<xsl:value-of select="$farside"/>Id" INT NOT NULL,
|
|
)
|
|
|
|
GO
|
|
<xsl:text>
|
|
|
|
</xsl:text>
|
|
---- permissions ------------------------------------------------------------------------------
|
|
<xsl:for-each select="../permission">
|
|
<xsl:call-template name="permission">
|
|
<xsl:with-param name="table" select="$tablename"/>
|
|
</xsl:call-template>
|
|
</xsl:for-each>
|
|
<xsl:text>
|
|
|
|
</xsl:text>
|
|
---- referential integrity --------------------------------------------------------------------
|
|
<xsl:choose>
|
|
<xsl:when test="$nearside=@entity">
|
|
ALTER TABLE "<xsl:value-of select="$tablename"/>"
|
|
ADD FOREIGN KEY ( "<xsl:value-of select="$nearside"/>Id")
|
|
REFERENCES "<xsl:value-of select="$nearside"/>" ON DELETE NO ACTION
|
|
|
|
GO
|
|
|
|
ALTER TABLE "<xsl:value-of select="$tablename"/>"
|
|
ADD FOREIGN KEY ( "<xsl:value-of select="$farside"/>Id")
|
|
REFERENCES "<xsl:value-of select="$nearside"/>" ON DELETE NO ACTION
|
|
|
|
GO
|
|
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
ALTER TABLE "<xsl:value-of select="$tablename"/>"
|
|
ADD FOREIGN KEY ( "<xsl:value-of select="$nearside"/>Id")
|
|
REFERENCES "<xsl:value-of select="$nearside"/>" ON DELETE CASCADE
|
|
|
|
GO
|
|
|
|
ALTER TABLE "<xsl:value-of select="$tablename"/>"
|
|
ADD FOREIGN KEY ( "<xsl:value-of select="@entity"/>Id")
|
|
REFERENCES "<xsl:value-of select="@entity"/>" ON DELETE CASCADE
|
|
|
|
GO
|
|
|
|
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
|
|
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
-- Suppressing generation of <xsl:value-of select="$tablename"/>, as it is not my responsibility
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
<xsl:if test="myresponsibility='true'">
|
|
</xsl:if>
|
|
</xsl:template>
|
|
|
|
<xsl:template match="property[@type='list']">
|
|
-- Suppressing output of property <xsl:value-of select="@name"/>,
|
|
-- as it is the 'one' end of a one-to-many relationship
|
|
</xsl:template>
|
|
|
|
<xsl:template match="property[@type='entity']">
|
|
"<xsl:value-of select="@name"/>" INT<xsl:if
|
|
test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if
|
|
test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
|
|
</xsl:text>
|
|
</xsl:template>
|
|
|
|
<xsl:template match="property[@type='defined']">
|
|
<xsl:variable name="name"><xsl:value-of select="@definition"/></xsl:variable>
|
|
<xsl:variable name="definitiontype"><xsl:value-of select="/application/definition[@name=$name]/@type"/></xsl:variable>
|
|
"<xsl:value-of select="@name"/>"<xsl:text> </xsl:text><xsl:choose>
|
|
<xsl:when test="$definitiontype='string'">VARCHAR( <xsl:value-of
|
|
select="/application/definition[@name=$name]/@size"/>)</xsl:when>
|
|
<xsl:when test="$definitiontype='integer'">INT</xsl:when>
|
|
<xsl:when test="$definitiontype='real'">DOUBLE PRECISION</xsl:when>
|
|
<xsl:otherwise><xsl:value-of select="$definitiontype"/></xsl:otherwise>
|
|
</xsl:choose><xsl:if
|
|
test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if
|
|
test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
|
|
</xsl:text>
|
|
</xsl:template>
|
|
|
|
|
|
<xsl:template match="property[@type='boolean']">
|
|
-- SQL Server doesn't have proper booleans!
|
|
"<xsl:value-of select="@name"/>" BIT<xsl:choose>
|
|
<xsl:when test="@default='true'"> DEFAULT 1</xsl:when>
|
|
<xsl:when test="@default='false'"> DEFAULT 0</xsl:when>
|
|
</xsl:choose><xsl:if test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
|
|
</xsl:text>
|
|
</xsl:template>
|
|
|
|
|
|
<xsl:template match="property[@type='string']">
|
|
"<xsl:value-of select="@name"/>" VARCHAR( <xsl:value-of select="@size"/>)<xsl:if
|
|
test="string(@default)"> DEFAULT '<xsl:value-of select="@default"/>'</xsl:if><xsl:if
|
|
test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
|
|
</xsl:text>
|
|
</xsl:template>
|
|
|
|
<xsl:template match="property[@type='date' or @type = 'time']">
|
|
"<xsl:value-of select="@name"/>" DATETIME<xsl:if
|
|
test="string(@default)"> DEFAULT <xsl:value-of select="@default"/>
|
|
</xsl:if><xsl:if
|
|
test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
|
|
</xsl:text>
|
|
</xsl:template>
|
|
|
|
|
|
<xsl:template match="property[@type='integer']">
|
|
"<xsl:value-of select="@name"/>" INT<xsl:if
|
|
test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if
|
|
test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
|
|
</xsl:text>
|
|
</xsl:template>
|
|
|
|
<xsl:template match="property[@type='real']">
|
|
"<xsl:value-of select="@name"/>" DOUBLE PRECISION<xsl:if
|
|
test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if
|
|
test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
|
|
</xsl:text>
|
|
</xsl:template>
|
|
|
|
<xsl:template match="property">
|
|
"<xsl:value-of select="@name"/>" <xsl:text> </xsl:text><xsl:value-of select="@type"/><xsl:if
|
|
test="string(@default)"> DEFAULT <xsl:value-of select="@default"/></xsl:if><xsl:if
|
|
test="@required='true'"> NOT NULL</xsl:if>,<xsl:text>
|
|
</xsl:text>
|
|
</xsl:template>
|
|
|
|
|
|
<!-- horrible, horrible hackery. Compare two strings and return
|
|
* 0 if they are identical,
|
|
* -1 if the first is earlier in the default collating sequence,
|
|
* 1 if the first is later.
|
|
In XSL 2.0 this could be done using the compare(string, string) function. -->
|
|
<xsl:template name="stringcompare">
|
|
<xsl:param name="node1"/>
|
|
<xsl:param name="node2"/>
|
|
<xsl:choose>
|
|
<xsl:when test="string($node1)=string($node2)">
|
|
<xsl:text>0</xsl:text>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:for-each select="$node1 | $node2">
|
|
<xsl:sort select="."/>
|
|
<xsl:if test="position()=1">
|
|
<xsl:choose>
|
|
<xsl:when test="string(.) = string($node1)">
|
|
<xsl:text>-1</xsl:text>
|
|
</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:text>1</xsl:text>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:if>
|
|
</xsl:for-each>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:template>
|
|
|
|
</xsl:stylesheet>
|