2007-07-24 Nagappan A <anagappan@novell.com>
[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                 bool isVariableSizeType;
50
51                 #endregion // Fields
52
53                 public TdsMetaParameter (string name, object value)
54                         : this (name, String.Empty, value)
55                 {
56                 }
57
58                 public TdsMetaParameter (string name, string typeName, object value)
59                 {
60                         ParameterName = name;
61                         Value = value;
62                         TypeName = typeName;
63                         IsNullable = false;
64                 }
65
66                 public TdsMetaParameter (string name, int size, bool isNullable, byte precision, byte scale, object value)
67                 {
68                         ParameterName = name;
69                         Size = size;
70                         IsNullable = isNullable;
71                         Precision = precision;
72                         Scale = scale;
73                         Value = value;
74                 }
75
76                 #region Properties
77
78                 public TdsParameterDirection Direction {
79                         get { return direction; }
80                         set { direction = value; }
81                 }
82
83                 public string TypeName {
84                         get { return typeName; }
85                         set { typeName = value; }
86                 }
87
88                 public string ParameterName {
89                         get { return name; }
90                         set { name = value; }
91                 }
92
93                 public bool IsNullable {
94                         get { return isNullable; }
95                         set { isNullable = value; }
96                 }
97
98                 public object Value {
99                         get { return value; }
100                         set { this.value = value; }
101                 }
102
103                 public byte Precision {
104                         get { return precision; }
105                         set { precision = value; }
106                 }
107
108                 public byte Scale {
109                         get { 
110                                 if (TypeName == "decimal" || TypeName == "numeric") {
111                                         if (scale == 0 && !Convert.IsDBNull(Value)) {
112                                                 int[] arr = Decimal.GetBits (
113                                                                 Convert.ToDecimal(Value));
114                                                 scale = (byte)((arr[3]>>16) & (int)0xFF);
115                                         }
116                                 }
117                                 return scale;
118                         }
119                         set { scale = value; }
120                 }
121
122                 public int Size {
123                         get { return GetSize (); }
124                         set {
125                                 size = value; 
126                                 isSizeSet = true;
127                         }
128                 }
129
130                 public bool IsVariableSizeType
131                 {
132                         get { return isVariableSizeType; }
133                         set { isVariableSizeType = value; }
134                 }
135
136                 #endregion // Properties
137
138                 #region Methods
139
140                 internal string Prepare ()
141                 {
142                         string typeName = TypeName;
143                         
144                         if (typeName == "varbinary") {
145                                 int size = Size;
146                                 if (size <= 0) {
147                                         size = GetActualSize ();
148                                 }
149                                 
150                                 if (size > 8000) {
151                                         typeName = "image";
152                                 }
153                         }
154                         
155                         string includeAt = "@";
156                         if (ParameterName [0] == '@')
157                                 includeAt = "";
158                         StringBuilder result = new StringBuilder (String.Format ("{0}{1} {2}", includeAt, ParameterName, typeName));
159                         switch (typeName) {
160                         case "decimal":
161                         case "numeric":
162                                 // msdotnet sends a default precision of 28
163                                 result.Append (String.Format ("({0},{1})",
164                                          (Precision == (byte)0 ? (byte)28 : Precision), Scale));
165                                 break;
166                         case "varchar":
167                         case "varbinary":
168                                 //A size of 0 is not allowed in declarations.
169                                 int size = Size;
170                                 if (size <= 0) {
171                                         size = GetActualSize ();
172                                         if (size <= 0)
173                                                 size = 1;
174                                 }
175                                 result.Append (size > 8000 ? "(max)" : String.Format ("({0})", size));
176                                 break;
177                         case "nvarchar":
178                                 result.Append (Size > 0 ? (Size > 8000 ? "(max)" : String.Format ("({0})", Size)) : "(4000)");
179                                 break;
180                         case "char":
181                         case "nchar":
182                         case "binary":
183                                 if (isSizeSet && Size > 0)
184                                         result.Append (String.Format ("({0})", Size));
185                                 break;
186                         }
187                         return result.ToString ();
188                 }
189
190                 internal int GetActualSize ()
191                 {
192                         if (Value == DBNull.Value || Value == null)
193                                 return 0;
194
195                         switch (Value.GetType ().ToString ()) {
196                         case "System.String":
197                                 int len = ((string)value).Length;
198                                 if (TypeName == "nvarchar" || TypeName == "nchar" || TypeName == "ntext")
199                                         len *= 2;
200                                 return len ;    
201                         case "System.Byte[]":
202                                 return ((byte[]) value).Length;
203                         }
204                         return GetSize ();
205                 }
206
207                 private int GetSize ()
208                 {
209                         switch (TypeName) {
210                         case "decimal":
211                                 return 17;
212                         case "uniqueidentifier":
213                                 return 16;
214                         case "bigint":
215                         case "datetime":
216                         case "float":
217                         case "money":
218                                 return 8;
219                         case "int":
220                         case "real":
221                         case "smalldatetime":
222                         case "smallmoney":
223                                 return 4;
224                         case "smallint":
225                                 return 2;
226                         case "tinyint":
227                         case "bit":
228                                 return 1;
229                         /*
230                         case "nvarchar" :
231                         */
232                         case "nchar" :
233                         case "ntext" :
234                                 return size*2 ;
235                         }
236                         return size;
237                 }
238
239                 internal byte[] GetBytes ()
240                 {
241                         byte[] result = {};
242                         if (Value == DBNull.Value || Value == null)
243                                 return result;
244
245                         switch (TypeName)
246                         {
247                                 case "nvarchar" :
248                                 case "nchar" :
249                                 case "ntext" :
250                                         return Encoding.Unicode.GetBytes ((string)Value);
251                                 case "varchar" :
252                                 case "char" :
253                                 case "text" :
254                                         return Encoding.Default.GetBytes ((string)Value);
255                                 default :
256                                         return ((byte[]) Value);
257                         }
258                 }
259
260                 internal TdsColumnType GetMetaType ()
261                 {
262                         switch (TypeName) {
263                         case "binary":
264                                 return TdsColumnType.BigBinary;
265                         case "bit":
266                                 if (IsNullable)
267                                         return TdsColumnType.BitN;
268                                 return TdsColumnType.Bit;
269                         case "bigint":
270                                 return TdsColumnType.IntN;
271                         case "char":
272                                 return TdsColumnType.Char;
273                         case "money":
274                                 if (IsNullable)
275                                         return TdsColumnType.MoneyN;
276                                 return TdsColumnType.Money;
277                         case "smallmoney":
278                                 if (IsNullable)
279                                         return TdsColumnType.MoneyN ;
280                                 return TdsColumnType.Money4;
281                         case "decimal":
282                                 return TdsColumnType.Decimal;
283                         case "datetime":
284                                 if (IsNullable)
285                                         return TdsColumnType.DateTimeN;
286                                 return TdsColumnType.DateTime;
287                         case "smalldatetime":
288                                 if (IsNullable)
289                                         return TdsColumnType.DateTimeN;
290                                 return TdsColumnType.DateTime4;
291                         case "float":
292                                 if (IsNullable)
293                                         return TdsColumnType.FloatN ;
294                                 return TdsColumnType.Float8;
295                         case "image":
296                                 return TdsColumnType.Image;
297                         case "int":
298                                 if (IsNullable)
299                                         return TdsColumnType.IntN;
300                                 return TdsColumnType.Int4;
301                         case "numeric":
302                                 return TdsColumnType.Numeric;
303                         case "nchar":
304                                 return TdsColumnType.NChar;
305                         case "ntext":
306                                 return TdsColumnType.NText;
307                         case "nvarchar":
308                                 return TdsColumnType.BigNVarChar;
309                         case "real":
310                                 if (IsNullable)
311                                         return TdsColumnType.FloatN ;
312                                 return TdsColumnType.Real;
313                         case "smallint":
314                                 if (IsNullable)
315                                         return TdsColumnType.IntN;
316                                 return TdsColumnType.Int2;
317                         case "text":
318                                 return TdsColumnType.Text;
319                         case "tinyint":
320                                 if (IsNullable)
321                                         return TdsColumnType.IntN;
322                                 return TdsColumnType.Int1;
323                         case "uniqueidentifier":
324                                 return TdsColumnType.UniqueIdentifier;
325                         case "varbinary":
326                                 return TdsColumnType.BigVarBinary;
327                         case "varchar":
328                                 return TdsColumnType.BigVarChar;
329                         default:
330                                 throw new NotSupportedException ("Unknown Type : " + TypeName);
331                         }
332                 }
333
334                 public void Validate (int index)
335                 {
336                         if ((this.direction == TdsParameterDirection.InputOutput || this.direction == TdsParameterDirection.Output) &&
337                                  this.isVariableSizeType && (Value == DBNull.Value || Value == null) && Size == 0
338                                 ) 
339                         {
340                                 throw new InvalidOperationException (String.Format ("{0}[{1}]: the Size property should " +
341                                                                                                 "not be of size 0",
342                                                                                                 this.typeName,
343                                                                                                 index));
344                         }
345                 }
346
347                 #endregion // Methods
348         }
349 }