4 // Part of managed C#/.NET library System.Data.OracleClient.dll
6 // Part of the Mono class libraries at
7 // mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci
9 // Assembly: System.Data.OracleClient.dll
10 // Namespace: System.Data.OracleClient.Oci
13 // Tim Coleman <tim@timcoleman.com>
14 // Daniel Morgan <danielmorgan@verizon.net>
16 // Copyright (C) Tim Coleman, 2003
17 // Copyright (C) Daniel Morgan, 2004
21 using System.Data.OracleClient;
22 using System.Runtime.InteropServices;
25 namespace System.Data.OracleClient.Oci
27 internal sealed class OciDefineHandle : OciHandle, IDisposable
31 bool disposed = false;
38 OciDataType definedType;
46 OciErrorHandle errorHandle;
48 OciLobLocator lobLocator;
55 public OciDefineHandle (OciHandle parent, IntPtr newHandle)
56 : base (OciHandleType.Define, parent, newHandle)
60 public void DefineByPosition (int position)
62 OciParameterDescriptor parameter = ((OciStatementHandle) Parent).GetParameter (position);
64 name = parameter.GetName ();
65 definedType = parameter.GetDataType ();
66 definedSize = parameter.GetDataSize ();
67 precision = parameter.GetPrecision ();
68 scale = parameter.GetScale ();
75 #endregion // Constructors
79 public OciDataType DataType {
80 get { return definedType; }
83 public Type FieldType {
84 get { return fieldType; }
87 public int DefinedSize {
88 get { return definedSize; }
91 public OciErrorHandle ErrorHandle {
92 get { return errorHandle; }
93 set { errorHandle = value; }
97 get { return (indicator == -1); }
101 get { return scale; }
105 get { return rlenp; }
108 public IntPtr Value {
109 get { return value; }
116 void Define (int position)
118 switch (definedType) {
119 case OciDataType.Date:
120 DefineDate (position);
122 case OciDataType.Clob:
123 case OciDataType.Blob:
124 DefineLob (position, definedType);
126 case OciDataType.Raw:
127 DefineRaw( position);
129 case OciDataType.RowIdDescriptor:
131 DefineChar (position);
133 case OciDataType.Integer:
134 case OciDataType.Number:
135 case OciDataType.Float:
136 DefineNumber (position);
139 DefineChar (position); // HANDLE ALL OTHERS AS CHAR FOR NOW
144 void DefineDate (int position)
147 ociType = OciDataType.Date;
148 fieldType = typeof(System.DateTime);
150 value = Marshal.AllocHGlobal (definedSize);
154 status = OciCalls.OCIDefineByPos (Parent,
167 OciErrorInfo info = ErrorHandle.HandleError ();
168 throw new OracleException (info.ErrorCode, info.ErrorMessage);
172 void DefineChar (int position)
174 fieldType = typeof (System.String);
176 // The buffer is able to contain twice the defined size
177 // to allow usage of multibyte characters
178 value = Marshal.AllocHGlobal (definedSize * 2);
180 ociType = OciDataType.Char;
184 status = OciCalls.OCIDefineByPos (Parent,
197 OciErrorInfo info = ErrorHandle.HandleError ();
198 throw new OracleException (info.ErrorCode, info.ErrorMessage);
202 void DefineNumber (int position)
204 fieldType = typeof (System.Decimal);
205 value = Marshal.AllocHGlobal (definedSize);
207 ociType = OciDataType.Char;
211 status = OciCalls.OCIDefineByPos (Parent,
224 OciErrorInfo info = ErrorHandle.HandleError ();
225 throw new OracleException (info.ErrorCode, info.ErrorMessage);
229 void DefineLob (int position, OciDataType type)
233 if (ociType == OciDataType.Clob)
234 fieldType = typeof(System.String);
235 else if (ociType == OciDataType.Blob)
236 fieldType = Type.GetType("System.Byte[]");
242 lobLocator = (OciLobLocator) Parent.Parent.Allocate (OciHandleType.LobLocator);
244 if (lobLocator == null) {
245 OciErrorInfo info = ErrorHandle.HandleError ();
246 throw new OracleException (info.ErrorCode, info.ErrorMessage);
249 value = lobLocator.Handle;
250 lobLocator.ErrorHandle = ErrorHandle;
251 lobLocator.Service = ((OciStatementHandle) Parent).Service;
253 status = OciCalls.OCIDefineByPosPtr (Parent,
265 definedSize = Int32.MaxValue;
268 OciErrorInfo info = ErrorHandle.HandleError ();
269 throw new OracleException (info.ErrorCode, info.ErrorMessage);
273 void DefineRaw (int position)
275 ociType = OciDataType.Raw;
276 fieldType = Type.GetType("System.Byte[]");
278 value = Marshal.AllocHGlobal (definedSize);
282 status = OciCalls.OCIDefineByPos (Parent,
294 OciErrorInfo info = ErrorHandle.HandleError ();
295 throw new OracleException (info.ErrorCode, info.ErrorMessage);
299 protected override void Dispose (bool disposing)
303 switch (definedType) {
304 case OciDataType.Clob:
305 case OciDataType.Blob:
308 Marshal.FreeHGlobal (value);
313 base.Dispose (disposing);
319 public OracleLob GetOracleLob ()
321 return new OracleLob (lobLocator, ociType);
324 public object GetValue ()
329 case OciDataType.VarChar2:
330 case OciDataType.String:
331 case OciDataType.VarChar:
332 case OciDataType.Char:
333 case OciDataType.CharZ:
334 case OciDataType.OciString:
335 case OciDataType.RowIdDescriptor:
336 case OciDataType.LongVarChar:
337 byte [] buffer = new byte [Size];
338 Marshal.Copy (Value, buffer, 0, Size);
340 // Get length of returned string
342 IntPtr env = Parent.Parent; // Parent is statement, grandparent is environment
343 OciCalls.OCICharSetToUnicode (env, null, buffer, out rsize);
346 StringBuilder ret = new StringBuilder(rsize);
347 OciCalls.OCICharSetToUnicode (env, ret, buffer, out rsize);
349 return ret.ToString ();
351 case OciDataType.Integer:
352 case OciDataType.Number:
353 case OciDataType.Float:
354 tmp = Marshal.PtrToStringAnsi (Value, Size);
356 return Decimal.Parse (String.Copy ((string) tmp));
358 case OciDataType.Date:
359 return UnpackDate ();
360 case OciDataType.Raw:
361 byte [] raw_buffer = new byte [Size];
362 Marshal.Copy (Value, raw_buffer, 0, Size);
364 case OciDataType.Blob:
365 case OciDataType.Clob:
366 return GetOracleLob ();
372 internal object GetOracleValue ()
374 object ovalue = GetValue ();
377 case OciDataType.Raw:
378 return new OracleBinary ((byte[]) ovalue);
379 case OciDataType.Date:
380 return new OracleDateTime ((DateTime) ovalue);
381 case OciDataType.Blob:
382 case OciDataType.Clob:
383 OracleLob lob = (OracleLob) ovalue;
385 case OciDataType.Integer:
386 case OciDataType.Number:
387 case OciDataType.Float:
388 return new OracleNumber ((decimal) ovalue);
389 case OciDataType.VarChar2:
390 case OciDataType.String:
391 case OciDataType.VarChar:
392 case OciDataType.Char:
393 case OciDataType.CharZ:
394 case OciDataType.OciString:
395 case OciDataType.LongVarChar:
396 case OciDataType.RowIdDescriptor:
397 return new OracleString ((string) ovalue);
399 // TODO: do other types
400 throw new NotImplementedException ();
404 [MonoTODO ("Be able to handle negative dates... i.e. BCE.")]
405 public DateTime UnpackDate ()
407 byte century = Marshal.ReadByte (value, 0);
408 byte year = Marshal.ReadByte (value, 1);
409 byte month = Marshal.ReadByte (value, 2);
410 byte day = Marshal.ReadByte (value, 3);
411 byte hour = Marshal.ReadByte (value, 4);
412 byte minute = Marshal.ReadByte (value, 5);
413 byte second = Marshal.ReadByte (value, 6);
415 return new DateTime ((century - 100) * 100 + (year - 100),
424 #endregion // Methods