{
this.name = name;
this.value = value;
+ if (value != null) {
+ this.sizeSet = true;
+ this.size = InferSize (value);
+ }
srcColumn = string.Empty;
SourceVersion = DataRowVersion.Current;
- InferOracleType (value);
+ InferOracleType (value);
}
public OracleParameter (string name, OracleType oracleType)
if (size < 0)
throw new ArgumentException("Size must be not be negative.");
this.size = size;
+ this.sizeSet = true;
this.value = value;
SourceColumnNullMapping = sourceColumnNullMapping;
OracleType = oracleType;
if (size < 0)
throw new ArgumentException("Size must be not be negative.");
this.size = size;
+ this.sizeSet = true;
this.value = value;
this.isNullable = isNullable;
this.precision = precision;
this.value = value;
if (!oracleTypeSet)
InferOracleType (value);
+ if (value != null) {
+ this.size = InferSize ();
+ this.sizeSet = true;
+ }
}
}
if (direction == ParameterDirection.Input ||
direction == ParameterDirection.InputOutput) {
- svalue = v.ToString () + '\0';
+ svalue = v.ToString ();
+
+ if (direction == ParameterDirection.Input && size > 0 && svalue.Length > size)
+ svalue = svalue.Substring(0, size);
+
+ svalue = svalue.ToString () + '\0';
}
// set bind length to size of data
- bindSize = (size + 1) * 4;
+ //bindSize = (size + 1) * 4;
+ if (direction == ParameterDirection.Input)
+ bindSize = Encoding.UTF8.GetMaxByteCount (svalue.Length);
+ else
+ bindSize = Encoding.UTF8.GetMaxByteCount (size + 1);
// allocate memory based on bind length
- bytes = new byte[bindSize];
+ bytes = new byte [bindSize];
if (direction == ParameterDirection.Input ||
direction == ParameterDirection.InputOutput) {
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;
OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, svalue, out rsize);
}
break;
- case OciDataType.Long:
- case OciDataType.LongVarChar:
- bindType = OciDataType.LongVarChar;
+ 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
+ // 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) {
+ indicator = 0;
+ svalue = "\0";
+ // convert value from managed type to type to marshal
+ if (direction == ParameterDirection.Input ||
+ direction == ParameterDirection.InputOutput) {
- svalue = v.ToString () + '\0';
- }
+ svalue = v.ToString () + '\0';
+ }
- bytes = new byte [bindSize];
- // LONG is only ANSI
- ASCIIEncoding enc = new ASCIIEncoding ();
-
- if (direction == ParameterDirection.Input ||
- direction == ParameterDirection.InputOutput) {
- int byteCount = 0;
- if (svalue.Length > 0) {
- byteCount = enc.GetBytes (svalue, 4, svalue.Length, bytes, 0);
- // LONG VARCHAR prepends a 4-byte length
- if (byteCount > 0) {
- byte[] byteArrayLen = BitConverter.GetBytes ((uint) byteCount);
- bytes[0] = byteArrayLen[0];
- bytes[1] = byteArrayLen[1];
- bytes[2] = byteArrayLen[2];
- bytes[3] = byteArrayLen[3];
- }
+ bytes = new byte [bindSize];
+ // LONG is only ANSI
+ ASCIIEncoding enc = new ASCIIEncoding ();
+
+ if (direction == ParameterDirection.Input ||
+ direction == ParameterDirection.InputOutput) {
+ int byteCount = 0;
+ if (svalue.Length > 0) {
+ byteCount = enc.GetBytes (svalue, 4, svalue.Length, bytes, 0);
+ // LONG VARCHAR prepends a 4-byte length
+ if (byteCount > 0) {
+ byte[] 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;
+ }
+ 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);
+ // 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);
+ // Fill buffer
+ bytes = new byte[rsize];
+ OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, svalue, out rsize);
- bindType = OciDataType.Long;
+ 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
+ bindSize = -1;
+ lobLocator = (OciLobLocator) connection.Environment.Allocate (OciHandleType.LobLocator);
+ if (lobLocator == null) {
+ OciErrorInfo info = connection.ErrorHandle.HandleError ();
+ throw new OracleException (info.ErrorCode, info.ErrorMessage);
+ }
+ bindOutValue = lobLocator.Handle;
+ bindValue = lobLocator.Handle;
+ lobLocator.ErrorHandle = connection.ErrorHandle;
+ lobLocator.Service = statement.Service;
+ useRef = true;
+ }
+ break;
+ case OciDataType.Blob:
+ if (direction == ParameterDirection.Input) {
+ if (v is byte[]) {
+ bytes = (byte[]) v;
+ bindType = OciDataType.LongRaw;
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
- bindSize = -1;
+ }
+ else if (v is OracleLob) {
+ OracleLob lob = (OracleLob) v;
+ if (lob.LobType == OracleType.Blob) {
+ lobLocator = lob.Locator;
+ bindOutValue = lobLocator.Handle;
+ bindValue = lobLocator.Handle;
+ lobLocator.ErrorHandle = connection.ErrorHandle;
+ lobLocator.Service = connection.ServiceContext;
+ useRef = true;
+ }
+ else
+ throw new NotImplementedException("For OracleType.Blob, data type OracleLob of LobType Clob/NClob is not implemented.");
+ }
+ else
+ throw new NotImplementedException ("For OracleType.Blob, data type not implemented: " + v.GetType().ToString()); // ?
+ }
+ else if (direction == ParameterDirection.InputOutput) {
+ // not the exact error that .net 2.0 throws, but this is better
+ throw new NotImplementedException ("Parameters of OracleType.Blob with direction of InputOutput are not supported.");
+ }
+ else {
+ bindSize = -1;
+ if (value != null && value is OracleLob) {
+ OracleLob blob = (OracleLob) value;
+ if (blob.LobType == OracleType.Blob)
+ if (value != OracleLob.Null) {
+ lobLocator = blob.Locator;
+ byte[] bs = (byte[]) blob.Value;
+ bindSize = bs.Length;
+ }
+ }
+ if (lobLocator == null) {
lobLocator = (OciLobLocator) connection.Environment.Allocate (OciHandleType.LobLocator);
if (lobLocator == null) {
OciErrorInfo info = connection.ErrorHandle.HandleError ();
throw new OracleException (info.ErrorCode, info.ErrorMessage);
}
- bindOutValue = lobLocator.Handle;
- bindValue = lobLocator.Handle;
- lobLocator.ErrorHandle = connection.ErrorHandle;
- lobLocator.Service = statement.Service;
- useRef = true;
}
- break;
+ bindOutValue = lobLocator.Handle;
+ bindValue = lobLocator.Handle;
+ lobLocator.ErrorHandle = connection.ErrorHandle;
+ lobLocator.Service = connection.ServiceContext;
+ useRef = true;
+ }
+ break;
default:
// FIXME: move this up - see how Char, Number, and Date are done...
if (direction == ParameterDirection.Output ||
bindOutValue = OciCalls.AllocateClear (bindSize);
bindValue = bindOutValue;
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;
- break;
- case OciDataType.Blob:
- bindSize = -1;
- lobLocator = (OciLobLocator) connection.Environment.Allocate (OciHandleType.LobLocator);
- if (lobLocator == null) {
- OciErrorInfo info = connection.ErrorHandle.HandleError ();
- throw new OracleException (info.ErrorCode, info.ErrorMessage);
- }
- bindOutValue = lobLocator.Handle;
- bindValue = lobLocator.Handle;
- lobLocator.ErrorHandle = connection.ErrorHandle;
- lobLocator.Service = statement.Service;
- useRef = true;
- break;
case OciDataType.RSet: // REF CURSOR
cursor = IntPtr.Zero;
OciCalls.OCIHandleAlloc (connection.Environment,
bindSize = 0;
}
else {
- sDate = "";
- dt = DateTime.MinValue;
- if (bindOracleType == OracleType.Timestamp){
- bindType = OciDataType.TimeStamp;
- bindSize = 11;
- dt = DateTime.MinValue;
- sDate = "";
- 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 = (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;
- dateTimeDesc.SetDateTime (connection.Session,
- connection.ErrorHandle,
- year, month, day, hour, min, sec, fsec,
- timezone);
- useRef = true;
- }
- else if (bindOracleType == OracleType.Blob) {
- bytes = (byte[]) v;
- bindType = OciDataType.LongRaw;
- bindSize = bytes.Length;
- }
- else if (bindOracleType == OracleType.Raw) {
+ if (bindOracleType == OracleType.Raw) {
byte[] val = v as byte[];
bindValue = OciCalls.AllocateClear (val.Length);
Marshal.Copy (val, 0, bindValue, val.Length);
OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, svalue, out rsize);
bindType = OciDataType.String;
- bindSize = svalue.Length;
+ bindSize = bytes.Length;
} // else oracleType
} // else - Input, Ouput...
break;
private void InferOracleType (object value)
{
+ // Should we throw an exception here?
+ if (value is null)
+ return;
+
Type type = value.GetType ();
string exception = String.Format ("The parameter data type of {0} is invalid.", type.FullName);
switch (type.FullName) {
break;
case DbType.StringFixedLength:
oracleType = OracleType.NChar;
- ociType = OciDataType.Char;
+ ociType = OciDataType.Char;
+
break;
default:
throw new ArgumentException (exception);
throw new ArgumentException (exception);
}
- if (!inferring)
+ if (!oracleTypeSet || !inferring )
oracleType = type;
bindOracleType = type;
}
break;
case OciDataType.Blob:
case OciDataType.Clob:
- OracleLob lob = new OracleLob (lobLocator, ociType);
- lob.connection = connection;
- value = lob;
+ if (value != null && value is OracleLob && value != OracleLob.Null) {
+ OracleLob lob2 = (OracleLob) value;
+ lob2.connection = connection;
+ }
+ else {
+ OracleLob lob = new OracleLob (lobLocator, ociType);
+ lob.connection = connection;
+ value = lob;
+ }
break;
case OciDataType.RSet: // REF CURSOR
OciStatementHandle cursorStatement = GetOutRefCursor (cmd);