diff options
Diffstat (limited to 'src/dtf/WixToolset.Dtf.WindowsInstaller/ColumnInfo.cs')
-rw-r--r-- | src/dtf/WixToolset.Dtf.WindowsInstaller/ColumnInfo.cs | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/src/dtf/WixToolset.Dtf.WindowsInstaller/ColumnInfo.cs b/src/dtf/WixToolset.Dtf.WindowsInstaller/ColumnInfo.cs new file mode 100644 index 00000000..43363230 --- /dev/null +++ b/src/dtf/WixToolset.Dtf.WindowsInstaller/ColumnInfo.cs | |||
@@ -0,0 +1,297 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Dtf.WindowsInstaller | ||
4 | { | ||
5 | using System; | ||
6 | using System.IO; | ||
7 | using System.Text; | ||
8 | using System.Globalization; | ||
9 | using System.Diagnostics.CodeAnalysis; | ||
10 | |||
11 | /// <summary> | ||
12 | /// Defines a single column of a table in an installer database. | ||
13 | /// </summary> | ||
14 | /// <remarks>Once created, a ColumnInfo object is immutable.</remarks> | ||
15 | public class ColumnInfo | ||
16 | { | ||
17 | private string name; | ||
18 | private Type type; | ||
19 | private int size; | ||
20 | private bool isRequired; | ||
21 | private bool isTemporary; | ||
22 | private bool isLocalizable; | ||
23 | |||
24 | /// <summary> | ||
25 | /// Creates a new ColumnInfo object from a column definition. | ||
26 | /// </summary> | ||
27 | /// <param name="name">name of the column</param> | ||
28 | /// <param name="columnDefinition">column definition string</param> | ||
29 | /// <seealso cref="ColumnDefinitionString"/> | ||
30 | public ColumnInfo(string name, string columnDefinition) | ||
31 | : this(name, typeof(String), 0, false, false, false) | ||
32 | { | ||
33 | if (name == null) | ||
34 | { | ||
35 | throw new ArgumentNullException("name"); | ||
36 | } | ||
37 | |||
38 | if (columnDefinition == null) | ||
39 | { | ||
40 | throw new ArgumentNullException("columnDefinition"); | ||
41 | } | ||
42 | |||
43 | switch (Char.ToLower(columnDefinition[0], CultureInfo.InvariantCulture)) | ||
44 | { | ||
45 | case 'i': this.type = typeof(Int32); | ||
46 | break; | ||
47 | case 'j': this.type = typeof(Int32); this.isTemporary = true; | ||
48 | break; | ||
49 | case 'g': this.type = typeof(String); this.isTemporary = true; | ||
50 | break; | ||
51 | case 'l': this.type = typeof(String); this.isLocalizable = true; | ||
52 | break; | ||
53 | case 'o': this.type = typeof(Stream); this.isTemporary = true; | ||
54 | break; | ||
55 | case 's': this.type = typeof(String); | ||
56 | break; | ||
57 | case 'v': this.type = typeof(Stream); | ||
58 | break; | ||
59 | default: throw new InstallerException(); | ||
60 | } | ||
61 | |||
62 | this.isRequired = Char.IsLower(columnDefinition[0]); | ||
63 | this.size = Int32.Parse( | ||
64 | columnDefinition.Substring(1), | ||
65 | CultureInfo.InvariantCulture.NumberFormat); | ||
66 | if (this.type == typeof(Int32) && this.size <= 2) | ||
67 | { | ||
68 | this.type = typeof(Int16); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | /// <summary> | ||
73 | /// Creates a new ColumnInfo object from a list of parameters. | ||
74 | /// </summary> | ||
75 | /// <param name="name">name of the column</param> | ||
76 | /// <param name="type">type of the column; must be one of the following: | ||
77 | /// Int16, Int32, String, or Stream</param> | ||
78 | /// <param name="size">the maximum number of characters for String columns; | ||
79 | /// ignored for other column types</param> | ||
80 | /// <param name="isRequired">true if the column is required to have a non-null value</param> | ||
81 | public ColumnInfo(string name, Type type, int size, bool isRequired) | ||
82 | : this(name, type, size, isRequired, false, false) | ||
83 | { | ||
84 | } | ||
85 | |||
86 | /// <summary> | ||
87 | /// Creates a new ColumnInfo object from a list of parameters. | ||
88 | /// </summary> | ||
89 | /// <param name="name">name of the column</param> | ||
90 | /// <param name="type">type of the column; must be one of the following: | ||
91 | /// Int16, Int32, String, or Stream</param> | ||
92 | /// <param name="size">the maximum number of characters for String columns; | ||
93 | /// ignored for other column types</param> | ||
94 | /// <param name="isRequired">true if the column is required to have a non-null value</param> | ||
95 | /// <param name="isTemporary">true to if the column is only in-memory and | ||
96 | /// not persisted with the database</param> | ||
97 | /// <param name="isLocalizable">for String columns, indicates the column | ||
98 | /// is localizable; ignored for other column types</param> | ||
99 | public ColumnInfo(string name, Type type, int size, bool isRequired, bool isTemporary, bool isLocalizable) | ||
100 | { | ||
101 | if (name == null) | ||
102 | { | ||
103 | throw new ArgumentNullException("name"); | ||
104 | } | ||
105 | |||
106 | if (type == typeof(Int32)) | ||
107 | { | ||
108 | size = 4; | ||
109 | isLocalizable = false; | ||
110 | } | ||
111 | else if (type == typeof(Int16)) | ||
112 | { | ||
113 | size = 2; | ||
114 | isLocalizable = false; | ||
115 | } | ||
116 | else if (type == typeof(String)) | ||
117 | { | ||
118 | } | ||
119 | else if (type == typeof(Stream)) | ||
120 | { | ||
121 | isLocalizable = false; | ||
122 | } | ||
123 | else | ||
124 | { | ||
125 | throw new ArgumentOutOfRangeException("type"); | ||
126 | } | ||
127 | |||
128 | this.name = name; | ||
129 | this.type = type; | ||
130 | this.size = size; | ||
131 | this.isRequired = isRequired; | ||
132 | this.isTemporary = isTemporary; | ||
133 | this.isLocalizable = isLocalizable; | ||
134 | } | ||
135 | |||
136 | /// <summary> | ||
137 | /// Gets the name of the column. | ||
138 | /// </summary> | ||
139 | /// <value>name of the column</value> | ||
140 | public string Name | ||
141 | { | ||
142 | get { return this.name; } | ||
143 | } | ||
144 | |||
145 | /// <summary> | ||
146 | /// Gets the type of the column as a System.Type. This is one of the following: Int16, Int32, String, or Stream | ||
147 | /// </summary> | ||
148 | /// <value>type of the column</value> | ||
149 | [SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")] | ||
150 | public Type Type | ||
151 | { | ||
152 | get { return this.type; } | ||
153 | } | ||
154 | |||
155 | /// <summary> | ||
156 | /// Gets the type of the column as an integer that can be cast to a System.Data.DbType. This is one of the following: Int16, Int32, String, or Binary | ||
157 | /// </summary> | ||
158 | /// <value>equivalent DbType of the column as an integer</value> | ||
159 | public int DBType | ||
160 | { | ||
161 | get | ||
162 | { | ||
163 | if (this.type == typeof(Int16)) return 10; | ||
164 | else if (this.type == typeof(Int32)) return 11; | ||
165 | else if (this.type == typeof(Stream)) return 1; | ||
166 | else return 16; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | /// <summary> | ||
171 | /// Gets the size of the column. | ||
172 | /// </summary> | ||
173 | /// <value>The size of integer columns this is either 2 or 4. For string columns this is the maximum | ||
174 | /// recommended length of the string, or 0 for unlimited length. For stream columns, 0 is returned.</value> | ||
175 | public int Size | ||
176 | { | ||
177 | get { return this.size; } | ||
178 | } | ||
179 | |||
180 | /// <summary> | ||
181 | /// Gets a value indicating whether the column must be non-null when inserting a record. | ||
182 | /// </summary> | ||
183 | /// <value>required status of the column</value> | ||
184 | public bool IsRequired | ||
185 | { | ||
186 | get { return this.isRequired; } | ||
187 | } | ||
188 | |||
189 | /// <summary> | ||
190 | /// Gets a value indicating whether the column is temporary. Temporary columns are not persisted | ||
191 | /// when the database is saved to disk. | ||
192 | /// </summary> | ||
193 | /// <value>temporary status of the column</value> | ||
194 | public bool IsTemporary | ||
195 | { | ||
196 | get { return this.isTemporary; } | ||
197 | } | ||
198 | |||
199 | /// <summary> | ||
200 | /// Gets a value indicating whether the column is a string column that is localizable. | ||
201 | /// </summary> | ||
202 | /// <value>localizable status of the column</value> | ||
203 | public bool IsLocalizable | ||
204 | { | ||
205 | get { return this.isLocalizable; } | ||
206 | } | ||
207 | |||
208 | /// <summary> | ||
209 | /// Gets an SQL fragment that can be used to create this column within a CREATE TABLE statement. | ||
210 | /// </summary> | ||
211 | /// <value>SQL fragment to be used for creating the column</value> | ||
212 | /// <remarks><p> | ||
213 | /// Examples: | ||
214 | /// <list type="bullet"> | ||
215 | /// <item>LONG</item> | ||
216 | /// <item>SHORT TEMPORARY</item> | ||
217 | /// <item>CHAR(0) LOCALIZABLE</item> | ||
218 | /// <item>CHAR(72) NOT NULL LOCALIZABLE</item> | ||
219 | /// <item>OBJECT</item> | ||
220 | /// </list> | ||
221 | /// </p></remarks> | ||
222 | public string SqlCreateString | ||
223 | { | ||
224 | get | ||
225 | { | ||
226 | StringBuilder s = new StringBuilder(); | ||
227 | s.AppendFormat("`{0}` ", this.name); | ||
228 | if (this.type == typeof(Int16)) s.Append("SHORT"); | ||
229 | else if (this.type == typeof(Int32)) s.Append("LONG"); | ||
230 | else if (this.type == typeof(String)) s.AppendFormat("CHAR({0})", this.size); | ||
231 | else s.Append("OBJECT"); | ||
232 | if (this.isRequired) s.Append(" NOT NULL"); | ||
233 | if (this.isTemporary) s.Append(" TEMPORARY"); | ||
234 | if (this.isLocalizable) s.Append(" LOCALIZABLE"); | ||
235 | return s.ToString(); | ||
236 | } | ||
237 | } | ||
238 | |||
239 | /// <summary> | ||
240 | /// Gets a short string defining the type and size of the column. | ||
241 | /// </summary> | ||
242 | /// <value> | ||
243 | /// The definition string consists | ||
244 | /// of a single letter representing the data type followed by the width of the column (in characters | ||
245 | /// when applicable, bytes otherwise). A width of zero designates an unbounded width (for example, | ||
246 | /// long text fields and streams). An uppercase letter indicates that null values are allowed in | ||
247 | /// the column. | ||
248 | /// </value> | ||
249 | /// <remarks><p> | ||
250 | /// <list> | ||
251 | /// <item>s? - String, variable length (?=1-255)</item> | ||
252 | /// <item>s0 - String, variable length</item> | ||
253 | /// <item>i2 - Short integer</item> | ||
254 | /// <item>i4 - Long integer</item> | ||
255 | /// <item>v0 - Binary Stream</item> | ||
256 | /// <item>g? - Temporary string (?=0-255)</item> | ||
257 | /// <item>j? - Temporary integer (?=0,1,2,4)</item> | ||
258 | /// <item>O0 - Temporary object (stream)</item> | ||
259 | /// <item>l? - Localizable string, variable length (?=1-255)</item> | ||
260 | /// <item>l0 - Localizable string, variable length</item> | ||
261 | /// </list> | ||
262 | /// </p></remarks> | ||
263 | public string ColumnDefinitionString | ||
264 | { | ||
265 | get | ||
266 | { | ||
267 | char t; | ||
268 | if (this.type == typeof(Int16) || this.type == typeof(Int32)) | ||
269 | { | ||
270 | t = (this.isTemporary ? 'j' : 'i'); | ||
271 | } | ||
272 | else if (this.type == typeof(String)) | ||
273 | { | ||
274 | t = (this.isTemporary ? 'g' : this.isLocalizable ? 'l' : 's'); | ||
275 | } | ||
276 | else | ||
277 | { | ||
278 | t = (this.isTemporary ? 'O' : 'v'); | ||
279 | } | ||
280 | return String.Format( | ||
281 | CultureInfo.InvariantCulture, | ||
282 | "{0}{1}", | ||
283 | (this.isRequired ? t : Char.ToUpper(t, CultureInfo.InvariantCulture)), | ||
284 | this.size); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | /// <summary> | ||
289 | /// Gets the name of the column. | ||
290 | /// </summary> | ||
291 | /// <returns>Name of the column.</returns> | ||
292 | public override string ToString() | ||
293 | { | ||
294 | return this.Name; | ||
295 | } | ||
296 | } | ||
297 | } | ||