aboutsummaryrefslogtreecommitdiff
path: root/src/dtf/WixToolset.Dtf.WindowsInstaller/DatabaseQuery.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/dtf/WixToolset.Dtf.WindowsInstaller/DatabaseQuery.cs412
1 files changed, 412 insertions, 0 deletions
diff --git a/src/dtf/WixToolset.Dtf.WindowsInstaller/DatabaseQuery.cs b/src/dtf/WixToolset.Dtf.WindowsInstaller/DatabaseQuery.cs
new file mode 100644
index 00000000..7c9e011e
--- /dev/null
+++ b/src/dtf/WixToolset.Dtf.WindowsInstaller/DatabaseQuery.cs
@@ -0,0 +1,412 @@
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.Collections;
7 using System.Collections.Generic;
8 using System.Globalization;
9 using System.Diagnostics.CodeAnalysis;
10
11 public partial class Database
12 {
13 /// <summary>
14 /// Gets a View object representing the query specified by a SQL string.
15 /// </summary>
16 /// <param name="sqlFormat">SQL query string, which may contain format items</param>
17 /// <param name="args">Zero or more objects to format</param>
18 /// <returns>A View object representing the query specified by a SQL string</returns>
19 /// <exception cref="BadQuerySyntaxException">the SQL syntax is invalid</exception>
20 /// <exception cref="InvalidHandleException">the Database handle is invalid</exception>
21 /// <remarks><p>
22 /// The <paramref name="sqlFormat"/> parameter is formatted using <see cref="String.Format(string,object[])"/>.
23 /// </p><p>
24 /// The View object should be <see cref="InstallerHandle.Close"/>d after use.
25 /// It is best that the handle be closed manually as soon as it is no longer
26 /// needed, as leaving lots of unused handles open can degrade performance.
27 /// </p><p>
28 /// Win32 MSI API:
29 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabaseopenview.asp">MsiDatabaseOpenView</a>
30 /// </p></remarks>
31 public View OpenView(string sqlFormat, params object[] args)
32 {
33 if (String.IsNullOrEmpty(sqlFormat))
34 {
35 throw new ArgumentNullException("sqlFormat");
36 }
37
38 string sql = (args == null || args.Length == 0 ? sqlFormat :
39 String.Format(CultureInfo.InvariantCulture, sqlFormat, args));
40 int viewHandle;
41 uint ret = RemotableNativeMethods.MsiDatabaseOpenView((int) this.Handle, sql, out viewHandle);
42 if (ret != 0)
43 {
44 throw InstallerException.ExceptionFromReturnCode(ret);
45 }
46
47 return new View((IntPtr) viewHandle, sql, this);
48 }
49
50 /// <summary>
51 /// Executes the query specified by a SQL string. The query may not be a SELECT statement.
52 /// </summary>
53 /// <param name="sqlFormat">SQL query string, which may contain format items</param>
54 /// <param name="args">Zero or more objects to format</param>
55 /// <exception cref="BadQuerySyntaxException">the SQL syntax is invalid</exception>
56 /// <exception cref="InstallerException">the View could not be executed</exception>
57 /// <exception cref="InvalidHandleException">the Database handle is invalid</exception>
58 /// <remarks><p>
59 /// The <paramref name="sqlFormat"/> parameter is formatted using
60 /// <see cref="String.Format(string,object[])"/>.
61 /// </p><p>
62 /// Win32 MSI APIs:
63 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabaseopenview.asp">MsiDatabaseOpenView</a>,
64 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewexecute.asp">MsiViewExecute</a>
65 /// </p></remarks>
66 public void Execute(string sqlFormat, params object[] args)
67 {
68 if (String.IsNullOrEmpty(sqlFormat))
69 {
70 throw new ArgumentNullException("sqlFormat");
71 }
72
73 this.Execute(
74 args == null || args.Length == 0 ?
75 sqlFormat : String.Format(CultureInfo.InvariantCulture, sqlFormat, args),
76 (Record) null);
77 }
78
79 /// <summary>
80 /// Executes the query specified by a SQL string. The query may not be a SELECT statement.
81 /// </summary>
82 /// <param name="sql">SQL query string</param>
83 /// <param name="record">Optional Record object containing the values that replace
84 /// the parameter tokens (?) in the SQL query.</param>
85 /// <exception cref="BadQuerySyntaxException">the SQL syntax is invalid</exception>
86 /// <exception cref="InstallerException">the View could not be executed</exception>
87 /// <exception cref="InvalidHandleException">the Database handle is invalid</exception>
88 /// <remarks><p>
89 /// Win32 MSI APIs:
90 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabaseopenview.asp">MsiDatabaseOpenView</a>,
91 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewexecute.asp">MsiViewExecute</a>
92 /// </p></remarks>
93 public void Execute(string sql, Record record)
94 {
95 if (String.IsNullOrEmpty(sql))
96 {
97 throw new ArgumentNullException("sql");
98 }
99
100 using (View view = this.OpenView(sql))
101 {
102 view.Execute(record);
103 }
104 }
105
106 /// <summary>
107 /// Executes the specified SQL SELECT query and returns all results.
108 /// </summary>
109 /// <param name="sqlFormat">SQL query string, which may contain format items</param>
110 /// <param name="args">Zero or more objects to format</param>
111 /// <returns>All results combined into an array</returns>
112 /// <exception cref="BadQuerySyntaxException">the SQL syntax is invalid</exception>
113 /// <exception cref="InstallerException">the View could not be executed</exception>
114 /// <exception cref="InvalidHandleException">the Database handle is invalid</exception>
115 /// <remarks><p>
116 /// The <paramref name="sqlFormat"/> parameter is formatted using
117 /// <see cref="String.Format(string,object[])"/>.
118 /// </p><p>
119 /// Multiple rows columns will be collapsed into a single one-dimensional list.
120 /// </p><p>
121 /// Win32 MSI APIs:
122 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabaseopenview.asp">MsiDatabaseOpenView</a>,
123 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewexecute.asp">MsiViewExecute</a>,
124 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewfetch.asp">MsiViewFetch</a>
125 /// </p></remarks>
126 public IList ExecuteQuery(string sqlFormat, params object[] args)
127 {
128 if (String.IsNullOrEmpty(sqlFormat))
129 {
130 throw new ArgumentNullException("sqlFormat");
131 }
132
133 return this.ExecuteQuery(
134 args == null || args.Length == 0 ?
135 sqlFormat : String.Format(CultureInfo.InvariantCulture, sqlFormat, args),
136 (Record) null);
137 }
138
139 /// <summary>
140 /// Executes the specified SQL SELECT query and returns all results.
141 /// </summary>
142 /// <param name="sql">SQL SELECT query string</param>
143 /// <param name="record">Optional Record object containing the values that replace
144 /// the parameter tokens (?) in the SQL query.</param>
145 /// <returns>All results combined into an array</returns>
146 /// <exception cref="BadQuerySyntaxException">the SQL syntax is invalid</exception>
147 /// <exception cref="InstallerException">the View could not be executed</exception>
148 /// <exception cref="InvalidHandleException">the Database handle is invalid</exception>
149 /// <remarks><p>
150 /// Multiple rows columns will be collapsed into a single one-dimensional list.
151 /// </p><p>
152 /// Win32 MSI APIs:
153 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabaseopenview.asp">MsiDatabaseOpenView</a>,
154 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewexecute.asp">MsiViewExecute</a>,
155 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewfetch.asp">MsiViewFetch</a>
156 /// </p></remarks>
157 public IList ExecuteQuery(string sql, Record record)
158 {
159 if (String.IsNullOrEmpty(sql))
160 {
161 throw new ArgumentNullException("sql");
162 }
163
164 using (View view = this.OpenView(sql))
165 {
166 view.Execute(record);
167 IList results = new ArrayList();
168 int fieldCount = 0;
169
170 foreach (Record rec in view) using (rec)
171 {
172 if (fieldCount == 0) fieldCount = rec.FieldCount;
173 for (int i = 1; i <= fieldCount; i++)
174 {
175 results.Add(rec[i]);
176 }
177 }
178
179 return results;
180 }
181 }
182
183 /// <summary>
184 /// Executes the specified SQL SELECT query and returns all results as integers.
185 /// </summary>
186 /// <param name="sqlFormat">SQL query string, which may contain format items</param>
187 /// <param name="args">Zero or more objects to format</param>
188 /// <returns>All results combined into an array</returns>
189 /// <exception cref="BadQuerySyntaxException">the SQL syntax is invalid</exception>
190 /// <exception cref="InstallerException">the View could not be executed</exception>
191 /// <exception cref="InvalidHandleException">the Database handle is invalid</exception>
192 /// <remarks><p>
193 /// The <paramref name="sqlFormat"/> parameter is formatted using
194 /// <see cref="String.Format(string,object[])"/>.
195 /// </p><p>
196 /// Multiple rows columns will be collapsed into a single one-dimensional list.
197 /// </p><p>
198 /// Win32 MSI APIs:
199 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabaseopenview.asp">MsiDatabaseOpenView</a>,
200 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewexecute.asp">MsiViewExecute</a>,
201 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewfetch.asp">MsiViewFetch</a>
202 /// </p></remarks>
203 public IList<int> ExecuteIntegerQuery(string sqlFormat, params object[] args)
204 {
205 if (String.IsNullOrEmpty(sqlFormat))
206 {
207 throw new ArgumentNullException("sqlFormat");
208 }
209
210 return this.ExecuteIntegerQuery(
211 args == null || args.Length == 0 ?
212 sqlFormat : String.Format(CultureInfo.InvariantCulture, sqlFormat, args),
213 (Record) null);
214 }
215
216 /// <summary>
217 /// Executes the specified SQL SELECT query and returns all results as integers.
218 /// </summary>
219 /// <param name="sql">SQL SELECT query string</param>
220 /// <param name="record">Optional Record object containing the values that replace
221 /// the parameter tokens (?) in the SQL query.</param>
222 /// <returns>All results combined into an array</returns>
223 /// <exception cref="BadQuerySyntaxException">the SQL syntax is invalid</exception>
224 /// <exception cref="InstallerException">the View could not be executed</exception>
225 /// <exception cref="InvalidHandleException">the Database handle is invalid</exception>
226 /// <remarks><p>
227 /// Multiple rows columns will be collapsed into a single one-dimensional list.
228 /// </p><p>
229 /// Win32 MSI APIs:
230 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabaseopenview.asp">MsiDatabaseOpenView</a>,
231 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewexecute.asp">MsiViewExecute</a>,
232 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewfetch.asp">MsiViewFetch</a>
233 /// </p></remarks>
234 public IList<int> ExecuteIntegerQuery(string sql, Record record)
235 {
236 if (String.IsNullOrEmpty(sql))
237 {
238 throw new ArgumentNullException("sql");
239 }
240
241 using (View view = this.OpenView(sql))
242 {
243 view.Execute(record);
244 IList<int> results = new List<int>();
245 int fieldCount = 0;
246
247 foreach (Record rec in view) using (rec)
248 {
249 if (fieldCount == 0) fieldCount = rec.FieldCount;
250 for (int i = 1; i <= fieldCount; i++)
251 {
252 results.Add(rec.GetInteger(i));
253 }
254 }
255
256 return results;
257 }
258 }
259
260 /// <summary>
261 /// Executes the specified SQL SELECT query and returns all results as strings.
262 /// </summary>
263 /// <param name="sqlFormat">SQL query string, which may contain format items</param>
264 /// <param name="args">Zero or more objects to format</param>
265 /// <returns>All results combined into an array</returns>
266 /// <exception cref="BadQuerySyntaxException">the SQL syntax is invalid</exception>
267 /// <exception cref="InstallerException">the View could not be executed</exception>
268 /// <exception cref="InvalidHandleException">the Database handle is invalid</exception>
269 /// <remarks><p>
270 /// The <paramref name="sqlFormat"/> parameter is formatted using
271 /// <see cref="String.Format(string,object[])"/>.
272 /// </p><p>
273 /// Multiple rows columns will be collapsed into a single on-dimensional list.
274 /// </p><p>
275 /// Win32 MSI APIs:
276 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabaseopenview.asp">MsiDatabaseOpenView</a>,
277 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewexecute.asp">MsiViewExecute</a>,
278 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewfetch.asp">MsiViewFetch</a>
279 /// </p></remarks>
280 public IList<string> ExecuteStringQuery(string sqlFormat, params object[] args)
281 {
282 if (String.IsNullOrEmpty(sqlFormat))
283 {
284 throw new ArgumentNullException("sqlFormat");
285 }
286
287 return this.ExecuteStringQuery(
288 args == null || args.Length == 0 ?
289 sqlFormat : String.Format(CultureInfo.InvariantCulture, sqlFormat, args),
290 (Record) null);
291 }
292
293 /// <summary>
294 /// Executes the specified SQL SELECT query and returns all results as strings.
295 /// </summary>
296 /// <param name="sql">SQL SELECT query string</param>
297 /// <param name="record">Optional Record object containing the values that replace
298 /// the parameter tokens (?) in the SQL query.</param>
299 /// <returns>All results combined into an array</returns>
300 /// <exception cref="BadQuerySyntaxException">the SQL syntax is invalid</exception>
301 /// <exception cref="InstallerException">the View could not be executed</exception>
302 /// <exception cref="InvalidHandleException">the Database handle is invalid</exception>
303 /// <remarks><p>
304 /// Multiple rows columns will be collapsed into a single on-dimensional list.
305 /// </p><p>
306 /// Win32 MSI APIs:
307 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabaseopenview.asp">MsiDatabaseOpenView</a>,
308 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewexecute.asp">MsiViewExecute</a>,
309 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewfetch.asp">MsiViewFetch</a>
310 /// </p></remarks>
311 public IList<string> ExecuteStringQuery(string sql, Record record)
312 {
313 if (String.IsNullOrEmpty(sql))
314 {
315 throw new ArgumentNullException("sql");
316 }
317
318 using (View view = this.OpenView(sql))
319 {
320 view.Execute(record);
321 IList<string> results = new List<string>();
322 int fieldCount = 0;
323
324 foreach (Record rec in view) using (rec)
325 {
326 if (fieldCount == 0) fieldCount = rec.FieldCount;
327 for (int i = 1; i <= fieldCount; i++)
328 {
329 results.Add(rec.GetString(i));
330 }
331 }
332
333 return results;
334 }
335 }
336
337 /// <summary>
338 /// Executes the specified SQL SELECT query and returns a single result.
339 /// </summary>
340 /// <param name="sqlFormat">SQL query string, which may contain format items</param>
341 /// <param name="args">Zero or more objects to format</param>
342 /// <returns>First field of the first result</returns>
343 /// <exception cref="BadQuerySyntaxException">the SQL syntax is invalid</exception>
344 /// <exception cref="InstallerException">the View could not be executed
345 /// or the query returned 0 results</exception>
346 /// <exception cref="InvalidHandleException">the Database handle is invalid</exception>
347 /// <remarks><p>
348 /// The <paramref name="sqlFormat"/> parameter is formatted using
349 /// <see cref="String.Format(string,object[])"/>.
350 /// </p><p>
351 /// Win32 MSI APIs:
352 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabaseopenview.asp">MsiDatabaseOpenView</a>,
353 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewexecute.asp">MsiViewExecute</a>,
354 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewfetch.asp">MsiViewFetch</a>
355 /// </p></remarks>
356 public object ExecuteScalar(string sqlFormat, params object[] args)
357 {
358 if (String.IsNullOrEmpty(sqlFormat))
359 {
360 throw new ArgumentNullException("sqlFormat");
361 }
362
363 return this.ExecuteScalar(
364 args == null || args.Length == 0 ?
365 sqlFormat : String.Format(CultureInfo.InvariantCulture, sqlFormat, args),
366 (Record) null);
367 }
368
369 /// <summary>
370 /// Executes the specified SQL SELECT query and returns a single result.
371 /// </summary>
372 /// <param name="sql">SQL SELECT query string</param>
373 /// <param name="record">Optional Record object containing the values that replace
374 /// the parameter tokens (?) in the SQL query.</param>
375 /// <returns>First field of the first result</returns>
376 /// <exception cref="BadQuerySyntaxException">the SQL syntax is invalid</exception>
377 /// <exception cref="InstallerException">the View could not be executed
378 /// or the query returned 0 results</exception>
379 /// <exception cref="InvalidHandleException">the Database handle is invalid</exception>
380 /// <remarks><p>
381 /// Win32 MSI APIs:
382 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabaseopenview.asp">MsiDatabaseOpenView</a>,
383 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewexecute.asp">MsiViewExecute</a>,
384 /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewfetch.asp">MsiViewFetch</a>
385 /// </p></remarks>
386 public object ExecuteScalar(string sql, Record record)
387 {
388 if (String.IsNullOrEmpty(sql))
389 {
390 throw new ArgumentNullException("sql");
391 }
392
393 View view = this.OpenView(sql);
394 Record rec = null;
395 try
396 {
397 view.Execute(record);
398 rec = view.Fetch();
399 if (rec == null)
400 {
401 throw InstallerException.ExceptionFromReturnCode((uint) NativeMethods.Error.NO_MORE_ITEMS);
402 }
403 return rec[1];
404 }
405 finally
406 {
407 if (rec != null) rec.Close();
408 view.Close();
409 }
410 }
411 }
412}