summaryrefslogtreecommitdiff
path: root/src/ext/Sql/wixext
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2021-05-04 22:50:16 -0700
committerRob Mensching <rob@firegiant.com>2021-05-04 22:50:16 -0700
commite713e6695bd531d1021482d454401b86c84f3f2d (patch)
treebf76f3a6a411edd1c4b47f3a54625f7f1023e95b /src/ext/Sql/wixext
parent2977d0ffabcd6d68790e711736d2edd1fe0cc0af (diff)
downloadwix-e713e6695bd531d1021482d454401b86c84f3f2d.tar.gz
wix-e713e6695bd531d1021482d454401b86c84f3f2d.tar.bz2
wix-e713e6695bd531d1021482d454401b86c84f3f2d.zip
Move Sql.wixext into ext
Diffstat (limited to 'src/ext/Sql/wixext')
-rw-r--r--src/ext/Sql/wixext/SqlCompiler.cs804
-rw-r--r--src/ext/Sql/wixext/SqlDecompiler.cs514
-rw-r--r--src/ext/Sql/wixext/SqlErrors.cs48
-rw-r--r--src/ext/Sql/wixext/SqlExtensionData.cs30
-rw-r--r--src/ext/Sql/wixext/SqlExtensionFactory.cs18
-rw-r--r--src/ext/Sql/wixext/SqlTableDefinitions.cs82
-rw-r--r--src/ext/Sql/wixext/SqlWindowsInstallerBackendExtension.cs13
-rw-r--r--src/ext/Sql/wixext/Symbols/SqlDatabaseSymbol.cs103
-rw-r--r--src/ext/Sql/wixext/Symbols/SqlFileSpecSymbol.cs79
-rw-r--r--src/ext/Sql/wixext/Symbols/SqlScriptSymbol.cs87
-rw-r--r--src/ext/Sql/wixext/Symbols/SqlStringSymbol.cs87
-rw-r--r--src/ext/Sql/wixext/Symbols/SqlSymbolDefinitions.cs51
-rw-r--r--src/ext/Sql/wixext/WixToolset.Sql.wixext.csproj30
-rw-r--r--src/ext/Sql/wixext/WixToolset.Sql.wixext.nuspec25
-rw-r--r--src/ext/Sql/wixext/WixToolset.Sql.wixext.targets11
15 files changed, 1982 insertions, 0 deletions
diff --git a/src/ext/Sql/wixext/SqlCompiler.cs b/src/ext/Sql/wixext/SqlCompiler.cs
new file mode 100644
index 00000000..46196e95
--- /dev/null
+++ b/src/ext/Sql/wixext/SqlCompiler.cs
@@ -0,0 +1,804 @@
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.Sql
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Xml.Linq;
8 using WixToolset.Data;
9 using WixToolset.Extensibility;
10 using WixToolset.Extensibility.Data;
11 using WixToolset.Sql.Symbols;
12
13 /// <summary>
14 /// The compiler for the WiX Toolset SQL Server Extension.
15 /// </summary>
16 public sealed class SqlCompiler : BaseCompilerExtension
17 {
18 // sql database attributes definitions (from sca.h)
19 internal const int DbCreateOnInstall = 0x00000001;
20 internal const int DbDropOnUninstall = 0x00000002;
21 internal const int DbContinueOnError = 0x00000004;
22 internal const int DbDropOnInstall = 0x00000008;
23 internal const int DbCreateOnUninstall = 0x00000010;
24 internal const int DbConfirmOverwrite = 0x00000020;
25 internal const int DbCreateOnReinstall = 0x00000040;
26 internal const int DbDropOnReinstall = 0x00000080;
27
28 // sql string/script attributes definitions (from sca.h)
29 internal const int SqlExecuteOnInstall = 0x00000001;
30 internal const int SqlExecuteOnUninstall = 0x00000002;
31 internal const int SqlContinueOnError = 0x00000004;
32 internal const int SqlRollback = 0x00000008;
33 internal const int SqlExecuteOnReinstall = 0x00000010;
34
35 public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/sql";
36
37 /// <summary>
38 /// Processes an element for the Compiler.
39 /// </summary>
40 /// <param name="intermediate"></param>
41 /// <param name="section"></param>
42 /// <param name="parentElement">Parent element of element to process.</param>
43 /// <param name="element">Element to process.</param>
44 /// <param name="context">Extra information about the context in which this element is being parsed.</param>
45 public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary<string, string> context)
46 {
47 switch (parentElement.Name.LocalName)
48 {
49 case "Component":
50 var componentId = context["ComponentId"];
51
52 switch (element.Name.LocalName)
53 {
54 case "SqlDatabase":
55 this.ParseSqlDatabaseElement(intermediate, section, element, componentId);
56 break;
57 case "SqlScript":
58 this.ParseSqlScriptElement(intermediate, section, element, componentId, null);
59 break;
60 case "SqlString":
61 this.ParseSqlStringElement(intermediate, section, element, componentId, null);
62 break;
63 default:
64 this.ParseHelper.UnexpectedElement(parentElement, element);
65 break;
66 }
67 break;
68 case "Fragment":
69 case "Module":
70 case "Package":
71 switch (element.Name.LocalName)
72 {
73 case "SqlDatabase":
74 this.ParseSqlDatabaseElement(intermediate, section, element, null);
75 break;
76 default:
77 this.ParseHelper.UnexpectedElement(parentElement, element);
78 break;
79 }
80 break;
81 default:
82 this.ParseHelper.UnexpectedElement(parentElement, element);
83 break;
84 }
85 }
86
87 /// <summary>
88 /// Parses a sql database element
89 /// </summary>
90 /// <param name="intermediate"></param>
91 /// <param name="section"></param>
92 /// <param name="element">Element to parse.</param>
93 /// <param name="componentId">Identifier for parent component.</param>
94 private void ParseSqlDatabaseElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
95 {
96 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
97 Identifier id = null;
98 int attributes = 0;
99 string database = null;
100 Identifier fileSpec = null;
101 string instance = null;
102 Identifier logFileSpec = null;
103 string server = null;
104 string user = null;
105
106 foreach (var attrib in element.Attributes())
107 {
108 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
109 {
110 switch (attrib.Name.LocalName)
111 {
112 case "Id":
113 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
114 break;
115 case "ConfirmOverwrite":
116 if (null == componentId)
117 {
118 this.Messaging.Write(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
119 }
120
121 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
122 {
123 attributes |= DbConfirmOverwrite;
124 }
125 break;
126 case "ContinueOnError":
127 if (null == componentId)
128 {
129 this.Messaging.Write(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
130 }
131
132 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
133 {
134 attributes |= DbContinueOnError;
135 }
136 break;
137 case "CreateOnInstall":
138 if (null == componentId)
139 {
140 this.Messaging.Write(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
141 }
142
143 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
144 {
145 attributes |= DbCreateOnInstall;
146 }
147 break;
148 case "CreateOnReinstall":
149 if (null == componentId)
150 {
151 this.Messaging.Write(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
152 }
153
154 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
155 {
156 attributes |= DbCreateOnReinstall;
157 }
158 break;
159 case "CreateOnUninstall":
160 if (null == componentId)
161 {
162 this.Messaging.Write(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
163 }
164
165 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
166 {
167 attributes |= DbCreateOnUninstall;
168 }
169 break;
170 case "Database":
171 database = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
172 break;
173 case "DropOnInstall":
174 if (null == componentId)
175 {
176 this.Messaging.Write(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
177 }
178
179 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
180 {
181 attributes |= DbDropOnInstall;
182 }
183 break;
184 case "DropOnReinstall":
185 if (null == componentId)
186 {
187 this.Messaging.Write(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
188 }
189
190 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
191 {
192 attributes |= DbDropOnReinstall;
193 }
194 break;
195
196 case "DropOnUninstall":
197 if (null == componentId)
198 {
199 this.Messaging.Write(SqlErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
200 }
201
202 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
203 {
204 attributes |= DbDropOnUninstall;
205 }
206 break;
207 case "Instance":
208 instance = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
209 break;
210 case "Server":
211 server = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
212 break;
213 case "User":
214 user = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
215 if (!this.ParseHelper.ContainsProperty(user))
216 {
217 user = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
218 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "User", user);
219 }
220 break;
221 default:
222 this.ParseHelper.UnexpectedAttribute(element, attrib);
223 break;
224 }
225 }
226 else
227 {
228 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
229 }
230 }
231
232 if (null == id)
233 {
234 id = this.ParseHelper.CreateIdentifier("sdb", componentId, server, database);
235 }
236
237 if (null == database)
238 {
239 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Database"));
240 }
241 else if (128 < database.Length)
242 {
243 this.Messaging.Write(ErrorMessages.IdentifierTooLongError(sourceLineNumbers, element.Name.LocalName, "Database", database, 128));
244 }
245
246 if (null == server)
247 {
248 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Server"));
249 }
250
251 if (0 == attributes && null != componentId)
252 {
253 this.Messaging.Write(SqlErrors.OneOfAttributesRequiredUnderComponent(sourceLineNumbers, element.Name.LocalName, "CreateOnInstall", "CreateOnUninstall", "DropOnInstall", "DropOnUninstall"));
254 }
255
256 foreach (var child in element.Elements())
257 {
258 if (this.Namespace == child.Name.Namespace)
259 {
260 var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
261 switch (child.Name.LocalName)
262 {
263 case "SqlScript":
264 if (null == componentId)
265 {
266 this.Messaging.Write(SqlErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
267 }
268
269 this.ParseSqlScriptElement(intermediate, section, child, componentId, id?.Id);
270 break;
271 case "SqlString":
272 if (null == componentId)
273 {
274 this.Messaging.Write(SqlErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
275 }
276
277 this.ParseSqlStringElement(intermediate, section, child, componentId, id?.Id);
278 break;
279 case "SqlFileSpec":
280 if (null == componentId)
281 {
282 this.Messaging.Write(SqlErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
283 }
284 else if (null != fileSpec)
285 {
286 this.Messaging.Write(ErrorMessages.TooManyElements(sourceLineNumbers, element.Name.LocalName, child.Name.LocalName, 1));
287 }
288
289 fileSpec = this.ParseSqlFileSpecElement(intermediate, section, child, id?.Id);
290 break;
291 case "SqlLogFileSpec":
292 if (null == componentId)
293 {
294 this.Messaging.Write(SqlErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
295 }
296 else if (null != logFileSpec)
297 {
298 this.Messaging.Write(ErrorMessages.TooManyElements(sourceLineNumbers, element.Name.LocalName, child.Name.LocalName, 1));
299 }
300
301 logFileSpec = this.ParseSqlFileSpecElement(intermediate, section, child, id?.Id);
302 break;
303 default:
304 this.ParseHelper.UnexpectedElement(element, child);
305 break;
306 }
307 }
308 else
309 {
310 this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
311 }
312 }
313
314 if (null != componentId)
315 {
316 // Reference InstallSqlData and UninstallSqlData since nothing will happen without it
317 this.AddReferenceToInstallSqlData(section, sourceLineNumbers);
318 }
319
320 if (!this.Messaging.EncounteredError)
321 {
322 var symbol = section.AddSymbol(new SqlDatabaseSymbol(sourceLineNumbers, id)
323 {
324 Server = server,
325 Instance = instance,
326 Database = database,
327 ComponentRef = componentId,
328 UserRef = user,
329 FileSpecRef = fileSpec?.Id,
330 LogFileSpecRef = logFileSpec?.Id,
331 });
332
333 if (0 != attributes)
334 {
335 symbol.Attributes = attributes;
336 }
337 }
338 }
339
340 /// <summary>
341 /// Parses a sql file specification element.
342 /// </summary>
343 /// <param name="intermediate"></param>
344 /// <param name="section"></param>
345 /// <param name="element">Element to parse.</param>
346 /// <returns>Identifier of sql file specification.</returns>
347 private Identifier ParseSqlFileSpecElement(Intermediate intermediate, IntermediateSection section, XElement element, string parentId)
348 {
349 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
350 Identifier id = null;
351 string fileName = null;
352 string growthSize = null;
353 string maxSize = null;
354 string name = null;
355 string size = null;
356
357 foreach (var attrib in element.Attributes())
358 {
359 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
360 {
361 switch (attrib.Name.LocalName)
362 {
363 case "Id":
364 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
365 break;
366 case "Name":
367 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
368 break;
369 case "Filename":
370 fileName = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
371 break;
372 case "Size":
373 size = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
374 break;
375 case "MaxSize":
376 maxSize = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
377 break;
378 case "GrowthSize":
379 growthSize = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
380 break;
381 default:
382 this.ParseHelper.UnexpectedAttribute(element, attrib);
383 break;
384 }
385 }
386 else
387 {
388 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
389 }
390 }
391
392 if (null == id)
393 {
394 id = this.ParseHelper.CreateIdentifier("sfs", parentId, name, fileName);
395 }
396
397 if (null == name)
398 {
399 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
400 }
401
402 if (null == fileName)
403 {
404 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Filename"));
405 }
406
407 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
408
409 if (!this.Messaging.EncounteredError)
410 {
411 var symbol = section.AddSymbol(new SqlFileSpecSymbol(sourceLineNumbers, id)
412 {
413 Name = name,
414 Filename = fileName,
415 });
416
417 if (null != size)
418 {
419 symbol.Size = size;
420 }
421
422 if (null != maxSize)
423 {
424 symbol.MaxSize = maxSize;
425 }
426
427 if (null != growthSize)
428 {
429 symbol.GrowthSize = growthSize;
430 }
431 }
432
433 return id;
434 }
435
436 /// <summary>
437 /// Parses a sql script element.
438 /// </summary>
439 /// <param name="element">Element to parse.</param>
440 /// <param name="componentId">Identifier for parent component.</param>
441 /// <param name="sqlDb">Optional database to execute script against.</param>
442 private void ParseSqlScriptElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string sqlDb)
443 {
444 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
445 Identifier id = null;
446 int attributes = 0;
447 var rollbackAttribute = false;
448 var nonRollbackAttribute = false;
449 string binaryRef = null;
450 var sequence = CompilerConstants.IntegerNotSet;
451 string user = null;
452
453 foreach (var attrib in element.Attributes())
454 {
455 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
456 {
457 switch (attrib.Name.LocalName)
458 {
459 case "Id":
460 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
461 break;
462 case "BinaryRef":
463 binaryRef = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
464 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Binary, binaryRef);
465 break;
466 case "Sequence":
467 sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue);
468 break;
469 case "SqlDb":
470 if (null != sqlDb)
471 {
472 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, element.Parent.Name.LocalName));
473 }
474 sqlDb = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
475 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SqlSymbolDefinitions.SqlDatabase, sqlDb);
476 break;
477 case "User":
478 user = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
479 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "User", user);
480 break;
481
482 // Flag-setting attributes
483 case "ContinueOnError":
484 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
485 {
486 attributes |= SqlContinueOnError;
487 }
488 break;
489 case "ExecuteOnInstall":
490 if (rollbackAttribute)
491 {
492 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall"));
493 }
494 nonRollbackAttribute = true;
495
496 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
497 {
498 attributes |= SqlExecuteOnInstall;
499 }
500 break;
501 case "ExecuteOnReinstall":
502 if (rollbackAttribute)
503 {
504 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall"));
505 }
506 nonRollbackAttribute = true;
507
508 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
509 {
510 attributes |= SqlExecuteOnReinstall;
511 }
512 break;
513 case "ExecuteOnUninstall":
514 if (rollbackAttribute)
515 {
516 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall"));
517 }
518 nonRollbackAttribute = true;
519
520 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
521 {
522 attributes |= SqlExecuteOnUninstall;
523 }
524 break;
525 case "RollbackOnInstall":
526 if (nonRollbackAttribute)
527 {
528 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall"));
529 }
530 rollbackAttribute = true;
531
532 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
533 {
534 attributes |= SqlExecuteOnInstall;
535 attributes |= SqlRollback;
536 }
537 break;
538 case "RollbackOnReinstall":
539 if (nonRollbackAttribute)
540 {
541 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall"));
542 }
543 rollbackAttribute = true;
544
545 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
546 {
547 attributes |= SqlExecuteOnReinstall;
548 attributes |= SqlRollback;
549 }
550 break;
551 case "RollbackOnUninstall":
552 if (nonRollbackAttribute)
553 {
554 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall"));
555 }
556 rollbackAttribute = true;
557
558 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
559 {
560 attributes |= SqlExecuteOnUninstall;
561 attributes |= SqlRollback;
562 }
563 break;
564 default:
565 this.ParseHelper.UnexpectedAttribute(element, attrib);
566 break;
567 }
568 }
569 else
570 {
571 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
572 }
573 }
574
575 if (null == id)
576 {
577 id = this.ParseHelper.CreateIdentifier("ssc", componentId, binaryRef, sqlDb);
578 }
579
580 if (null == binaryRef)
581 {
582 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "BinaryRef"));
583 }
584
585 if (null == sqlDb)
586 {
587 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "SqlDb"));
588 }
589
590 if (0 == attributes)
591 {
592 this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall", "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall"));
593 }
594
595 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
596
597 // Reference InstallSqlData and UninstallSqlData since nothing will happen without it
598 this.AddReferenceToInstallSqlData(section, sourceLineNumbers);
599
600 if (!this.Messaging.EncounteredError)
601 {
602 var symbol = section.AddSymbol(new SqlScriptSymbol(sourceLineNumbers, id)
603 {
604 SqlDbRef = sqlDb,
605 ComponentRef = componentId,
606 ScriptBinaryRef = binaryRef,
607 UserRef = user,
608 Attributes = attributes,
609 });
610
611 if (CompilerConstants.IntegerNotSet != sequence)
612 {
613 symbol.Sequence = sequence;
614 }
615 }
616 }
617
618 /// <summary>
619 /// Parses a sql string element.
620 /// </summary>
621 /// <param name="element">Element to parse.</param>
622 /// <param name="componentId">Identifier for parent component.</param>
623 /// <param name="sqlDb">Optional database to execute string against.</param>
624 private void ParseSqlStringElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string sqlDb)
625 {
626 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
627 Identifier id = null;
628 int attributes = 0;
629 var rollbackAttribute = false;
630 var nonRollbackAttribute = false;
631 var sequence = CompilerConstants.IntegerNotSet;
632 string sql = null;
633 string user = null;
634
635 foreach (var attrib in element.Attributes())
636 {
637 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
638 {
639 switch (attrib.Name.LocalName)
640 {
641 case "Id":
642 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
643 break;
644 case "ContinueOnError":
645 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
646 {
647 attributes |= SqlContinueOnError;
648 }
649 break;
650 case "ExecuteOnInstall":
651 if (rollbackAttribute)
652 {
653 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall"));
654 }
655 nonRollbackAttribute = true;
656
657 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
658 {
659 attributes |= SqlExecuteOnInstall;
660 }
661 break;
662 case "ExecuteOnReinstall":
663 if (rollbackAttribute)
664 {
665 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall"));
666 }
667 nonRollbackAttribute = true;
668
669 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
670 {
671 attributes |= SqlExecuteOnReinstall;
672 }
673 break;
674 case "ExecuteOnUninstall":
675 if (rollbackAttribute)
676 {
677 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall"));
678 }
679 nonRollbackAttribute = true;
680
681 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
682 {
683 attributes |= SqlExecuteOnUninstall;
684 }
685 break;
686 case "RollbackOnInstall":
687 if (nonRollbackAttribute)
688 {
689 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall"));
690 }
691 rollbackAttribute = true;
692
693 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
694 {
695 attributes |= SqlExecuteOnInstall;
696 attributes |= SqlRollback;
697 }
698 break;
699 case "RollbackOnReinstall":
700 if (nonRollbackAttribute)
701 {
702 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall"));
703 }
704 rollbackAttribute = true;
705
706 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
707 {
708 attributes |= SqlExecuteOnReinstall;
709 attributes |= SqlRollback;
710 }
711 break;
712 case "RollbackOnUninstall":
713 if (nonRollbackAttribute)
714 {
715 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall"));
716 }
717 rollbackAttribute = true;
718
719 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
720 {
721 attributes |= SqlExecuteOnUninstall;
722 attributes |= SqlRollback;
723 }
724 break;
725 case "Sequence":
726 sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue);
727 break;
728 case "SQL":
729 sql = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
730 break;
731 case "SqlDb":
732 if (null != sqlDb)
733 {
734 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "SqlDb", "SqlDatabase"));
735 }
736
737 sqlDb = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
738 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SqlSymbolDefinitions.SqlDatabase, sqlDb);
739 break;
740 case "User":
741 user = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
742 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "User", user);
743 break;
744 default:
745 this.ParseHelper.UnexpectedAttribute(element, attrib);
746 break;
747 }
748 }
749 else
750 {
751 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
752 }
753 }
754
755 if (null == id)
756 {
757 id = this.ParseHelper.CreateIdentifier("sst", componentId, sql, sqlDb);
758 }
759
760 if (null == sql)
761 {
762 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "SQL"));
763 }
764
765 if (null == sqlDb)
766 {
767 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "SqlDb"));
768 }
769
770 if (0 == attributes)
771 {
772 this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "ExecuteOnInstall", "ExecuteOnReinstall", "ExecuteOnUninstall", "RollbackOnInstall", "RollbackOnReinstall", "RollbackOnUninstall"));
773 }
774
775 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
776
777 // Reference InstallSqlData and UninstallSqlData since nothing will happen without it
778 this.AddReferenceToInstallSqlData(section, sourceLineNumbers);
779
780 if (!this.Messaging.EncounteredError)
781 {
782 var symbol = section.AddSymbol(new SqlStringSymbol(sourceLineNumbers, id)
783 {
784 SqlDbRef = sqlDb,
785 ComponentRef = componentId,
786 SQL = sql,
787 UserRef = user,
788 Attributes = attributes,
789 });
790
791 if (CompilerConstants.IntegerNotSet != sequence)
792 {
793 symbol.Sequence = sequence;
794 }
795 }
796 }
797
798 private void AddReferenceToInstallSqlData(IntermediateSection section, SourceLineNumber sourceLineNumbers)
799 {
800 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4InstallSqlData", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
801 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4UninstallSqlData", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
802 }
803 }
804}
diff --git a/src/ext/Sql/wixext/SqlDecompiler.cs b/src/ext/Sql/wixext/SqlDecompiler.cs
new file mode 100644
index 00000000..52436b87
--- /dev/null
+++ b/src/ext/Sql/wixext/SqlDecompiler.cs
@@ -0,0 +1,514 @@
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.Sql
4{
5#if TODO_CONSIDER_DECOMPILER
6 using System.Collections;
7 using WixToolset.Data;
8 using WixToolset.Extensibility;
9 using Sql = WixToolset.Extensions.Serialize.Sql;
10 using Wix = WixToolset.Data.Serialize;
11
12 /// <summary>
13 /// The decompiler for the WiX Toolset SQL Server Extension.
14 /// </summary>
15 public sealed class SqlDecompiler : DecompilerExtension
16 {
17 /// <summary>
18 /// Creates a decompiler for SQL Extension.
19 /// </summary>
20 public SqlDecompiler()
21 {
22 this.TableDefinitions = SqlExtensionData.GetExtensionTableDefinitions();
23 }
24
25 /// <summary>
26 /// Get the extensions library to be removed.
27 /// </summary>
28 /// <param name="tableDefinitions">Table definitions for library.</param>
29 /// <returns>Library to remove from decompiled output.</returns>
30 public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions)
31 {
32 return SqlExtensionData.GetExtensionLibrary(tableDefinitions);
33 }
34
35 /// <summary>
36 /// Decompiles an extension table.
37 /// </summary>
38 /// <param name="table">The table to decompile.</param>
39 public override void DecompileTable(Table table)
40 {
41 switch (table.Name)
42 {
43 case "SqlDatabase":
44 this.DecompileSqlDatabaseTable(table);
45 break;
46 case "SqlFileSpec":
47 // handled in FinalizeSqlFileSpecTable
48 break;
49 case "SqlScript":
50 this.DecompileSqlScriptTable(table);
51 break;
52 case "SqlString":
53 this.DecompileSqlStringTable(table);
54 break;
55 default:
56 base.DecompileTable(table);
57 break;
58 }
59 }
60
61 /// <summary>
62 /// Finalize decompilation.
63 /// </summary>
64 /// <param name="tables">The collection of all tables.</param>
65 public override void Finish(TableIndexedCollection tables)
66 {
67 this.FinalizeSqlFileSpecTable(tables);
68 this.FinalizeSqlScriptAndSqlStringTables(tables);
69 }
70
71 /// <summary>
72 /// Decompile the SqlDatabase table.
73 /// </summary>
74 /// <param name="table">The table to decompile.</param>
75 private void DecompileSqlDatabaseTable(Table table)
76 {
77 foreach (Row row in table.Rows)
78 {
79 Sql.SqlDatabase sqlDatabase = new Sql.SqlDatabase();
80
81 sqlDatabase.Id = (string)row[0];
82
83 if (null != row[1])
84 {
85 sqlDatabase.Server = (string)row[1];
86 }
87
88 if (null != row[2])
89 {
90 sqlDatabase.Instance = (string)row[2];
91 }
92
93 sqlDatabase.Database = (string)row[3];
94
95 if (null != row[5])
96 {
97 sqlDatabase.User = (string)row[5];
98 }
99
100 // the FileSpec_ and FileSpec_Log columns will be handled in FinalizeSqlFileSpecTable
101
102 if (null != row[8])
103 {
104 int attributes = (int)row[8];
105
106 if (SqlCompiler.DbCreateOnInstall == (attributes & SqlCompiler.DbCreateOnInstall))
107 {
108 sqlDatabase.CreateOnInstall = Sql.YesNoType.yes;
109 }
110
111 if (SqlCompiler.DbDropOnUninstall == (attributes & SqlCompiler.DbDropOnUninstall))
112 {
113 sqlDatabase.DropOnUninstall = Sql.YesNoType.yes;
114 }
115
116 if (SqlCompiler.DbContinueOnError == (attributes & SqlCompiler.DbContinueOnError))
117 {
118 sqlDatabase.ContinueOnError = Sql.YesNoType.yes;
119 }
120
121 if (SqlCompiler.DbDropOnInstall == (attributes & SqlCompiler.DbDropOnInstall))
122 {
123 sqlDatabase.DropOnInstall = Sql.YesNoType.yes;
124 }
125
126 if (SqlCompiler.DbCreateOnUninstall == (attributes & SqlCompiler.DbCreateOnUninstall))
127 {
128 sqlDatabase.CreateOnUninstall = Sql.YesNoType.yes;
129 }
130
131 if (SqlCompiler.DbConfirmOverwrite == (attributes & SqlCompiler.DbConfirmOverwrite))
132 {
133 sqlDatabase.ConfirmOverwrite = Sql.YesNoType.yes;
134 }
135
136 if (SqlCompiler.DbCreateOnReinstall == (attributes & SqlCompiler.DbCreateOnReinstall))
137 {
138 sqlDatabase.CreateOnReinstall = Sql.YesNoType.yes;
139 }
140
141 if (SqlCompiler.DbDropOnReinstall == (attributes & SqlCompiler.DbDropOnReinstall))
142 {
143 sqlDatabase.DropOnReinstall = Sql.YesNoType.yes;
144 }
145 }
146
147 if (null != row[4])
148 {
149 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[4]);
150
151 if (null != component)
152 {
153 component.AddChild(sqlDatabase);
154 }
155 else
156 {
157 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[4], "Component"));
158 }
159 }
160 else
161 {
162 this.Core.RootElement.AddChild(sqlDatabase);
163 }
164 this.Core.IndexElement(row, sqlDatabase);
165 }
166 }
167
168 /// <summary>
169 /// Decompile the SqlScript table.
170 /// </summary>
171 /// <param name="table">The table to decompile.</param>
172 private void DecompileSqlScriptTable(Table table)
173 {
174 foreach (Row row in table.Rows)
175 {
176 Sql.SqlScript sqlScript = new Sql.SqlScript();
177
178 sqlScript.Id = (string)row[0];
179
180 // the Db_ and Component_ columns are handled in FinalizeSqlScriptAndSqlStringTables
181
182 sqlScript.BinaryKey = (string)row[3];
183
184 if (null != row[4])
185 {
186 sqlScript.User = (string)row[4];
187 }
188
189 int attributes = (int)row[5];
190
191 if (SqlCompiler.SqlContinueOnError == (attributes & SqlCompiler.SqlContinueOnError))
192 {
193 sqlScript.ContinueOnError = Sql.YesNoType.yes;
194 }
195
196 if (SqlCompiler.SqlExecuteOnInstall == (attributes & SqlCompiler.SqlExecuteOnInstall))
197 {
198 sqlScript.ExecuteOnInstall = Sql.YesNoType.yes;
199 }
200
201 if (SqlCompiler.SqlExecuteOnReinstall == (attributes & SqlCompiler.SqlExecuteOnReinstall))
202 {
203 sqlScript.ExecuteOnReinstall = Sql.YesNoType.yes;
204 }
205
206 if (SqlCompiler.SqlExecuteOnUninstall == (attributes & SqlCompiler.SqlExecuteOnUninstall))
207 {
208 sqlScript.ExecuteOnUninstall = Sql.YesNoType.yes;
209 }
210
211 if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnInstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnInstall)))
212 {
213 sqlScript.RollbackOnInstall = Sql.YesNoType.yes;
214 }
215
216 if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnReinstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnReinstall)))
217 {
218 sqlScript.RollbackOnReinstall = Sql.YesNoType.yes;
219 }
220
221 if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnUninstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnUninstall)))
222 {
223 sqlScript.RollbackOnUninstall = Sql.YesNoType.yes;
224 }
225
226 if (null != row[6])
227 {
228 sqlScript.Sequence = (int)row[6];
229 }
230
231 this.Core.IndexElement(row, sqlScript);
232 }
233 }
234
235 /// <summary>
236 /// Decompile the SqlString table.
237 /// </summary>
238 /// <param name="table">The table to decompile.</param>
239 private void DecompileSqlStringTable(Table table)
240 {
241 foreach (Row row in table.Rows)
242 {
243 Sql.SqlString sqlString = new Sql.SqlString();
244
245 sqlString.Id = (string)row[0];
246
247 // the Db_ and Component_ columns are handled in FinalizeSqlScriptAndSqlStringTables
248
249 sqlString.SQL = (string)row[3];
250
251 if (null != row[4])
252 {
253 sqlString.User = (string)row[4];
254 }
255
256 int attributes = (int)row[5];
257
258 if (SqlCompiler.SqlContinueOnError == (attributes & SqlCompiler.SqlContinueOnError))
259 {
260 sqlString.ContinueOnError = Sql.YesNoType.yes;
261 }
262
263 if (SqlCompiler.SqlExecuteOnInstall == (attributes & SqlCompiler.SqlExecuteOnInstall))
264 {
265 sqlString.ExecuteOnInstall = Sql.YesNoType.yes;
266 }
267
268 if (SqlCompiler.SqlExecuteOnReinstall == (attributes & SqlCompiler.SqlExecuteOnReinstall))
269 {
270 sqlString.ExecuteOnReinstall = Sql.YesNoType.yes;
271 }
272
273 if (SqlCompiler.SqlExecuteOnUninstall == (attributes & SqlCompiler.SqlExecuteOnUninstall))
274 {
275 sqlString.ExecuteOnUninstall = Sql.YesNoType.yes;
276 }
277
278 if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnInstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnInstall)))
279 {
280 sqlString.RollbackOnInstall = Sql.YesNoType.yes;
281 }
282
283 if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnReinstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnReinstall)))
284 {
285 sqlString.RollbackOnReinstall = Sql.YesNoType.yes;
286 }
287
288 if ((SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnUninstall) == (attributes & (SqlCompiler.SqlRollback | SqlCompiler.SqlExecuteOnUninstall)))
289 {
290 sqlString.RollbackOnUninstall = Sql.YesNoType.yes;
291 }
292
293 if (null != row[6])
294 {
295 sqlString.Sequence = (int)row[6];
296 }
297
298 this.Core.IndexElement(row, sqlString);
299 }
300 }
301
302 /// <summary>
303 /// Finalize the SqlFileSpec table.
304 /// </summary>
305 /// <param name="tables">The collection of all tables.</param>
306 /// <remarks>
307 /// Since rows of the SqlFileSpec table are represented by either
308 /// the SqlFileSpec or SqlLogFileSpec depending upon the context in
309 /// which they are used in the SqlDatabase table, decompilation of this
310 /// table must occur after the SqlDatbase parents are decompiled.
311 /// </remarks>
312 private void FinalizeSqlFileSpecTable(TableIndexedCollection tables)
313 {
314 Table sqlDatabaseTable = tables["SqlDatabase"];
315 Table sqlFileSpecTable = tables["SqlFileSpec"];
316
317 if (null != sqlDatabaseTable && null != sqlFileSpecTable)
318 {
319 Hashtable sqlFileSpecRows = new Hashtable();
320
321 // index each SqlFileSpec row by its primary key
322 foreach (Row row in sqlFileSpecTable.Rows)
323 {
324 sqlFileSpecRows.Add(row[0], row);
325 }
326
327 // create the necessary SqlFileSpec and SqlLogFileSpec elements for each row
328 foreach (Row row in sqlDatabaseTable.Rows)
329 {
330 Sql.SqlDatabase sqlDatabase = (Sql.SqlDatabase)this.Core.GetIndexedElement(row);
331
332 if (null != row[6])
333 {
334 Row sqlFileSpecRow = (Row)sqlFileSpecRows[row[6]];
335
336 if (null != sqlFileSpecRow)
337 {
338 Sql.SqlFileSpec sqlFileSpec = new Sql.SqlFileSpec();
339
340 sqlFileSpec.Id = (string)sqlFileSpecRow[0];
341
342 if (null != sqlFileSpecRow[1])
343 {
344 sqlFileSpec.Name = (string)sqlFileSpecRow[1];
345 }
346
347 sqlFileSpec.Filename = (string)sqlFileSpecRow[2];
348
349 if (null != sqlFileSpecRow[3])
350 {
351 sqlFileSpec.Size = (string)sqlFileSpecRow[3];
352 }
353
354 if (null != sqlFileSpecRow[4])
355 {
356 sqlFileSpec.MaxSize = (string)sqlFileSpecRow[4];
357 }
358
359 if (null != sqlFileSpecRow[5])
360 {
361 sqlFileSpec.GrowthSize = (string)sqlFileSpecRow[5];
362 }
363
364 sqlDatabase.AddChild(sqlFileSpec);
365 }
366 else
367 {
368 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, sqlDatabaseTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "FileSpec_", (string)row[6], "SqlFileSpec"));
369 }
370 }
371
372 if (null != row[7])
373 {
374 Row sqlFileSpecRow = (Row)sqlFileSpecRows[row[7]];
375
376 if (null != sqlFileSpecRow)
377 {
378 Sql.SqlLogFileSpec sqlLogFileSpec = new Sql.SqlLogFileSpec();
379
380 sqlLogFileSpec.Id = (string)sqlFileSpecRow[0];
381
382 if (null != sqlFileSpecRow[1])
383 {
384 sqlLogFileSpec.Name = (string)sqlFileSpecRow[1];
385 }
386
387 sqlLogFileSpec.Filename = (string)sqlFileSpecRow[2];
388
389 if (null != sqlFileSpecRow[3])
390 {
391 sqlLogFileSpec.Size = (string)sqlFileSpecRow[3];
392 }
393
394 if (null != sqlFileSpecRow[4])
395 {
396 sqlLogFileSpec.MaxSize = (string)sqlFileSpecRow[4];
397 }
398
399 if (null != sqlFileSpecRow[5])
400 {
401 sqlLogFileSpec.GrowthSize = (string)sqlFileSpecRow[5];
402 }
403
404 sqlDatabase.AddChild(sqlLogFileSpec);
405 }
406 else
407 {
408 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, sqlDatabaseTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "FileSpec_Log", (string)row[7], "SqlFileSpec"));
409 }
410 }
411 }
412 }
413 }
414
415 /// <summary>
416 /// Finalize the SqlScript table.
417 /// </summary>
418 /// <param name="tables">The collection of all tables.</param>
419 /// <remarks>
420 /// The SqlScript and SqlString tables contain a foreign key into the SqlDatabase
421 /// and Component tables. Depending upon the parent of the SqlDatabase
422 /// element, the SqlScript and SqlString elements are nested under either the
423 /// SqlDatabase or the Component element.
424 /// </remarks>
425 private void FinalizeSqlScriptAndSqlStringTables(TableIndexedCollection tables)
426 {
427 Table sqlDatabaseTable = tables["SqlDatabase"];
428 Table sqlScriptTable = tables["SqlScript"];
429 Table sqlStringTable = tables["SqlString"];
430
431 Hashtable sqlDatabaseRows = new Hashtable();
432
433 // index each SqlDatabase row by its primary key
434 if (null != sqlDatabaseTable)
435 {
436 foreach (Row row in sqlDatabaseTable.Rows)
437 {
438 sqlDatabaseRows.Add(row[0], row);
439 }
440 }
441
442 if (null != sqlScriptTable)
443 {
444 foreach (Row row in sqlScriptTable.Rows)
445 {
446 Sql.SqlScript sqlScript = (Sql.SqlScript)this.Core.GetIndexedElement(row);
447
448 Row sqlDatabaseRow = (Row)sqlDatabaseRows[row[1]];
449 string databaseComponent = (string)sqlDatabaseRow[4];
450
451 // determine if the SqlScript element should be nested under the database or another component
452 if (null != databaseComponent && databaseComponent == (string)row[2])
453 {
454 Sql.SqlDatabase sqlDatabase = (Sql.SqlDatabase)this.Core.GetIndexedElement(sqlDatabaseRow);
455
456 sqlDatabase.AddChild(sqlScript);
457 }
458 else // nest under the component of the SqlDatabase row
459 {
460 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
461
462 // set the Database value
463 sqlScript.SqlDb = (string)row[1];
464
465 if (null != component)
466 {
467 component.AddChild(sqlScript);
468 }
469 else
470 {
471 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, sqlScriptTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
472 }
473 }
474 }
475 }
476
477 if (null != sqlStringTable)
478 {
479 foreach (Row row in sqlStringTable.Rows)
480 {
481 Sql.SqlString sqlString = (Sql.SqlString)this.Core.GetIndexedElement(row);
482
483 Row sqlDatabaseRow = (Row)sqlDatabaseRows[row[1]];
484 string databaseComponent = (string)sqlDatabaseRow[4];
485
486 // determine if the SqlScript element should be nested under the database or another component
487 if (null != databaseComponent && databaseComponent == (string)row[2])
488 {
489 Sql.SqlDatabase sqlDatabase = (Sql.SqlDatabase)this.Core.GetIndexedElement(sqlDatabaseRow);
490
491 sqlDatabase.AddChild(sqlString);
492 }
493 else // nest under the component of the SqlDatabase row
494 {
495 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[2]);
496
497 // set the Database value
498 sqlString.SqlDb = (string)row[1];
499
500 if (null != component)
501 {
502 component.AddChild(sqlString);
503 }
504 else
505 {
506 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, sqlStringTable.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[2], "Component"));
507 }
508 }
509 }
510 }
511 }
512 }
513#endif
514}
diff --git a/src/ext/Sql/wixext/SqlErrors.cs b/src/ext/Sql/wixext/SqlErrors.cs
new file mode 100644
index 00000000..f25728bd
--- /dev/null
+++ b/src/ext/Sql/wixext/SqlErrors.cs
@@ -0,0 +1,48 @@
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.Sql
4{
5 using System.Resources;
6 using WixToolset.Data;
7
8 public static class SqlErrors
9 {
10 public static Message IllegalAttributeWithoutComponent(SourceLineNumber sourceLineNumbers, string elementName, string attributeName)
11 {
12 return Message(sourceLineNumbers, Ids.IllegalAttributeWithoutComponent, "The {0}/@{1} attribute cannot be specified unless the element has a Component as an ancestor. A {0} that does not have a Component ancestor is not installed.", elementName, attributeName);
13 }
14
15 public static Message IllegalElementWithoutComponent(SourceLineNumber sourceLineNumbers, string elementName)
16 {
17 return Message(sourceLineNumbers, Ids.IllegalElementWithoutComponent, "The {0} element cannot be specified unless the element has a Component as an ancestor. A {0} that does not have a Component ancestor is not installed.", elementName);
18 }
19
20 public static Message OneOfAttributesRequiredUnderComponent(SourceLineNumber sourceLineNumbers, string elementName, string attributeName1, string attributeName2, string attributeName3, string attributeName4)
21 {
22 return Message(sourceLineNumbers, Ids.OneOfAttributesRequiredUnderComponent, "When nested under a Component, the {0} element must have one of the following attributes specified: {1}, {2}, {3} or {4}.", elementName, attributeName1, attributeName2, attributeName3, attributeName4);
23 }
24
25 public static Message DeprecatedBinaryChildElement(SourceLineNumber sourceLineNumbers, string elementName)
26 {
27 return Message(sourceLineNumbers, Ids.DeprecatedBinaryChildElement, "The {0} element contains a deprecated child Binary element. Please move the Binary element under a Fragment, Module, or Product element and set the {0}/@BinaryKey attribute to the value of the Binary/@Id attribute.", elementName);
28 }
29
30 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args)
31 {
32 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args);
33 }
34
35 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args)
36 {
37 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, resourceManager, resourceName, args);
38 }
39
40 public enum Ids
41 {
42 IllegalAttributeWithoutComponent = 5100,
43 IllegalElementWithoutComponent = 5101,
44 OneOfAttributesRequiredUnderComponent = 5102,
45 DeprecatedBinaryChildElement = 5103,
46 }
47 }
48} \ No newline at end of file
diff --git a/src/ext/Sql/wixext/SqlExtensionData.cs b/src/ext/Sql/wixext/SqlExtensionData.cs
new file mode 100644
index 00000000..60de94fe
--- /dev/null
+++ b/src/ext/Sql/wixext/SqlExtensionData.cs
@@ -0,0 +1,30 @@
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.Sql
4{
5 using WixToolset.Data;
6 using WixToolset.Extensibility;
7
8 /// <summary>
9 /// The WiX Toolset SQL Server Extension.
10 /// </summary>
11 public sealed class SqlExtensionData : BaseExtensionData
12 {
13 /// <summary>
14 /// Gets the default culture.
15 /// </summary>
16 /// <value>The default culture.</value>
17 public override string DefaultCulture => "en-US";
18
19 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
20 {
21 symbolDefinition = SqlSymbolDefinitions.ByName(name);
22 return symbolDefinition != null;
23 }
24
25 public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions)
26 {
27 return Intermediate.Load(typeof(SqlExtensionData).Assembly, "WixToolset.Sql.sql.wixlib", symbolDefinitions);
28 }
29 }
30}
diff --git a/src/ext/Sql/wixext/SqlExtensionFactory.cs b/src/ext/Sql/wixext/SqlExtensionFactory.cs
new file mode 100644
index 00000000..279106d3
--- /dev/null
+++ b/src/ext/Sql/wixext/SqlExtensionFactory.cs
@@ -0,0 +1,18 @@
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.Sql
4{
5 using System;
6 using System.Collections.Generic;
7 using WixToolset.Extensibility;
8
9 public class SqlExtensionFactory : BaseExtensionFactory
10 {
11 protected override IReadOnlyCollection<Type> ExtensionTypes => new[]
12 {
13 typeof(SqlCompiler),
14 typeof(SqlExtensionData),
15 typeof(SqlWindowsInstallerBackendBinderExtension),
16 };
17 }
18}
diff --git a/src/ext/Sql/wixext/SqlTableDefinitions.cs b/src/ext/Sql/wixext/SqlTableDefinitions.cs
new file mode 100644
index 00000000..029a092e
--- /dev/null
+++ b/src/ext/Sql/wixext/SqlTableDefinitions.cs
@@ -0,0 +1,82 @@
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.Sql
4{
5 using WixToolset.Data.WindowsInstaller;
6
7 public static class SqlTableDefinitions
8 {
9 public static readonly TableDefinition SqlDatabase = new TableDefinition(
10 "Wix4SqlDatabase",
11 SqlSymbolDefinitions.SqlDatabase,
12 new[]
13 {
14 new ColumnDefinition("SqlDb", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
15 new ColumnDefinition("Server", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Primary key, name of server running SQL Server"),
16 new ColumnDefinition("Instance", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Primary key, name of SQL Server instance"),
17 new ColumnDefinition("Database", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Primary key, name of database in a SQL Server"),
18 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key, Component used to determine install state ", modularizeType: ColumnModularizeType.Column),
19 new ColumnDefinition("User_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "User", keyColumn: 1, description: "Foreign key, User used to log into database", modularizeType: ColumnModularizeType.Column),
20 new ColumnDefinition("FileSpec_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "Wix4SqlFileSpec", keyColumn: 1, description: "Foreign key referencing SqlFileSpec.", modularizeType: ColumnModularizeType.Column),
21 new ColumnDefinition("FileSpec_Log", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "Wix4SqlFileSpec", keyColumn: 1, description: "Foreign key referencing SqlFileSpec.", modularizeType: ColumnModularizeType.Column),
22 new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, minValue: 0, maxValue: 255, description: "1 == create on install, 2 == drop on uninstall, 4 == continue on error, 8 == drop on install, 16 == create on uninstall, 32 == confirm update existing table, 64 == create on reinstall, 128 == drop on reinstall"),
23 },
24 symbolIdIsPrimaryKey: true
25 );
26
27 public static readonly TableDefinition SqlFileSpec = new TableDefinition(
28 "Wix4SqlFileSpec",
29 SqlSymbolDefinitions.SqlFileSpec,
30 new[]
31 {
32 new ColumnDefinition("FileSpec", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token", modularizeType: ColumnModularizeType.Column),
33 new ColumnDefinition("Name", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Logical name of filespec", modularizeType: ColumnModularizeType.Property),
34 new ColumnDefinition("Filename", ColumnType.String, 255, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Filename to use (path must exist)", modularizeType: ColumnModularizeType.Property),
35 new ColumnDefinition("Size", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Initial size for file", modularizeType: ColumnModularizeType.Property),
36 new ColumnDefinition("MaxSize", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Maximum size for file", modularizeType: ColumnModularizeType.Property),
37 new ColumnDefinition("GrowthSize", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Size file should grow when necessary", modularizeType: ColumnModularizeType.Property),
38 },
39 symbolIdIsPrimaryKey: true
40 );
41
42 public static readonly TableDefinition SqlScript = new TableDefinition(
43 "Wix4SqlScript",
44 SqlSymbolDefinitions.SqlScript,
45 new[]
46 {
47 new ColumnDefinition("Script", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Primary key, non-localized token"),
48 new ColumnDefinition("SqlDb_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Wix4SqlDatabase", keyColumn: 1, description: "Foreign key, SQL Server key", modularizeType: ColumnModularizeType.Column),
49 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key, Component used to determine install state", modularizeType: ColumnModularizeType.Column),
50 new ColumnDefinition("ScriptBinary_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Binary", keyColumn: 1, description: "Foreign key, Binary stream that contains SQL Script to execute", modularizeType: ColumnModularizeType.Column),
51 new ColumnDefinition("User_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "User", keyColumn: 1, description: "Foreign key, User used to log into database", modularizeType: ColumnModularizeType.Column),
52 new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, possibilities: "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31", description: "1 == execute on install, 2 == execute on uninstall, 4 == continue on error, 8 == rollback on install, 16 == rollback on uninstall"),
53 new ColumnDefinition("Sequence", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Order to execute SQL Queries in"),
54 },
55 symbolIdIsPrimaryKey: true
56 );
57
58 public static readonly TableDefinition SqlString = new TableDefinition(
59 "Wix4SqlString",
60 SqlSymbolDefinitions.SqlString,
61 new[]
62 {
63 new ColumnDefinition("String", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "Id for the Wix4SqlString", modularizeType: ColumnModularizeType.Column),
64 new ColumnDefinition("SqlDb_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Wix4SqlDatabase", keyColumn: 1, description: "Foreign key, SQL Server key", modularizeType: ColumnModularizeType.Column),
65 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key, Component used to determine install state", modularizeType: ColumnModularizeType.Column),
66 new ColumnDefinition("SQL", ColumnType.String, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "SQL query to execute"),
67 new ColumnDefinition("User_", ColumnType.String, 72, primaryKey: false, nullable: true, ColumnCategory.Identifier, keyTable: "User", keyColumn: 1, description: "Foreign key, User used to log into database", modularizeType: ColumnModularizeType.Column),
68 new ColumnDefinition("Attributes", ColumnType.Number, 2, primaryKey: false, nullable: false, ColumnCategory.Unknown, possibilities: "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25;26;27;28;29;30;31", description: "1 == execute on install, 2 == execute on uninstall, 4 == continue on error, 8 == rollback on install, 16 == rollback on uninstall"),
69 new ColumnDefinition("Sequence", ColumnType.Number, 2, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Order to execute SQL Queries in"),
70 },
71 symbolIdIsPrimaryKey: true
72 );
73
74 public static readonly TableDefinition[] All = new[]
75 {
76 SqlDatabase,
77 SqlFileSpec,
78 SqlScript,
79 SqlString,
80 };
81 }
82}
diff --git a/src/ext/Sql/wixext/SqlWindowsInstallerBackendExtension.cs b/src/ext/Sql/wixext/SqlWindowsInstallerBackendExtension.cs
new file mode 100644
index 00000000..2ccdcc56
--- /dev/null
+++ b/src/ext/Sql/wixext/SqlWindowsInstallerBackendExtension.cs
@@ -0,0 +1,13 @@
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.Sql
4{
5 using System.Collections.Generic;
6 using WixToolset.Data.WindowsInstaller;
7 using WixToolset.Extensibility;
8
9 public class SqlWindowsInstallerBackendBinderExtension : BaseWindowsInstallerBackendBinderExtension
10 {
11 public override IReadOnlyCollection<TableDefinition> TableDefinitions => SqlTableDefinitions.All;
12 }
13}
diff --git a/src/ext/Sql/wixext/Symbols/SqlDatabaseSymbol.cs b/src/ext/Sql/wixext/Symbols/SqlDatabaseSymbol.cs
new file mode 100644
index 00000000..6f0820ac
--- /dev/null
+++ b/src/ext/Sql/wixext/Symbols/SqlDatabaseSymbol.cs
@@ -0,0 +1,103 @@
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.Sql
4{
5 using WixToolset.Data;
6 using WixToolset.Sql.Symbols;
7
8 public static partial class SqlSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition SqlDatabase = new IntermediateSymbolDefinition(
11 SqlSymbolDefinitionType.SqlDatabase.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(SqlDatabaseSymbolFields.Server), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(SqlDatabaseSymbolFields.Instance), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(SqlDatabaseSymbolFields.Database), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(SqlDatabaseSymbolFields.ComponentRef), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(SqlDatabaseSymbolFields.UserRef), IntermediateFieldType.String),
19 new IntermediateFieldDefinition(nameof(SqlDatabaseSymbolFields.FileSpecRef), IntermediateFieldType.String),
20 new IntermediateFieldDefinition(nameof(SqlDatabaseSymbolFields.LogFileSpecRef), IntermediateFieldType.String),
21 new IntermediateFieldDefinition(nameof(SqlDatabaseSymbolFields.Attributes), IntermediateFieldType.Number),
22 },
23 typeof(SqlDatabaseSymbol));
24 }
25}
26
27namespace WixToolset.Sql.Symbols
28{
29 using WixToolset.Data;
30
31 public enum SqlDatabaseSymbolFields
32 {
33 Server,
34 Instance,
35 Database,
36 ComponentRef,
37 UserRef,
38 FileSpecRef,
39 LogFileSpecRef,
40 Attributes,
41 }
42
43 public class SqlDatabaseSymbol : IntermediateSymbol
44 {
45 public SqlDatabaseSymbol() : base(SqlSymbolDefinitions.SqlDatabase, null, null)
46 {
47 }
48
49 public SqlDatabaseSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(SqlSymbolDefinitions.SqlDatabase, sourceLineNumber, id)
50 {
51 }
52
53 public IntermediateField this[SqlDatabaseSymbolFields index] => this.Fields[(int)index];
54
55 public string Server
56 {
57 get => this.Fields[(int)SqlDatabaseSymbolFields.Server].AsString();
58 set => this.Set((int)SqlDatabaseSymbolFields.Server, value);
59 }
60
61 public string Instance
62 {
63 get => this.Fields[(int)SqlDatabaseSymbolFields.Instance].AsString();
64 set => this.Set((int)SqlDatabaseSymbolFields.Instance, value);
65 }
66
67 public string Database
68 {
69 get => this.Fields[(int)SqlDatabaseSymbolFields.Database].AsString();
70 set => this.Set((int)SqlDatabaseSymbolFields.Database, value);
71 }
72
73 public string ComponentRef
74 {
75 get => this.Fields[(int)SqlDatabaseSymbolFields.ComponentRef].AsString();
76 set => this.Set((int)SqlDatabaseSymbolFields.ComponentRef, value);
77 }
78
79 public string UserRef
80 {
81 get => this.Fields[(int)SqlDatabaseSymbolFields.UserRef].AsString();
82 set => this.Set((int)SqlDatabaseSymbolFields.UserRef, value);
83 }
84
85 public string FileSpecRef
86 {
87 get => this.Fields[(int)SqlDatabaseSymbolFields.FileSpecRef].AsString();
88 set => this.Set((int)SqlDatabaseSymbolFields.FileSpecRef, value);
89 }
90
91 public string LogFileSpecRef
92 {
93 get => this.Fields[(int)SqlDatabaseSymbolFields.LogFileSpecRef].AsString();
94 set => this.Set((int)SqlDatabaseSymbolFields.LogFileSpecRef, value);
95 }
96
97 public int Attributes
98 {
99 get => this.Fields[(int)SqlDatabaseSymbolFields.Attributes].AsNumber();
100 set => this.Set((int)SqlDatabaseSymbolFields.Attributes, value);
101 }
102 }
103} \ No newline at end of file
diff --git a/src/ext/Sql/wixext/Symbols/SqlFileSpecSymbol.cs b/src/ext/Sql/wixext/Symbols/SqlFileSpecSymbol.cs
new file mode 100644
index 00000000..d9eecc62
--- /dev/null
+++ b/src/ext/Sql/wixext/Symbols/SqlFileSpecSymbol.cs
@@ -0,0 +1,79 @@
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.Sql
4{
5 using WixToolset.Data;
6 using WixToolset.Sql.Symbols;
7
8 public static partial class SqlSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition SqlFileSpec = new IntermediateSymbolDefinition(
11 SqlSymbolDefinitionType.SqlFileSpec.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(SqlFileSpecSymbolFields.Name), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(SqlFileSpecSymbolFields.Filename), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(SqlFileSpecSymbolFields.Size), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(SqlFileSpecSymbolFields.MaxSize), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(SqlFileSpecSymbolFields.GrowthSize), IntermediateFieldType.String),
19 },
20 typeof(SqlFileSpecSymbol));
21 }
22}
23
24namespace WixToolset.Sql.Symbols
25{
26 using WixToolset.Data;
27
28 public enum SqlFileSpecSymbolFields
29 {
30 Name,
31 Filename,
32 Size,
33 MaxSize,
34 GrowthSize,
35 }
36
37 public class SqlFileSpecSymbol : IntermediateSymbol
38 {
39 public SqlFileSpecSymbol() : base(SqlSymbolDefinitions.SqlFileSpec, null, null)
40 {
41 }
42
43 public SqlFileSpecSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(SqlSymbolDefinitions.SqlFileSpec, sourceLineNumber, id)
44 {
45 }
46
47 public IntermediateField this[SqlFileSpecSymbolFields index] => this.Fields[(int)index];
48
49 public string Name
50 {
51 get => this.Fields[(int)SqlFileSpecSymbolFields.Name].AsString();
52 set => this.Set((int)SqlFileSpecSymbolFields.Name, value);
53 }
54
55 public string Filename
56 {
57 get => this.Fields[(int)SqlFileSpecSymbolFields.Filename].AsString();
58 set => this.Set((int)SqlFileSpecSymbolFields.Filename, value);
59 }
60
61 public string Size
62 {
63 get => this.Fields[(int)SqlFileSpecSymbolFields.Size].AsString();
64 set => this.Set((int)SqlFileSpecSymbolFields.Size, value);
65 }
66
67 public string MaxSize
68 {
69 get => this.Fields[(int)SqlFileSpecSymbolFields.MaxSize].AsString();
70 set => this.Set((int)SqlFileSpecSymbolFields.MaxSize, value);
71 }
72
73 public string GrowthSize
74 {
75 get => this.Fields[(int)SqlFileSpecSymbolFields.GrowthSize].AsString();
76 set => this.Set((int)SqlFileSpecSymbolFields.GrowthSize, value);
77 }
78 }
79} \ No newline at end of file
diff --git a/src/ext/Sql/wixext/Symbols/SqlScriptSymbol.cs b/src/ext/Sql/wixext/Symbols/SqlScriptSymbol.cs
new file mode 100644
index 00000000..94c70390
--- /dev/null
+++ b/src/ext/Sql/wixext/Symbols/SqlScriptSymbol.cs
@@ -0,0 +1,87 @@
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.Sql
4{
5 using WixToolset.Data;
6 using WixToolset.Sql.Symbols;
7
8 public static partial class SqlSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition SqlScript = new IntermediateSymbolDefinition(
11 SqlSymbolDefinitionType.SqlScript.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(SqlScriptSymbolFields.SqlDbRef), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(SqlScriptSymbolFields.ComponentRef), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(SqlScriptSymbolFields.ScriptBinaryRef), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(SqlScriptSymbolFields.UserRef), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(SqlScriptSymbolFields.Attributes), IntermediateFieldType.Number),
19 new IntermediateFieldDefinition(nameof(SqlScriptSymbolFields.Sequence), IntermediateFieldType.Number),
20 },
21 typeof(SqlScriptSymbol));
22 }
23}
24
25namespace WixToolset.Sql.Symbols
26{
27 using WixToolset.Data;
28
29 public enum SqlScriptSymbolFields
30 {
31 SqlDbRef,
32 ComponentRef,
33 ScriptBinaryRef,
34 UserRef,
35 Attributes,
36 Sequence,
37 }
38
39 public class SqlScriptSymbol : IntermediateSymbol
40 {
41 public SqlScriptSymbol() : base(SqlSymbolDefinitions.SqlScript, null, null)
42 {
43 }
44
45 public SqlScriptSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(SqlSymbolDefinitions.SqlScript, sourceLineNumber, id)
46 {
47 }
48
49 public IntermediateField this[SqlScriptSymbolFields index] => this.Fields[(int)index];
50
51 public string SqlDbRef
52 {
53 get => this.Fields[(int)SqlScriptSymbolFields.SqlDbRef].AsString();
54 set => this.Set((int)SqlScriptSymbolFields.SqlDbRef, value);
55 }
56
57 public string ComponentRef
58 {
59 get => this.Fields[(int)SqlScriptSymbolFields.ComponentRef].AsString();
60 set => this.Set((int)SqlScriptSymbolFields.ComponentRef, value);
61 }
62
63 public string ScriptBinaryRef
64 {
65 get => this.Fields[(int)SqlScriptSymbolFields.ScriptBinaryRef].AsString();
66 set => this.Set((int)SqlScriptSymbolFields.ScriptBinaryRef, value);
67 }
68
69 public string UserRef
70 {
71 get => this.Fields[(int)SqlScriptSymbolFields.UserRef].AsString();
72 set => this.Set((int)SqlScriptSymbolFields.UserRef, value);
73 }
74
75 public int Attributes
76 {
77 get => this.Fields[(int)SqlScriptSymbolFields.Attributes].AsNumber();
78 set => this.Set((int)SqlScriptSymbolFields.Attributes, value);
79 }
80
81 public int? Sequence
82 {
83 get => this.Fields[(int)SqlScriptSymbolFields.Sequence].AsNullableNumber();
84 set => this.Set((int)SqlScriptSymbolFields.Sequence, value);
85 }
86 }
87} \ No newline at end of file
diff --git a/src/ext/Sql/wixext/Symbols/SqlStringSymbol.cs b/src/ext/Sql/wixext/Symbols/SqlStringSymbol.cs
new file mode 100644
index 00000000..73a8206e
--- /dev/null
+++ b/src/ext/Sql/wixext/Symbols/SqlStringSymbol.cs
@@ -0,0 +1,87 @@
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.Sql
4{
5 using WixToolset.Data;
6 using WixToolset.Sql.Symbols;
7
8 public static partial class SqlSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition SqlString = new IntermediateSymbolDefinition(
11 SqlSymbolDefinitionType.SqlString.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(SqlStringSymbolFields.SqlDbRef), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(SqlStringSymbolFields.ComponentRef), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(SqlStringSymbolFields.SQL), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(SqlStringSymbolFields.UserRef), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(SqlStringSymbolFields.Attributes), IntermediateFieldType.Number),
19 new IntermediateFieldDefinition(nameof(SqlStringSymbolFields.Sequence), IntermediateFieldType.Number),
20 },
21 typeof(SqlStringSymbol));
22 }
23}
24
25namespace WixToolset.Sql.Symbols
26{
27 using WixToolset.Data;
28
29 public enum SqlStringSymbolFields
30 {
31 SqlDbRef,
32 ComponentRef,
33 SQL,
34 UserRef,
35 Attributes,
36 Sequence,
37 }
38
39 public class SqlStringSymbol : IntermediateSymbol
40 {
41 public SqlStringSymbol() : base(SqlSymbolDefinitions.SqlString, null, null)
42 {
43 }
44
45 public SqlStringSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(SqlSymbolDefinitions.SqlString, sourceLineNumber, id)
46 {
47 }
48
49 public IntermediateField this[SqlStringSymbolFields index] => this.Fields[(int)index];
50
51 public string SqlDbRef
52 {
53 get => this.Fields[(int)SqlStringSymbolFields.SqlDbRef].AsString();
54 set => this.Set((int)SqlStringSymbolFields.SqlDbRef, value);
55 }
56
57 public string ComponentRef
58 {
59 get => this.Fields[(int)SqlStringSymbolFields.ComponentRef].AsString();
60 set => this.Set((int)SqlStringSymbolFields.ComponentRef, value);
61 }
62
63 public string SQL
64 {
65 get => this.Fields[(int)SqlStringSymbolFields.SQL].AsString();
66 set => this.Set((int)SqlStringSymbolFields.SQL, value);
67 }
68
69 public string UserRef
70 {
71 get => this.Fields[(int)SqlStringSymbolFields.UserRef].AsString();
72 set => this.Set((int)SqlStringSymbolFields.UserRef, value);
73 }
74
75 public int Attributes
76 {
77 get => this.Fields[(int)SqlStringSymbolFields.Attributes].AsNumber();
78 set => this.Set((int)SqlStringSymbolFields.Attributes, value);
79 }
80
81 public int? Sequence
82 {
83 get => this.Fields[(int)SqlStringSymbolFields.Sequence].AsNullableNumber();
84 set => this.Set((int)SqlStringSymbolFields.Sequence, value);
85 }
86 }
87} \ No newline at end of file
diff --git a/src/ext/Sql/wixext/Symbols/SqlSymbolDefinitions.cs b/src/ext/Sql/wixext/Symbols/SqlSymbolDefinitions.cs
new file mode 100644
index 00000000..336f1546
--- /dev/null
+++ b/src/ext/Sql/wixext/Symbols/SqlSymbolDefinitions.cs
@@ -0,0 +1,51 @@
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.Sql
4{
5 using System;
6 using WixToolset.Data;
7
8 public enum SqlSymbolDefinitionType
9 {
10 SqlDatabase,
11 SqlFileSpec,
12 SqlScript,
13 SqlString,
14 }
15
16 public static partial class SqlSymbolDefinitions
17 {
18 public static readonly Version Version = new Version("4.0.0");
19
20 public static IntermediateSymbolDefinition ByName(string name)
21 {
22 if (!Enum.TryParse(name, out SqlSymbolDefinitionType type))
23 {
24 return null;
25 }
26
27 return ByType(type);
28 }
29
30 public static IntermediateSymbolDefinition ByType(SqlSymbolDefinitionType type)
31 {
32 switch (type)
33 {
34 case SqlSymbolDefinitionType.SqlDatabase:
35 return SqlSymbolDefinitions.SqlDatabase;
36
37 case SqlSymbolDefinitionType.SqlFileSpec:
38 return SqlSymbolDefinitions.SqlFileSpec;
39
40 case SqlSymbolDefinitionType.SqlScript:
41 return SqlSymbolDefinitions.SqlScript;
42
43 case SqlSymbolDefinitionType.SqlString:
44 return SqlSymbolDefinitions.SqlString;
45
46 default:
47 throw new ArgumentOutOfRangeException(nameof(type));
48 }
49 }
50 }
51}
diff --git a/src/ext/Sql/wixext/WixToolset.Sql.wixext.csproj b/src/ext/Sql/wixext/WixToolset.Sql.wixext.csproj
new file mode 100644
index 00000000..5a1ebeb0
--- /dev/null
+++ b/src/ext/Sql/wixext/WixToolset.Sql.wixext.csproj
@@ -0,0 +1,30 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4<Project Sdk="Microsoft.NET.Sdk">
5 <PropertyGroup>
6 <TargetFramework>netstandard2.0</TargetFramework>
7 <RootNamespace>WixToolset.Sql</RootNamespace>
8 <Description>WiX Toolset Sql Extension</Description>
9 <Title>WiX Toolset Sql Extension</Title>
10 <DebugType>embedded</DebugType>
11 <IncludeSymbols>true</IncludeSymbols>
12 </PropertyGroup>
13
14 <ItemGroup>
15 <EmbeddedResource Include="$(OutputPath)..\sql.wixlib" />
16 </ItemGroup>
17
18 <ItemGroup>
19 <ProjectReference Include="..\wixlib\sql.wixproj" ReferenceOutputAssembly="false" Condition=" '$(NCrunch)'=='' " />
20 </ItemGroup>
21
22 <ItemGroup>
23 <PackageReference Include="WixToolset.Extensibility" Version="4.0.*" PrivateAssets="All" />
24 </ItemGroup>
25
26 <ItemGroup>
27 <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
28 <PackageReference Include="Nerdbank.GitVersioning" Version="3.3.37" PrivateAssets="All" />
29 </ItemGroup>
30</Project>
diff --git a/src/ext/Sql/wixext/WixToolset.Sql.wixext.nuspec b/src/ext/Sql/wixext/WixToolset.Sql.wixext.nuspec
new file mode 100644
index 00000000..ba3eaade
--- /dev/null
+++ b/src/ext/Sql/wixext/WixToolset.Sql.wixext.nuspec
@@ -0,0 +1,25 @@
1<?xml version="1.0"?>
2<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
3 <metadata minClientVersion="4.0">
4 <id>$id$</id>
5 <version>$version$</version>
6 <title>$title$</title>
7 <description>$description$</description>
8 <authors>$authors$</authors>
9 <license type="expression">MS-RL</license>
10 <requireLicenseAcceptance>false</requireLicenseAcceptance>
11 <copyright>$copyright$</copyright>
12 <projectUrl>$projectUrl$</projectUrl>
13 <repository type="$repositorytype$" url="$repositoryurl$" commit="$repositorycommit$" />
14 </metadata>
15
16 <files>
17 <file src="$projectFolder$$id$.targets" target="build" />
18
19 <file src="netstandard2.0\$id$.dll" target="tools" />
20
21 <file src="ARM64\*.pdb" target="pdbs\ARM64" />
22 <file src="x86\*.pdb" target="pdbs\x86" />
23 <file src="x64\*.pdb" target="pdbs\x64" />
24 </files>
25</package>
diff --git a/src/ext/Sql/wixext/WixToolset.Sql.wixext.targets b/src/ext/Sql/wixext/WixToolset.Sql.wixext.targets
new file mode 100644
index 00000000..4950e119
--- /dev/null
+++ b/src/ext/Sql/wixext/WixToolset.Sql.wixext.targets
@@ -0,0 +1,11 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
5 <PropertyGroup>
6 <WixToolsetSqlWixextPath Condition=" '$(WixToolsetSqlWixextPath)' == '' ">$(MSBuildThisFileDirectory)..\tools\WixToolset.Sql.wixext.dll</WixToolsetSqlWixextPath>
7 </PropertyGroup>
8 <ItemGroup>
9 <WixExtension Include="$(WixToolsetSqlWixextPath)" />
10 </ItemGroup>
11</Project>