diff options
Diffstat (limited to 'src/wixext/SqlCompiler.cs')
-rw-r--r-- | src/wixext/SqlCompiler.cs | 793 |
1 files changed, 793 insertions, 0 deletions
diff --git a/src/wixext/SqlCompiler.cs b/src/wixext/SqlCompiler.cs new file mode 100644 index 00000000..eecfbba0 --- /dev/null +++ b/src/wixext/SqlCompiler.cs | |||
@@ -0,0 +1,793 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Extensions | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | using System.Xml.Linq; | ||
8 | using WixToolset.Data; | ||
9 | using WixToolset.Extensibility; | ||
10 | |||
11 | /// <summary> | ||
12 | /// The compiler for the WiX Toolset SQL Server Extension. | ||
13 | /// </summary> | ||
14 | public sealed class SqlCompiler : CompilerExtension | ||
15 | { | ||
16 | // sql database attributes definitions (from sca.h) | ||
17 | internal const int DbCreateOnInstall = 0x00000001; | ||
18 | internal const int DbDropOnUninstall = 0x00000002; | ||
19 | internal const int DbContinueOnError = 0x00000004; | ||
20 | internal const int DbDropOnInstall = 0x00000008; | ||
21 | internal const int DbCreateOnUninstall = 0x00000010; | ||
22 | internal const int DbConfirmOverwrite = 0x00000020; | ||
23 | internal const int DbCreateOnReinstall = 0x00000040; | ||
24 | internal const int DbDropOnReinstall = 0x00000080; | ||
25 | |||
26 | // sql string/script attributes definitions (from sca.h) | ||
27 | internal const int SqlExecuteOnInstall = 0x00000001; | ||
28 | internal const int SqlExecuteOnUninstall = 0x00000002; | ||
29 | internal const int SqlContinueOnError = 0x00000004; | ||
30 | internal const int SqlRollback = 0x00000008; | ||
31 | internal const int SqlExecuteOnReinstall = 0x00000010; | ||
32 | |||
33 | /// <summary> | ||
34 | /// Instantiate a new SqlCompiler. | ||
35 | /// </summary> | ||
36 | public SqlCompiler() | ||
37 | { | ||
38 | this.Namespace = "http://wixtoolset.org/schemas/v4/wxs/sql"; | ||
39 | } | ||
40 | |||
41 | /// <summary> | ||
42 | /// Processes an element for the Compiler. | ||
43 | /// </summary> | ||
44 | /// <param name="sourceLineNumbers">Source line number for the parent element.</param> | ||
45 | /// <param name="parentElement">Parent element of element to process.</param> | ||
46 | /// <param name="element">Element to process.</param> | ||
47 | /// <param name="contextValues">Extra information about the context in which this element is being parsed.</param> | ||
48 | public override void ParseElement(XElement parentElement, XElement element, IDictionary<string, string> context) | ||
49 | { | ||
50 | switch (parentElement.Name.LocalName) | ||
51 | { | ||
52 | case "Component": | ||
53 | string componentId = context["ComponentId"]; | ||
54 | string directoryId = context["DirectoryId"]; | ||
55 | |||
56 | switch (element.Name.LocalName) | ||
57 | { | ||
58 | case "SqlDatabase": | ||
59 | this.ParseSqlDatabaseElement(element, componentId); | ||
60 | break; | ||
61 | case "SqlScript": | ||
62 | this.ParseSqlScriptElement(element, componentId, null); | ||
63 | break; | ||
64 | case "SqlString": | ||
65 | this.ParseSqlStringElement(element, componentId, null); | ||
66 | break; | ||
67 | default: | ||
68 | this.Core.UnexpectedElement(parentElement, element); | ||
69 | break; | ||
70 | } | ||
71 | break; | ||
72 | case "Fragment": | ||
73 | case "Module": | ||
74 | case "Product": | ||
75 | switch (element.Name.LocalName) | ||
76 | { | ||
77 | case "SqlDatabase": | ||
78 | this.ParseSqlDatabaseElement(element, null); | ||
79 | break; | ||
80 | default: | ||
81 | this.Core.UnexpectedElement(parentElement, element); | ||
82 | break; | ||
83 | } | ||
84 | break; | ||
85 | default: | ||
86 | this.Core.UnexpectedElement(parentElement, element); | ||
87 | break; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | /// <summary> | ||
92 | /// Parses a sql database element | ||
93 | /// </summary> | ||
94 | /// <param name="node">Element to parse.</param> | ||
95 | /// <param name="componentId">Identifier for parent component.</param> | ||
96 | private void ParseSqlDatabaseElement(XElement node, string componentId) | ||
97 | { | ||
98 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
99 | string id = null; | ||
100 | int attributes = 0; | ||
101 | string database = null; | ||
102 | string fileSpec = null; | ||
103 | string instance = null; | ||
104 | string logFileSpec = null; | ||
105 | string server = null; | ||
106 | string user = null; | ||
107 | |||
108 | foreach (XAttribute attrib in node.Attributes()) | ||
109 | { | ||
110 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
111 | { | ||
112 | switch (attrib.Name.LocalName) | ||
113 | { | ||
114 | case "Id": | ||
115 | id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
116 | break; | ||
117 | case "ConfirmOverwrite": | ||
118 | if (null == componentId) | ||
119 | { | ||
120 | this.Core.OnMessage(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
121 | } | ||
122 | |||
123 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
124 | { | ||
125 | attributes |= DbConfirmOverwrite; | ||
126 | } | ||
127 | break; | ||
128 | case "ContinueOnError": | ||
129 | if (null == componentId) | ||
130 | { | ||
131 | this.Core.OnMessage(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
132 | } | ||
133 | |||
134 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
135 | { | ||
136 | attributes |= DbContinueOnError; | ||
137 | } | ||
138 | break; | ||
139 | case "CreateOnInstall": | ||
140 | if (null == componentId) | ||
141 | { | ||
142 | this.Core.OnMessage(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
143 | } | ||
144 | |||
145 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
146 | { | ||
147 | attributes |= DbCreateOnInstall; | ||
148 | } | ||
149 | break; | ||
150 | case "CreateOnReinstall": | ||
151 | if (null == componentId) | ||
152 | { | ||
153 | this.Core.OnMessage(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
154 | } | ||
155 | |||
156 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
157 | { | ||
158 | attributes |= DbCreateOnReinstall; | ||
159 | } | ||
160 | break; | ||
161 | case "CreateOnUninstall": | ||
162 | if (null == componentId) | ||
163 | { | ||
164 | this.Core.OnMessage(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
165 | } | ||
166 | |||
167 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
168 | { | ||
169 | attributes |= DbCreateOnUninstall; | ||
170 | } | ||
171 | break; | ||
172 | case "Database": | ||
173 | database = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
174 | break; | ||
175 | case "DropOnInstall": | ||
176 | if (null == componentId) | ||
177 | { | ||
178 | this.Core.OnMessage(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
179 | } | ||
180 | |||
181 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
182 | { | ||
183 | attributes |= DbDropOnInstall; | ||
184 | } | ||
185 | break; | ||
186 | case "DropOnReinstall": | ||
187 | if (null == componentId) | ||
188 | { | ||
189 | this.Core.OnMessage(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
190 | } | ||
191 | |||
192 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
193 | { | ||
194 | attributes |= DbDropOnReinstall; | ||
195 | } | ||
196 | break; | ||
197 | |||
198 | case "DropOnUninstall": | ||
199 | if (null == componentId) | ||
200 | { | ||
201 | this.Core.OnMessage(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); | ||
202 | } | ||
203 | |||
204 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
205 | { | ||
206 | attributes |= DbDropOnUninstall; | ||
207 | } | ||
208 | break; | ||
209 | case "Instance": | ||
210 | instance = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
211 | break; | ||
212 | case "Server": | ||
213 | server = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
214 | break; | ||
215 | case "User": | ||
216 | user = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
217 | if (!this.Core.ContainsProperty(user)) | ||
218 | { | ||
219 | user = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
220 | this.Core.CreateSimpleReference(sourceLineNumbers, "User", user); | ||
221 | } | ||
222 | break; | ||
223 | default: | ||
224 | this.Core.UnexpectedAttribute(node, attrib); | ||
225 | break; | ||
226 | } | ||
227 | } | ||
228 | else | ||
229 | { | ||
230 | this.Core.ParseExtensionAttribute(node, attrib); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | if (null == id) | ||
235 | { | ||
236 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); | ||
237 | } | ||
238 | |||
239 | if (null == database) | ||
240 | { | ||
241 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Database")); | ||
242 | } | ||
243 | else if (128 < database.Length) | ||
244 | { | ||
245 | this.Core.OnMessage(WixErrors.IdentifierTooLongError(sourceLineNumbers, node.Name.LocalName, "Database", database, 128)); | ||
246 | } | ||
247 | |||
248 | if (null == server) | ||
249 | { | ||
250 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Server")); | ||
251 | } | ||
252 | |||
253 | if (0 == attributes && null != componentId) | ||
254 | { | ||
255 | this.Core.OnMessage(SqlErrors.OneOfAttributesRequiredUnderComponent(sourceLineNumbers, node.Name.LocalName, "CreateOnInstall", "CreateOnUninstall", "DropOnInstall", "DropOnUninstall")); | ||
256 | } | ||
257 | |||
258 | foreach (XElement child in node.Elements()) | ||
259 | { | ||
260 | if (this.Namespace == child.Name.Namespace) | ||
261 | { | ||
262 | SourceLineNumber childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child); | ||
263 | switch (child.Name.LocalName) | ||
264 | { | ||
265 | case "SqlScript": | ||
266 | if (null == componentId) | ||
267 | { | ||
268 | this.Core.OnMessage(SqlErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
269 | } | ||
270 | |||
271 | this.ParseSqlScriptElement(child, componentId, id); | ||
272 | break; | ||
273 | case "SqlString": | ||
274 | if (null == componentId) | ||
275 | { | ||
276 | this.Core.OnMessage(SqlErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
277 | } | ||
278 | |||
279 | this.ParseSqlStringElement(child, componentId, id); | ||
280 | break; | ||
281 | case "SqlFileSpec": | ||
282 | if (null == componentId) | ||
283 | { | ||
284 | this.Core.OnMessage(SqlErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
285 | } | ||
286 | else if (null != fileSpec) | ||
287 | { | ||
288 | this.Core.OnMessage(WixErrors.TooManyElements(sourceLineNumbers, node.Name.LocalName, child.Name.LocalName, 1)); | ||
289 | } | ||
290 | |||
291 | fileSpec = this.ParseSqlFileSpecElement(child); | ||
292 | break; | ||
293 | case "SqlLogFileSpec": | ||
294 | if (null == componentId) | ||
295 | { | ||
296 | this.Core.OnMessage(SqlErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName)); | ||
297 | } | ||
298 | else if (null != logFileSpec) | ||
299 | { | ||
300 | this.Core.OnMessage(WixErrors.TooManyElements(sourceLineNumbers, node.Name.LocalName, child.Name.LocalName, 1)); | ||
301 | } | ||
302 | |||
303 | logFileSpec = this.ParseSqlFileSpecElement(child); | ||
304 | break; | ||
305 | default: | ||
306 | this.Core.UnexpectedElement(node, child); | ||
307 | break; | ||
308 | } | ||
309 | } | ||
310 | else | ||
311 | { | ||
312 | this.Core.ParseExtensionElement(node, child); | ||
313 | } | ||
314 | } | ||
315 | |||
316 | if (null != componentId) | ||
317 | { | ||
318 | // Reference InstallSqlData and UninstallSqlData since nothing will happen without it | ||
319 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "InstallSqlData"); | ||
320 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "UninstallSqlData"); | ||
321 | } | ||
322 | |||
323 | if (!this.Core.EncounteredError) | ||
324 | { | ||
325 | Row row = this.Core.CreateRow(sourceLineNumbers, "SqlDatabase"); | ||
326 | row[0] = id; | ||
327 | row[1] = server; | ||
328 | row[2] = instance; | ||
329 | row[3] = database; | ||
330 | row[4] = componentId; | ||
331 | row[5] = user; | ||
332 | row[6] = fileSpec; | ||
333 | row[7] = logFileSpec; | ||
334 | if (0 != attributes) | ||
335 | { | ||
336 | row[8] = attributes; | ||
337 | } | ||
338 | } | ||
339 | } | ||
340 | |||
341 | /// <summary> | ||
342 | /// Parses a sql file specification element. | ||
343 | /// </summary> | ||
344 | /// <param name="node">Element to parse.</param> | ||
345 | /// <returns>Identifier of sql file specification.</returns> | ||
346 | private string ParseSqlFileSpecElement(XElement node) | ||
347 | { | ||
348 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
349 | string id = null; | ||
350 | string fileName = null; | ||
351 | string growthSize = null; | ||
352 | string maxSize = null; | ||
353 | string name = null; | ||
354 | string size = null; | ||
355 | |||
356 | foreach (XAttribute attrib in node.Attributes()) | ||
357 | { | ||
358 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
359 | { | ||
360 | switch (attrib.Name.LocalName) | ||
361 | { | ||
362 | case "Id": | ||
363 | id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
364 | break; | ||
365 | case "Name": | ||
366 | name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
367 | break; | ||
368 | case "Filename": | ||
369 | fileName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
370 | break; | ||
371 | case "Size": | ||
372 | size = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
373 | break; | ||
374 | case "MaxSize": | ||
375 | maxSize = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
376 | break; | ||
377 | case "GrowthSize": | ||
378 | growthSize = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
379 | break; | ||
380 | default: | ||
381 | this.Core.UnexpectedAttribute(node, attrib); | ||
382 | break; | ||
383 | } | ||
384 | } | ||
385 | else | ||
386 | { | ||
387 | this.Core.ParseExtensionAttribute(node, attrib); | ||
388 | } | ||
389 | } | ||
390 | |||
391 | if (null == id) | ||
392 | { | ||
393 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); | ||
394 | } | ||
395 | |||
396 | if (null == name) | ||
397 | { | ||
398 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name")); | ||
399 | } | ||
400 | |||
401 | if (null == fileName) | ||
402 | { | ||
403 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Filename")); | ||
404 | } | ||
405 | |||
406 | this.Core.ParseForExtensionElements(node); | ||
407 | |||
408 | if (!this.Core.EncounteredError) | ||
409 | { | ||
410 | Row row = this.Core.CreateRow(sourceLineNumbers, "SqlFileSpec"); | ||
411 | row[0] = id; | ||
412 | row[1] = name; | ||
413 | row[2] = fileName; | ||
414 | if (null != size) | ||
415 | { | ||
416 | row[3] = size; | ||
417 | } | ||
418 | |||
419 | if (null != maxSize) | ||
420 | { | ||
421 | row[4] = maxSize; | ||
422 | } | ||
423 | |||
424 | if (null != growthSize) | ||
425 | { | ||
426 | row[5] = growthSize; | ||
427 | } | ||
428 | } | ||
429 | |||
430 | return id; | ||
431 | } | ||
432 | |||
433 | /// <summary> | ||
434 | /// Parses a sql script element. | ||
435 | /// </summary> | ||
436 | /// <param name="node">Element to parse.</param> | ||
437 | /// <param name="componentId">Identifier for parent component.</param> | ||
438 | /// <param name="sqlDb">Optional database to execute script against.</param> | ||
439 | private void ParseSqlScriptElement(XElement node, string componentId, string sqlDb) | ||
440 | { | ||
441 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
442 | string id = null; | ||
443 | int attributes = 0; | ||
444 | bool rollbackAttribute = false; | ||
445 | bool nonRollbackAttribute = false; | ||
446 | string binary = null; | ||
447 | int sequence = CompilerConstants.IntegerNotSet; | ||
448 | string user = null; | ||
449 | |||
450 | foreach (XAttribute attrib in node.Attributes()) | ||
451 | { | ||
452 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
453 | { | ||
454 | switch (attrib.Name.LocalName) | ||
455 | { | ||
456 | case "Id": | ||
457 | id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
458 | break; | ||
459 | case "BinaryKey": | ||
460 | binary = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
461 | this.Core.CreateSimpleReference(sourceLineNumbers, "Binary", binary); | ||
462 | break; | ||
463 | case "Sequence": | ||
464 | sequence = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue); | ||
465 | break; | ||
466 | case "SqlDb": | ||
467 | if (null != sqlDb) | ||
468 | { | ||
469 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, node.Parent.Name.LocalName)); | ||
470 | } | ||
471 | sqlDb = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
472 | this.Core.CreateSimpleReference(sourceLineNumbers, "SqlDatabase", sqlDb); | ||
473 | break; | ||
474 | case "User": | ||
475 | user = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
476 | this.Core.CreateSimpleReference(sourceLineNumbers, "User", user); | ||
477 | break; | ||
478 | |||
479 | // Flag-setting attributes | ||
480 | case "ContinueOnError": | ||
481 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
482 | { | ||
483 | attributes |= SqlContinueOnError; | ||
484 | } | ||
485 | break; | ||
486 | case "ExecuteOnInstall": | ||
487 | if (rollbackAttribute) | ||
488 | { | ||
489 | this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall")); | ||
490 | } | ||
491 | nonRollbackAttribute = true; | ||
492 | |||
493 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
494 | { | ||
495 | attributes |= SqlExecuteOnInstall; | ||
496 | } | ||
497 | break; | ||
498 | case "ExecuteOnReinstall": | ||
499 | if (rollbackAttribute) | ||
500 | { | ||
501 | this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall")); | ||
502 | } | ||
503 | nonRollbackAttribute = true; | ||
504 | |||
505 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
506 | { | ||
507 | attributes |= SqlExecuteOnReinstall; | ||
508 | } | ||
509 | break; | ||
510 | case "ExecuteOnUninstall": | ||
511 | if (rollbackAttribute) | ||
512 | { | ||
513 | this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall")); | ||
514 | } | ||
515 | nonRollbackAttribute = true; | ||
516 | |||
517 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
518 | { | ||
519 | attributes |= SqlExecuteOnUninstall; | ||
520 | } | ||
521 | break; | ||
522 | case "RollbackOnInstall": | ||
523 | if (nonRollbackAttribute) | ||
524 | { | ||
525 | this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall")); | ||
526 | } | ||
527 | rollbackAttribute = true; | ||
528 | |||
529 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
530 | { | ||
531 | attributes |= SqlExecuteOnInstall; | ||
532 | attributes |= SqlRollback; | ||
533 | } | ||
534 | break; | ||
535 | case "RollbackOnReinstall": | ||
536 | if (nonRollbackAttribute) | ||
537 | { | ||
538 | this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall")); | ||
539 | } | ||
540 | rollbackAttribute = true; | ||
541 | |||
542 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
543 | { | ||
544 | attributes |= SqlExecuteOnReinstall; | ||
545 | attributes |= SqlRollback; | ||
546 | } | ||
547 | break; | ||
548 | case "RollbackOnUninstall": | ||
549 | if (nonRollbackAttribute) | ||
550 | { | ||
551 | this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall")); | ||
552 | } | ||
553 | rollbackAttribute = true; | ||
554 | |||
555 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
556 | { | ||
557 | attributes |= SqlExecuteOnUninstall; | ||
558 | attributes |= SqlRollback; | ||
559 | } | ||
560 | break; | ||
561 | default: | ||
562 | this.Core.UnexpectedAttribute(node, attrib); | ||
563 | break; | ||
564 | } | ||
565 | } | ||
566 | else | ||
567 | { | ||
568 | this.Core.ParseExtensionAttribute(node, attrib); | ||
569 | } | ||
570 | } | ||
571 | |||
572 | if (null == id) | ||
573 | { | ||
574 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); | ||
575 | } | ||
576 | |||
577 | if (null == binary) | ||
578 | { | ||
579 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "BinaryKey")); | ||
580 | } | ||
581 | |||
582 | if (null == sqlDb) | ||
583 | { | ||
584 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "SqlDb")); | ||
585 | } | ||
586 | |||
587 | if (0 == attributes) | ||
588 | { | ||
589 | this.Core.OnMessage(WixErrors.ExpectedAttributes(sourceLineNumbers, node.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall", "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall")); | ||
590 | } | ||
591 | |||
592 | this.Core.ParseForExtensionElements(node); | ||
593 | |||
594 | // Reference InstallSqlData and UninstallSqlData since nothing will happen without it | ||
595 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "InstallSqlData"); | ||
596 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "UninstallSqlData"); | ||
597 | |||
598 | if (!this.Core.EncounteredError) | ||
599 | { | ||
600 | Row row = this.Core.CreateRow(sourceLineNumbers, "SqlScript"); | ||
601 | row[0] = id; | ||
602 | row[1] = sqlDb; | ||
603 | row[2] = componentId; | ||
604 | row[3] = binary; | ||
605 | row[4] = user; | ||
606 | row[5] = attributes; | ||
607 | if (CompilerConstants.IntegerNotSet != sequence) | ||
608 | { | ||
609 | row[6] = sequence; | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | |||
614 | /// <summary> | ||
615 | /// Parses a sql string element. | ||
616 | /// </summary> | ||
617 | /// <param name="node">Element to parse.</param> | ||
618 | /// <param name="componentId">Identifier for parent component.</param> | ||
619 | /// <param name="sqlDb">Optional database to execute string against.</param> | ||
620 | private void ParseSqlStringElement(XElement node, string componentId, string sqlDb) | ||
621 | { | ||
622 | SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); | ||
623 | string id = null; | ||
624 | int attributes = 0; | ||
625 | bool rollbackAttribute = false; | ||
626 | bool nonRollbackAttribute = false; | ||
627 | int sequence = CompilerConstants.IntegerNotSet; | ||
628 | string sql = null; | ||
629 | string user = null; | ||
630 | |||
631 | foreach (XAttribute attrib in node.Attributes()) | ||
632 | { | ||
633 | if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) | ||
634 | { | ||
635 | switch (attrib.Name.LocalName) | ||
636 | { | ||
637 | case "Id": | ||
638 | id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
639 | break; | ||
640 | case "ContinueOnError": | ||
641 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
642 | { | ||
643 | attributes |= SqlContinueOnError; | ||
644 | } | ||
645 | break; | ||
646 | case "ExecuteOnInstall": | ||
647 | if (rollbackAttribute) | ||
648 | { | ||
649 | this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall")); | ||
650 | } | ||
651 | nonRollbackAttribute = true; | ||
652 | |||
653 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
654 | { | ||
655 | attributes |= SqlExecuteOnInstall; | ||
656 | } | ||
657 | break; | ||
658 | case "ExecuteOnReinstall": | ||
659 | if (rollbackAttribute) | ||
660 | { | ||
661 | this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall")); | ||
662 | } | ||
663 | nonRollbackAttribute = true; | ||
664 | |||
665 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
666 | { | ||
667 | attributes |= SqlExecuteOnReinstall; | ||
668 | } | ||
669 | break; | ||
670 | case "ExecuteOnUninstall": | ||
671 | if (rollbackAttribute) | ||
672 | { | ||
673 | this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall")); | ||
674 | } | ||
675 | nonRollbackAttribute = true; | ||
676 | |||
677 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
678 | { | ||
679 | attributes |= SqlExecuteOnUninstall; | ||
680 | } | ||
681 | break; | ||
682 | case "RollbackOnInstall": | ||
683 | if (nonRollbackAttribute) | ||
684 | { | ||
685 | this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall")); | ||
686 | } | ||
687 | rollbackAttribute = true; | ||
688 | |||
689 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
690 | { | ||
691 | attributes |= SqlExecuteOnInstall; | ||
692 | attributes |= SqlRollback; | ||
693 | } | ||
694 | break; | ||
695 | case "RollbackOnReinstall": | ||
696 | if (nonRollbackAttribute) | ||
697 | { | ||
698 | this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall")); | ||
699 | } | ||
700 | rollbackAttribute = true; | ||
701 | |||
702 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
703 | { | ||
704 | attributes |= SqlExecuteOnReinstall; | ||
705 | attributes |= SqlRollback; | ||
706 | } | ||
707 | break; | ||
708 | case "RollbackOnUninstall": | ||
709 | if (nonRollbackAttribute) | ||
710 | { | ||
711 | this.Core.OnMessage(WixErrors.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall")); | ||
712 | } | ||
713 | rollbackAttribute = true; | ||
714 | |||
715 | if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) | ||
716 | { | ||
717 | attributes |= SqlExecuteOnUninstall; | ||
718 | attributes |= SqlRollback; | ||
719 | } | ||
720 | break; | ||
721 | case "Sequence": | ||
722 | sequence = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue); | ||
723 | break; | ||
724 | case "SQL": | ||
725 | sql = this.Core.GetAttributeValue(sourceLineNumbers, attrib); | ||
726 | break; | ||
727 | case "SqlDb": | ||
728 | if (null != sqlDb) | ||
729 | { | ||
730 | this.Core.OnMessage(WixErrors.IllegalAttributeWhenNested(sourceLineNumbers, node.Name.LocalName, "SqlDb", "SqlDatabase")); | ||
731 | } | ||
732 | |||
733 | sqlDb = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
734 | this.Core.CreateSimpleReference(sourceLineNumbers, "SqlDatabase", sqlDb); | ||
735 | break; | ||
736 | case "User": | ||
737 | user = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); | ||
738 | this.Core.CreateSimpleReference(sourceLineNumbers, "User", user); | ||
739 | break; | ||
740 | default: | ||
741 | this.Core.UnexpectedAttribute(node, attrib); | ||
742 | break; | ||
743 | } | ||
744 | } | ||
745 | else | ||
746 | { | ||
747 | this.Core.ParseExtensionAttribute(node, attrib); | ||
748 | } | ||
749 | } | ||
750 | |||
751 | if (null == id) | ||
752 | { | ||
753 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); | ||
754 | } | ||
755 | |||
756 | if (null == sql) | ||
757 | { | ||
758 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "SQL")); | ||
759 | } | ||
760 | |||
761 | if (null == sqlDb) | ||
762 | { | ||
763 | this.Core.OnMessage(WixErrors.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "SqlDb")); | ||
764 | } | ||
765 | |||
766 | if (0 == attributes) | ||
767 | { | ||
768 | this.Core.OnMessage(WixErrors.ExpectedAttributes(sourceLineNumbers, node.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall", "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall")); | ||
769 | } | ||
770 | |||
771 | this.Core.ParseForExtensionElements(node); | ||
772 | |||
773 | // Reference InstallSqlData and UninstallSqlData since nothing will happen without it | ||
774 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "InstallSqlData"); | ||
775 | this.Core.CreateSimpleReference(sourceLineNumbers, "CustomAction", "UninstallSqlData"); | ||
776 | |||
777 | if (!this.Core.EncounteredError) | ||
778 | { | ||
779 | Row row = this.Core.CreateRow(sourceLineNumbers, "SqlString"); | ||
780 | row[0] = id; | ||
781 | row[1] = sqlDb; | ||
782 | row[2] = componentId; | ||
783 | row[3] = sql; | ||
784 | row[4] = user; | ||
785 | row[5] = attributes; | ||
786 | if (CompilerConstants.IntegerNotSet != sequence) | ||
787 | { | ||
788 | row[6] = sequence; | ||
789 | } | ||
790 | } | ||
791 | } | ||
792 | } | ||
793 | } | ||