[bcl] Remove ONLY_1_1 defines from class libs
[mono-project.git] / mcs / class / System.Data / System.Data.Odbc / OdbcParameter.cs
blob9b80f9b4ebcb72e17982551604cdebe589a3b8ed
1 //
2 // System.Data.Odbc.OdbcParameter
3 //
4 // Authors:
5 // Brian Ritchie (brianlritchie@hotmail.com)
6 // Sureshkumar T <tsureshkumar@novell.com> 2004.
7 //
8 // Copyright (C) Brian Ritchie, 2002
9 //
12 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 //
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 //
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System;
35 using System.Text;
36 using System.Data;
37 using System.Data.Common;
38 using System.Runtime.InteropServices;
39 using System.Globalization;
40 using System.ComponentModel;
42 namespace System.Data.Odbc
44 [TypeConverterAttribute ("System.Data.Odbc.OdbcParameter+OdbcParameterConverter, " + Consts.AssemblySystem_Data)]
45 public sealed class OdbcParameter :
46 DbParameter,
47 ICloneable, IDbDataParameter, IDataParameter
49 #region Fields
51 string name;
52 ParameterDirection direction;
53 bool isNullable;
54 int size;
55 DataRowVersion sourceVersion;
56 string sourceColumn;
57 byte _precision;
58 byte _scale;
59 object _value;
61 private OdbcTypeMap _typeMap;
62 private NativeBuffer _nativeBuffer = new NativeBuffer ();
63 private NativeBuffer _cbLengthInd;
64 private OdbcParameterCollection container;
66 #endregion
68 #region Constructors
70 public OdbcParameter ()
72 _cbLengthInd = new NativeBuffer ();
73 ParameterName = String.Empty;
74 IsNullable = false;
75 SourceColumn = String.Empty;
76 Direction = ParameterDirection.Input;
77 _typeMap = OdbcTypeConverter.GetTypeMap (OdbcType.NVarChar);
80 public OdbcParameter (string name, object value)
81 : this ()
83 this.ParameterName = name;
84 Value = value;
85 //FIXME: MS.net does not infer OdbcType from value unless a type is provided
86 _typeMap = OdbcTypeConverter.InferFromValue (value);
87 if (value != null && !value.GetType ().IsValueType) {
88 Type type = value.GetType ();
89 if (type.IsArray)
90 Size = type.GetElementType () == typeof (byte) ?
91 ((Array) value).Length : 0;
92 else
93 Size = value.ToString ().Length;
97 public OdbcParameter (string name, OdbcType type)
98 : this ()
100 this.ParameterName = name;
101 _typeMap = (OdbcTypeMap) OdbcTypeConverter.GetTypeMap (type);
104 public OdbcParameter (string name, OdbcType type, int size)
105 : this (name, type)
107 this.Size = size;
110 public OdbcParameter (string name, OdbcType type, int size, string sourcecolumn)
111 : this (name, type, size)
113 this.SourceColumn = sourcecolumn;
116 [EditorBrowsable (EditorBrowsableState.Advanced)]
117 public OdbcParameter (string parameterName, OdbcType odbcType, int size,
118 ParameterDirection parameterDirection, bool isNullable,
119 byte precision, byte scale, string srcColumn,
120 DataRowVersion srcVersion, object value)
121 : this (parameterName, odbcType, size, srcColumn)
123 this.Direction = parameterDirection;
124 this.IsNullable = isNullable;
125 this.SourceVersion = srcVersion;
128 #endregion
130 #region Properties
132 // Used to ensure that only one collection can contain this
133 // parameter
134 internal OdbcParameterCollection Container {
135 get { return container; }
136 set { container = value; }
139 [OdbcCategory ("Data")]
140 [OdbcDescriptionAttribute ("The parameter generic type")]
141 public
142 override
143 DbType DbType {
144 get { return _typeMap.DbType; }
145 set {
146 if (value == _typeMap.DbType)
147 return;
149 _typeMap = OdbcTypeConverter.GetTypeMap (value);
153 [OdbcCategory ("Data")]
154 [OdbcDescriptionAttribute ("Input, output, or bidirectional parameter")]
155 [RefreshPropertiesAttribute (RefreshProperties.All)]
156 public
157 override
158 ParameterDirection Direction {
159 get { return direction; }
160 set { direction = value; }
163 [OdbcDescriptionAttribute ("A design-time property used for strongly typed code generation")]
164 public
165 override
166 bool IsNullable {
167 get { return isNullable; }
168 set { isNullable = value; }
171 [DefaultValue (OdbcType.NChar)]
172 [OdbcDescriptionAttribute ("The parameter native type")]
173 [RefreshPropertiesAttribute (RefreshProperties.All)]
174 [OdbcCategory ("Data")]
175 [DbProviderSpecificTypeProperty (true)]
176 public OdbcType OdbcType {
177 get { return _typeMap.OdbcType; }
178 set {
179 if (value == _typeMap.OdbcType)
180 return;
182 _typeMap = OdbcTypeConverter.GetTypeMap (value);
186 [OdbcDescription ("DataParameter_ParameterName")]
187 public
188 override
189 string ParameterName {
190 get { return name; }
191 set { name = value; }
194 [OdbcDescription ("DbDataParameter_Precision")]
195 [OdbcCategory ("DataCategory_Data")]
196 [DefaultValue (0)]
197 public byte Precision {
198 get { return _precision; }
199 set { _precision = value; }
202 [OdbcDescription ("DbDataParameter_Scale")]
203 [OdbcCategory ("DataCategory_Data")]
204 [DefaultValue (0)]
205 public byte Scale {
206 get { return _scale; }
207 set { _scale = value; }
210 [OdbcDescription ("DbDataParameter_Size")]
211 [OdbcCategory ("DataCategory_Data")]
212 public
213 override
214 int Size {
215 get { return size; }
216 set { size = value; }
219 [OdbcDescription ("DataParameter_SourceColumn")]
220 [OdbcCategory ("DataCategory_Data")]
221 public
222 override
223 string SourceColumn {
224 get { return sourceColumn; }
225 set { sourceColumn = value; }
228 [OdbcDescription ("DataParameter_SourceVersion")]
229 [OdbcCategory ("DataCategory_Data")]
230 public
231 override
232 DataRowVersion SourceVersion {
233 get { return sourceVersion; }
234 set { sourceVersion = value; }
237 [TypeConverter (typeof(StringConverter))]
238 [OdbcDescription ("DataParameter_Value")]
239 [OdbcCategory ("DataCategory_Data")]
240 [RefreshPropertiesAttribute (RefreshProperties.All)]
241 public
242 override
243 object Value {
244 get { return _value; }
245 set { _value = value; }
248 #endregion // Properties
250 #region Methods
252 internal void Bind (OdbcCommand command, IntPtr hstmt, int ParamNum)
254 OdbcReturn ret;
255 int len;
257 // Convert System.Data.ParameterDirection into odbc enum
258 OdbcInputOutputDirection paramdir = libodbc.ConvertParameterDirection (this.Direction);
260 _cbLengthInd.EnsureAlloc (Marshal.SizeOf (typeof (int)));
261 if (Value is DBNull)
262 len = (int)OdbcLengthIndicator.NullData;
263 else {
264 len = GetNativeSize ();
265 AllocateBuffer ();
268 Marshal.WriteInt32 (_cbLengthInd, len);
269 ret = libodbc.SQLBindParameter (hstmt, (ushort) ParamNum, (short) paramdir,
270 _typeMap.NativeType, _typeMap.SqlType, Convert.ToUInt32 (Size),
271 0, (IntPtr) _nativeBuffer, 0, _cbLengthInd);
273 // Check for error condition
274 if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo))
275 throw command.Connection.CreateOdbcException (OdbcHandleType.Stmt, hstmt);
278 [MonoTODO]
279 object ICloneable.Clone ()
281 throw new NotImplementedException ();
284 public override string ToString ()
286 return ParameterName;
289 private int GetNativeSize ()
291 TextInfo ti = CultureInfo.InvariantCulture.TextInfo;
292 Encoding enc = Encoding.GetEncoding (ti.ANSICodePage);
294 switch (_typeMap.OdbcType) {
295 case OdbcType.Binary:
296 if (Value.GetType ().IsArray &&
297 Value.GetType ().GetElementType () == typeof (byte))
298 return ( (Array) Value).Length;
299 else
300 return Value.ToString ().Length;
301 case OdbcType.Bit:
302 return Marshal.SizeOf (typeof (byte));
303 case OdbcType.Double:
304 return Marshal.SizeOf (typeof (double));
305 case OdbcType.Real:
306 return Marshal.SizeOf (typeof (float));
307 case OdbcType.Int:
308 return Marshal.SizeOf (typeof (int));
309 case OdbcType.BigInt:
310 return Marshal.SizeOf (typeof (long));
311 case OdbcType.Decimal:
312 case OdbcType.Numeric:
313 return 19;
314 case OdbcType.SmallInt:
315 return Marshal.SizeOf (typeof (Int16));
316 case OdbcType.TinyInt:
317 return Marshal.SizeOf (typeof (byte));
318 case OdbcType.Char:
319 case OdbcType.Text:
320 case OdbcType.VarChar:
321 return enc.GetByteCount (Convert.ToString (Value)) + 1;
322 case OdbcType.NChar:
323 case OdbcType.NText:
324 case OdbcType.NVarChar:
325 // FIXME: Change to unicode
326 return enc.GetByteCount (Convert.ToString (Value)) + 1;
327 case OdbcType.VarBinary:
328 case OdbcType.Image:
329 if (Value.GetType ().IsArray &&
330 Value.GetType ().GetElementType () == typeof (byte))
331 return ((Array) Value).Length;
332 throw new ArgumentException ("Unsupported Native Type!");
333 case OdbcType.Date:
334 case OdbcType.DateTime:
335 case OdbcType.SmallDateTime:
336 case OdbcType.Time:
337 case OdbcType.Timestamp:
338 return 18;
339 case OdbcType.UniqueIdentifier:
340 return Marshal.SizeOf (typeof (Guid));
343 if (Value.GetType ().IsArray &&
344 Value.GetType ().GetElementType () == typeof (byte))
345 return ((Array) Value).Length;
347 return Value.ToString ().Length;
350 private void AllocateBuffer ()
352 int size = GetNativeSize ();
354 if (_nativeBuffer.Size == size)
355 return;
357 _nativeBuffer.AllocBuffer (size);
360 internal void CopyValue ()
362 if (_nativeBuffer.Handle == IntPtr.Zero)
363 return;
365 if (Value is DBNull)
366 return;
368 DateTime dt;
369 TextInfo ti = CultureInfo.InvariantCulture.TextInfo;
370 Encoding enc = Encoding.GetEncoding (ti.ANSICodePage);
371 byte [] nativeBytes, buffer;
373 switch (_typeMap.OdbcType) {
374 case OdbcType.Bit:
375 Marshal.WriteByte (_nativeBuffer, Convert.ToByte (Value));
376 return;
377 case OdbcType.Double:
378 Marshal.StructureToPtr (Convert.ToDouble (Value), _nativeBuffer, false);
379 return;
380 case OdbcType.Real:
381 Marshal.StructureToPtr (Convert.ToSingle (Value), _nativeBuffer, false);
382 return;
383 case OdbcType.Int:
384 Marshal.WriteInt32 (_nativeBuffer, Convert.ToInt32 (Value));
385 return;
386 case OdbcType.BigInt:
387 Marshal.WriteInt64 (_nativeBuffer, Convert.ToInt64 (Value));
388 return;
389 case OdbcType.Decimal:
390 case OdbcType.Numeric:
391 // for numeric, the buffer is a packed decimal struct.
392 // ref http://www.it-faq.pl/mskb/181/254.HTM
393 int [] bits = Decimal.GetBits (Convert.ToDecimal (Value));
394 buffer = new byte [19]; // ref sqltypes.h
395 buffer [0] = Precision;
396 buffer [1] = (byte) ((bits [3] & 0x00FF0000) >> 16); // scale
397 buffer [2] = (byte) ((bits [3] & 0x80000000) > 0 ? 2 : 1); //sign
398 Buffer.BlockCopy (bits, 0, buffer, 3, 12); // copy data
399 for (int j = 16; j < 19; j++) // pad with 0
400 buffer [j] = 0;
401 Marshal.Copy (buffer, 0, _nativeBuffer, 19);
402 return;
403 case OdbcType.SmallInt:
404 Marshal.WriteInt16 (_nativeBuffer, Convert.ToInt16 (Value));
405 return;
406 case OdbcType.TinyInt:
407 Marshal.WriteByte (_nativeBuffer, Convert.ToByte (Value));
408 return;
409 case OdbcType.Char:
410 case OdbcType.Text:
411 case OdbcType.VarChar:
412 buffer = new byte [GetNativeSize ()];
413 nativeBytes = enc.GetBytes (Convert.ToString (Value));
414 Array.Copy (nativeBytes, 0, buffer, 0, nativeBytes.Length);
415 buffer [buffer.Length-1] = (byte) 0;
416 Marshal.Copy (buffer, 0, _nativeBuffer, buffer.Length);
417 Marshal.WriteInt32 (_cbLengthInd, -3);
418 return;
419 case OdbcType.NChar:
420 case OdbcType.NText:
421 case OdbcType.NVarChar:
422 // FIXME : change to unicode
423 buffer = new byte [GetNativeSize ()];
424 nativeBytes = enc.GetBytes (Convert.ToString (Value));
425 Array.Copy (nativeBytes, 0, buffer, 0, nativeBytes.Length);
426 buffer [buffer.Length-1] = (byte) 0;
427 Marshal.Copy (buffer, 0, _nativeBuffer, buffer.Length);
428 Marshal.WriteInt32 (_cbLengthInd, -3);
429 return;
430 case OdbcType.VarBinary:
431 case OdbcType.Image:
432 case OdbcType.Binary:
433 if (Value.GetType ().IsArray &&
434 Value.GetType ().GetElementType () == typeof (byte)) {
435 Marshal.Copy ( (byte []) Value, 0, _nativeBuffer, ((byte []) Value).Length);
436 }else
437 throw new ArgumentException ("Unsupported Native Type!");
438 return;
439 case OdbcType.Date:
440 dt = (DateTime) Value;
441 Marshal.WriteInt16 (_nativeBuffer, 0, (short) dt.Year);
442 Marshal.WriteInt16 (_nativeBuffer, 2, (short) dt.Month);
443 Marshal.WriteInt16 (_nativeBuffer, 4, (short) dt.Day);
444 return;
445 case OdbcType.Time:
446 dt = (DateTime) Value;
447 Marshal.WriteInt16 (_nativeBuffer, 0, (short) dt.Hour);
448 Marshal.WriteInt16 (_nativeBuffer, 2, (short) dt.Minute);
449 Marshal.WriteInt16 (_nativeBuffer, 4, (short) dt.Second);
450 return;
451 case OdbcType.SmallDateTime:
452 case OdbcType.Timestamp:
453 case OdbcType.DateTime:
454 dt = (DateTime) Value;
455 Marshal.WriteInt16 (_nativeBuffer, 0, (short) dt.Year);
456 Marshal.WriteInt16 (_nativeBuffer, 2, (short) dt.Month);
457 Marshal.WriteInt16 (_nativeBuffer, 4, (short) dt.Day);
458 Marshal.WriteInt16 (_nativeBuffer, 6, (short) dt.Hour);
459 Marshal.WriteInt16 (_nativeBuffer, 8, (short) dt.Minute);
460 Marshal.WriteInt16 (_nativeBuffer, 10, (short) dt.Second);
461 Marshal.WriteInt32 (_nativeBuffer, 12, (int) (dt.Ticks % 10000000) * 100);
462 return;
463 case OdbcType.UniqueIdentifier:
464 throw new NotImplementedException ();
467 if (Value.GetType ().IsArray &&
468 Value.GetType ().GetElementType () == typeof (byte)) {
469 Marshal.Copy ( (byte []) Value, 0, _nativeBuffer, ((byte []) Value).Length);
470 }else
471 throw new ArgumentException ("Unsupported Native Type!");
474 public override bool SourceColumnNullMapping {
475 get { return false; }
476 set { }
479 public override void ResetDbType ()
481 _typeMap = OdbcTypeConverter.GetTypeMap (OdbcType.NVarChar);
484 public void ResetOdbcType ()
486 _typeMap = OdbcTypeConverter.GetTypeMap (OdbcType.NVarChar);
489 #endregion