322 lines
16 KiB
HTML
Executable file
322 lines
16 KiB
HTML
Executable file
<?xml version="1.0"?>
|
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
<!-- :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -->
|
|
<!-- -->
|
|
<!-- adl2psql.xsl -->
|
|
<!-- -->
|
|
<!-- Purpose: -->
|
|
<!-- XSL stylesheet to generate Postgresql [7|8] from ADL. -->
|
|
<!-- -->
|
|
<!-- Author: Simon Brooke <sb@cygnets.co.uk> -->
|
|
<!-- Created: 24th January 2006 -->
|
|
<!-- Copyright: (c) 2008 Cygnet Solutions -->
|
|
<!--
|
|
JACQUARD 2 APPLICATION DESCRIPTION LANGUAGE FRAMEWORK
|
|
|
|
$Revision: 1.1 $
|
|
|
|
NOTES:
|
|
|
|
Needless to say this is all hugely experimental.
|
|
|
|
Running the primary key field last is a hack which gets around the fact that
|
|
otherwise it's extremely complex to lose the comma after the last field.
|
|
Ideally where there is one 'distinct="system"' property of an entity that
|
|
should be the primary key and perhaps we'll achieve that in the long run...
|
|
|
|
Still to do:
|
|
|
|
References in convenience views for fields which have their reference value at
|
|
two removes (i.e. the 'distinguish' mechanism in ADL
|
|
-->
|
|
|
|
<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 PostgreSQL [7|8] using adl2psql.xsl $Revision: 1.1 $
|
|
--
|
|
-- Code generator (c) 2006 Simon Brooke [sb@cygnets.co.uk]
|
|
-- http://www.weft.co.uk/library/jacquard/
|
|
--
|
|
-------------------------------------------------------------------------------------------------
|
|
|
|
-------------------------------------------------------------------------------------------------
|
|
-- authentication roles
|
|
-------------------------------------------------------------------------------------------------
|
|
<xsl:apply-templates select="group"/>
|
|
|
|
-------------------------------------------------------------------------------------------------
|
|
-- tables, views and permissions
|
|
-------------------------------------------------------------------------------------------------
|
|
<xsl:apply-templates select="entity"/>
|
|
|
|
-------------------------------------------------------------------------------------------------
|
|
-- 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 select="property[@type='link']">
|
|
<xsl:call-template name="linkintegrity">
|
|
<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">
|
|
CREATE GROUP <xsl:value-of select="@name"/>;
|
|
</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 CONSTRAINT ri_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@name"/>
|
|
FOREIGN KEY ( <xsl:value-of select="@name"/>) REFERENCES <xsl:value-of select="@entity"/> ON DELETE NO ACTION;
|
|
</xsl:template>
|
|
|
|
|
|
<xsl:template name="linkintegrity">
|
|
<xsl:param name="nearside"/>
|
|
<!-- set up referential integrity constraints for link tables -->
|
|
ALTER TABLE ln_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@entity"/>
|
|
ADD CONSTRAINT ri_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@entity"/>_<xsl:value-of select="$nearside"/>_id
|
|
FOREIGN KEY ( <xsl:value-of select="$nearside"/>_id) REFERENCES <xsl:value-of select="$nearside"/> ON DELETE CASCADE;
|
|
|
|
ALTER TABLE ln_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@entity"/>
|
|
ADD CONSTRAINT ri_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@entity"/>_<xsl:value-of select="@entity"/>_id
|
|
FOREIGN KEY ( <xsl:value-of select="@entity"/>_id) REFERENCES <xsl:value-of select="@entity"/> ON DELETE CASCADE;
|
|
|
|
</xsl:template>
|
|
|
|
|
|
<xsl:template match="entity">
|
|
<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 SERIAL NOT NULL PRIMARY KEY
|
|
);
|
|
|
|
---- permissions ------------------------------------------------------------------------------
|
|
<xsl:for-each select="permission">
|
|
<xsl:call-template name="permission">
|
|
<xsl:with-param name="table" select="$table"/>
|
|
</xsl:call-template>
|
|
</xsl:for-each>
|
|
-------------------------------------------------------------------------------------------------
|
|
-- convenience view lv_<xsl:value-of select="@name"/> for lists
|
|
-------------------------------------------------------------------------------------------------
|
|
CREATE VIEW lv_<xsl:value-of select="@name"/> AS
|
|
SELECT <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>;
|
|
|
|
---- 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>
|
|
---- permissions ------------------------------------------------------------------------------
|
|
<xsl:variable name="farside" select="@entity"/>
|
|
<xsl:for-each select="../permission">
|
|
<xsl:call-template name="permission">
|
|
<xsl:with-param name="table">ln_<xsl:value-of select="$table"/>_<xsl:value-of select="$farside"/></xsl:with-param>
|
|
</xsl:call-template>
|
|
</xsl:for-each>
|
|
</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 GROUP <xsl:value-of select="@group"/>;</xsl:when>
|
|
<xsl:when test="@permission='insert'">GRANT INSERT ON <xsl:value-of
|
|
select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:when>
|
|
<xsl:when test="@permission='noedit'">GRANT SELECT, INSERT ON <xsl:value-of
|
|
select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:when>
|
|
<xsl:when test="@permission='edit'">GRANT SELECT, INSERT, UPDATE ON <xsl:value-of
|
|
select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:when>
|
|
<xsl:when test="@permission='all'">GRANT SELECT, INSERT, UPDATE, DELETE ON <xsl:value-of
|
|
select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:when>
|
|
<xsl:otherwise>REVOKE ALL ON <xsl:value-of
|
|
select="$table"/> FROM GROUP <xsl:value-of select="@group"/>;</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 lv_<xsl:value-of
|
|
select="$table"/> FROM GROUP <xsl:value-of select="@group"/>;</xsl:when>
|
|
<xsl:when test="@permission='insert'">REVOKE ALL ON lv_<xsl:value-of
|
|
select="$table"/> FROM GROUP <xsl:value-of select="@group"/>;</xsl:when>
|
|
<xsl:otherwise>GRANT SELECT ON lv_<xsl:value-of
|
|
select="$table"/> TO GROUP <xsl:value-of select="@group"/>;</xsl:otherwise>
|
|
</xsl:choose>
|
|
<xsl:text>
|
|
|
|
</xsl:text>
|
|
</xsl:template>
|
|
|
|
|
|
<xsl:template name="linktable">
|
|
<xsl:param name="nearside"/>
|
|
<xsl:variable name="farside">
|
|
<xsl:choose>
|
|
<xsl:when test="@entity = $nearside"><xsl:value-of select="@entity"/>_1</xsl:when>
|
|
<xsl:otherwise>
|
|
<xsl:value-of select="@entity"/>
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</xsl:variable>
|
|
<!-- create a linking table -->
|
|
|
|
-------------------------------------------------------------------------------------------------
|
|
-- link table joining <xsl:value-of select="$nearside"/> with <xsl:value-of select="@entity"/>
|
|
-------------------------------------------------------------------------------------------------
|
|
CREATE TABLE ln_<xsl:value-of select="$nearside"/>_<xsl:value-of select="@entity"/>
|
|
(
|
|
<xsl:value-of select="$nearside"/>_id INT NOT NULL,
|
|
<xsl:value-of select="$farside"/>_id INT NOT NULL,
|
|
);
|
|
<xsl:text>
|
|
|
|
</xsl:text>
|
|
<!-- TODO: permissions for link tables! -->
|
|
|
|
</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='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='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>
|
|
|
|
</xsl:stylesheet>
|