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;
39 using System.Runtime.InteropServices;
40 using System.Globalization;
43 using System.Data.ProviderBase;
45 using System.ComponentModel;
47 namespace System.Data.Odbc
49 [TypeConverterAttribute (typeof (OdbcParameterConverter))]
51 public sealed class OdbcParameter : DbParameterBase, ICloneable
53 public sealed class OdbcParameter : MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable
60 ParameterDirection direction;
63 DataRowVersion sourceVersion;
70 private OdbcTypeMap _typeMap;
71 private NativeBuffer _nativeBuffer = new NativeBuffer ();
72 private NativeBuffer _cbLengthInd;
73 private OdbcParameterCollection container = null;
79 public OdbcParameter ()
81 _cbLengthInd = new NativeBuffer ();
82 ParameterName = String.Empty;
84 SourceColumn = String.Empty;
85 Direction = ParameterDirection.Input;
86 _typeMap = OdbcTypeConverter.GetTypeMap (OdbcType.VarChar);
89 public OdbcParameter (string name, object value)
92 this.ParameterName = name;
94 _typeMap = OdbcTypeConverter.InferFromValue (value);
95 if (value != null && !value.GetType ().IsValueType) {
96 Type type = value.GetType ();
98 Size = type.GetElementType () == typeof (byte) ?
99 ((Array) value).Length : 0;
101 Size = value.ToString ().Length;
105 public OdbcParameter (string name, OdbcType odbcType)
108 this.ParameterName = name;
109 _typeMap = (OdbcTypeMap) OdbcTypeConverter.GetTypeMap (odbcType);
112 public OdbcParameter (string name, OdbcType odbcType, int size)
113 : this (name, odbcType)
118 public OdbcParameter (string name, OdbcType odbcType, int size, string srcColumn)
119 : this (name, odbcType, size)
121 this.SourceColumn = srcColumn;
124 [EditorBrowsable (EditorBrowsableState.Advanced)]
125 public OdbcParameter(string name, OdbcType odbcType, int size,
126 ParameterDirection direction, bool isNullable,
127 byte precision, byte scale, string srcColumn,
128 DataRowVersion srcVersion, object value)
129 : this (name, odbcType, size, srcColumn)
131 this.Direction = direction;
132 this.IsNullable = isNullable;
133 this.SourceVersion = srcVersion;
140 // Used to ensure that only one collection can contain this
142 internal OdbcParameterCollection Container {
143 get { return container; }
144 set { container = value; }
147 [BrowsableAttribute (false)]
148 [OdbcDescriptionAttribute ("The parameter generic type")]
149 [RefreshPropertiesAttribute (RefreshProperties.All)]
150 [DesignerSerializationVisibilityAttribute (DesignerSerializationVisibility.Hidden)]
151 [OdbcCategory ("Data")]
157 get { return _typeMap.DbType; }
159 if (value == _typeMap.DbType)
162 _typeMap = OdbcTypeConverter.GetTypeMap (value);
167 [OdbcCategory ("Data")]
168 [OdbcDescriptionAttribute ("Input, output, or bidirectional parameter")]
169 [DefaultValue (ParameterDirection.Input)]
170 public ParameterDirection Direction {
171 get { return direction; }
172 set { direction = value; }
175 [BrowsableAttribute (false)]
176 [OdbcDescriptionAttribute ("A design-time property used for strongly typed code generation")]
177 [DesignOnlyAttribute (true)]
178 [EditorBrowsableAttribute (EditorBrowsableState.Advanced)]
179 [DefaultValue (false)]
180 public bool IsNullable {
181 get { return isNullable; }
182 set { isNullable = value; }
187 [DefaultValue (OdbcType.NChar)]
188 [OdbcDescriptionAttribute ("The parameter native type")]
189 [RefreshPropertiesAttribute (RefreshProperties.All)]
190 [OdbcCategory ("Data")]
191 public OdbcType OdbcType {
192 get { return _typeMap.OdbcType; }
194 if (value == OdbcType)
197 _typeMap = OdbcTypeConverter.GetTypeMap (value);
202 [OdbcDescription ("DataParameter_ParameterName")]
204 public string ParameterName {
206 set { name = value; }
209 [OdbcDescription ("DbDataParameter_Precision")]
210 [OdbcCategory ("DataCategory_Data")]
212 public byte Precision {
213 get { return _precision; }
214 set { _precision = value; }
217 [OdbcDescription ("DbDataParameter_Scale")]
218 [OdbcCategory ("DataCategory_Data")]
221 get { return _scale; }
222 set { _scale = value; }
225 [OdbcDescription ("DbDataParameter_Size")]
226 [OdbcCategory ("DataCategory_Data")]
230 set { size = value; }
233 [OdbcDescription ("DataParameter_SourceColumn")]
234 [OdbcCategory ("DataCategory_Data")]
236 public string SourceColumn {
237 get { return sourceColumn; }
238 set { sourceColumn = value; }
241 [OdbcDescription ("DataParameter_SourceVersion")]
242 [OdbcCategory ("DataCategory_Data")]
243 [DefaultValue ("Current")]
244 public DataRowVersion SourceVersion {
245 get { return sourceVersion; }
246 set { sourceVersion = value; }
249 [TypeConverter (typeof(StringConverter))]
250 [OdbcDescription ("DataParameter_Value")]
251 [OdbcCategory ("DataCategory_Data")]
252 [DefaultValue (null)]
253 public object Value {
264 #endregion // Properties
268 internal void Bind(IntPtr hstmt, int ParamNum) {
271 // Convert System.Data.ParameterDirection into odbc enum
272 OdbcInputOutputDirection paramdir = libodbc.ConvertParameterDirection(this.Direction);
274 _cbLengthInd.EnsureAlloc (Marshal.SizeOf (typeof (int)));
275 Marshal.WriteInt32 (_cbLengthInd, GetNativeSize ());
277 ret = libodbc.SQLBindParameter(hstmt, (ushort) ParamNum, (short) paramdir,
278 _typeMap.NativeType, _typeMap.SqlType, Convert.ToUInt32(Size),
279 0, (IntPtr) _nativeBuffer, 0, _cbLengthInd);
281 // Check for error condition
282 if ((ret != OdbcReturn.Success) && (ret != OdbcReturn.SuccessWithInfo))
283 throw new OdbcException(new OdbcError("SQLBindParam", OdbcHandleType.Stmt, hstmt));
287 object ICloneable.Clone ()
289 throw new NotImplementedException ();
292 public override string ToString ()
294 return ParameterName;
297 private int GetNativeSize ()
299 TextInfo ti = CultureInfo.InvariantCulture.TextInfo;
300 Encoding enc = Encoding.GetEncoding (ti.ANSICodePage);
302 switch (_typeMap.OdbcType) {
303 case OdbcType.Binary:
304 if (Value.GetType ().IsArray &&
305 Value.GetType ().GetElementType () == typeof (byte))
306 return ( (Array) Value).Length;
308 return Value.ToString ().Length;
310 return Marshal.SizeOf (typeof (byte));
311 case OdbcType.Double:
312 return Marshal.SizeOf (typeof (double));
314 return Marshal.SizeOf (typeof (float));
316 return Marshal.SizeOf (typeof (int));
317 case OdbcType.BigInt:
318 return Marshal.SizeOf (typeof (long));
319 case OdbcType.Decimal:
320 case OdbcType.Numeric:
322 case OdbcType.SmallInt:
323 return Marshal.SizeOf (typeof (Int16));
324 case OdbcType.TinyInt:
325 return Marshal.SizeOf (typeof (byte));
328 case OdbcType.VarChar:
329 return enc.GetByteCount (Convert.ToString (Value)) + 1;
332 case OdbcType.NVarChar:
333 // FIXME: Change to unicode
334 return enc.GetByteCount (Convert.ToString (Value)) + 1;
335 case OdbcType.VarBinary:
337 if (Value.GetType ().IsArray &&
338 Value.GetType ().GetElementType () == typeof (byte))
339 return ( (Array) Value).Length;
340 throw new ArgumentException ("Unsupported Native Type!");
342 case OdbcType.DateTime:
343 case OdbcType.SmallDateTime:
345 case OdbcType.Timestamp:
347 case OdbcType.UniqueIdentifier:
348 return Marshal.SizeOf (typeof (Guid));
351 if (Value.GetType ().IsArray &&
352 Value.GetType ().GetElementType () == typeof (byte))
353 return ( (Array) Value).Length;
355 return Value.ToString ().Length;
358 private void AllocateBuffer ()
360 int size = GetNativeSize ();
362 if (_nativeBuffer.Size == size)
365 _nativeBuffer.AllocBuffer (size);
368 internal void CopyValue ()
370 if (_nativeBuffer.Handle == IntPtr.Zero)
374 TextInfo ti = CultureInfo.InvariantCulture.TextInfo;
375 Encoding enc = Encoding.GetEncoding (ti.ANSICodePage);
376 byte [] nativeBytes, buffer;
378 switch (_typeMap.OdbcType) {
379 case OdbcType.Binary:
380 throw new NotImplementedException ();
382 Marshal.WriteByte (_nativeBuffer, Convert.ToByte (Value));
384 case OdbcType.Double:
385 Marshal.StructureToPtr (Convert.ToDouble (Value), _nativeBuffer, false);
388 Marshal.StructureToPtr (Convert.ToSingle (Value), _nativeBuffer, false);
391 Marshal.WriteInt32 (_nativeBuffer, Convert.ToInt32 (Value));
393 case OdbcType.BigInt:
394 Marshal.WriteInt64 (_nativeBuffer, Convert.ToInt64 (Value));
396 case OdbcType.Decimal:
397 case OdbcType.Numeric:
398 // for numeric, the buffer is a packed decimal struct.
399 // ref http://www.it-faq.pl/mskb/181/254.HTM
400 int [] bits = Decimal.GetBits (Convert.ToDecimal (Value));
401 buffer = new byte [19]; // ref sqltypes.h
402 buffer [0] = Precision;
403 buffer [1] = (byte) ((bits [3] & 0x00FF0000) >> 16); // scale
404 buffer [2] = (byte) ((bits [3] & 0x80000000) > 0 ? 2 : 1); //sign
405 Buffer.BlockCopy (bits, 0, buffer, 3, 12); // copy data
406 for (int j = 16; j < 19; j++) // pad with 0
408 Marshal.Copy (buffer, 0, _nativeBuffer, 19);
410 case OdbcType.SmallInt:
411 Marshal.WriteInt16 (_nativeBuffer, Convert.ToInt16 (Value));
413 case OdbcType.TinyInt:
414 Marshal.WriteByte (_nativeBuffer, Convert.ToByte (Value));
418 case OdbcType.VarChar:
419 buffer = new byte [GetNativeSize ()];
420 nativeBytes = enc.GetBytes (Convert.ToString (Value));
421 Array.Copy (nativeBytes, 0, buffer, 0, nativeBytes.Length);
422 buffer [buffer.Length-1] = (byte) 0;
423 Marshal.Copy (buffer, 0, _nativeBuffer, buffer.Length);
424 Marshal.WriteInt32 (_cbLengthInd, -3);
428 case OdbcType.NVarChar:
429 // FIXME : change to unicode
430 buffer = new byte [GetNativeSize ()];
431 nativeBytes = enc.GetBytes (Convert.ToString (Value));
432 Array.Copy (nativeBytes, 0, buffer, 0, nativeBytes.Length);
433 buffer [buffer.Length-1] = (byte) 0;
434 Marshal.Copy (buffer, 0, _nativeBuffer, buffer.Length);
435 Marshal.WriteInt32 (_cbLengthInd, -3);
437 case OdbcType.VarBinary:
439 if (Value.GetType ().IsArray &&
440 Value.GetType ().GetElementType () == typeof (byte)) {
441 Marshal.Copy ( (byte []) Value, 0, _nativeBuffer, ((byte []) Value).Length);
443 throw new ArgumentException ("Unsupported Native Type!");
446 dt = (DateTime) Value;
447 Marshal.WriteInt16 (_nativeBuffer, 0, (short) dt.Year);
448 Marshal.WriteInt16 (_nativeBuffer, 2, (short) dt.Month);
449 Marshal.WriteInt16 (_nativeBuffer, 4, (short) dt.Day);
452 dt = (DateTime) Value;
453 Marshal.WriteInt16 (_nativeBuffer, 0, (short) dt.Hour);
454 Marshal.WriteInt16 (_nativeBuffer, 2, (short) dt.Minute);
455 Marshal.WriteInt16 (_nativeBuffer, 4, (short) dt.Second);
457 case OdbcType.SmallDateTime:
458 case OdbcType.Timestamp:
459 case OdbcType.DateTime:
460 dt = (DateTime) Value;
461 Marshal.WriteInt16 (_nativeBuffer, 0, (short) dt.Year);
462 Marshal.WriteInt16 (_nativeBuffer, 2, (short) dt.Month);
463 Marshal.WriteInt16 (_nativeBuffer, 4, (short) dt.Day);
464 Marshal.WriteInt16 (_nativeBuffer, 6, (short) dt.Hour);
465 Marshal.WriteInt16 (_nativeBuffer, 8, (short) dt.Minute);
466 Marshal.WriteInt16 (_nativeBuffer, 10, (short) dt.Second);
467 Marshal.WriteInt32 (_nativeBuffer, 12, (int) (dt.Ticks % 10000000) * 100);
469 case OdbcType.UniqueIdentifier:
470 throw new NotImplementedException ();
473 if (Value.GetType ().IsArray &&
474 Value.GetType ().GetElementType () == typeof (byte)) {
475 Marshal.Copy ( (byte []) Value, 0, _nativeBuffer, ((byte []) Value).Length);
477 throw new ArgumentException ("Unsupported Native Type!");
482 public override bool SourceColumnNullMapping {
488 public override void PropertyChanging ()
493 protected override byte ValuePrecision (object value)
495 throw new NotImplementedException ();
499 protected override byte ValueScale (object value)
501 throw new NotImplementedException ();
505 protected override int ValueSize (object value)
507 throw new NotImplementedException ();
511 public override void ResetDbType ()
513 throw new NotImplementedException ();