aboutsummaryrefslogtreecommitdiff
path: root/src/dtf/WixToolset.Dtf.WindowsInstaller/TableInfo.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/dtf/WixToolset.Dtf.WindowsInstaller/TableInfo.cs264
1 files changed, 264 insertions, 0 deletions
diff --git a/src/dtf/WixToolset.Dtf.WindowsInstaller/TableInfo.cs b/src/dtf/WixToolset.Dtf.WindowsInstaller/TableInfo.cs
new file mode 100644
index 00000000..e5a850b0
--- /dev/null
+++ b/src/dtf/WixToolset.Dtf.WindowsInstaller/TableInfo.cs
@@ -0,0 +1,264 @@
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.Dtf.WindowsInstaller
4{
5 using System;
6 using System.Text;
7 using System.Collections.Generic;
8 using System.Collections.ObjectModel;
9
10 /// <summary>
11 /// Defines a table in an installation database.
12 /// </summary>
13 public class TableInfo
14 {
15 private string name;
16 private ColumnCollection columns;
17 private ReadOnlyCollection<string> primaryKeys;
18
19 /// <summary>
20 /// Creates a table definition.
21 /// </summary>
22 /// <param name="name">Name of the table.</param>
23 /// <param name="columns">Columns in the table.</param>
24 /// <param name="primaryKeys">The primary keys of the table.</param>
25 public TableInfo(string name, ICollection<ColumnInfo> columns, IList<string> primaryKeys)
26 {
27 if (String.IsNullOrEmpty(name))
28 {
29 throw new ArgumentNullException("name");
30 }
31
32 if (columns == null || columns.Count == 0)
33 {
34 throw new ArgumentNullException("columns");
35 }
36
37 if (primaryKeys == null || primaryKeys.Count == 0)
38 {
39 throw new ArgumentNullException("primaryKeys");
40 }
41
42 this.name = name;
43 this.columns = new ColumnCollection(columns);
44 this.primaryKeys = new List<string>(primaryKeys).AsReadOnly();
45 foreach (string primaryKey in this.primaryKeys)
46 {
47 if (!this.columns.Contains(primaryKey))
48 {
49 throw new ArgumentOutOfRangeException("primaryKeys");
50 }
51 }
52 }
53
54 internal TableInfo(Database db, string name)
55 {
56 if (db == null)
57 {
58 throw new ArgumentNullException("db");
59 }
60
61 if (String.IsNullOrEmpty(name))
62 {
63 throw new ArgumentNullException("name");
64 }
65
66 this.name = name;
67
68 using (View columnsView = db.OpenView("SELECT * FROM `{0}`", name))
69 {
70 this.columns = new ColumnCollection(columnsView);
71 }
72
73 this.primaryKeys = new ReadOnlyCollection<string>(
74 TableInfo.GetTablePrimaryKeys(db, name));
75 }
76
77 /// <summary>
78 /// Gets the name of the table.
79 /// </summary>
80 public string Name
81 {
82 get
83 {
84 return this.name;
85 }
86 }
87
88 /// <summary>
89 /// Gets information about the columns in this table.
90 /// </summary>
91 /// <remarks><p>
92 /// This property queries the database every time it is called,
93 /// to ensure the returned values are up-to-date. For best performance,
94 /// hold onto the returned collection if using it more than once.
95 /// </p></remarks>
96 public ColumnCollection Columns
97 {
98 get
99 {
100 return this.columns;
101 }
102 }
103
104 /// <summary>
105 /// Gets the names of the columns that are primary keys of the table.
106 /// </summary>
107 public IList<string> PrimaryKeys
108 {
109 get
110 {
111 return this.primaryKeys;
112 }
113 }
114
115 /// <summary>
116 /// Gets an SQL CREATE string that can be used to create the table.
117 /// </summary>
118 public string SqlCreateString
119 {
120 get
121 {
122 StringBuilder s = new StringBuilder("CREATE TABLE `");
123 s.Append(this.name);
124 s.Append("` (");
125 int count = 0;
126 foreach (ColumnInfo col in this.Columns)
127 {
128 if (count > 0)
129 {
130 s.Append(", ");
131 }
132 s.Append(col.SqlCreateString);
133 count++;
134 }
135 s.Append(" PRIMARY KEY ");
136 count = 0;
137 foreach (string key in this.PrimaryKeys)
138 {
139 if (count > 0)
140 {
141 s.Append(", ");
142 }
143 s.AppendFormat("`{0}`", key);
144 count++;
145 }
146 s.Append(')');
147 return s.ToString();
148 }
149 }
150
151 /// <summary>
152 /// Gets an SQL INSERT string that can be used insert a new record into the table.
153 /// </summary>
154 /// <remarks><p>
155 /// The values are expressed as question-mark tokens, to be supplied by the record.
156 /// </p></remarks>
157 public string SqlInsertString
158 {
159 get
160 {
161 StringBuilder s = new StringBuilder("INSERT INTO `");
162 s.Append(this.name);
163 s.Append("` (");
164 int count = 0;
165 foreach (ColumnInfo col in this.Columns)
166 {
167 if (count > 0)
168 {
169 s.Append(", ");
170 }
171
172 s.AppendFormat("`{0}`", col.Name);
173 count++;
174 }
175 s.Append(") VALUES (");
176 while (count > 0)
177 {
178 count--;
179 s.Append("?");
180
181 if (count > 0)
182 {
183 s.Append(", ");
184 }
185 }
186 s.Append(')');
187 return s.ToString();
188 }
189 }
190
191 /// <summary>
192 /// Gets an SQL SELECT string that can be used to select all columns of the table.
193 /// </summary>
194 /// <remarks><p>
195 /// The columns are listed explicitly in the SELECT string, as opposed to using "SELECT *".
196 /// </p></remarks>
197 public string SqlSelectString
198 {
199 get
200 {
201 StringBuilder s = new StringBuilder("SELECT ");
202 int count = 0;
203 foreach (ColumnInfo col in this.Columns)
204 {
205 if (count > 0) s.Append(", ");
206 s.AppendFormat("`{0}`", col.Name);
207 count++;
208 }
209 s.AppendFormat(" FROM `{0}`", this.Name);
210 return s.ToString();
211 }
212 }
213
214 /// <summary>
215 /// Gets a string representation of the table.
216 /// </summary>
217 /// <returns>The name of the table.</returns>
218 public override string ToString()
219 {
220 return this.name;
221 }
222
223 private static IList<string> GetTablePrimaryKeys(Database db, string table)
224 {
225 if (table == "_Tables")
226 {
227 return new string[] { "Name" };
228 }
229 else if (table == "_Columns")
230 {
231 return new string[] { "Table", "Number" };
232 }
233 else if (table == "_Storages")
234 {
235 return new string[] { "Name" };
236 }
237 else if (table == "_Streams")
238 {
239 return new string[] { "Name" };
240 }
241 else
242 {
243 int hrec;
244 uint ret = RemotableNativeMethods.MsiDatabaseGetPrimaryKeys(
245 (int) db.Handle, table, out hrec);
246 if (ret != 0)
247 {
248 throw InstallerException.ExceptionFromReturnCode(ret);
249 }
250
251 using (Record rec = new Record((IntPtr) hrec, true, null))
252 {
253 string[] keys = new string[rec.FieldCount];
254 for (int i = 0; i < keys.Length; i++)
255 {
256 keys[i] = rec.GetString(i + 1);
257 }
258
259 return keys;
260 }
261 }
262 }
263 }
264}