1 |
gerard.lemson |
148 |
<?xml version="1.0" encoding="UTF-8"?> |
2 |
gerard.lemson |
208 |
<!-- |
3 |
|
|
This XSLT script transforms a data model from our |
4 |
bourges.laurent |
238 |
intermediate representation to a relational database |
5 |
gerard.lemson |
208 |
Data Definition Language script. |
6 |
gerard.lemson |
148 |
|
7 |
gerard.lemson |
343 |
By default we use the "joined" object-relational mapping strategy. |
8 |
|
|
That is, each objectType has a table of its own, in which only those features defined on |
9 |
|
|
the objectType are mapped to columns, the inherited are mapped by base classes. |
10 |
gerard.lemson |
208 |
|
11 |
|
|
We also generate view definitions representing each objectType. |
12 |
|
|
|
13 |
|
|
We assume that all tables are in a single schema. |
14 |
|
|
For now we assume that objectType's names are unique over the complete model. |
15 |
|
|
TODO We need to check this explicitly and modify the generation if not. |
16 |
|
|
|
17 |
|
|
--> |
18 |
|
|
|
19 |
gerard.lemson |
148 |
<!DOCTYPE stylesheet [ |
20 |
|
|
<!ENTITY cr "<xsl:text> |
21 |
|
|
</xsl:text>"> |
22 |
|
|
<!ENTITY bl "<xsl:text> </xsl:text>"> |
23 |
bourges.laurent |
197 |
<!ENTITY tab "<xsl:text> </xsl:text>"> |
24 |
gerard.lemson |
148 |
]> |
25 |
|
|
|
26 |
|
|
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> |
27 |
|
|
|
28 |
|
|
|
29 |
bourges.laurent |
251 |
<xsl:output method="text" encoding="UTF-8" indent="no" /> |
30 |
bourges.laurent |
197 |
|
31 |
gerard.lemson |
148 |
<xsl:strip-space elements="*" /> |
32 |
|
|
|
33 |
gerard.lemson |
229 |
<xsl:key name="element" match="*//*" use="@xmiid"/> |
34 |
|
|
|
35 |
|
|
|
36 |
bourges.laurent |
287 |
<xsl:param name="lastModified"/> |
37 |
gerard.lemson |
148 |
|
38 |
bourges.laurent |
155 |
|
39 |
gerard.lemson |
219 |
<xsl:param name="schema"/> <!-- select="'SNAP.'" --> |
40 |
bourges.laurent |
238 |
|
41 |
gerard.lemson |
148 |
|
42 |
gerard.lemson |
295 |
<!-- Define parameters/variables that can be reused in this script an in others using it (JPA) --> |
43 |
gerard.lemson |
230 |
<!-- next two might also be parameters, or obtained from a config file --> |
44 |
gerard.lemson |
219 |
<xsl:variable name="defaultVarcharLength" select="'256'"/> |
45 |
gerard.lemson |
295 |
<xsl:variable name="unboundedstringtype" select="'text'"/> <!-- SQLServer specific --> |
46 |
bourges.laurent |
238 |
|
47 |
gerard.lemson |
295 |
<xsl:variable name="discriminatorColumnName" select="'DTYPE'"/> |
48 |
|
|
<xsl:variable name="discriminatorColumnLength" select="'128'"/> |
49 |
gerard.lemson |
343 |
<xsl:variable name="discriminatorColumnType"> varchar(<xsl:value-of select="$discriminatorColumnLength"/>) </xsl:variable> |
50 |
bourges.laurent |
238 |
|
51 |
gerard.lemson |
295 |
<xsl:variable name="primaryKeyColumnName" select="'ID'"/> |
52 |
bourges.laurent |
238 |
|
53 |
gerard.lemson |
295 |
|
54 |
|
|
|
55 |
|
|
<!-- start --> |
56 |
gerard.lemson |
148 |
<xsl:template match="/"> |
57 |
gerard.lemson |
343 |
<xsl:apply-templates select="model" mode="tables"/> |
58 |
gerard.lemson |
148 |
</xsl:template> |
59 |
|
|
|
60 |
|
|
|
61 |
|
|
|
62 |
|
|
|
63 |
gerard.lemson |
343 |
<xsl:template match="model" mode="dropTables"> |
64 |
|
|
<xsl:apply-templates select=".//objectType" mode="droptable"/> |
65 |
|
|
</xsl:template> |
66 |
|
|
|
67 |
|
|
|
68 |
|
|
|
69 |
|
|
|
70 |
|
|
<xsl:template match="model" mode="tables"> |
71 |
gerard.lemson |
148 |
<xsl:message>Model = <xsl:value-of select="name"></xsl:value-of></xsl:message> |
72 |
bourges.laurent |
197 |
|
73 |
bourges.laurent |
238 |
-- last modification date of the UML model <xsl:value-of select="$lastModified"/>&cr; |
74 |
gerard.lemson |
343 |
<xsl:apply-templates select=".//objectType" mode="joined"/> |
75 |
bourges.laurent |
238 |
|
76 |
gerard.lemson |
148 |
</xsl:template> |
77 |
gerard.lemson |
343 |
|
78 |
|
|
|
79 |
|
|
|
80 |
gerard.lemson |
148 |
|
81 |
gerard.lemson |
343 |
<xsl:template match="objectType"> |
82 |
bourges.laurent |
238 |
<!-- generate a single table for the whole object hierarchy below the matched objectType --> |
83 |
gerard.lemson |
234 |
<xsl:variable name="tableName"> |
84 |
|
|
<xsl:apply-templates select="." mode="tableName"/> |
85 |
|
|
</xsl:variable> |
86 |
gerard.lemson |
343 |
CREATE TABLE <xsl:value-of select="$tableName"/> ( |
87 |
|
|
id bigint not null |
88 |
|
|
<xsl:if test="not(extends)"><xsl:apply-templates select="." mode="discriminatorColumnDeclaration"/></xsl:if> |
89 |
|
|
<xsl:apply-templates select="." mode="container"/> |
90 |
|
|
<xsl:apply-templates select="attribute" /> |
91 |
|
|
<xsl:apply-templates select="reference" />);&cr;&cr; |
92 |
gerard.lemson |
148 |
</xsl:template> |
93 |
|
|
|
94 |
|
|
|
95 |
bourges.laurent |
238 |
|
96 |
gerard.lemson |
343 |
<!-- determine whether there is a class that contains this class. |
97 |
|
|
If so generate a containerID column. |
98 |
|
|
NOTE we should ensure that there is only 1 --> |
99 |
gerard.lemson |
232 |
<xsl:template match="objectType" mode="container"> |
100 |
|
|
<xsl:variable name="xmiid" select="@xmiid"/> |
101 |
|
|
<xsl:if test="/model//objectType[collection/datatype/@xmiidref = $xmiid]">, containerId bigint not null -- <xsl:value-of select="/model//objectType[collection/datatype/@xmiidref = $xmiid]/name"/>&cr; |
102 |
|
|
</xsl:if> |
103 |
gerard.lemson |
229 |
</xsl:template> |
104 |
gerard.lemson |
232 |
|
105 |
bourges.laurent |
238 |
|
106 |
|
|
|
107 |
|
|
|
108 |
gerard.lemson |
232 |
<xsl:template match="attribute" > |
109 |
|
|
<xsl:param name="prefix"/> |
110 |
|
|
|
111 |
|
|
<xsl:variable name="columnname"> |
112 |
|
|
<xsl:choose> |
113 |
|
|
<xsl:when test="$prefix"> |
114 |
|
|
<xsl:value-of select="concat($prefix,'_',name)"/> |
115 |
|
|
</xsl:when> |
116 |
|
|
<xsl:otherwise> |
117 |
|
|
<xsl:value-of select="name"/> |
118 |
|
|
</xsl:otherwise> |
119 |
|
|
</xsl:choose> |
120 |
|
|
</xsl:variable> |
121 |
|
|
|
122 |
|
|
<xsl:choose> |
123 |
|
|
<xsl:when test="datatype/@class"><xsl:apply-templates select="key('element',datatype/@xmiidref)" mode="columns"><xsl:with-param name="prefix" select="$columnname"/></xsl:apply-templates></xsl:when> |
124 |
|
|
<xsl:otherwise> |
125 |
|
|
<xsl:variable name="sqltype"> |
126 |
|
|
<xsl:call-template name="sqltype"> |
127 |
|
|
<xsl:with-param name="type" select="datatype/@type"/> |
128 |
|
|
<xsl:with-param name="constraints" select="constraints"/> |
129 |
|
|
</xsl:call-template> |
130 |
|
|
</xsl:variable>, <xsl:value-of select="$columnname"/>&bl;<xsl:value-of select="$sqltype"/><xsl:if test="multiplicity = '1'"> not null</xsl:if>&cr; |
131 |
|
|
</xsl:otherwise> |
132 |
|
|
</xsl:choose> |
133 |
|
|
|
134 |
|
|
</xsl:template> |
135 |
|
|
|
136 |
|
|
|
137 |
|
|
|
138 |
gerard.lemson |
229 |
|
139 |
gerard.lemson |
219 |
<!-- We need lengths for (var)char datatypes --> |
140 |
gerard.lemson |
232 |
<xsl:template name="sqltype"> |
141 |
|
|
<xsl:param name="type"/> |
142 |
gerard.lemson |
230 |
<xsl:param name="constraints"/> |
143 |
bourges.laurent |
238 |
|
144 |
bourges.laurent |
287 |
<!-- |
145 |
|
|
Primitive types : |
146 |
|
|
boolean |
147 |
|
|
short |
148 |
|
|
int |
149 |
|
|
long |
150 |
|
|
float |
151 |
|
|
double |
152 |
|
|
|
153 |
|
|
Date type : |
154 |
|
|
datetime |
155 |
|
|
|
156 |
|
|
Characters type : |
157 |
|
|
string |
158 |
|
|
|
159 |
|
|
Unsupported type (later) => string : |
160 |
|
|
complex |
161 |
|
|
rational |
162 |
|
|
--> |
163 |
gerard.lemson |
219 |
<xsl:choose> |
164 |
gerard.lemson |
232 |
<xsl:when test="$type = 'boolean'">bit</xsl:when> |
165 |
bourges.laurent |
287 |
<xsl:when test="@type = 'short'">integer</xsl:when> |
166 |
gerard.lemson |
232 |
<xsl:when test="$type = 'integer'">integer</xsl:when> |
167 |
|
|
<xsl:when test="$type = 'long'">bigint</xsl:when> |
168 |
bourges.laurent |
287 |
<xsl:when test="@type = 'float'">float</xsl:when> |
169 |
|
|
<xsl:when test="@type = 'double'">real</xsl:when> |
170 |
|
|
<xsl:when test="@type = 'datetime'">timestamp</xsl:when> |
171 |
gerard.lemson |
219 |
<xsl:otherwise> |
172 |
|
|
<xsl:variable name="length"> |
173 |
|
|
<xsl:choose> |
174 |
gerard.lemson |
230 |
<xsl:when test="$constraints/length"> |
175 |
|
|
<xsl:value-of select="$constraints/length"/> |
176 |
gerard.lemson |
219 |
</xsl:when> |
177 |
gerard.lemson |
230 |
<xsl:when test="$constraints/maxLength"> |
178 |
|
|
<xsl:value-of select="$constraints/maxLength"/> |
179 |
|
|
</xsl:when> |
180 |
gerard.lemson |
219 |
<xsl:otherwise> |
181 |
|
|
<xsl:value-of select="$defaultVarcharLength"/> |
182 |
|
|
</xsl:otherwise> |
183 |
|
|
</xsl:choose> |
184 |
gerard.lemson |
230 |
</xsl:variable> |
185 |
|
|
<xsl:choose> |
186 |
gerard.lemson |
295 |
<xsl:when test="$length <= 0"><xsl:value-of select="$unboundedstringtype"/></xsl:when> |
187 |
gerard.lemson |
230 |
<xsl:otherwise>varchar(<xsl:value-of select="$length"/>)</xsl:otherwise> |
188 |
bourges.laurent |
238 |
</xsl:choose></xsl:otherwise> |
189 |
gerard.lemson |
219 |
</xsl:choose> |
190 |
gerard.lemson |
148 |
</xsl:template> |
191 |
|
|
|
192 |
bourges.laurent |
238 |
|
193 |
|
|
|
194 |
|
|
|
195 |
gerard.lemson |
232 |
<!-- We need lengths for (var)char datatypes --> |
196 |
|
|
<xsl:template match="*/dataType" mode="columns"> |
197 |
|
|
<xsl:param name="prefix"/> |
198 |
|
|
<xsl:choose> |
199 |
|
|
<xsl:when test="not(attribute)">, <xsl:value-of select="$prefix"/> varchar(256) -- <xsl:value-of select="name"/>&cr;</xsl:when> |
200 |
|
|
<xsl:otherwise><xsl:apply-templates select="attribute"><xsl:with-param name="prefix" select="$prefix"/></xsl:apply-templates></xsl:otherwise> |
201 |
|
|
</xsl:choose> |
202 |
|
|
</xsl:template> |
203 |
bourges.laurent |
238 |
|
204 |
|
|
|
205 |
|
|
|
206 |
bourges.laurent |
287 |
|
207 |
gerard.lemson |
232 |
<!-- We need lengths for (var)char datatypes --> |
208 |
|
|
<xsl:template match="*/enumeration" mode="columns"> |
209 |
gerard.lemson |
343 |
<xsl:param name="prefix"/>, <xsl:value-of select="$prefix"/> varchar(256) -- <xsl:value-of select="name"/>&cr; |
210 |
gerard.lemson |
232 |
</xsl:template> |
211 |
gerard.lemson |
148 |
|
212 |
|
|
|
213 |
gerard.lemson |
232 |
|
214 |
|
|
|
215 |
gerard.lemson |
219 |
<xsl:template match="reference"> |
216 |
bourges.laurent |
238 |
<xsl:if test="not(subsets)">, <xsl:value-of select="name"/>Id&bl;bigint <xsl:call-template name="nullity"><xsl:with-param name="multiplicity" select="multiplicity"/></xsl:call-template>-- <xsl:value-of select="datatype/@class"/>&cr; |
217 |
|
|
</xsl:if> |
218 |
gerard.lemson |
148 |
</xsl:template> |
219 |
|
|
|
220 |
bourges.laurent |
238 |
|
221 |
|
|
|
222 |
|
|
|
223 |
gerard.lemson |
233 |
<xsl:template name="nullity"> |
224 |
|
|
<xsl:param name="multiplicity"/> |
225 |
|
|
<xsl:choose> |
226 |
|
|
<xsl:when test="$multiplicity = '1' or $multiplicity = '1..*'">not null</xsl:when> |
227 |
|
|
<xsl:otherwise>null</xsl:otherwise> |
228 |
|
|
</xsl:choose> |
229 |
|
|
</xsl:template> |
230 |
gerard.lemson |
229 |
|
231 |
bourges.laurent |
238 |
|
232 |
|
|
|
233 |
|
|
|
234 |
gerard.lemson |
233 |
|
235 |
gerard.lemson |
219 |
<!-- TODO |
236 |
|
|
Add templates retrieving for a given objectType the table it is in |
237 |
|
|
for a given attribute the column(s) it is in |
238 |
|
|
for a given reference the column it is in |
239 |
|
|
for a given collection the containerId column it is in. |
240 |
|
|
--> |
241 |
gerard.lemson |
148 |
|
242 |
gerard.lemson |
234 |
<!-- for now no special camelcase 2 '_' transformation --> |
243 |
bourges.laurent |
238 |
<xsl:template match="objectType" mode="tableName"> |
244 |
gerard.lemson |
234 |
<xsl:value-of select="name"/> |
245 |
bourges.laurent |
238 |
</xsl:template> |
246 |
gerard.lemson |
148 |
|
247 |
gerard.lemson |
295 |
|
248 |
|
|
<!-- Maybe somewhat too much indirection here? --> |
249 |
|
|
<xsl:template match="objectType" mode="PK_COLUMN"> |
250 |
|
|
<xsl:value-of select="$primaryKeyColumnName"/> bigint not null |
251 |
|
|
</xsl:template> |
252 |
|
|
|
253 |
|
|
|
254 |
|
|
|
255 |
|
|
|
256 |
|
|
<!-- Discriminator column templates --> |
257 |
gerard.lemson |
343 |
<xsl:template match="objectType" mode="discriminatorColumnDeclaration">, <xsl:value-of select="$discriminatorColumnName"/> <xsl:value-of select="$discriminatorColumnType"/>&cr; |
258 |
gerard.lemson |
295 |
</xsl:template> |
259 |
gerard.lemson |
234 |
|
260 |
gerard.lemson |
295 |
|
261 |
|
|
|
262 |
|
|
<xsl:template match="attribute" mode="columnName"> |
263 |
|
|
<xsl:value-of select="name"/> |
264 |
|
|
</xsl:template> |
265 |
|
|
|
266 |
|
|
|
267 |
|
|
|
268 |
|
|
|
269 |
|
|
|
270 |
|
|
<xsl:template match="reference" mode="columnName"> |
271 |
|
|
<xsl:value-of select="concat(name,'Id')"/> |
272 |
|
|
</xsl:template> |
273 |
|
|
|
274 |
gerard.lemson |
148 |
</xsl:stylesheet> |