2 // Mono.Data.Tds.TdsMetaParameter.cs
5 // Tim Coleman (tim@timcoleman.com)
7 // Copyright (C) Tim Coleman, 2002
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:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
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.
31 using Mono.Data.Tds.Protocol;
35 namespace Mono.Data.Tds {
36 public delegate object FrameworkValueGetter (object rawValue, ref bool updated);
38 public class TdsMetaParameter
42 TdsParameterDirection direction = TdsParameterDirection.Input;
48 bool isSizeSet = false;
51 bool isVariableSizeType;
52 FrameworkValueGetter frameworkValueGetter;
58 public TdsMetaParameter (string name, object value)
59 : this (name, String.Empty, value)
63 public TdsMetaParameter (string name, FrameworkValueGetter valueGetter)
64 : this (name, String.Empty, null)
66 frameworkValueGetter = valueGetter;
69 public TdsMetaParameter (string name, string typeName, object value)
77 public TdsMetaParameter (string name, int size, bool isNullable, byte precision, byte scale, object value)
81 IsNullable = isNullable;
82 Precision = precision;
87 public TdsMetaParameter (string name, int size, bool isNullable, byte precision, byte scale, FrameworkValueGetter valueGetter)
91 IsNullable = isNullable;
92 Precision = precision;
94 frameworkValueGetter = valueGetter;
99 public TdsParameterDirection Direction {
100 get { return direction; }
101 set { direction = value; }
104 public string TypeName {
105 get { return typeName; }
106 set { typeName = value; }
109 public string ParameterName {
111 set { name = value; }
114 public bool IsNullable {
115 get { return isNullable; }
116 set { isNullable = value; }
119 public object Value {
121 if (frameworkValueGetter != null) {
122 object newValue = frameworkValueGetter (rawValue, ref isUpdated);
128 value = ResizeValue (value);
134 rawValue = this.value = value;
139 public object RawValue {
140 get { return rawValue; }
141 set { Value = value; }
144 public byte Precision {
145 get { return precision; }
146 set { precision = value; }
151 if (TypeName == "decimal" || TypeName == "numeric") {
152 if (scale == 0 && !Convert.IsDBNull(Value)) {
153 int[] arr = Decimal.GetBits (
154 Convert.ToDecimal(Value));
155 scale = (byte)((arr[3]>>16) & (int)0xFF);
160 set { scale = value; }
164 get { return GetSize (); }
172 public bool IsVariableSizeType
174 get { return isVariableSizeType; }
175 set { isVariableSizeType = value; }
178 #endregion // Properties
182 object ResizeValue (object newValue)
184 if (newValue == DBNull.Value || newValue == null)
187 if (!isSizeSet || size <= 0)
190 // if size is set, truncate the value to specified size
191 string text = newValue as string;
193 if (TypeName == "nvarchar" ||
194 TypeName == "nchar" ||
196 if (text.Length > size)
197 return text.Substring (0, size);
199 } else if (newValue.GetType () == typeof (byte [])) {
200 byte [] buffer = (byte []) newValue;
201 if (buffer.Length > size) {
202 byte [] tmpVal = new byte [size];
203 Array.Copy (buffer, tmpVal, size);
210 internal string Prepare ()
212 string typeName = TypeName;
214 if (typeName == "varbinary") {
217 size = GetActualSize ();
221 typeName = "varbinary(max)";
225 string includeAt = "@";
226 if (ParameterName [0] == '@')
228 StringBuilder result = new StringBuilder (String.Format ("{0}{1} {2}", includeAt, ParameterName, typeName));
232 // msdotnet sends a default precision of 29
233 result.Append (String.Format ("({0},{1})",
234 (Precision == (byte)0 ? (byte)38 : Precision), Scale));
238 //A size of 0 is not allowed in declarations.
241 size = GetActualSize ();
245 result.Append (size > 8000 ? "(max)" : String.Format ("({0})", size));
249 int paramSize = Size < 0 ? GetActualSize () / 2 : Size;
250 result.Append (paramSize > 0 ? (paramSize > 4000 ? "(max)" : String.Format ("({0})", paramSize)) : "(4000)");
255 if (isSizeSet && Size > 0)
256 result.Append (String.Format ("({0})", Size));
259 return result.ToString ();
262 internal int GetActualSize ()
264 if (Value == DBNull.Value || Value == null)
267 switch (Value.GetType ().ToString ()) {
268 case "System.String":
269 int len = ((string)value).Length;
270 if (TypeName == "nvarchar" || TypeName == "nchar"
271 || TypeName == "ntext"
272 || TypeName == "xml")
275 case "System.Byte[]":
276 return ((byte[]) value).Length;
281 private int GetSize ()
286 case "uniqueidentifier":
295 case "smalldatetime":
313 internal byte[] GetBytes ()
316 if (Value == DBNull.Value || Value == null)
325 return Encoding.Unicode.GetBytes ((string)Value);
329 return Encoding.Default.GetBytes ((string)Value);
331 return ((byte[]) Value);
335 internal TdsColumnType GetMetaType ()
339 return TdsColumnType.BigBinary;
342 return TdsColumnType.BitN;
343 return TdsColumnType.Bit;
346 return TdsColumnType.IntN ;
347 return TdsColumnType.BigInt;
349 return TdsColumnType.Char;
352 return TdsColumnType.MoneyN;
353 return TdsColumnType.Money;
356 return TdsColumnType.MoneyN ;
357 return TdsColumnType.Money4;
359 return TdsColumnType.Decimal;
362 return TdsColumnType.DateTimeN;
363 return TdsColumnType.DateTime;
364 case "smalldatetime":
366 return TdsColumnType.DateTimeN;
367 return TdsColumnType.DateTime4;
370 return TdsColumnType.FloatN ;
371 return TdsColumnType.Float8;
373 return TdsColumnType.Image;
376 return TdsColumnType.IntN;
377 return TdsColumnType.Int4;
379 return TdsColumnType.Numeric;
381 return TdsColumnType.NChar;
383 return TdsColumnType.NText;
386 return TdsColumnType.BigNVarChar;
389 return TdsColumnType.FloatN ;
390 return TdsColumnType.Real;
393 return TdsColumnType.IntN;
394 return TdsColumnType.Int2;
396 return TdsColumnType.Text;
399 return TdsColumnType.IntN;
400 return TdsColumnType.Int1;
401 case "uniqueidentifier":
402 return TdsColumnType.UniqueIdentifier;
404 return TdsColumnType.BigVarBinary;
406 return TdsColumnType.BigVarChar;
408 throw new NotSupportedException ("Unknown Type : " + TypeName);
412 public void Validate (int index)
414 if ((this.direction == TdsParameterDirection.InputOutput || this.direction == TdsParameterDirection.Output) &&
415 this.isVariableSizeType && (Value == DBNull.Value || Value == null) && Size == 0
418 throw new InvalidOperationException (String.Format ("{0}[{1}]: the Size property should " +
425 #endregion // Methods