+
+ // allocate memory based on bind size
+ bytes = new byte [bindSize];
+
+ // Fill buffer
+ status = OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, svalue, out rsize);
+ } else {
+ // for Output and ReturnValue parameters, get size in bytes
+ bindSize = Encoding.UTF8.GetMaxByteCount (size + 1);
+ // allocate memory for oracle to place the results for the Return or Output param
+ bytes = new byte [bindSize];
+ }
+ break;
+ case OciDataType.Date:
+ bindType = OciDataType.Date;
+ bindSize = 7;
+ // convert value from managed type to type to marshal
+ if (direction == ParameterDirection.Input ||
+ direction == ParameterDirection.InputOutput) {
+
+ if (isnull)
+ bytes = new byte [7];
+ else {
+ sDate = "";
+ dt = DateTime.MinValue;
+ if (v is String) {
+ sDate = (string) v;
+ dt = DateTime.Parse (sDate);
+ }
+ else if (v is DateTime)
+ dt = (DateTime) v;
+ else if (v is OracleString) {
+ sDate = v.ToString ();
+ dt = DateTime.Parse (sDate);
+ }
+ else if (v is OracleDateTime) {
+ OracleDateTime odt = (OracleDateTime) v;
+ dt = (DateTime) odt.Value;
+ }
+ else
+ throw new NotImplementedException ("For OracleType.DateTime, data type not implemented: " + v.GetType().ToString() + ".");
+
+ // for Input and InputOuput, create byte array and pack DateTime into it
+ bytes = PackDate (dt);
+ }
+ } else {
+ // allocate 7-byte array for Output and ReturnValue to put date
+ bytes = new byte [7];
+ }
+ break;
+ case OciDataType.TimeStamp:
+ dateTimeDesc = (OciDateTimeDescriptor) connection.Environment.Allocate (OciHandleType.TimeStamp);
+ if (dateTimeDesc == null) {
+ OciErrorInfo info = connection.ErrorHandle.HandleError ();
+ throw new OracleException (info.ErrorCode, info.ErrorMessage);
+ }
+ dateTimeDesc.ErrorHandle = connection.ErrorHandle;
+ bindSize = 11;
+ bindType = OciDataType.TimeStamp;
+ bindOutValue = dateTimeDesc.Handle;
+ bindValue = dateTimeDesc.Handle;
+ useRef = true;
+ if (direction == ParameterDirection.Input ||
+ direction == ParameterDirection.InputOutput) {
+
+ dt = DateTime.MinValue;
+ sDate = "";
+ if (isnull)
+ indicator = -1;
+ else if (v is String) {
+ sDate = (string) v;
+ dt = DateTime.Parse (sDate);
+ }
+ else if (v is DateTime)
+ dt = (DateTime) v;
+ else if (v is OracleString) {
+ sDate = (string) v;
+ dt = DateTime.Parse (sDate);
+ }
+ else if (v is OracleDateTime) {
+ OracleDateTime odt = (OracleDateTime) v;
+ dt = (DateTime) odt.Value;
+ }
+ else
+ throw new NotImplementedException ("For OracleType.Timestamp, data type not implemented: " + v.GetType().ToString()); // ?
+
+ short year = (short) dt.Year;
+ byte month = (byte) dt.Month;
+ byte day = (byte) dt.Day;
+ byte hour = (byte) dt.Hour;
+ byte min = (byte) dt.Minute;
+ byte sec = (byte) dt.Second;
+ uint fsec = (uint) dt.Millisecond;
+ string timezone = "";
+ dateTimeDesc.SetDateTime (connection.Session,
+ connection.ErrorHandle,
+ year, month, day, hour, min, sec, fsec,
+ timezone);
+ }
+ break;
+ case OciDataType.Integer:
+ case OciDataType.Float:
+ case OciDataType.Number:
+ bindType = OciDataType.String;
+ indicator = 0;
+ svalue = "\0";
+ // convert value from managed type to type to marshal
+ if (direction == ParameterDirection.Input ||
+ direction == ParameterDirection.InputOutput) {
+
+ svalue = null;
+ if(v is IFormattable)
+ svalue = ((IFormattable)v).ToString (null, con.SessionFormatProvider);
+ else if (v is OracleNumber)
+ svalue = ((OracleNumber)v).ToString(con.SessionFormatProvider);
+ else
+ svalue = v.ToString();
+
+ svalue = svalue + "\0";
+
+ rsize = 0;
+ // Get size of buffer
+ OciCalls.OCIUnicodeToCharSet (statement.Parent, null, svalue, out rsize);
+
+ // Fill buffer
+
+ if (direction == ParameterDirection.Input)
+ bindSize = rsize;
+ else
+ bindSize = 30; // need room for output possibly being bigger than the input
+
+ bytes = new byte [bindSize];
+ OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, svalue, out rsize);
+ } else {
+ // Output and ReturnValue parameters allocate memory
+ bindSize = 30;
+ bytes = new byte [bindSize];
+ }
+ break;
+ case OciDataType.Long:
+ case OciDataType.LongVarChar:
+ bindType = OciDataType.LongVarChar;
+
+ // FIXME: use piecewise fetching for Long, Clob, Blob, and Long Raw
+ // See http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14250/oci05bnd.htm#sthref724
+
+ bindSize = Size + 5; // 4 bytes prepended for length, bytes, 1 byte NUL character
+
+ indicator = 0;
+ svalue = "\0";
+ // convert value from managed type to type to marshal
+ if (direction == ParameterDirection.Input ||
+ direction == ParameterDirection.InputOutput) {
+
+ svalue = v.ToString () + '\0';
+ }
+
+ bytes = new byte [bindSize];
+ // LONG is only ANSI
+ ASCIIEncoding enc = new ASCIIEncoding ();
+
+ if (direction == ParameterDirection.Input ||
+ direction == ParameterDirection.InputOutput) {
+ if (svalue.Length > 0) {
+ byteCount = enc.GetBytes (svalue, 4, svalue.Length, bytes, 0);
+ // LONG VARCHAR prepends a 4-byte length
+ if (byteCount > 0) {
+ byteArrayLen = BitConverter.GetBytes ((uint) byteCount);
+ bytes[0] = byteArrayLen[0];
+ bytes[1] = byteArrayLen[1];
+ bytes[2] = byteArrayLen[2];
+ bytes[3] = byteArrayLen[3];
+ }
+ }
+ }
+ break;
+ case OciDataType.Clob:
+ if (direction == ParameterDirection.Input) {
+ svalue = v.ToString();
+ rsize = 0;
+
+ // Get size of buffer
+ OciCalls.OCIUnicodeToCharSet (statement.Parent, null, svalue, out rsize);
+
+ // Fill buffer
+ bytes = new byte[rsize];
+ OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, svalue, out rsize);
+
+ bindType = OciDataType.Long;
+ bindSize = bytes.Length;
+ }
+ else if (direction == ParameterDirection.InputOutput) {
+ // not the exact error that .net 2.0 throws, but this is better
+ throw new NotImplementedException ("Parameters of OracleType.Clob with direction of InputOutput are not supported.");
+ }
+ else {
+ // Output and Return parameters