* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / Mono.Data.Tds / Mono.Data.Tds / TdsMetaParameter.cs
1 //
2 // Mono.Data.Tds.TdsMetaParameter.cs
3 //
4 // Author:
5 //   Tim Coleman (tim@timcoleman.com)
6 //
7 // Copyright (C) Tim Coleman, 2002
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using Mono.Data.Tds.Protocol;
32 using System;
33 using System.Text;
34
35 namespace Mono.Data.Tds {
36         public class TdsMetaParameter
37         {
38                 #region Fields
39
40                 TdsParameterDirection direction = TdsParameterDirection.Input;
41                 byte precision;
42                 byte scale;
43                 int size;
44                 string typeName;
45                 string name;
46                 bool isSizeSet = false;
47                 bool isNullable;
48                 object value;
49
50                 #endregion // Fields
51
52                 public TdsMetaParameter (string name, object value)
53                         : this (name, String.Empty, value)
54                 {
55                 }
56
57                 public TdsMetaParameter (string name, string typeName, object value)
58                 {
59                         ParameterName = name;
60                         Value = value;
61                         TypeName = typeName;
62                         IsNullable = false;
63                 }
64
65                 public TdsMetaParameter (string name, int size, bool isNullable, byte precision, byte scale, object value)
66                 {
67                         ParameterName = name;
68                         Size = size;
69                         IsNullable = isNullable;
70                         Precision = precision;
71                         Scale = scale;
72                         Value = value;
73                 }
74
75                 #region Properties
76
77                 public TdsParameterDirection Direction {
78                         get { return direction; }
79                         set { direction = value; }
80                 }
81
82                 public string TypeName {
83                         get { return typeName; }
84                         set { typeName = value; }
85                 }
86
87                 public string ParameterName {
88                         get { return name; }
89                         set { name = value; }
90                 }
91
92                 public bool IsNullable {
93                         get { return isNullable; }
94                         set { isNullable = value; }
95                 }
96
97                 public object Value {
98                         get { return value; }
99                         set { this.value = value; }
100                 }
101
102                 public byte Precision {
103                         get { return precision; }
104                         set { precision = value; }
105                 }
106
107                 public byte Scale {
108                         get { 
109                                 if (TypeName == "decimal" || TypeName == "numeric") {
110                                         if (scale == 0 && !Convert.IsDBNull(Value)) {
111                                                 int[] arr = Decimal.GetBits (
112                                                                 Convert.ToDecimal(Value));
113                                                 scale = (byte)((arr[3]>>16) & (int)0xFF);
114                                         }
115                                 }
116                                 return scale;
117                         }
118                         set { scale = value; }
119                 }
120
121                 public int Size {
122                         get { return GetSize (); }
123                         set {
124                                 size = value; 
125                                 isSizeSet = true;
126                         }
127                 }
128
129                 #endregion // Properties
130
131                 #region Methods
132
133                 internal string Prepare ()
134                 {
135                         string typeName = TypeName;
136                         
137                         if (typeName == "varbinary") {
138                                 int size = Size;
139                                 if (size <= 0) {
140                                         size = GetActualSize ();
141                                 }
142                                 
143                                 if (size > 8000) {
144                                         typeName = "image";
145                                 }
146                         }
147                         
148                         StringBuilder result = new StringBuilder (String.Format ("{0} {1}", ParameterName, typeName));
149                         switch (typeName) {
150                         case "decimal":
151                         case "numeric":
152                                 // msdotnet sends a default precision of 28
153                                 result.Append (String.Format ("({0},{1})",
154                                          (Precision == (byte)0 ? (byte)28 : Precision), Scale));
155                                 break;
156                         case "varchar":
157                         case "varbinary":
158                                 //A size of 0 is not allowed in declarations.
159                                 int size = Size;
160                                 if (size <= 0) {
161                                         size = GetActualSize ();
162                                         if (size <= 0)
163                                                 size = 1;
164                                 }
165                                 result.Append (String.Format ("({0})", size));
166                                 break;
167                         case "nvarchar":
168                                 result.Append (String.Format ("({0})", Size > 0 ? Size : 4000));
169                                 break;
170                         case "char":
171                         case "nchar":
172                         case "binary":
173                                 if (isSizeSet && Size > 0)
174                                         result.Append (String.Format ("({0})", Size));
175                                 break;
176                         }
177                         return result.ToString ();
178                 }
179
180                 internal int GetActualSize ()
181                 {
182                         if (Value == DBNull.Value || Value == null)
183                                 return 0;
184
185                         switch (Value.GetType ().ToString ()) {
186                         case "System.String":
187                                 return ((string) value).Length;
188                         case "System.Byte[]":
189                                 return ((byte[]) value).Length;
190                         }
191                         return GetSize ();
192                 }
193
194                 private int GetSize ()
195                 {
196                         if (IsNullable) {
197                                 switch (TypeName) {
198                                 case "bigint":
199                                         return 8;
200                                 case "datetime":
201                                         return 8;
202                                 case "float":
203                                         return 8;
204                                 case "int":
205                                         return 4;
206                                 case "real":
207                                         return 4;
208                                 case "smalldatetime":
209                                         return 4;
210                                 case "smallint":
211                                         return 2;
212                                 case "tinyint":
213                                         return 1;
214                                 }
215                         }
216                         return size;
217                 }
218
219                 internal TdsColumnType GetMetaType ()
220                 {
221                         switch (TypeName) {
222                         case "binary":
223                                 return TdsColumnType.Binary;
224                         case "bit":
225                                 return TdsColumnType.Bit;
226                         case "char":
227                                 return TdsColumnType.Char;
228                         case "decimal":
229                                 return TdsColumnType.Decimal;
230                         case "datetime":
231                                 if (IsNullable)
232                                         return TdsColumnType.DateTimeN;
233                                 return TdsColumnType.DateTime;
234                         case "float":
235                                 return TdsColumnType.Float8;
236                         case "image":
237                                 return TdsColumnType.Image;
238                         case "int":
239                                 if (IsNullable)
240                                         return TdsColumnType.IntN;
241                                 return TdsColumnType.Int4;
242                         case "numeric":
243                                 return TdsColumnType.Numeric;
244                         case "nchar":
245                                 return TdsColumnType.NChar;
246                         case "ntext":
247                                 return TdsColumnType.NText;
248                         case "nvarchar":
249                                 return TdsColumnType.NVarChar;
250                         case "real":
251                                 return TdsColumnType.Real;
252                         case "smallint":
253                                 if (IsNullable)
254                                         return TdsColumnType.IntN;
255                                 return TdsColumnType.Int2;
256                         case "text":
257                                 return TdsColumnType.Text;
258                         case "tinyint":
259                                 if (IsNullable)
260                                         return TdsColumnType.IntN;
261                                 return TdsColumnType.Int1;
262                         case "uniqueidentifier":
263                                 return TdsColumnType.UniqueIdentifier;
264                         case "varbinary":
265                                 return TdsColumnType.VarBinary;
266                         case "varchar":
267                                 return TdsColumnType.VarChar;
268                         default:
269                                 throw new NotSupportedException ();
270                         }
271                 }
272
273                 #endregion // Methods
274         }
275 }