aboutsummaryrefslogtreecommitdiff
path: root/src/wixext/SqlCompiler.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/wixext/SqlCompiler.cs')
-rw-r--r--src/wixext/SqlCompiler.cs793
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
3namespace 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}