Skip to content

Instantly share code, notes, and snippets.

@ashalkhakov
Last active Jul 10, 2019
Embed
What would you like to do?
Mapping DCIL to D4. Added more constraints. Well, only those that my ORM model needs, at the moment. Added support for clustered and sparse keys.
<?xml version="1.0" encoding="utf-8"?>
<!-- Author: Artyom Shalkhakov (artyom.shalkhakov@gmail.com)
License: BSD v3
I've used bits and pieces of other transforms bundled
with NORMA for reference, so I'm not the sole author
of this.
-->
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:dcl="http://schemas.orm.net/DIL/DCIL"
xmlns:exsl="http://exslt.org/common"
xmlns:dep="http://schemas.orm.net/DIL/DILEP"
xmlns:ddt="http://schemas.orm.net/DIL/DILDT"
xmlns:oct="urn:ORMCustomTool:ItemProperties"
exclude-result-prefixes="dcl dep ddt exsl"
extension-element-prefixes="exsl oct">
<xsl:import href="DILSupportFunctions.xslt"/>
<xsl:output method="text" encoding="utf-8" indent="no" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<!--
TODO exclusion constraint on functional roles -> row constraint
-->
<xsl:param name="Period" select="'.'"/>
<xsl:param name="NewLine" select="'&#x0D;&#x0A;'"/>
<xsl:param name="IndentChar" select="'&#x09;'"/>
<xsl:param name="StatementStartBracket" select="'{'"/>
<xsl:param name="StatementEndBracket" select="'}'"/>
<xsl:param name="LeftParen" select="'('"/>
<xsl:param name="RightParen" select="')'"/>
<xsl:param name="ConcatenationOperator" select="'+'"/>
<xsl:param name="StatementDelimiter" select="';'"/>
<xsl:param name="SetClauseEqualsOperator" select="'='"/>
<xsl:param name="StatementBlockDelimeter" select="''"/>
<xsl:variable name="DcilSchemaName" select="string(dcl:schema/@name)"/>
<xsl:variable name="DcilTables" select="dcl:schema/dcl:table"/>
<xsl:variable name="ProjectNameFragment">
<xsl:choose>
<xsl:when test="function-available('oct:GetProjectProperty')">
<xsl:value-of select="oct:GetProjectProperty('Title')"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>ProjectName</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="ProjectName" select="string($ProjectNameFragment)"/>
<xsl:template match="dcl:schema">
<xsl:param name="indent"/>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:text>EnsureGenerators();</xsl:text>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:text>// Data Types</xsl:text>
<!-- TODO: create data types for identity columns
of tables, provided they haven't been promoted
to domains
-->
<xsl:apply-templates select="dcl:domain">
<xsl:with-param name="indent" select="$indent"/>
</xsl:apply-templates>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:text>// Tables (Base RelVars)</xsl:text>
<xsl:apply-templates select="dcl:table" mode="ForTableDefinition">
<xsl:with-param name="indent" select="$indent"/>
</xsl:apply-templates>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:text>// Table and Database Constraints</xsl:text>
<xsl:apply-templates select="dcl:table" mode="ForTableAndDatabaseConstraints">
<xsl:with-param name="indent" select="$indent"/>
</xsl:apply-templates>
<!-- TODO map triggers? -->
</xsl:template>
<xsl:template match="dcl:table" mode="ForTableDefinition">
<xsl:param name="indent"/>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:text>create table </xsl:text>
<xsl:call-template name="RenderSchemaQualifiedIdentifier">
<xsl:with-param name="schemaName" select="$DcilSchemaName"/>
<xsl:with-param name="identifier" select="@name"/>
</xsl:call-template>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:value-of select="$StatementStartBracket"/>
<xsl:apply-templates select="dcl:column">
<xsl:with-param name="indent" select="concat($indent, $IndentChar)"/>
</xsl:apply-templates>
<xsl:text>,</xsl:text>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="concat($indent, $IndentChar)"/>
<!-- always output the primary key first, also mark it as clustered -->
<xsl:apply-templates select="dcl:uniquenessConstraint[@isPrimary = 'true' or @isPrimary = 1]">
<xsl:with-param name="indent" select="concat($indent, $IndentChar)"/>
</xsl:apply-templates>
<xsl:text> tags { DAE.IsClustered = 'true' }</xsl:text>
<!-- output other keys, if any -->
<xsl:if test="dcl:uniquenessConstraint[not(@isPrimary = 'true' or @isPrimary = 1)]">
<xsl:text>,</xsl:text>
<xsl:value-of select="concat($indent, $IndentChar)"/>
<xsl:apply-templates select="dcl:uniquenessConstraint[not(@isPrimary = 'true' or @isPrimary = 1)]">
<xsl:with-param name="indent" select="concat($indent, $IndentChar)"/>
</xsl:apply-templates>
</xsl:if>
<xsl:if test="dcl:checkConstraint">
<xsl:text>,</xsl:text>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="concat($indent, $IndentChar)"/>
<!--
TODO table constraints
dcl:checkConstraint -> check (also probably metadata?)
-->
<xsl:apply-templates select="dcl:checkConstraint" mode="ForRowConstraints">
<xsl:with-param name="indent" select="concat($indent, $IndentChar)"/>
</xsl:apply-templates>
</xsl:if>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:value-of select="$StatementEndBracket"/>
<xsl:value-of select="$StatementDelimiter"/>
</xsl:template>
<xsl:template match="dcl:column">
<xsl:param name="indent"/>
<xsl:if test="not(position()=1)">
<xsl:text>,</xsl:text>
</xsl:if>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:apply-templates select="@name" mode="ForColumnName"/>
<xsl:text> : </xsl:text>
<xsl:apply-templates select="." mode="GetDbType"/>
<xsl:text> </xsl:text>
<xsl:choose>
<xsl:when test="@isNullable = 'true' or @isNullable = 1">
<xsl:text>nil</xsl:text>
</xsl:when>
<xsl:when test="not(@isNullable = 'true' or @isNullable = 1)">
<xsl:text>not nil</xsl:text>
</xsl:when>
</xsl:choose>
<xsl:if test="@isIdentity = 'true' or @isIdentity = 1">
<xsl:text> </xsl:text>
<xsl:value-of select="$StatementStartBracket"/>
<xsl:text> default </xsl:text>
<!-- FIXME what about other defaults? -->
<xsl:text>GetNextGenerator("</xsl:text>
<!-- UNDONE decide when we actually want
to qualify names
<xsl:call-template name="RenderIdentifier">
<xsl:with-param name="name" select="$DcilSchemaName"/>
</xsl:call-template>
<xsl:value-of select="$Period"/>-->
<xsl:call-template name="RenderIdentifier">
<xsl:with-param name="name" select="parent::*/@name"/>
</xsl:call-template>
<xsl:value-of select="$Period"/>
<xsl:call-template name="RenderIdentifier">
<xsl:with-param name="name" select="@name"/>
</xsl:call-template>
<xsl:text>") </xsl:text>
<xsl:value-of select="$StatementEndBracket"/>
</xsl:if>
<xsl:if test="child::dcl:predefinedDataType">
<xsl:apply-templates select="child::dcl:predefinedDataType" mode="ForBasicDataTypeConstraints">
<xsl:with-param name="indent" select="concat($indent, $IndentChar)"/>
<xsl:with-param name="braketize" select="true()"/>
</xsl:apply-templates>
<xsl:apply-templates select="child::dcl:predefinedDataType" mode="ForTags">
<xsl:with-param name="indent" select="concat($indent, $IndentChar)"/>
</xsl:apply-templates>
</xsl:if>
<!-- UNDONE column constraints? dcl:checkConstraint -->
</xsl:template>
<xsl:template match="@name" mode="ForColumnName">
<xsl:call-template name="RenderIdentifier">
<xsl:with-param name="name" select="."/>
</xsl:call-template>
</xsl:template>
<xsl:template match="dcl:column" mode="GetDbType">
<xsl:choose>
<xsl:when test="dcl:domainRef">
<xsl:call-template name="RenderSchemaQualifiedIdentifier">
<xsl:with-param name="schemaName" select="$DcilSchemaName"/>
<xsl:with-param name="identifier" select="dcl:domainRef/@name"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="dcl:predefinedDataType">
<xsl:call-template name="GetDbTypeFromDcilPredefinedDataType">
<xsl:with-param name="predefinedDataType" select="dcl:predefinedDataType"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:message>GetDbType for column failed</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="GetDbTypeFromDcilPredefinedDataType">
<xsl:param name="predefinedDataType"/>
<xsl:variable name="predefinedDataTypeName" select="$predefinedDataType/@name"/>
<xsl:choose>
<xsl:when test="$predefinedDataTypeName = 'CHARACTER'">
<xsl:value-of select="'String'"/>
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'CHARACTER VARYING'">
<xsl:value-of select="'String'"/>
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'CHARACTER LARGE OBJECT'">
<xsl:value-of select="'String'"/>
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'BINARY'">
<xsl:value-of select="'Binary'"/>
</xsl:when>
<!-- NOTE: in ConceptualDBtoDCIL.xslt, ormdt:PictureRawDataDataType is mapped to BINARY VARYING,
and so are a few others (e.g. Ole), but since we are only interested
in pictures, we will map to a Binary
FIXME: we need a converter from ORM/OIAL straight to D4.
-->
<xsl:when test="$predefinedDataTypeName = 'BINARY VARYING'">
<xsl:value-of select="'Graphic'"/>
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'BINARY LARGE OBJECT'">
<xsl:value-of select="'Binary'"/>
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'NUMERIC'">
<xsl:value-of select="'Decimal'"/>
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'DECIMAL'">
<xsl:value-of select="'Decimal'"/>
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'TINYINT'">
<xsl:value-of select="'Byte'"/>
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'SMALLINT'">
<xsl:value-of select="'Short'"/>
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'INTEGER'">
<xsl:value-of select="'Integer'"/>
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'BIGINT'">
<xsl:value-of select="'Long'"/>
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'FLOAT'">
<xsl:message>FLOAT is not supported in Dataphor</xsl:message>
<!--
<xsl:choose>
<xsl:when test="string($predefinedDataTypeName/@percision)">
<xsl:choose>
<xsl:when test="$predefinedDataTypeName/@percision &lt;= 24">
<xsl:value-of select="'Single'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'Double'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'Double'"/>
</xsl:otherwise>
</xsl:choose>-->
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'REAL'">
<xsl:message>REAL datatype not supported in Dataphor</xsl:message>
<!-- <xsl:value-of select="'Single'"/> -->
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'DOUBLE PRECISION'">
<xsl:message>DOUBLE PRECISION datatype not supported in Dataphor</xsl:message>
<!--<xsl:value-of select="'Double'"/>-->
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'BOOLEAN'">
<xsl:value-of select="'Boolean'"/>
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'DATE'">
<xsl:value-of select="'Date'"/>
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'TIME'">
<xsl:value-of select="'Time'"/>
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'TIMESTAMP'">
<xsl:value-of select="'DateTime'"/>
</xsl:when>
<xsl:when test="$predefinedDataTypeName = 'INTERVAL'">
<xsl:value-of select="'TimeSpan'"/>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="dcl:uniquenessConstraint">
<xsl:param name="indent"/>
<xsl:if test="not(position()=1)">
<xsl:text>,</xsl:text>
</xsl:if>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:text>key </xsl:text>
<xsl:text>/* </xsl:text>
<xsl:call-template name="RenderIdentifier">
<xsl:with-param name="name" select="@name"/>
</xsl:call-template>
<xsl:text> */ </xsl:text>
<xsl:value-of select="$StatementStartBracket"/>
<xsl:text> </xsl:text>
<xsl:apply-templates select="dcl:columnRef"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$StatementEndBracket"/>
<!-- mark some keys as sparse -->
<xsl:apply-templates select="." mode="MarkSparseKey"/>
</xsl:template>
<xsl:key name="column" match="dcl:table/dcl:column" use="concat(../@name, '.', @name)"/>
<xsl:template match="dcl:uniquenessConstraint" mode="MarkSparseKey">
<!-- FIXME: we just want to check for non-empty intersection here;
is any of the columns in the constraint nullable?
-->
<xsl:variable name="opts">
<xsl:for-each select="dcl:columnRef">
<xsl:variable name="colname" select="@name"/>
<xsl:if test="../../dcl:column[@name = $colname and (@isNullable = 'true' or @isNullable = 1)]">
<xsl:text>true</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:if test="string-length($opts) > 0">
<xsl:text> tags </xsl:text>
<xsl:value-of select="$StatementStartBracket"/>
<xsl:text> </xsl:text>
<xsl:text>DAE.IsSparse = 'true'</xsl:text>
<xsl:text> </xsl:text>
<xsl:value-of select="$StatementEndBracket"/>
</xsl:if>
</xsl:template>
<xsl:template match="dcl:columnRef">
<xsl:if test="not(position()=1)">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:call-template name="RenderIdentifier">
<xsl:with-param name="name" select="@name"/>
</xsl:call-template>
</xsl:template>
<xsl:template match="dcl:domain">
<xsl:param name="indent"/>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:text>create type </xsl:text>
<xsl:call-template name="RenderSchemaQualifiedIdentifier">
<xsl:with-param name="schemaName" select="$DcilSchemaName"/>
<xsl:with-param name="identifier" select="@name"/>
</xsl:call-template>
<xsl:text> like </xsl:text>
<xsl:call-template name="GetDbTypeFromDcilPredefinedDataType">
<xsl:with-param name="predefinedDataType" select="dcl:predefinedDataType"/>
</xsl:call-template>
<xsl:if test="dcl:checkConstraint">
<!-- map check constraints (dcl:checkConstraint) -->
<xsl:text> </xsl:text>
<xsl:value-of select="$StatementStartBracket"/>
<xsl:apply-templates select="dcl:checkConstraint" mode="ForTypeConstraints">
<xsl:with-param name="indent" select="concat($indent, $IndentChar)"/>
</xsl:apply-templates>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:value-of select="$StatementEndBracket"/>
</xsl:if>
<xsl:apply-templates select="dcl:predefinedDataType" mode="ForTags">
<xsl:with-param name="indent" select="concat($indent, $IndentChar)"/>
</xsl:apply-templates>
<xsl:value-of select="$StatementDelimiter"/>
</xsl:template>
<xsl:template match="dcl:predefinedDataType" mode="ForBasicDataTypeConstraints">
<xsl:param name="indent"/>
<xsl:param name="braketize" select="false()"/>
<xsl:choose>
<xsl:when test="(@name = 'CHARACTER' or @name = 'CHARACTER VARYING' or @name = 'CHARACTER LARGE OBJECT') and @length">
<xsl:if test="$braketize = true()">
<xsl:value-of select="$StatementStartBracket"/>
</xsl:if>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="concat($indent, $IndentChar)"/>
<xsl:text>constraint LengthValid Length</xsl:text>
<xsl:value-of select="$LeftParen"/>
<xsl:text>value</xsl:text>
<xsl:value-of select="$RightParen"/>
<xsl:text> &lt;= </xsl:text>
<xsl:value-of select="@length"/>
<xsl:if test="$braketize = true()">
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:value-of select="$StatementEndBracket"/>
</xsl:if>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="dcl:predefinedDataType" mode="ForTags">
<xsl:param name="indent"/>
<xsl:choose>
<xsl:when test="(@name = 'CHARACTER' or @name = 'CHARACTER VARYING' or @name = 'CHARACTER LARGE OBJECT') and @length">
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:text>tags </xsl:text>
<xsl:value-of select="$StatementStartBracket"/>
<xsl:text>Frontend.Width = </xsl:text>
<xsl:text>'</xsl:text>
<xsl:value-of select="@length"/>
<xsl:text>'</xsl:text>
<xsl:value-of select="$StatementEndBracket"/>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:text>static tags </xsl:text>
<xsl:value-of select="$StatementStartBracket"/>
<xsl:text>Storage.Length = </xsl:text>
<xsl:text>'</xsl:text>
<xsl:value-of select="@length"/>
<xsl:text>'</xsl:text>
<xsl:value-of select="$StatementEndBracket"/>
</xsl:when>
<xsl:when test="(@name = 'NUMERIC' or @name = 'DECIMAL')">
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:text>static tags </xsl:text>
<xsl:value-of select="$StatementStartBracket"/>
<xsl:text>Storage.Precision = </xsl:text>
<xsl:text>'</xsl:text>
<xsl:value-of select="@precision"/>
<xsl:text>'</xsl:text>
<xsl:text>,</xsl:text>
<xsl:text>Storage.Scale = </xsl:text>
<xsl:text>'</xsl:text>
<xsl:value-of select="@scale"/>
<xsl:text>'</xsl:text>
<xsl:value-of select="$StatementEndBracket"/>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="dcl:table[child::dcl:referenceConstraint]" mode="ForTableAndDatabaseConstraints">
<xsl:param name="indent"/>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:variable name="sourceTableName" select="@name"/>
<xsl:for-each select="dcl:referenceConstraint">
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:text>create reference </xsl:text>
<xsl:call-template name="RenderSchemaQualifiedIdentifier">
<xsl:with-param name="schemaName" select="$DcilSchemaName"/>
<xsl:with-param name="identifier" select="@name"/>
</xsl:call-template>
<xsl:text> </xsl:text>
<xsl:call-template name="RenderSchemaQualifiedIdentifier">
<xsl:with-param name="schemaName" select="$DcilSchemaName"/>
<xsl:with-param name="identifier" select="$sourceTableName"/>
</xsl:call-template>
<xsl:text> </xsl:text>
<xsl:value-of select="$StatementStartBracket"/>
<xsl:text> </xsl:text>
<xsl:for-each select="dcl:columnRef">
<xsl:if test="not(position()=1)">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:call-template name="RenderIdentifier">
<xsl:with-param name="name" select="@sourceName"/>
</xsl:call-template>
</xsl:for-each>
<xsl:text> </xsl:text>
<xsl:value-of select="$StatementEndBracket"/>
<xsl:text> references </xsl:text>
<!-- UNDONE: we should be using @targetSchema instead,
but NORMA currently emits exactly one dcl:schema
and @targetSchema is empty
-->
<xsl:call-template name="RenderSchemaQualifiedIdentifier">
<xsl:with-param name="schemaName" select="$DcilSchemaName"/>
<xsl:with-param name="identifier" select="@targetTable"/>
</xsl:call-template>
<xsl:text> </xsl:text>
<xsl:value-of select="$StatementStartBracket"/>
<xsl:text> </xsl:text>
<xsl:for-each select="dcl:columnRef">
<xsl:if test="not(position()=1)">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:call-template name="RenderIdentifier">
<xsl:with-param name="name" select="@targetName"/>
</xsl:call-template>
</xsl:for-each>
<xsl:text> </xsl:text>
<xsl:value-of select="$StatementEndBracket"/>
<xsl:value-of select="$StatementDelimiter"/>
</xsl:for-each>
</xsl:template>
<xsl:template match="dcl:checkConstraint" mode="ForRowConstraints">
<xsl:param name="indent"/>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<xsl:text>constraint </xsl:text>
<xsl:call-template name="RenderIdentifier">
<xsl:with-param name="name" select="@name"/>
</xsl:call-template>
<xsl:text> </xsl:text>
<xsl:apply-templates select="child::*" mode="ForCheckConstraint"/>
</xsl:template>
<xsl:template match="dcl:checkConstraint" mode="ForTypeConstraints">
<xsl:param name="indent"/>
<xsl:value-of select="$NewLine"/>
<xsl:value-of select="$indent"/>
<!-- NOTE: [value] is a free variable in the type constraint expression;
it is bound by the constraint expression
-->
<xsl:text>constraint </xsl:text>
<xsl:call-template name="RenderIdentifier">
<xsl:with-param name="name" select="@name"/>
</xsl:call-template>
<xsl:text> </xsl:text>
<xsl:apply-templates select="child::*" mode="ForCheckConstraint"/>
</xsl:template>
<xsl:template match="dep:valueKeyword">
<xsl:text>value</xsl:text>
</xsl:template>
<xsl:template match="dep:or" mode="ForCheckConstraint">
<xsl:value-of select="$LeftParen"/>
<xsl:for-each select="child::*">
<xsl:if test="not(position()=1)">
<xsl:text> or </xsl:text>
</xsl:if>
<xsl:apply-templates select="." mode="ForCheckConstraint"/>
</xsl:for-each>
<xsl:value-of select="$RightParen"/>
</xsl:template>
<xsl:template match="dep:and" mode="ForCheckConstraint">
<xsl:value-of select="$LeftParen"/>
<xsl:for-each select="child::*">
<xsl:if test="not(position()=1)">
<xsl:text> and </xsl:text>
</xsl:if>
<xsl:apply-templates select="." mode="ForCheckConstraint"/>
</xsl:for-each>
<xsl:value-of select="$RightParen"/>
</xsl:template>
<xsl:template match="dep:nullPredicate" mode="ForCheckConstraint">
<xsl:choose>
<xsl:when test="@type = 'NOT NULL'">
<xsl:value-of select="$LeftParen"/>
<xsl:text>not IsNil</xsl:text>
<xsl:value-of select="$LeftParen"/>
<xsl:apply-templates select="child::*" mode="ForCheckConstraint"/>
<xsl:value-of select="$RightParen"/>
<xsl:value-of select="$RightParen"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>IsNil</xsl:text>
<xsl:value-of select="$LeftParen"/>
<xsl:apply-templates select="child::*" mode="ForCheckConstraint"/>
<xsl:value-of select="$RightParen"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="dep:inPredicate" mode="ForCheckConstraint">
<!-- first child of dep:inPredicate is dep:valueKeyword, other
children are part of the list -->
<xsl:apply-templates select="dep:valueKeyword"/>
<xsl:text> in </xsl:text>
<xsl:value-of select="$StatementStartBracket"/>
<xsl:for-each select="child::*[position() &gt; 1]">
<xsl:if test="not(position()=1)">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:apply-templates select="."/>
</xsl:for-each>
<xsl:value-of select="$StatementEndBracket"/>
</xsl:template>
<xsl:template match="dep:betweenPredicate" mode="ForCheckConstraint">
<xsl:value-of select="$LeftParen"/>
<xsl:apply-templates select="dep:valueKeyword"/>
<xsl:text> &gt;= </xsl:text>
<xsl:apply-templates select="child::*[position() = 2]"/>
<xsl:text> and </xsl:text>
<xsl:apply-templates select="dep:valueKeyword"/>
<xsl:text> &lt;= </xsl:text>
<xsl:apply-templates select="child::*[position() = 3]"/>
<xsl:value-of select="$RightParen"/>
</xsl:template>
<xsl:template match="dep:comparisonPredicate" mode="ForCheckConstraint">
<xsl:value-of select="$LeftParen"/>
<!-- two children (i.e., arity is 2) -->
<xsl:apply-templates select="child::*[1]"/>
<xsl:text> </xsl:text>
<xsl:call-template name="ComparisonPredicateOp">
<xsl:with-param name="operator" select="@operator"/>
</xsl:call-template>
<xsl:text> </xsl:text>
<xsl:apply-templates select="child::*[2]"/>
<xsl:value-of select="$RightParen"/>
</xsl:template>
<xsl:template name="ComparisonPredicateOp">
<xsl:param name="operator"/>
<xsl:choose>
<xsl:when test="$operator = 'equals'">
<xsl:text>=</xsl:text>
</xsl:when>
<xsl:when test="$operator = 'notEquals'">
<xsl:text>&lt;&gt;</xsl:text>
</xsl:when>
<xsl:when test="$operator = 'lessThan'">
<xsl:text>&lt;</xsl:text>
</xsl:when>
<xsl:when test="$operator = 'greaterThan'">
<xsl:text>&gt;</xsl:text>
</xsl:when>
<xsl:when test="$operator = 'lessThanOrEquals'">
<xsl:text>&lt;=</xsl:text>
</xsl:when>
<xsl:when test="$operator = 'greaterThanOrEquals'">
<xsl:text>&gt;=</xsl:text>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="dep:columnReference" mode="ForCheckConstraint">
<xsl:call-template name="RenderIdentifier">
<xsl:with-param name="name" select="@name"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="RenderSchemaQualifiedIdentifier">
<xsl:param name="schemaName"/>
<xsl:param name="identifier"/>
<!-- UNDONE it seems that if we set any library
as current in Dataphoria, then we don't need
qualified names in the schema unless we would
like to reference something from a library
other than the current
<xsl:call-template name="RenderIdentifier">
<xsl:with-param name="name" select="$schemaName"/>
</xsl:call-template>
<xsl:value-of select="$Period"/>
-->
<xsl:call-template name="RenderIdentifier">
<xsl:with-param name="name" select="$identifier"/>
</xsl:call-template>
</xsl:template>
<!-- handling of literals -->
<xsl:template match="ddt:characterStringLiteral">
<xsl:text>'</xsl:text>
<xsl:call-template name="RenderStringLiteral">
<xsl:with-param name="value" select="@value"/>
</xsl:call-template>
<xsl:text>'</xsl:text>
</xsl:template>
<xsl:template name="RenderStringLiteral">
<xsl:param name="value"/>
<xsl:choose>
<xsl:when test="contains($value, &quot;'&quot;)">
<xsl:value-of select="substring-before($value, &quot;'&quot;)"/>
<xsl:text>''</xsl:text>
<xsl:call-template name="RenderStringLiteral">
<xsl:with-param name="value" select="substring-after($value, &quot;'&quot;)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="ddt:binaryStringLiteral">
<xsl:message>Not supported. What syntax is used in D4 for binary string literals?</xsl:message>
</xsl:template>
<xsl:template match="ddt:exactNumericLiteral | ddt:approximateNumericLiteral">
<xsl:value-of select="@value"/>
</xsl:template>
<xsl:template match="ddt:dateLiteral">
<xsl:text>Date</xsl:text>
<xsl:value-of select="$LeftParen"/>
<!-- from format YYYY-MM-DD to YYYY,MM,DD -->
<xsl:value-of select="translate(@value, '-', ',')"/>
<xsl:value-of select="$RightParen"/>
</xsl:template>
<xsl:template match="ddt:timeLiteral">
<xsl:text>Time</xsl:text>
<xsl:value-of select="$LeftParen"/>
<!-- FIXME can't handle full format:
hh:mm:ss[.ssssssssssss][Z|(+|-)hh:mm]
in particular, time zone and fractional seconds not supported
in Dataphor, though they could be
-->
<xsl:if test="contains(@value, '.') or contains(@value, 'Z') or contains(@value, '+') or contains(@value, '-')">
<xsl:message>Time literal: timezone, fractional parts of second are not supported</xsl:message>
</xsl:if>
<xsl:value-of select="translate(@value,':', ',')"/>
<xsl:value-of select="$RightParen"/>
</xsl:template>
<xsl:template match="ddt:timestampLiteral">
<xsl:message>TimeStamp datatype not supported in Dataphor</xsl:message>
</xsl:template>
<xsl:template match="ddt:interval">
<xsl:message>Intervals are not supported!</xsl:message>
<!-- FIXME is it a TimeSpan? UNDONE yes it is!
<xsl:apply-templates select="@type" mode="ForDataType"/>
<xsl:text> </xsl:text>
<xsl:apply-templates select="@fields" mode="ForIntervalDataType"/>
<xsl:apply-templates select="@precision" mode="ForIntervalDataType"/>
-->
</xsl:template>
<xsl:template match="ddt:booleanLiteral">
<xsl:choose>
<xsl:when test="@value = 'TRUE'">
<xsl:text>True</xsl:text>
</xsl:when>
<xsl:when test="@value = 'FALSE'">
<xsl:text>False</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>nil</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- end of literals -->
<!-- NOTE by convention, all D4 keywords start with lower-cased
letters, so we start all variable names with upper-cased
letters to avoid any confusion
-->
<xsl:template name="RenderIdentifier">
<xsl:param name="name" select="."/>
<xsl:choose>
<xsl:when test="substring($name, 1,1) = '&quot;'">
<xsl:call-template name="RenderIdentifierCont">
<xsl:with-param name="name" select="substring($name, 2)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="RenderIdentifierCont">
<xsl:with-param name="name" select="$name"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="RenderIdentifierCont">
<xsl:param name="name"/>
<xsl:choose>
<xsl:when test="contains($name, '_')">
<xsl:variable name="p1" select="substring-before($name, '_')"/>
<xsl:variable name="p2" select="substring-after($name, '_')"/>
<xsl:call-template name="CapitalizeIdentifier">
<xsl:with-param name="name" select="$p1"/>
</xsl:call-template>
<!-- TODO: remove this (names get too long quickly) -->
<xsl:text>_</xsl:text>
<xsl:call-template name="RenderIdentifierCont">
<xsl:with-param name="name" select="$p2"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="'&quot;' = substring($name, string-length($name))">
<xsl:call-template name="CapitalizeIdentifier">
<xsl:with-param name="name" select="substring-before($name, '&quot;')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="CapitalizeIdentifier">
<xsl:with-param name="name" select="$name"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="CapitalizeIdentifier">
<xsl:param name="name"/>
<!-- FIXME a bit too restrictive... -->
<xsl:value-of select="concat(
translate(substring($name, 1, 1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
substring($name,2))"/>
</xsl:template>
</xsl:stylesheet>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment