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)
127 srcColumn = string.Empty;
128 SourceVersion = DataRowVersion.Current;
129 InferOracleType (value);
131 // Find the OciType before inferring for the size
132 if (value != null && value != DBNull.Value) {
134 this.size = InferSize ();
139 public OracleParameter (string name, OracleType oracleType)
140 : this (name, oracleType, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
144 public OracleParameter (string name, OracleType oracleType, int size)
145 : this (name, oracleType, size, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
149 public OracleParameter (string name, OracleType oracleType, int size, string srcColumn)
150 : this (name, oracleType, size, ParameterDirection.Input, false, 0, 0, srcColumn, DataRowVersion.Current, null)
155 public OracleParameter (string name, OracleType oracleType, int size, ParameterDirection direction, string sourceColumn, DataRowVersion sourceVersion, bool sourceColumnNullMapping, object value)
159 throw new ArgumentException("Size must be not be negative.");
163 // set sizeSet to true iff value is not-null or non-zero size value
164 if (value != null && value != DBNull.Value && size > 0)
167 SourceColumnNullMapping = sourceColumnNullMapping;
168 OracleType = oracleType;
169 Direction = direction;
170 SourceColumn = sourceColumn;
171 SourceVersion = sourceVersion;
175 public OracleParameter (string name, OracleType oracleType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string srcColumn, DataRowVersion srcVersion, object value)
179 throw new ArgumentException("Size must be not be negative.");
184 // set sizeSet to true iff value is not-null or non-zero size value
185 if (value != null && value != DBNull.Value && size > 0)
188 this.isNullable = isNullable;
189 this.precision = precision;
192 OracleType = oracleType;
193 Direction = direction;
194 SourceColumn = srcColumn;
195 SourceVersion = srcVersion;
198 #endregion // Constructors
202 internal OracleParameterCollection Container {
203 get { return container; }
204 set { container = value; }
209 [RefreshProperties (RefreshProperties.All)]
210 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
217 get { return dbType; }
218 set { SetDbType (value); }
222 [DefaultValue (ParameterDirection.Input)]
224 [RefreshProperties (RefreshProperties.All)]
229 ParameterDirection Direction {
230 get { return direction; }
231 set { direction = value; }
237 [DefaultValue (false)]
238 [EditorBrowsable (EditorBrowsableState.Never)]
245 get { return isNullable; }
246 set { isNullable = value; }
250 [EditorBrowsable (EditorBrowsableState.Advanced)]
256 get { return offset; }
257 set { offset = value; }
260 [DefaultValue (OracleType.VarChar)]
261 [RefreshProperties (RefreshProperties.All)]
263 [DbProviderSpecificTypeProperty (true)]
265 public OracleType OracleType {
266 get { return oracleType; }
268 oracleTypeSet = true;
269 SetOracleType (value, false);
280 string ParameterName {
286 set { name = value; }
291 [EditorBrowsable (EditorBrowsableState.Never)]
292 [Obsolete("Set the precision of a decimal use the Math classes.")]
296 public byte Precision {
297 get { return precision; }
298 set { /* NO EFFECT*/ }
303 [EditorBrowsable (EditorBrowsableState.Never)]
304 [Obsolete("Set the precision of a decimal use the Math classes.")]
309 get { return scale; }
310 set { /* NO EFFECT*/ }
335 string SourceColumn {
336 get { return srcColumn; }
337 set { srcColumn = value; }
342 public override bool SourceColumnNullMapping {
343 get { return sourceColumnNullMapping; }
344 set { sourceColumnNullMapping = value; }
349 [DefaultValue ("Current")]
355 DataRowVersion SourceVersion {
356 get { return srcVersion; }
357 set { srcVersion = value; }
361 [DefaultValue (null)]
363 [RefreshProperties (RefreshProperties.All)]
364 [TypeConverter (typeof(StringConverter))]
370 get { return this.value; }
374 InferOracleType (value);
376 if (value != null && value != DBNull.Value) {
377 this.size = InferSize ();
384 #endregion // Properties
388 private void AssertSizeIsSet ()
391 case OciDataType.VarChar2:
392 case OciDataType.String:
393 case OciDataType.VarChar:
394 case OciDataType.Char:
395 case OciDataType.CharZ:
396 case OciDataType.OciString:
398 throw new Exception ("Size must be set.");
405 internal void Bind (OciStatementHandle statement, OracleConnection con, uint pos)
409 if (bindHandle == null)
410 bindHandle = new OciBindHandle ((OciHandle) statement);
412 IntPtr tmpHandle = bindHandle.Handle;
414 if (Direction != ParameterDirection.Input)
430 if (direction == ParameterDirection.Input || direction == ParameterDirection.InputOutput) {
433 else if (v is DBNull)
436 INullable mynullable = v as INullable;
437 if (mynullable != null)
438 isnull = mynullable.IsNull;
442 if (isnull == true && direction == ParameterDirection.Input) {
444 bindType = OciDataType.VarChar2;
448 case OciDataType.VarChar2:
449 case OciDataType.String:
450 case OciDataType.VarChar:
451 case OciDataType.Char:
452 case OciDataType.CharZ:
453 case OciDataType.OciString:
454 bindType = OciDataType.String;
457 // convert value from managed type to type to marshal
458 if (direction == ParameterDirection.Input ||
459 direction == ParameterDirection.InputOutput) {
461 svalue = v.ToString ();
463 if (direction == ParameterDirection.Input && size > 0 && svalue.Length > size)
464 svalue = svalue.Substring(0, size);
466 svalue = svalue.ToString () + '\0';
469 // set bind length to size of data
470 //bindSize = (size + 1) * 4;
471 if (direction == ParameterDirection.Input)
472 bindSize = Encoding.UTF8.GetMaxByteCount (svalue.Length);
474 bindSize = Encoding.UTF8.GetMaxByteCount (size + 1);
476 // allocate memory based on bind length
477 bytes = new byte [bindSize];
479 if (direction == ParameterDirection.Input ||
480 direction == ParameterDirection.InputOutput) {
482 // convert managed type to memory allocated earlier
483 // in this case using OCIUnicodeToCharSet
485 // Get size of buffer
486 status = OciCalls.OCIUnicodeToCharSet (statement.Parent, null, svalue, out rsize);
488 status = OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, svalue, out rsize);
491 case OciDataType.Date:
492 bindType = OciDataType.Date;
494 // convert value from managed type to type to marshal
495 if (direction == ParameterDirection.Input ||
496 direction == ParameterDirection.InputOutput) {
499 bytes = new byte [7];
502 dt = DateTime.MinValue;
505 dt = DateTime.Parse (sDate);
507 else if (v is DateTime)
509 else if (v is OracleString) {
510 sDate = v.ToString ();
511 dt = DateTime.Parse (sDate);
513 else if (v is OracleDateTime) {
514 OracleDateTime odt = (OracleDateTime) v;
515 dt = (DateTime) odt.Value;
518 throw new NotImplementedException ("For OracleType.DateTime, data type not implemented: " + v.GetType().ToString() + ".");
520 // for Input and InputOuput, create byte array and pack DateTime into it
521 bytes = PackDate (dt);
524 // allocate 7-byte array for Output and ReturnValue to put date
525 bytes = new byte [7];
528 case OciDataType.TimeStamp:
529 dateTimeDesc = (OciDateTimeDescriptor) connection.Environment.Allocate (OciHandleType.TimeStamp);
530 if (dateTimeDesc == null) {
531 OciErrorInfo info = connection.ErrorHandle.HandleError ();
532 throw new OracleException (info.ErrorCode, info.ErrorMessage);
534 dateTimeDesc.ErrorHandle = connection.ErrorHandle;
536 bindType = OciDataType.TimeStamp;
537 bindOutValue = dateTimeDesc.Handle;
538 bindValue = dateTimeDesc.Handle;
540 if (direction == ParameterDirection.Input ||
541 direction == ParameterDirection.InputOutput) {
543 dt = DateTime.MinValue;
547 else if (v is String) {
549 dt = DateTime.Parse (sDate);
551 else if (v is DateTime)
553 else if (v is OracleString) {
555 dt = DateTime.Parse (sDate);
557 else if (v is OracleDateTime) {
558 OracleDateTime odt = (OracleDateTime) v;
559 dt = (DateTime) odt.Value;
562 throw new NotImplementedException ("For OracleType.Timestamp, data type not implemented: " + v.GetType().ToString()); // ?
564 short year = (short) dt.Year;
565 byte month = (byte) dt.Month;
566 byte day = (byte) dt.Day;
567 byte hour = (byte) dt.Hour;
568 byte min = (byte) dt.Minute;
569 byte sec = (byte) dt.Second;
570 uint fsec = (uint) dt.Millisecond;
571 string timezone = "";
572 dateTimeDesc.SetDateTime (connection.Session,
573 connection.ErrorHandle,
574 year, month, day, hour, min, sec, fsec,
578 case OciDataType.Integer:
579 case OciDataType.Float:
580 case OciDataType.Number:
581 bindType = OciDataType.String;
584 // define size for binding
585 bindSize = 30; // a NUMBER is 22 bytes but as a string we need more
587 bytes = new byte [bindSize];
588 // convert value from managed type to type to marshal
589 if (direction == ParameterDirection.Input ||
590 direction == ParameterDirection.InputOutput) {
593 if(v is IFormattable)
594 svalue = ((IFormattable)v).ToString (null, con.SessionFormatProvider);
595 else if (v is OracleNumber)
596 svalue = ((OracleNumber)v).ToString(con.SessionFormatProvider);
598 svalue = v.ToString();
600 svalue = svalue + "\0";
603 // Get size of buffer
604 OciCalls.OCIUnicodeToCharSet (statement.Parent, null, svalue, out rsize);
607 bytes = new byte [bindSize];
608 OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, svalue, out rsize);
611 case OciDataType.Long:
612 case OciDataType.LongVarChar:
613 bindType = OciDataType.LongVarChar;
615 // FIXME: use piecewise fetching for Long, Clob, Blob, and Long Raw
616 // See http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14250/oci05bnd.htm#sthref724
618 bindSize = Size + 5; // 4 bytes prepended for length, bytes, 1 byte NUL character
622 // convert value from managed type to type to marshal
623 if (direction == ParameterDirection.Input ||
624 direction == ParameterDirection.InputOutput) {
626 svalue = v.ToString () + '\0';
629 bytes = new byte [bindSize];
631 ASCIIEncoding enc = new ASCIIEncoding ();
633 if (direction == ParameterDirection.Input ||
634 direction == ParameterDirection.InputOutput) {
636 if (svalue.Length > 0) {
637 byteCount = enc.GetBytes (svalue, 4, svalue.Length, bytes, 0);
638 // LONG VARCHAR prepends a 4-byte length
640 byte[] byteArrayLen = BitConverter.GetBytes ((uint) byteCount);
641 bytes[0] = byteArrayLen[0];
642 bytes[1] = byteArrayLen[1];
643 bytes[2] = byteArrayLen[2];
644 bytes[3] = byteArrayLen[3];
649 case OciDataType.Clob:
650 if (direction == ParameterDirection.Input) {
651 svalue = v.ToString();
654 // Get size of buffer
655 OciCalls.OCIUnicodeToCharSet (statement.Parent, null, svalue, out rsize);
658 bytes = new byte[rsize];
659 OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, svalue, out rsize);
661 bindType = OciDataType.Long;
662 bindSize = bytes.Length;
664 else if (direction == ParameterDirection.InputOutput) {
665 // not the exact error that .net 2.0 throws, but this is better
666 throw new NotImplementedException ("Parameters of OracleType.Clob with direction of InputOutput are not supported.");
669 // Output and Return parameters
671 lobLocator = (OciLobLocator) connection.Environment.Allocate (OciHandleType.LobLocator);
672 if (lobLocator == null) {
673 OciErrorInfo info = connection.ErrorHandle.HandleError ();
674 throw new OracleException (info.ErrorCode, info.ErrorMessage);
676 bindOutValue = lobLocator.Handle;
677 bindValue = lobLocator.Handle;
678 lobLocator.ErrorHandle = connection.ErrorHandle;
679 lobLocator.Service = statement.Service;
683 case OciDataType.Blob:
684 if (direction == ParameterDirection.Input) {
687 bindType = OciDataType.LongRaw;
688 bindSize = bytes.Length;
690 else if (v is OracleLob) {
691 OracleLob lob = (OracleLob) v;
692 if (lob.LobType == OracleType.Blob) {
693 lobLocator = lob.Locator;
694 bindOutValue = lobLocator.Handle;
695 bindValue = lobLocator.Handle;
696 lobLocator.ErrorHandle = connection.ErrorHandle;
697 lobLocator.Service = connection.ServiceContext;
701 throw new NotImplementedException("For OracleType.Blob, data type OracleLob of LobType Clob/NClob is not implemented.");
704 throw new NotImplementedException ("For OracleType.Blob, data type not implemented: " + v.GetType().ToString()); // ?
706 else if (direction == ParameterDirection.InputOutput) {
707 // not the exact error that .net 2.0 throws, but this is better
708 throw new NotImplementedException ("Parameters of OracleType.Blob with direction of InputOutput are not supported.");
712 if (value != null && value is OracleLob) {
713 OracleLob blob = (OracleLob) value;
714 if (blob.LobType == OracleType.Blob)
715 if (value != OracleLob.Null) {
716 lobLocator = blob.Locator;
717 byte[] bs = (byte[]) blob.Value;
718 bindSize = bs.Length;
721 if (lobLocator == null) {
722 lobLocator = (OciLobLocator) connection.Environment.Allocate (OciHandleType.LobLocator);
723 if (lobLocator == null) {
724 OciErrorInfo info = connection.ErrorHandle.HandleError ();
725 throw new OracleException (info.ErrorCode, info.ErrorMessage);
728 bindOutValue = lobLocator.Handle;
729 bindValue = lobLocator.Handle;
730 lobLocator.ErrorHandle = connection.ErrorHandle;
731 lobLocator.Service = connection.ServiceContext;
736 // FIXME: move this up - see how Char, Number, and Date are done...
737 if (direction == ParameterDirection.Output ||
738 direction == ParameterDirection.InputOutput ||
739 direction == ParameterDirection.ReturnValue) {
742 case OciDataType.RowIdDescriptor:
744 bindType = OciDataType.Char;
746 bindOutValue = OciCalls.AllocateClear (bindSize);
747 bindValue = bindOutValue;
749 case OciDataType.RSet: // REF CURSOR
750 cursor = IntPtr.Zero;
751 OciCalls.OCIHandleAlloc (connection.Environment,
753 OciHandleType.Statement,
758 bindType = OciDataType.RSet;
761 // define other types
762 throw new NotImplementedException ("Data Type not implemented: " + ociType.ToString() + ".");
763 } // switch of ociDataType for output
764 bindValue = bindOutValue;
766 else if ((v == DBNull.Value || v == null || isnull == true) && direction == ParameterDirection.Input) {
768 bindType = OciDataType.VarChar2;
772 if (bindOracleType == OracleType.Raw) {
773 byte[] val = v as byte[];
774 bindValue = OciCalls.AllocateClear (val.Length);
775 Marshal.Copy (val, 0, bindValue, val.Length);
776 bindSize = val.Length;
778 svalue = v.ToString () + '\0';
781 // Get size of buffer
782 OciCalls.OCIUnicodeToCharSet (statement.Parent, null, svalue, out rsize);
785 bytes = new byte[rsize];
786 OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, svalue, out rsize);
788 bindType = OciDataType.String;
789 bindSize = bytes.Length;
791 } // else - Input, Ouput...
796 // Now, call the appropriate OCI Bind function;
798 if (useRef == true) {
799 if (bindType == OciDataType.TimeStamp) {
800 bindValue = dateTimeDesc.Handle;
801 status = OciCalls.OCIBindByNameRef (statement,
803 connection.ErrorHandle,
805 ParameterName.Length,
817 status = OciCalls.OCIBindByNameRef (statement,
819 connection.ErrorHandle,
821 ParameterName.Length,
833 else if (bindType == OciDataType.RSet) {
834 status = OciCalls.OCIBindByNameRef (statement,
836 connection.ErrorHandle,
838 ParameterName.Length,
849 else if (bytes != null) {
850 status = OciCalls.OCIBindByNameBytes (statement,
852 connection.ErrorHandle,
854 ParameterName.Length,
866 status = OciCalls.OCIBindByName (statement,
868 connection.ErrorHandle,
870 ParameterName.Length, // FIXME: this should be in bytes!
881 OciErrorHandle.ThrowExceptionIfError (connection.ErrorHandle, status);
883 bindHandle.SetHandle (tmpHandle);
886 object ICloneable.Clone ()
888 return new OracleParameter(this);
891 private void InferOracleType (object value)
893 // Should we throw an exception here?
894 if (value == null || value == DBNull.Value)
897 Type type = value.GetType ();
898 string exception = String.Format ("The parameter data type of {0} is invalid.", type.FullName);
899 switch (type.FullName) {
901 SetOracleType (OracleType.Number, true);
903 case "System.Boolean":
905 SetOracleType (OracleType.Byte, true);
907 case "System.String":
908 case "System.Data.OracleClient.OracleString":
909 SetOracleType (OracleType.VarChar, true);
911 case "System.Data.OracleClient.OracleDateTime":
912 case "System.DateTime":
913 SetOracleType (OracleType.DateTime, true);
915 case "System.Decimal":
916 case "System.Data.OracleClient.OracleNumber":
917 SetOracleType (OracleType.Number, true);
919 case "System.Double":
920 SetOracleType (OracleType.Double, true);
922 case "System.Byte[]":
924 SetOracleType (OracleType.Raw, true);
927 SetOracleType (OracleType.Int32, true);
929 case "System.Single":
930 SetOracleType (OracleType.Float, true);
933 SetOracleType (OracleType.Int16, true);
935 case "System.DBNull":
936 break; //unable to guess type
937 case "System.Data.OracleClient.OracleLob":
938 SetOracleType (((OracleLob) value).LobType, true);
941 throw new ArgumentException (exception);
945 private int InferSize ()
950 case OciDataType.VarChar2:
951 case OciDataType.String:
952 case OciDataType.VarChar:
953 case OciDataType.Char:
954 case OciDataType.CharZ:
955 case OciDataType.OciString:
956 case OciDataType.Long:
957 case OciDataType.LongVarChar:
958 if (value == null || value == DBNull.Value)
961 newSize = value.ToString ().Length;
963 case OciDataType.RowIdDescriptor:
966 case OciDataType.Integer:
967 case OciDataType.Number:
968 case OciDataType.Float:
971 case OciDataType.Date:
974 case OciDataType.TimeStamp:
977 case OciDataType.Blob:
978 case OciDataType.Clob:
979 case OciDataType.RSet: // REF CURSOR
983 if (value == null || value == DBNull.Value)
986 newSize = value.ToString ().Length;
995 private void SetDbType (DbType type)
997 string exception = String.Format ("No mapping exists from DbType {0} to a known OracleType.", type);
999 case DbType.AnsiString:
1000 oracleType = OracleType.VarChar;
1001 ociType = OciDataType.VarChar;
1003 case DbType.AnsiStringFixedLength:
1004 oracleType = OracleType.Char;
1005 ociType = OciDataType.Char;
1009 oracleType = OracleType.Raw;
1010 ociType = OciDataType.Raw;
1012 case DbType.Boolean:
1014 oracleType = OracleType.Byte;
1015 ociType = OciDataType.Integer;
1017 case DbType.Currency:
1018 case DbType.Decimal:
1020 oracleType = OracleType.Number;
1021 ociType = OciDataType.Number;
1024 case DbType.DateTime:
1026 oracleType = OracleType.DateTime;
1027 ociType = OciDataType.Char;
1030 oracleType = OracleType.Double;
1031 ociType = OciDataType.Float;
1034 oracleType = OracleType.Int16;
1035 ociType = OciDataType.Integer;
1038 oracleType = OracleType.Int32;
1039 ociType = OciDataType.Integer;
1042 oracleType = OracleType.Blob;
1043 ociType = OciDataType.Blob;
1046 oracleType = OracleType.Float;
1047 ociType = OciDataType.Float;
1050 oracleType = OracleType.NVarChar;
1051 ociType = OciDataType.VarChar;
1053 case DbType.StringFixedLength:
1054 oracleType = OracleType.NChar;
1055 ociType = OciDataType.Char;
1059 throw new ArgumentException (exception);
1064 private void SetOracleType (OracleType type, bool inferring)
1067 string exception = String.Format ("No mapping exists from OracleType {0} to a known DbType.", type);
1069 case OracleType.BFile:
1070 case OracleType.Blob:
1071 dbType = DbType.Binary;
1072 ociType = OciDataType.Blob;
1074 case OracleType.LongRaw:
1075 case OracleType.Raw:
1076 dbType = DbType.Binary;
1077 ociType = OciDataType.Raw;
1079 case OracleType.Byte:
1080 dbType = DbType.Byte;
1081 ociType = OciDataType.Number;
1083 case OracleType.Char:
1084 dbType = DbType.AnsiString;
1085 ociType = OciDataType.Char;
1087 case OracleType.Clob:
1088 dbType = DbType.AnsiString;
1089 ociType = OciDataType.Clob;
1091 case OracleType.LongVarChar:
1092 case OracleType.RowId:
1093 case OracleType.VarChar:
1094 dbType = DbType.AnsiString;
1095 ociType = OciDataType.VarChar;
1097 case OracleType.Cursor: // REF CURSOR
1098 ociType = OciDataType.RSet;
1099 dbType = DbType.Object;
1101 case OracleType.IntervalDayToSecond:
1102 dbType = DbType.AnsiStringFixedLength;
1103 ociType = OciDataType.Char;
1105 case OracleType.Timestamp:
1106 case OracleType.TimestampLocal:
1107 case OracleType.TimestampWithTZ:
1108 dbType = DbType.DateTime;
1109 ociType = OciDataType.TimeStamp;
1111 case OracleType.DateTime:
1112 dbType = DbType.DateTime;
1113 ociType = OciDataType.Date;
1115 case OracleType.Double:
1116 dbType = DbType.Double;
1117 ociType = OciDataType.Number;
1119 case OracleType.Float:
1120 dbType = DbType.Single;
1121 ociType = OciDataType.Number;
1123 case OracleType.Int16:
1124 dbType = DbType.Int16;
1125 ociType = OciDataType.Number;
1127 case OracleType.Int32:
1128 case OracleType.IntervalYearToMonth:
1129 dbType = DbType.Int32;
1130 ociType = OciDataType.Number;
1132 case OracleType.NChar:
1133 dbType = DbType.StringFixedLength;
1134 ociType = OciDataType.Char;
1136 case OracleType.NClob:
1137 case OracleType.NVarChar:
1138 dbType = DbType.String;
1139 ociType = OciDataType.Char;
1141 case OracleType.Number:
1142 dbType = DbType.VarNumeric;
1143 ociType = OciDataType.Number;
1145 case OracleType.SByte:
1146 dbType = DbType.SByte;
1147 ociType = OciDataType.Number;
1149 case OracleType.UInt16:
1150 dbType = DbType.UInt16;
1151 ociType = OciDataType.Number;
1153 case OracleType.UInt32:
1154 dbType = DbType.UInt32;
1155 ociType = OciDataType.Number;
1158 throw new ArgumentException (exception);
1161 if (!oracleTypeSet || !inferring )
1163 bindOracleType = type;
1167 public override void ResetDbType ()
1172 public void ResetOracleType ()
1174 oracleTypeSet = false;
1175 InferOracleType (value);
1179 public override string ToString ()
1181 return ParameterName;
1184 private void GetOutValue (OracleCommand cmd)
1186 // used to update the parameter value
1187 // for Output, the output of InputOutput, and Return parameters
1188 value = DBNull.Value;
1189 if (indicator == -1)
1193 IntPtr env = IntPtr.Zero;
1194 StringBuilder ret = null;
1196 // FIXME: redo all types - see how Char, Number, and Date are done
1197 // here and in Bind()
1200 case OciDataType.VarChar2:
1201 case OciDataType.String:
1202 case OciDataType.VarChar:
1203 case OciDataType.Char:
1204 case OciDataType.CharZ:
1205 case OciDataType.OciString:
1206 case OciDataType.RowIdDescriptor:
1207 // Get length of returned string
1209 env = cmd.Connection.Environment;
1210 OciCalls.OCICharSetToUnicode (env, null, bytes, out rsize);
1213 ret = new StringBuilder(rsize);
1214 OciCalls.OCICharSetToUnicode (env, ret, bytes, out rsize);
1216 value = ret.ToString ();
1218 case OciDataType.Long:
1219 case OciDataType.LongVarChar:
1221 if (BitConverter.IsLittleEndian)
1222 longSize = BitConverter.ToInt32 (new byte [] {bytes [0], bytes [1], bytes [2], bytes [3]}, 0);
1224 longSize = BitConverter.ToInt32 (new byte [] {bytes [3], bytes [2], bytes [1], bytes [0]}, 0);
1226 ASCIIEncoding encoding = new ASCIIEncoding ();
1227 value = encoding.GetString (bytes, 4, longSize);
1230 case OciDataType.Integer:
1231 case OciDataType.Number:
1232 case OciDataType.Float:
1234 env = cmd.Connection.Environment;
1235 OciCalls.OCICharSetToUnicode (env, null, bytes, out rsize);
1238 ret = new StringBuilder(rsize);
1239 OciCalls.OCICharSetToUnicode (env, ret, bytes, out rsize);
1241 // if not empty, parse string as a decimal using session format
1243 value = Decimal.Parse (ret.ToString (), cmd.Connection.SessionFormatProvider);
1245 case OciDataType.TimeStamp:
1246 value = dateTimeDesc.GetDateTime (connection.Environment, dateTimeDesc.ErrorHandle);
1248 case OciDataType.Date:
1249 value = UnpackDate (bytes);
1251 case OciDataType.Blob:
1252 case OciDataType.Clob:
1253 if (value != null && value is OracleLob && value != OracleLob.Null) {
1254 OracleLob lob2 = (OracleLob) value;
1255 lob2.connection = connection;
1258 OracleLob lob = new OracleLob (lobLocator, ociType);
1259 lob.connection = connection;
1263 case OciDataType.RSet: // REF CURSOR
1264 OciStatementHandle cursorStatement = GetOutRefCursor (cmd);
1265 value = new OracleDataReader (cursorStatement.Command, cursorStatement, true, CommandBehavior.Default);
1268 throw new NotImplementedException ("Data Type not implemented: " + ociType.ToString() + ".");
1272 internal OciStatementHandle GetOutRefCursor (OracleCommand cmd)
1274 OciStatementHandle cursorStatement = new OciStatementHandle (cmd.Connection.ServiceContext, cursor);
1276 cursorStatement.ErrorHandle = cmd.ErrorHandle;
1277 cursorStatement.Command = cmd;
1278 cursorStatement.SetupRefCursorResult (cmd.Connection);
1279 cursorStatement.Service = cmd.Connection.ServiceContext;
1280 cursor = IntPtr.Zero;
1281 return cursorStatement;
1284 internal void Update (OracleCommand cmd)
1286 if (Direction != ParameterDirection.Input)
1292 internal void FreeHandle ()
1295 case OciDataType.Clob:
1296 case OciDataType.Blob:
1299 case OciDataType.Raw:
1300 Marshal.FreeHGlobal (bindValue);
1302 case OciDataType.TimeStamp:
1305 Marshal.FreeHGlobal (bindOutValue);
1309 bindOutValue = IntPtr.Zero;
1310 bindValue = IntPtr.Zero;
1316 // copied from OciDefineHandle
1317 [MonoTODO ("Be able to handle negative dates... i.e. BCE.")]
1318 private DateTime UnpackDate (byte[] bytes)
1320 byte century = bytes [0];
1321 byte year = bytes [1];
1322 byte month = bytes [2];
1323 byte day = bytes [3];
1324 byte hour = bytes [4];
1325 byte minute = bytes [5];
1326 byte second = bytes [6];
1329 return new DateTime ((century - 100) * 100 + (year - 100),
1338 private byte[] PackDate (DateTime dateValue)
1340 byte[] buffer = new byte[7];
1342 buffer[0] = (byte)((dateValue.Year / 100) + 100); //century
1343 buffer[1] = (byte)((dateValue.Year % 100) + 100); // Year
1344 buffer[2] = (byte)dateValue.Month;
1345 buffer[3] = (byte)dateValue.Day;
1346 buffer[4] = (byte)(dateValue.Hour+1);
1347 buffer[5] = (byte)(dateValue.Minute+1);
1348 buffer[6] = (byte)(dateValue.Second+1);
1353 #endregion // Methods
1355 internal sealed class OracleParameterConverter : ExpandableObjectConverter
1357 public OracleParameterConverter ()
1362 public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
1364 throw new NotImplementedException ();
1368 public override object ConvertTo (ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
1370 throw new NotImplementedException ();