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
41 public const int maxVarCharCharacters = 2147483647; // According to MS, max size is 2GB, 1 Byte Characters
42 public const int maxNVarCharCharacters = 1073741823; // According to MS, max size is 2GB, 2 Byte Characters
47 TdsParameterDirection direction = TdsParameterDirection.Input;
53 bool isSizeSet = false;
56 bool isVariableSizeType;
57 FrameworkValueGetter frameworkValueGetter;
63 public TdsMetaParameter (string name, object value)
64 : this (name, String.Empty, value)
68 public TdsMetaParameter (string name, FrameworkValueGetter valueGetter)
69 : this (name, String.Empty, null)
71 frameworkValueGetter = valueGetter;
74 public TdsMetaParameter (string name, string typeName, object value)
82 public TdsMetaParameter (string name, int size, bool isNullable, byte precision, byte scale, object value)
86 IsNullable = isNullable;
87 Precision = precision;
92 public TdsMetaParameter (string name, int size, bool isNullable, byte precision, byte scale, FrameworkValueGetter valueGetter)
96 IsNullable = isNullable;
97 Precision = precision;
99 frameworkValueGetter = valueGetter;
104 public TdsParameterDirection Direction {
105 get { return direction; }
106 set { direction = value; }
109 public string TypeName {
110 get { return typeName; }
111 set { typeName = value; }
114 public string ParameterName {
116 set { name = value; }
119 public bool IsNullable {
120 get { return isNullable; }
121 set { isNullable = value; }
124 public object Value {
126 if (frameworkValueGetter != null) {
127 object newValue = frameworkValueGetter (rawValue, ref isUpdated);
133 value = ResizeValue (value);
139 rawValue = this.value = value;
144 public object RawValue {
145 get { return rawValue; }
146 set { Value = value; }
149 public byte Precision {
150 get { return precision; }
151 set { precision = value; }
156 if (TypeName == "decimal" || TypeName == "numeric") {
157 if (scale == 0 && !Convert.IsDBNull(Value)) {
158 int[] arr = Decimal.GetBits (
159 Convert.ToDecimal(Value));
160 scale = (byte)((arr[3]>>16) & (int)0xFF);
165 set { scale = value; }
169 get { return GetSize (); }
177 public bool IsVariableSizeType
179 get { return isVariableSizeType; }
180 set { isVariableSizeType = value; }
183 public bool IsVarNVarCharMax
185 get { return (TypeName == "ntext" && size >= maxNVarCharCharacters); }
188 public bool IsVarCharMax
190 get { return (TypeName == "text" && size >= maxVarCharCharacters); }
193 public bool IsAnyVarCharMax
195 get { return IsVarNVarCharMax || IsVarCharMax; }
198 public bool IsNonUnicodeText
201 TdsColumnType colType = GetMetaType();
202 return (colType == TdsColumnType.VarChar ||
203 colType == TdsColumnType.BigVarChar ||
204 colType == TdsColumnType.Text ||
205 colType == TdsColumnType.Char ||
206 colType == TdsColumnType.BigChar);
210 public bool IsMoneyType
213 TdsColumnType colType = GetMetaType();
214 return (colType == TdsColumnType.Money ||
215 colType == TdsColumnType.MoneyN ||
216 colType == TdsColumnType.Money4 ||
217 colType == TdsColumnType.SmallMoney);
221 public bool IsDateTimeType
224 TdsColumnType colType = GetMetaType();
225 return (colType == TdsColumnType.DateTime ||
226 colType == TdsColumnType.DateTime4 ||
227 colType == TdsColumnType.DateTimeN);
231 public bool IsTextType
234 TdsColumnType colType = GetMetaType();
235 return (colType == TdsColumnType.VarChar ||
236 colType == TdsColumnType.BigVarChar ||
237 colType == TdsColumnType.BigChar ||
238 colType == TdsColumnType.Char ||
239 colType == TdsColumnType.BigNVarChar ||
240 colType == TdsColumnType.NChar ||
241 colType == TdsColumnType.Text ||
242 colType == TdsColumnType.NText);
246 public bool IsDecimalType
249 TdsColumnType colType = GetMetaType();
250 return (colType == TdsColumnType.Decimal ||
251 colType == TdsColumnType.Numeric);
255 #endregion // Properties
259 object ResizeValue (object newValue)
261 if (newValue == DBNull.Value || newValue == null)
264 if (!isSizeSet || size <= 0)
267 // if size is set, truncate the value to specified size
268 string text = newValue as string;
270 if (TypeName == "nvarchar" ||
271 TypeName == "nchar" ||
273 if (text.Length > size)
274 return text.Substring (0, size);
276 } else if (newValue.GetType () == typeof (byte [])) {
277 byte [] buffer = (byte []) newValue;
278 if (buffer.Length > size) {
279 byte [] tmpVal = new byte [size];
280 Array.Copy (buffer, tmpVal, size);
287 internal string Prepare ()
289 string typeName = TypeName;
291 if (typeName == "varbinary") {
294 size = GetActualSize ();
298 typeName = "varbinary(max)";
302 string includeAt = "@";
303 if (ParameterName [0] == '@')
305 StringBuilder result = new StringBuilder (String.Format ("{0}{1} {2}", includeAt, ParameterName, typeName));
309 // msdotnet sends a default precision of 29
310 result.Append (String.Format ("({0},{1})",
311 (Precision == (byte)0 ? (byte)38 : Precision), Scale));
315 //A size of 0 is not allowed in declarations.
318 size = GetActualSize ();
322 result.Append (size > 8000 ? "(max)" : String.Format ("({0})", size));
326 int paramSize = Size < 0 ? GetActualSize () / 2 : Size;
327 result.Append (paramSize > 0 ? (paramSize > 4000 ? "(max)" : String.Format ("({0})", paramSize)) : "(4000)");
332 if (isSizeSet && Size > 0)
333 result.Append (String.Format ("({0})", Size));
336 return result.ToString ();
339 internal int GetActualSize ()
341 if (Value == DBNull.Value || Value == null)
344 switch (Value.GetType ().ToString ()) {
345 case "System.String":
346 int len = ((string)value).Length;
347 if (TypeName == "nvarchar" || TypeName == "nchar"
348 || TypeName == "ntext"
349 || TypeName == "xml")
352 case "System.Byte[]":
353 return ((byte[]) value).Length;
358 private int GetSize ()
363 case "uniqueidentifier":
372 case "smalldatetime":
390 internal byte[] GetBytes ()
393 if (Value == DBNull.Value || Value == null)
402 return Encoding.Unicode.GetBytes ((string)Value);
406 return Encoding.Default.GetBytes ((string)Value);
408 return ((byte[]) Value);
412 internal TdsColumnType GetMetaType ()
416 return TdsColumnType.BigBinary;
419 return TdsColumnType.BitN;
420 return TdsColumnType.Bit;
423 return TdsColumnType.IntN ;
424 return TdsColumnType.BigInt;
426 return TdsColumnType.BigChar;
429 return TdsColumnType.MoneyN;
430 return TdsColumnType.Money;
433 return TdsColumnType.MoneyN ;
434 return TdsColumnType.SmallMoney;
436 return TdsColumnType.Decimal;
439 return TdsColumnType.DateTimeN;
440 return TdsColumnType.DateTime;
441 case "smalldatetime":
443 return TdsColumnType.DateTimeN;
444 return TdsColumnType.DateTime4;
447 return TdsColumnType.FloatN ;
448 return TdsColumnType.Float8;
450 return TdsColumnType.Image;
453 return TdsColumnType.IntN;
454 return TdsColumnType.Int4;
456 return TdsColumnType.Numeric;
458 return TdsColumnType.NChar;
460 return TdsColumnType.NText;
463 return TdsColumnType.BigNVarChar;
466 return TdsColumnType.FloatN ;
467 return TdsColumnType.Real;
470 return TdsColumnType.IntN;
471 return TdsColumnType.Int2;
473 return TdsColumnType.Text;
476 return TdsColumnType.IntN;
477 return TdsColumnType.Int1;
478 case "uniqueidentifier":
479 return TdsColumnType.UniqueIdentifier;
481 return TdsColumnType.BigVarBinary;
483 return TdsColumnType.BigVarChar;
485 throw new NotSupportedException ("Unknown Type : " + TypeName);
489 public void CalculateIsVariableType()
491 switch (GetMetaType ()) {
492 case TdsColumnType.UniqueIdentifier:
493 case TdsColumnType.BigVarChar:
494 case TdsColumnType.BigVarBinary:
495 case TdsColumnType.IntN:
496 case TdsColumnType.Text:
497 case TdsColumnType.FloatN:
498 case TdsColumnType.BigNVarChar:
499 case TdsColumnType.NText:
500 case TdsColumnType.Image:
501 case TdsColumnType.Decimal:
502 case TdsColumnType.BigBinary:
503 case TdsColumnType.DateTimeN:
504 case TdsColumnType.MoneyN:
505 case TdsColumnType.BitN:
506 case TdsColumnType.Char:
507 case TdsColumnType.BigChar:
508 case TdsColumnType.NChar:
509 IsVariableSizeType = true;
512 IsVariableSizeType = false;
517 public void Validate (int index)
519 if ((this.direction == TdsParameterDirection.InputOutput || this.direction == TdsParameterDirection.Output) &&
520 this.isVariableSizeType && (Value == DBNull.Value || Value == null) && Size == 0
523 throw new InvalidOperationException (String.Format ("{0}[{1}]: the Size property should " +
530 #endregion // Methods