2 // System.Data.Odbc.OdbcParameter
5 // Brian Ritchie (brianlritchie@hotmail.com)
6 // Sureshkumar T <tsureshkumar@novell.com> 2004.
8 // Copyright (C) Brian Ritchie, 2002
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:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
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.
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 (typeof (OdbcParameterConverter))]
46 public sealed class OdbcParameter : DbParameter, ICloneable
48 public sealed class OdbcParameter : MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable
54 ParameterDirection direction;
57 DataRowVersion sourceVersion;
63 private OdbcTypeMap _typeMap;
64 private NativeBuffer _nativeBuffer = new NativeBuffer ();
65 private NativeBuffer _cbLengthInd;
66 private OdbcParameterCollection container = null;
72 public OdbcParameter ()
74 _cbLengthInd = new NativeBuffer ();
75 ParameterName = String.Empty;
77 SourceColumn = String.Empty;
78 Direction = ParameterDirection.Input;
79 _typeMap = OdbcTypeConverter.GetTypeMap (OdbcType.VarChar);
82 public OdbcParameter (string name, object value)
85 this.ParameterName = name;
87 _typeMap = OdbcTypeConverter.InferFromValue (value);
88 if (value != null && !value.GetType ().IsValueType) {
89 Type type = value.GetType ();
91 Size = type.GetElementType () == typeof (byte) ?
92 ((Array) value).Length : 0;
94 Size = value.ToString ().Length;
98 public OdbcParameter (string name, OdbcType odbcType)
101 this.ParameterName = name;
102 _typeMap = (OdbcTypeMap) OdbcTypeConverter.GetTypeMap (odbcType);
105 public OdbcParameter (string name, OdbcType odbcType, int size)
106 : this (name, odbcType)
111 public OdbcParameter (string name, OdbcType odbcType, int size, string srcColumn)
112 : this (name, odbcType, size)
114 this.SourceColumn = srcColumn;
117 [EditorBrowsable (EditorBrowsableState.Advanced)]
118 public OdbcParameter(string name, OdbcType odbcType, int size,
119 ParameterDirection direction, bool isNullable,
120 byte precision, byte scale, string srcColumn,
121 DataRowVersion srcVersion, object value)
122 : this (name, odbcType, size, srcColumn)
124 this.Direction = direction;
125 this.IsNullable = isNullable;
126 this.SourceVersion = srcVersion;
133 // Used to ensure that only one collection can contain this
135 internal OdbcParameterCollection Container {
136 get { return container; }
137 set { container = value; }
140 [BrowsableAttribute (false)]
141 [OdbcDescriptionAttribute ("The parameter generic type")]
142 [RefreshPropertiesAttribute (RefreshProperties.All)]
143 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
144 [OdbcCategory ("Data")]
150 get { return _typeMap.DbType; }
152 if (value == _typeMap.DbType)
155 _typeMap = OdbcTypeConverter.GetTypeMap (value);
159 [OdbcCategory ("Data")]
160 [OdbcDescriptionAttribute ("Input, output, or bidirectional parameter")]
161 [DefaultValue (ParameterDirection.Input)]
166 ParameterDirection Direction {
167 get { return direction; }
168 set { direction = value; }
171 [BrowsableAttribute (false)]
172 [OdbcDescriptionAttribute ("A design-time property used for strongly typed code generation")]
173 [DesignOnlyAttribute (true)]
174 [EditorBrowsableAttribute (EditorBrowsableState.Advanced)]
175 [DefaultValue (false)]
181 get { return isNullable; }
182 set { isNullable = value; }
186 [DefaultValue (OdbcType.NChar)]
187 [OdbcDescriptionAttribute ("The parameter native type")]
188 [RefreshPropertiesAttribute (RefreshProperties.All)]
189 [OdbcCategory ("Data")]
190 public OdbcType OdbcType {
191 get { return _typeMap.OdbcType; }
193 if (value == OdbcType)
196 _typeMap = OdbcTypeConverter.GetTypeMap (value);
200 [OdbcDescription ("DataParameter_ParameterName")]
206 string ParameterName {
208 set { name = value; }
211 [OdbcDescription ("DbDataParameter_Precision")]
212 [OdbcCategory ("DataCategory_Data")]
214 public byte Precision {
215 get { return _precision; }
216 set { _precision = value; }
219 [OdbcDescription ("DbDataParameter_Scale")]
220 [OdbcCategory ("DataCategory_Data")]
223 get { return _scale; }
224 set { _scale = value; }
227 [OdbcDescription ("DbDataParameter_Size")]
228 [OdbcCategory ("DataCategory_Data")]
236 set { size = value; }
239 [OdbcDescription ("DataParameter_SourceColumn")]
240 [OdbcCategory ("DataCategory_Data")]
246 string SourceColumn {
247 get { return sourceColumn; }
248 set { sourceColumn = value; }
251 [OdbcDescription ("DataParameter_SourceVersion")]
252 [OdbcCategory ("DataCategory_Data")]
253 [DefaultValue ("Current")]
258 DataRowVersion SourceVersion {
259 get { return sourceVersion; }
260 set { sourceVersion = value; }
263 [TypeConverter (typeof(StringConverter))]
264 [OdbcDescription ("DataParameter_Value")]
265 [OdbcCategory ("DataCategory_Data")]
266 [DefaultValue (null)]
280 #endregion // Properties
284 internal void Bind(IntPtr hstmt, int ParamNum) {
287 // Convert System.Data.ParameterDirection into odbc enum
288 OdbcInputOutputDirection paramdir = libodbc.ConvertParameterDirection(this.Direction);
290 _cbLengthInd.EnsureAlloc (Marshal.SizeOf (typeof (int)));
291 Marshal.WriteInt32 (_cbLengthInd, GetNativeSize ());
293 ret = libodbc.SQLBindParameter(hstmt, (ushort) ParamNum, (short) paramdir,
294 _typeMap.NativeType, _typeMap.SqlType, Convert.ToUInt32(Size),
295 0, (IntPtr) _nativeBuffer, 0, _cbLengthInd);
297 // Check for error condition
298 if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo))
299 throw new OdbcException(new OdbcError("SQLBindParam", OdbcHandleType.Stmt, hstmt));
303 object ICloneable.Clone ()
305 throw new NotImplementedException ();
308 public override string ToString ()
310 return ParameterName;
313 private int GetNativeSize ()
315 TextInfo ti = CultureInfo.InvariantCulture.TextInfo;
316 Encoding enc = Encoding.GetEncoding (ti.ANSICodePage);
318 switch (_typeMap.OdbcType) {
319 case OdbcType.Binary:
320 if (Value.GetType ().IsArray &&
321 Value.GetType ().GetElementType () == typeof (byte))
322 return ( (Array) Value).Length;
324 return Value.ToString ().Length;
326 return Marshal.SizeOf (typeof (byte));
327 case OdbcType.Double:
328 return Marshal.SizeOf (typeof (double));
330 return Marshal.SizeOf (typeof (float));
332 return Marshal.SizeOf (typeof (int));
333 case OdbcType.BigInt:
334 return Marshal.SizeOf (typeof (long));
335 case OdbcType.Decimal:
336 case OdbcType.Numeric:
338 case OdbcType.SmallInt:
339 return Marshal.SizeOf (typeof (Int16));
340 case OdbcType.TinyInt:
341 return Marshal.SizeOf (typeof (byte));
344 case OdbcType.VarChar:
345 return enc.GetByteCount (Convert.ToString (Value)) + 1;
348 case OdbcType.NVarChar:
349 // FIXME: Change to unicode
350 return enc.GetByteCount (Convert.ToString (Value)) + 1;
351 case OdbcType.VarBinary:
353 if (Value.GetType ().IsArray &&
354 Value.GetType ().GetElementType () == typeof (byte))
355 return ( (Array) Value).Length;
356 throw new ArgumentException ("Unsupported Native Type!");
358 case OdbcType.DateTime:
359 case OdbcType.SmallDateTime:
361 case OdbcType.Timestamp:
363 case OdbcType.UniqueIdentifier:
364 return Marshal.SizeOf (typeof (Guid));
367 if (Value.GetType ().IsArray &&
368 Value.GetType ().GetElementType () == typeof (byte))
369 return ( (Array) Value).Length;
371 return Value.ToString ().Length;
374 private void AllocateBuffer ()
376 int size = GetNativeSize ();
378 if (_nativeBuffer.Size == size)
381 _nativeBuffer.AllocBuffer (size);
384 internal void CopyValue ()
386 if (_nativeBuffer.Handle == IntPtr.Zero)
390 TextInfo ti = CultureInfo.InvariantCulture.TextInfo;
391 Encoding enc = Encoding.GetEncoding (ti.ANSICodePage);
392 byte [] nativeBytes, buffer;
394 switch (_typeMap.OdbcType) {
395 case OdbcType.Binary:
396 throw new NotImplementedException ();
398 Marshal.WriteByte (_nativeBuffer, Convert.ToByte (Value));
400 case OdbcType.Double:
401 Marshal.StructureToPtr (Convert.ToDouble (Value), _nativeBuffer, false);
404 Marshal.StructureToPtr (Convert.ToSingle (Value), _nativeBuffer, false);
407 Marshal.WriteInt32 (_nativeBuffer, Convert.ToInt32 (Value));
409 case OdbcType.BigInt:
410 Marshal.WriteInt64 (_nativeBuffer, Convert.ToInt64 (Value));
412 case OdbcType.Decimal:
413 case OdbcType.Numeric:
414 // for numeric, the buffer is a packed decimal struct.
415 // ref http://www.it-faq.pl/mskb/181/254.HTM
416 int [] bits = Decimal.GetBits (Convert.ToDecimal (Value));
417 buffer = new byte [19]; // ref sqltypes.h
418 buffer [0] = Precision;
419 buffer [1] = (byte) ((bits [3] & 0x00FF0000) >> 16); // scale
420 buffer [2] = (byte) ((bits [3] & 0x80000000) > 0 ? 2 : 1); //sign
421 Buffer.BlockCopy (bits, 0, buffer, 3, 12); // copy data
422 for (int j = 16; j < 19; j++) // pad with 0
424 Marshal.Copy (buffer, 0, _nativeBuffer, 19);
426 case OdbcType.SmallInt:
427 Marshal.WriteInt16 (_nativeBuffer, Convert.ToInt16 (Value));
429 case OdbcType.TinyInt:
430 Marshal.WriteByte (_nativeBuffer, Convert.ToByte (Value));
434 case OdbcType.VarChar:
435 buffer = new byte [GetNativeSize ()];
436 nativeBytes = enc.GetBytes (Convert.ToString (Value));
437 Array.Copy (nativeBytes, 0, buffer, 0, nativeBytes.Length);
438 buffer [buffer.Length-1] = (byte) 0;
439 Marshal.Copy (buffer, 0, _nativeBuffer, buffer.Length);
440 Marshal.WriteInt32 (_cbLengthInd, -3);
444 case OdbcType.NVarChar:
445 // FIXME : change to unicode
446 buffer = new byte [GetNativeSize ()];
447 nativeBytes = enc.GetBytes (Convert.ToString (Value));
448 Array.Copy (nativeBytes, 0, buffer, 0, nativeBytes.Length);
449 buffer [buffer.Length-1] = (byte) 0;
450 Marshal.Copy (buffer, 0, _nativeBuffer, buffer.Length);
451 Marshal.WriteInt32 (_cbLengthInd, -3);
453 case OdbcType.VarBinary:
455 if (Value.GetType ().IsArray &&
456 Value.GetType ().GetElementType () == typeof (byte)) {
457 Marshal.Copy ( (byte []) Value, 0, _nativeBuffer, ((byte []) Value).Length);
459 throw new ArgumentException ("Unsupported Native Type!");
462 dt = (DateTime) Value;
463 Marshal.WriteInt16 (_nativeBuffer, 0, (short) dt.Year);
464 Marshal.WriteInt16 (_nativeBuffer, 2, (short) dt.Month);
465 Marshal.WriteInt16 (_nativeBuffer, 4, (short) dt.Day);
468 dt = (DateTime) Value;
469 Marshal.WriteInt16 (_nativeBuffer, 0, (short) dt.Hour);
470 Marshal.WriteInt16 (_nativeBuffer, 2, (short) dt.Minute);
471 Marshal.WriteInt16 (_nativeBuffer, 4, (short) dt.Second);
473 case OdbcType.SmallDateTime:
474 case OdbcType.Timestamp:
475 case OdbcType.DateTime:
476 dt = (DateTime) Value;
477 Marshal.WriteInt16 (_nativeBuffer, 0, (short) dt.Year);
478 Marshal.WriteInt16 (_nativeBuffer, 2, (short) dt.Month);
479 Marshal.WriteInt16 (_nativeBuffer, 4, (short) dt.Day);
480 Marshal.WriteInt16 (_nativeBuffer, 6, (short) dt.Hour);
481 Marshal.WriteInt16 (_nativeBuffer, 8, (short) dt.Minute);
482 Marshal.WriteInt16 (_nativeBuffer, 10, (short) dt.Second);
483 Marshal.WriteInt32 (_nativeBuffer, 12, (int) (dt.Ticks % 10000000) * 100);
485 case OdbcType.UniqueIdentifier:
486 throw new NotImplementedException ();
489 if (Value.GetType ().IsArray &&
490 Value.GetType ().GetElementType () == typeof (byte)) {
491 Marshal.Copy ( (byte []) Value, 0, _nativeBuffer, ((byte []) Value).Length);
493 throw new ArgumentException ("Unsupported Native Type!");
497 public override bool SourceColumnNullMapping {
502 public override void ResetDbType ()
504 throw new NotImplementedException ();