4 // Part of the Mono class libraries at
5 // mcs/class/System.Data.OracleClient/System.Data.OracleClient
7 // Assembly: System.Data.OracleClient.dll
8 // Namespace: System.Data.OracleClient
11 // Tim Coleman <tim@timcoleman.com>
12 // Daniel Moragn <monodanmorg@yahoo.com>
13 // Hubert FONGARNAND <informatique.internet@fiducial.fr>
15 // Copyright (C) Tim Coleman , 2003
16 // Copyright (C) Daniel Morgan, 2005, 2008
17 // Copyright (C) Hubert FONGARNAND, 2005
19 // Licensed under the MIT/X11 License.
23 using System.Collections;
24 using System.ComponentModel;
27 using System.Data.Common;
29 using System.Data.SqlTypes;
30 using System.Data.OracleClient.Oci;
31 using System.Globalization;
32 using System.Runtime.InteropServices;
35 namespace System.Data.OracleClient
37 [TypeConverter (typeof(OracleParameter.OracleParameterConverter))]
38 public sealed class OracleParameter :
40 DbParameter, IDbDataParameter, ICloneable
42 MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable
48 OracleType oracleType = OracleType.VarChar;
51 ParameterDirection direction = ParameterDirection.Input;
57 bool sourceColumnNullMapping;
59 DataRowVersion srcVersion;
60 DbType dbType = DbType.AnsiString;
64 object value = DBNull.Value;
65 OciLobLocator lobLocator; // only if Blob or Clob
66 IntPtr bindOutValue = IntPtr.Zero;
67 OciDateTimeDescriptor dateTimeDesc;
68 IntPtr cursor = IntPtr.Zero;
70 OracleParameterCollection container;
71 OciBindHandle bindHandle;
72 OracleConnection connection;
74 IntPtr bindValue = IntPtr.Zero;
77 OracleType bindOracleType;
86 // constructor for cloning the object
87 private OracleParameter (OracleParameter value)
89 this.name = value.name;
90 this.oracleType = value.oracleType;
91 this.ociType = value.ociType;
92 this.size = value.size;
93 this.direction = value.direction;
94 this.isNullable = value.isNullable;
95 this.precision = value.precision;
96 this.scale = value.scale;
97 this.srcColumn = value.srcColumn;
98 this.srcVersion = value.srcVersion;
99 this.dbType = value.dbType;
100 this.offset = value.offset;
101 this.sizeSet = value.sizeSet;
102 this.value = value.value;
103 this.lobLocator = value.lobLocator;
104 this.oracleTypeSet = value.oracleTypeSet;
107 public OracleParameter ()
109 this.name = String.Empty;
110 this.oracleType = OracleType.VarChar;
112 this.direction = ParameterDirection.Input;
113 this.isNullable = false;
116 this.srcColumn = String.Empty;
117 this.srcVersion = DataRowVersion.Current;
119 this.oracleTypeSet = false;
122 public OracleParameter (string name, object value)
126 srcColumn = string.Empty;
127 SourceVersion = DataRowVersion.Current;
128 InferOracleType (value);
131 public OracleParameter (string name, OracleType oracleType)
132 : this (name, oracleType, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
136 public OracleParameter (string name, OracleType oracleType, int size)
137 : this (name, oracleType, size, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
141 public OracleParameter (string name, OracleType oracleType, int size, string srcColumn)
142 : this (name, oracleType, size, ParameterDirection.Input, false, 0, 0, srcColumn, DataRowVersion.Current, null)
147 public OracleParameter (string name, OracleType oracleType, int size, ParameterDirection direction, string sourceColumn, DataRowVersion sourceVersion, bool sourceColumnNullMapping, object value)
151 throw new ArgumentException("Size must be not be negative.");
154 SourceColumnNullMapping = sourceColumnNullMapping;
155 OracleType = oracleType;
156 Direction = direction;
157 SourceColumn = sourceColumn;
158 SourceVersion = sourceVersion;
162 public OracleParameter (string name, OracleType oracleType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string srcColumn, DataRowVersion srcVersion, object value)
166 throw new ArgumentException("Size must be not be negative.");
169 this.isNullable = isNullable;
170 this.precision = precision;
173 OracleType = oracleType;
174 Direction = direction;
175 SourceColumn = srcColumn;
176 SourceVersion = srcVersion;
179 #endregion // Constructors
183 internal OracleParameterCollection Container {
184 get { return container; }
185 set { container = value; }
190 [RefreshProperties (RefreshProperties.All)]
191 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
198 get { return dbType; }
199 set { SetDbType (value); }
203 [DefaultValue (ParameterDirection.Input)]
205 [RefreshProperties (RefreshProperties.All)]
210 ParameterDirection Direction {
211 get { return direction; }
212 set { direction = value; }
218 [DefaultValue (false)]
219 [EditorBrowsable (EditorBrowsableState.Never)]
226 get { return isNullable; }
227 set { isNullable = value; }
231 [EditorBrowsable (EditorBrowsableState.Advanced)]
237 get { return offset; }
238 set { offset = value; }
241 [DefaultValue (OracleType.VarChar)]
242 [RefreshProperties (RefreshProperties.All)]
244 [DbProviderSpecificTypeProperty (true)]
246 public OracleType OracleType {
247 get { return oracleType; }
249 oracleTypeSet = true;
250 SetOracleType (value, false);
261 string ParameterName {
267 set { name = value; }
272 [EditorBrowsable (EditorBrowsableState.Never)]
273 [Obsolete("Set the precision of a decimal use the Math classes.")]
277 public byte Precision {
278 get { return precision; }
279 set { /* NO EFFECT*/ }
284 [EditorBrowsable (EditorBrowsableState.Never)]
285 [Obsolete("Set the precision of a decimal use the Math classes.")]
290 get { return scale; }
291 set { /* NO EFFECT*/ }
316 string SourceColumn {
317 get { return srcColumn; }
318 set { srcColumn = value; }
323 public override bool SourceColumnNullMapping {
324 get { return sourceColumnNullMapping; }
325 set { sourceColumnNullMapping = value; }
330 [DefaultValue ("Current")]
336 DataRowVersion SourceVersion {
337 get { return srcVersion; }
338 set { srcVersion = value; }
342 [DefaultValue (null)]
344 [RefreshProperties (RefreshProperties.All)]
345 [TypeConverter (typeof(StringConverter))]
351 get { return this.value; }
355 InferOracleType (value);
359 #endregion // Properties
363 private void AssertSizeIsSet ()
366 case OciDataType.VarChar2:
367 case OciDataType.String:
368 case OciDataType.VarChar:
369 case OciDataType.Char:
370 case OciDataType.CharZ:
371 case OciDataType.OciString:
373 throw new Exception ("Size must be set.");
380 internal void Bind (OciStatementHandle statement, OracleConnection con, uint pos)
384 if (bindHandle == null)
385 bindHandle = new OciBindHandle ((OciHandle) statement);
387 IntPtr tmpHandle = bindHandle.Handle;
389 if (Direction != ParameterDirection.Input)
405 if (direction == ParameterDirection.Input || direction == ParameterDirection.InputOutput) {
408 else if (v is DBNull)
411 INullable mynullable = v as INullable;
412 if (mynullable != null)
413 isnull = mynullable.IsNull;
417 if (isnull == true && direction == ParameterDirection.Input) {
419 bindType = OciDataType.VarChar2;
423 case OciDataType.VarChar2:
424 case OciDataType.String:
425 case OciDataType.VarChar:
426 case OciDataType.Char:
427 case OciDataType.CharZ:
428 case OciDataType.OciString:
429 bindType = OciDataType.String;
432 // convert value from managed type to type to marshal
433 if (direction == ParameterDirection.Input ||
434 direction == ParameterDirection.InputOutput) {
436 svalue = v.ToString () + '\0';
439 // set bind length to size of data
440 bindSize = (size + 1) * 4;
442 // allocate memory based on bind length
443 bytes = new byte[bindSize];
445 if (direction == ParameterDirection.Input ||
446 direction == ParameterDirection.InputOutput) {
448 // convert managed type to memory allocated earlier
449 // in this case using OCIUnicodeToCharSet
451 // Get size of buffer
452 status = OciCalls.OCIUnicodeToCharSet (statement.Parent, null, svalue, out rsize);
454 status = OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, svalue, out rsize);
457 case OciDataType.Date:
458 bindType = OciDataType.Date;
460 // convert value from managed type to type to marshal
461 if (direction == ParameterDirection.Input ||
462 direction == ParameterDirection.InputOutput) {
465 bytes = new byte [7];
468 dt = DateTime.MinValue;
471 dt = DateTime.Parse (sDate);
473 else if (v is DateTime)
475 else if (v is OracleString) {
476 sDate = v.ToString ();
477 dt = DateTime.Parse (sDate);
479 else if (v is OracleDateTime) {
480 OracleDateTime odt = (OracleDateTime) v;
481 dt = (DateTime) odt.Value;
484 throw new NotImplementedException ("For OracleType.DateTime, data type not implemented: " + v.GetType().ToString() + ".");
486 // for Input and InputOuput, create byte array and pack DateTime into it
487 bytes = PackDate (dt);
490 // allocate 7-byte array for Output and ReturnValue to put date
491 bytes = new byte [7];
494 case OciDataType.Number:
495 bindType = OciDataType.String;
498 // define size for binding
499 bindSize = 30; // a NUMBER is 22 bytes but as a string we need more
501 bytes = new byte [bindSize];
502 // convert value from managed type to type to marshal
503 if (direction == ParameterDirection.Input ||
504 direction == ParameterDirection.InputOutput) {
507 if(v is IFormattable)
508 svalue = ((IFormattable)v).ToString (null, con.SessionFormatProvider);
509 else if (v is OracleNumber)
510 svalue = ((OracleNumber)v).ToString(con.SessionFormatProvider);
512 svalue = v.ToString();
514 svalue = svalue + "\0";
517 // Get size of buffer
518 OciCalls.OCIUnicodeToCharSet (statement.Parent, null, svalue, out rsize);
521 bytes = new byte [bindSize];
522 OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, svalue, out rsize);
525 case OciDataType.Long:
526 case OciDataType.LongVarChar:
527 bindType = OciDataType.LongVarChar;
529 // FIXME: use piecewise fetching for Long, Clob, Blob, and Long Raw
530 // See http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14250/oci05bnd.htm#sthref724
532 bindSize = Size + 5; // 4 bytes prepended for length, bytes, 1 byte NUL character
536 // convert value from managed type to type to marshal
537 if (direction == ParameterDirection.Input ||
538 direction == ParameterDirection.InputOutput) {
540 svalue = v.ToString () + '\0';
543 bytes = new byte [bindSize];
545 ASCIIEncoding enc = new ASCIIEncoding ();
547 if (direction == ParameterDirection.Input ||
548 direction == ParameterDirection.InputOutput) {
550 if (svalue.Length > 0) {
551 byteCount = enc.GetBytes (svalue, 4, svalue.Length, bytes, 0);
552 // LONG VARCHAR prepends a 4-byte length
554 byte[] byteArrayLen = BitConverter.GetBytes ((uint) byteCount);
555 bytes[0] = byteArrayLen[0];
556 bytes[1] = byteArrayLen[1];
557 bytes[2] = byteArrayLen[2];
558 bytes[3] = byteArrayLen[3];
563 case OciDataType.Clob:
564 if (direction == ParameterDirection.Input) {
565 svalue = v.ToString();
568 // Get size of buffer
569 OciCalls.OCIUnicodeToCharSet (statement.Parent, null, svalue, out rsize);
572 bytes = new byte[rsize];
573 OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, svalue, out rsize);
575 bindType = OciDataType.Long;
576 bindSize = bytes.Length;
578 else if (direction == ParameterDirection.InputOutput)
579 // not the exact error that .net 2.0 throws, but this is better
580 throw new NotImplementedException ("Parameters of OracleType.Clob with direction of InputOutput are not supported.");
582 // Output and Return parameters
584 lobLocator = (OciLobLocator) connection.Environment.Allocate (OciHandleType.LobLocator);
585 if (lobLocator == null) {
586 OciErrorInfo info = connection.ErrorHandle.HandleError ();
587 throw new OracleException (info.ErrorCode, info.ErrorMessage);
589 bindOutValue = lobLocator.Handle;
590 bindValue = lobLocator.Handle;
591 lobLocator.ErrorHandle = connection.ErrorHandle;
592 lobLocator.Service = statement.Service;
597 // FIXME: move this up - see how Char, Number, and Date are done...
598 if (direction == ParameterDirection.Output ||
599 direction == ParameterDirection.InputOutput ||
600 direction == ParameterDirection.ReturnValue) {
603 case OciDataType.RowIdDescriptor:
605 bindType = OciDataType.Char;
607 bindOutValue = OciCalls.AllocateClear (bindSize);
608 bindValue = bindOutValue;
610 case OciDataType.TimeStamp:
611 dateTimeDesc = (OciDateTimeDescriptor) connection.Environment.Allocate (OciHandleType.TimeStamp);
612 if (dateTimeDesc == null) {
613 OciErrorInfo info = connection.ErrorHandle.HandleError ();
614 throw new OracleException (info.ErrorCode, info.ErrorMessage);
616 dateTimeDesc.ErrorHandle = connection.ErrorHandle;
618 bindType = OciDataType.TimeStamp;
619 bindOutValue = dateTimeDesc.Handle;
620 bindValue = dateTimeDesc.Handle;
623 case OciDataType.Blob:
625 lobLocator = (OciLobLocator) connection.Environment.Allocate (OciHandleType.LobLocator);
626 if (lobLocator == null) {
627 OciErrorInfo info = connection.ErrorHandle.HandleError ();
628 throw new OracleException (info.ErrorCode, info.ErrorMessage);
630 bindOutValue = lobLocator.Handle;
631 bindValue = lobLocator.Handle;
632 lobLocator.ErrorHandle = connection.ErrorHandle;
633 lobLocator.Service = statement.Service;
636 case OciDataType.RSet: // REF CURSOR
637 cursor = IntPtr.Zero;
638 OciCalls.OCIHandleAlloc (connection.Environment,
640 OciHandleType.Statement,
645 bindType = OciDataType.RSet;
648 // define other types
649 throw new NotImplementedException ("Data Type not implemented: " + ociType.ToString() + ".");
650 } // switch of ociDataType for output
651 bindValue = bindOutValue;
653 else if ((v == DBNull.Value || v == null || isnull == true) && direction == ParameterDirection.Input) {
655 bindType = OciDataType.VarChar2;
660 dt = DateTime.MinValue;
661 if (bindOracleType == OracleType.Timestamp){
662 bindType = OciDataType.TimeStamp;
664 dt = DateTime.MinValue;
668 dt = DateTime.Parse (sDate);
670 else if (v is DateTime)
672 else if (v is OracleString){
674 dt = DateTime.Parse (sDate);
676 else if (v is OracleDateTime) {
677 OracleDateTime odt = (OracleDateTime) v;
678 dt = (DateTime) odt.Value;
681 throw new NotImplementedException ("For OracleType.Timestamp, data type not implemented: " + v.GetType().ToString()); // ?
683 short year = (short) dt.Year;
684 byte month = (byte) dt.Month;
685 byte day = (byte) dt.Day;
686 byte hour = (byte) dt.Hour;
687 byte min = (byte) dt.Minute;
688 byte sec = (byte) dt.Second;
689 uint fsec = (uint) dt.Millisecond;
690 string timezone = "";
691 dateTimeDesc = (OciDateTimeDescriptor) connection.Environment.Allocate (OciHandleType.TimeStamp);
692 if (dateTimeDesc == null) {
693 OciErrorInfo info = connection.ErrorHandle.HandleError ();
694 throw new OracleException (info.ErrorCode, info.ErrorMessage);
696 dateTimeDesc.ErrorHandle = connection.ErrorHandle;
697 dateTimeDesc.SetDateTime (connection.Session,
698 connection.ErrorHandle,
699 year, month, day, hour, min, sec, fsec,
703 else if (bindOracleType == OracleType.Blob) {
705 bindType = OciDataType.LongRaw;
706 bindSize = bytes.Length;
708 else if (bindOracleType == OracleType.Raw) {
709 byte[] val = v as byte[];
710 bindValue = OciCalls.AllocateClear (val.Length);
711 Marshal.Copy (val, 0, bindValue, val.Length);
712 bindSize = val.Length;
714 svalue = v.ToString () + '\0';
717 // Get size of buffer
718 OciCalls.OCIUnicodeToCharSet (statement.Parent, null, svalue, out rsize);
721 bytes = new byte[rsize];
722 OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, svalue, out rsize);
724 bindType = OciDataType.String;
725 bindSize = svalue.Length;
727 } // else - Input, Ouput...
732 // Now, call the appropriate OCI Bind function;
734 if (useRef == true) {
735 if (bindType == OciDataType.TimeStamp) {
736 bindValue = dateTimeDesc.Handle;
737 status = OciCalls.OCIBindByNameRef (statement,
739 connection.ErrorHandle,
741 ParameterName.Length,
753 status = OciCalls.OCIBindByNameRef (statement,
755 connection.ErrorHandle,
757 ParameterName.Length,
769 else if (bindType == OciDataType.RSet) {
770 status = OciCalls.OCIBindByNameRef (statement,
772 connection.ErrorHandle,
774 ParameterName.Length,
785 else if (bytes != null) {
786 status = OciCalls.OCIBindByNameBytes (statement,
788 connection.ErrorHandle,
790 ParameterName.Length,
802 status = OciCalls.OCIBindByName (statement,
804 connection.ErrorHandle,
806 ParameterName.Length, // FIXME: this should be in bytes!
817 OciErrorHandle.ThrowExceptionIfError (connection.ErrorHandle, status);
819 bindHandle.SetHandle (tmpHandle);
822 object ICloneable.Clone ()
824 return new OracleParameter(this);
827 private void InferOracleType (object value)
829 Type type = value.GetType ();
830 string exception = String.Format ("The parameter data type of {0} is invalid.", type.FullName);
831 switch (type.FullName) {
833 SetOracleType (OracleType.Number, true);
835 case "System.Boolean":
837 SetOracleType (OracleType.Byte, true);
839 case "System.String":
840 case "System.Data.OracleClient.OracleString":
841 SetOracleType (OracleType.VarChar, true);
843 case "System.Data.OracleClient.OracleDateTime":
844 case "System.DateTime":
845 SetOracleType (OracleType.DateTime, true);
847 case "System.Decimal":
848 case "System.Data.OracleClient.OracleNumber":
849 SetOracleType (OracleType.Number, true);
851 case "System.Double":
852 SetOracleType (OracleType.Double, true);
854 case "System.Byte[]":
856 SetOracleType (OracleType.Raw, true);
859 SetOracleType (OracleType.Int32, true);
861 case "System.Single":
862 SetOracleType (OracleType.Float, true);
865 SetOracleType (OracleType.Int16, true);
867 case "System.DBNull":
868 break; //unable to guess type
869 case "System.Data.OracleClient.OracleLob":
870 SetOracleType (((OracleLob) value).LobType, true);
873 throw new ArgumentException (exception);
877 private int InferSize ()
882 case OciDataType.VarChar2:
883 case OciDataType.String:
884 case OciDataType.VarChar:
885 case OciDataType.Char:
886 case OciDataType.CharZ:
887 case OciDataType.OciString:
888 case OciDataType.Long:
889 case OciDataType.LongVarChar:
890 if (value == null || value == DBNull.Value)
893 newSize = value.ToString ().Length;
895 case OciDataType.RowIdDescriptor:
898 case OciDataType.Integer:
899 case OciDataType.Number:
900 case OciDataType.Float:
903 case OciDataType.Date:
906 case OciDataType.TimeStamp:
909 case OciDataType.Blob:
910 case OciDataType.Clob:
911 case OciDataType.RSet: // REF CURSOR
915 if (value == null || value == DBNull.Value)
918 newSize = value.ToString ().Length;
927 private void SetDbType (DbType type)
929 string exception = String.Format ("No mapping exists from DbType {0} to a known OracleType.", type);
931 case DbType.AnsiString:
932 oracleType = OracleType.VarChar;
933 ociType = OciDataType.VarChar;
935 case DbType.AnsiStringFixedLength:
936 oracleType = OracleType.Char;
937 ociType = OciDataType.Char;
941 oracleType = OracleType.Raw;
942 ociType = OciDataType.Raw;
946 oracleType = OracleType.Byte;
947 ociType = OciDataType.Integer;
949 case DbType.Currency:
952 oracleType = OracleType.Number;
953 ociType = OciDataType.Number;
956 case DbType.DateTime:
958 oracleType = OracleType.DateTime;
959 ociType = OciDataType.Char;
962 oracleType = OracleType.Double;
963 ociType = OciDataType.Float;
966 oracleType = OracleType.Int16;
967 ociType = OciDataType.Integer;
970 oracleType = OracleType.Int32;
971 ociType = OciDataType.Integer;
974 oracleType = OracleType.Blob;
975 ociType = OciDataType.Blob;
978 oracleType = OracleType.Float;
979 ociType = OciDataType.Float;
982 oracleType = OracleType.NVarChar;
983 ociType = OciDataType.VarChar;
985 case DbType.StringFixedLength:
986 oracleType = OracleType.NChar;
987 ociType = OciDataType.Char;
990 throw new ArgumentException (exception);
995 private void SetOracleType (OracleType type, bool inferring)
998 string exception = String.Format ("No mapping exists from OracleType {0} to a known DbType.", type);
1000 case OracleType.BFile:
1001 case OracleType.Blob:
1002 dbType = DbType.Binary;
1003 ociType = OciDataType.Blob;
1005 case OracleType.LongRaw:
1006 case OracleType.Raw:
1007 dbType = DbType.Binary;
1008 ociType = OciDataType.Raw;
1010 case OracleType.Byte:
1011 dbType = DbType.Byte;
1012 ociType = OciDataType.Number;
1014 case OracleType.Char:
1015 dbType = DbType.AnsiString;
1016 ociType = OciDataType.Char;
1018 case OracleType.Clob:
1019 dbType = DbType.AnsiString;
1020 ociType = OciDataType.Clob;
1022 case OracleType.LongVarChar:
1023 case OracleType.RowId:
1024 case OracleType.VarChar:
1025 dbType = DbType.AnsiString;
1026 ociType = OciDataType.VarChar;
1028 case OracleType.Cursor: // REF CURSOR
1029 ociType = OciDataType.RSet;
1030 dbType = DbType.Object;
1032 case OracleType.IntervalDayToSecond:
1033 dbType = DbType.AnsiStringFixedLength;
1034 ociType = OciDataType.Char;
1036 case OracleType.Timestamp:
1037 case OracleType.TimestampLocal:
1038 case OracleType.TimestampWithTZ:
1039 dbType = DbType.DateTime;
1040 ociType = OciDataType.TimeStamp;
1042 case OracleType.DateTime:
1043 dbType = DbType.DateTime;
1044 ociType = OciDataType.Date;
1046 case OracleType.Double:
1047 dbType = DbType.Double;
1048 ociType = OciDataType.Number;
1050 case OracleType.Float:
1051 dbType = DbType.Single;
1052 ociType = OciDataType.Number;
1054 case OracleType.Int16:
1055 dbType = DbType.Int16;
1056 ociType = OciDataType.Number;
1058 case OracleType.Int32:
1059 case OracleType.IntervalYearToMonth:
1060 dbType = DbType.Int32;
1061 ociType = OciDataType.Number;
1063 case OracleType.NChar:
1064 dbType = DbType.StringFixedLength;
1065 ociType = OciDataType.Char;
1067 case OracleType.NClob:
1068 case OracleType.NVarChar:
1069 dbType = DbType.String;
1070 ociType = OciDataType.Char;
1072 case OracleType.Number:
1073 dbType = DbType.VarNumeric;
1074 ociType = OciDataType.Number;
1076 case OracleType.SByte:
1077 dbType = DbType.SByte;
1078 ociType = OciDataType.Number;
1080 case OracleType.UInt16:
1081 dbType = DbType.UInt16;
1082 ociType = OciDataType.Number;
1084 case OracleType.UInt32:
1085 dbType = DbType.UInt32;
1086 ociType = OciDataType.Number;
1089 throw new ArgumentException (exception);
1094 bindOracleType = type;
1098 public override void ResetDbType ()
1103 public void ResetOracleType ()
1105 oracleTypeSet = false;
1106 InferOracleType (value);
1110 public override string ToString ()
1112 return ParameterName;
1115 private void GetOutValue (OracleCommand cmd)
1117 // used to update the parameter value
1118 // for Output, the output of InputOutput, and Return parameters
1119 value = DBNull.Value;
1120 if (indicator == -1)
1124 IntPtr env = IntPtr.Zero;
1125 StringBuilder ret = null;
1127 // FIXME: redo all types - see how Char, Number, and Date are done
1128 // here and in Bind()
1131 case OciDataType.VarChar2:
1132 case OciDataType.String:
1133 case OciDataType.VarChar:
1134 case OciDataType.Char:
1135 case OciDataType.CharZ:
1136 case OciDataType.OciString:
1137 case OciDataType.RowIdDescriptor:
1138 // Get length of returned string
1140 env = cmd.Connection.Environment;
1141 OciCalls.OCICharSetToUnicode (env, null, bytes, out rsize);
1144 ret = new StringBuilder(rsize);
1145 OciCalls.OCICharSetToUnicode (env, ret, bytes, out rsize);
1147 value = ret.ToString ();
1149 case OciDataType.Long:
1150 case OciDataType.LongVarChar:
1152 if (BitConverter.IsLittleEndian)
1153 longSize = BitConverter.ToInt32 (new byte [] {bytes [0], bytes [1], bytes [2], bytes [3]}, 0);
1155 longSize = BitConverter.ToInt32 (new byte [] {bytes [3], bytes [2], bytes [1], bytes [0]}, 0);
1157 ASCIIEncoding encoding = new ASCIIEncoding ();
1158 value = encoding.GetString (bytes, 4, longSize);
1161 case OciDataType.Integer:
1162 case OciDataType.Number:
1163 case OciDataType.Float:
1165 env = cmd.Connection.Environment;
1166 OciCalls.OCICharSetToUnicode (env, null, bytes, out rsize);
1169 ret = new StringBuilder(rsize);
1170 OciCalls.OCICharSetToUnicode (env, ret, bytes, out rsize);
1172 // if not empty, parse string as a decimal using session format
1174 value = Decimal.Parse (ret.ToString (), cmd.Connection.SessionFormatProvider);
1176 case OciDataType.TimeStamp:
1177 value = dateTimeDesc.GetDateTime (connection.Environment, dateTimeDesc.ErrorHandle);
1179 case OciDataType.Date:
1180 value = UnpackDate (bytes);
1182 case OciDataType.Blob:
1183 case OciDataType.Clob:
1184 OracleLob lob = new OracleLob (lobLocator, ociType);
1185 lob.connection = connection;
1188 case OciDataType.RSet: // REF CURSOR
1189 OciStatementHandle cursorStatement = GetOutRefCursor (cmd);
1190 value = new OracleDataReader (cursorStatement.Command, cursorStatement, true, CommandBehavior.Default);
1193 throw new NotImplementedException ("Data Type not implemented: " + ociType.ToString() + ".");
1197 internal OciStatementHandle GetOutRefCursor (OracleCommand cmd)
1199 OciStatementHandle cursorStatement = new OciStatementHandle (cmd.Connection.ServiceContext, cursor);
1201 cursorStatement.ErrorHandle = cmd.ErrorHandle;
1202 cursorStatement.Command = cmd;
1203 cursorStatement.SetupRefCursorResult (cmd.Connection);
1204 cursorStatement.Service = cmd.Connection.ServiceContext;
1205 cursor = IntPtr.Zero;
1206 return cursorStatement;
1209 internal void Update (OracleCommand cmd)
1211 if (Direction != ParameterDirection.Input)
1217 internal void FreeHandle ()
1220 case OciDataType.Clob:
1221 case OciDataType.Blob:
1224 case OciDataType.Raw:
1225 Marshal.FreeHGlobal (bindValue);
1227 case OciDataType.TimeStamp:
1230 Marshal.FreeHGlobal (bindOutValue);
1234 bindOutValue = IntPtr.Zero;
1235 bindValue = IntPtr.Zero;
1241 // copied from OciDefineHandle
1242 [MonoTODO ("Be able to handle negative dates... i.e. BCE.")]
1243 private DateTime UnpackDate (byte[] bytes)
1245 byte century = bytes [0];
1246 byte year = bytes [1];
1247 byte month = bytes [2];
1248 byte day = bytes [3];
1249 byte hour = bytes [4];
1250 byte minute = bytes [5];
1251 byte second = bytes [6];
1254 return new DateTime ((century - 100) * 100 + (year - 100),
1263 private byte[] PackDate (DateTime dateValue)
1265 byte[] buffer = new byte[7];
1267 buffer[0] = (byte)((dateValue.Year / 100) + 100); //century
1268 buffer[1] = (byte)((dateValue.Year % 100) + 100); // Year
1269 buffer[2] = (byte)dateValue.Month;
1270 buffer[3] = (byte)dateValue.Day;
1271 buffer[4] = (byte)(dateValue.Hour+1);
1272 buffer[5] = (byte)(dateValue.Minute+1);
1273 buffer[6] = (byte)(dateValue.Second+1);
1278 #endregion // Methods
1280 internal sealed class OracleParameterConverter : ExpandableObjectConverter
1282 public OracleParameterConverter ()
1287 public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
1289 throw new NotImplementedException ();
1293 public override object ConvertTo (ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
1295 throw new NotImplementedException ();