OciDefineHandle.cs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. //
  2. // OciDefineHandle.cs
  3. //
  4. // Part of managed C#/.NET library System.Data.OracleClient.dll
  5. //
  6. // Part of the Mono class libraries at
  7. // mcs/class/System.Data.OracleClient/System.Data.OracleClient.Oci
  8. //
  9. // Assembly: System.Data.OracleClient.dll
  10. // Namespace: System.Data.OracleClient.Oci
  11. //
  12. // Authors:
  13. // Tim Coleman <[email protected]>
  14. // Daniel Morgan <[email protected]>
  15. //
  16. // Copyright (C) Tim Coleman, 2003
  17. // Copyright (C) Daniel Morgan, 2004
  18. //
  19. using System;
  20. using System.Data.OracleClient;
  21. using System.Runtime.InteropServices;
  22. using System.Text;
  23. namespace System.Data.OracleClient.Oci
  24. {
  25. internal sealed class OciDefineHandle : OciHandle, IDisposable
  26. {
  27. #region Fields
  28. bool disposed = false;
  29. IntPtr handle;
  30. IntPtr value;
  31. short indicator;
  32. OracleType type;
  33. OciDataType ociType;
  34. OciDataType definedType;
  35. int definedSize;
  36. short rlenp = 0;
  37. short precision;
  38. short scale;
  39. Type fieldType;
  40. string name;
  41. OciErrorHandle errorHandle;
  42. OciLobLocator lobLocator;
  43. byte[] date;
  44. #endregion // Fields
  45. #region Constructors
  46. public OciDefineHandle (OciHandle parent, IntPtr newHandle)
  47. : base (OciHandleType.Define, parent, newHandle)
  48. {
  49. }
  50. public void DefineByPosition (int position)
  51. {
  52. OciParameterDescriptor parameter = ((OciStatementHandle) Parent).GetParameter (position);
  53. name = parameter.GetName ();
  54. definedType = parameter.GetDataType ();
  55. definedSize = parameter.GetDataSize ();
  56. precision = parameter.GetPrecision ();
  57. scale = parameter.GetScale ();
  58. Define (position);
  59. parameter.Dispose ();
  60. }
  61. #endregion // Constructors
  62. #region Properties
  63. public OciDataType DataType {
  64. get { return definedType; }
  65. }
  66. public Type FieldType {
  67. get { return fieldType; }
  68. }
  69. public int DefinedSize {
  70. get { return definedSize; }
  71. }
  72. public OciErrorHandle ErrorHandle {
  73. get { return errorHandle; }
  74. set { errorHandle = value; }
  75. }
  76. public bool IsNull {
  77. get { return (indicator == -1); }
  78. }
  79. public short Scale {
  80. get { return scale; }
  81. }
  82. public short Size {
  83. get { return rlenp; }
  84. }
  85. public IntPtr Value {
  86. get { return value; }
  87. }
  88. #endregion
  89. #region Methods
  90. void Define (int position)
  91. {
  92. switch (definedType) {
  93. case OciDataType.Date:
  94. DefineDate (position);
  95. return;
  96. case OciDataType.Clob:
  97. case OciDataType.Blob:
  98. DefineLob (position, definedType);
  99. return;
  100. case OciDataType.Raw:
  101. DefineRaw( position);
  102. return;
  103. case OciDataType.RowIdDescriptor:
  104. definedSize = 10;
  105. DefineChar (position);
  106. return;
  107. case OciDataType.Integer:
  108. case OciDataType.Number:
  109. case OciDataType.Float:
  110. DefineNumber (position);
  111. return;
  112. default:
  113. DefineChar (position); // HANDLE ALL OTHERS AS CHAR FOR NOW
  114. return;
  115. }
  116. }
  117. void DefineDate (int position)
  118. {
  119. definedSize = 7;
  120. ociType = OciDataType.Date;
  121. fieldType = typeof(System.DateTime);
  122. value = Marshal.AllocHGlobal (definedSize);
  123. int status = 0;
  124. status = OciCalls.OCIDefineByPos (Parent,
  125. out handle,
  126. ErrorHandle,
  127. position + 1,
  128. value,
  129. definedSize,
  130. ociType,
  131. ref indicator,
  132. ref rlenp,
  133. IntPtr.Zero,
  134. 0);
  135. if (status != 0) {
  136. OciErrorInfo info = ErrorHandle.HandleError ();
  137. throw new OracleException (info.ErrorCode, info.ErrorMessage);
  138. }
  139. }
  140. void DefineChar (int position)
  141. {
  142. fieldType = typeof (System.String);
  143. // The buffer is able to contain twice the defined size
  144. // to allow usage of multibyte characters
  145. value = Marshal.AllocHGlobal (definedSize * 2);
  146. ociType = OciDataType.Char;
  147. int status = 0;
  148. status = OciCalls.OCIDefineByPos (Parent,
  149. out handle,
  150. ErrorHandle,
  151. position + 1,
  152. value,
  153. definedSize * 2,
  154. ociType,
  155. ref indicator,
  156. ref rlenp,
  157. IntPtr.Zero,
  158. 0);
  159. if (status != 0) {
  160. OciErrorInfo info = ErrorHandle.HandleError ();
  161. throw new OracleException (info.ErrorCode, info.ErrorMessage);
  162. }
  163. }
  164. void DefineNumber (int position)
  165. {
  166. fieldType = typeof (System.Decimal);
  167. value = Marshal.AllocHGlobal (definedSize);
  168. ociType = OciDataType.Char;
  169. int status = 0;
  170. status = OciCalls.OCIDefineByPos (Parent,
  171. out handle,
  172. ErrorHandle,
  173. position + 1,
  174. value,
  175. definedSize * 2,
  176. ociType,
  177. ref indicator,
  178. ref rlenp,
  179. IntPtr.Zero,
  180. 0);
  181. if (status != 0) {
  182. OciErrorInfo info = ErrorHandle.HandleError ();
  183. throw new OracleException (info.ErrorCode, info.ErrorMessage);
  184. }
  185. }
  186. void DefineLob (int position, OciDataType type)
  187. {
  188. ociType = type;
  189. if (ociType == OciDataType.Clob)
  190. fieldType = typeof(System.String);
  191. else if (ociType == OciDataType.Blob)
  192. fieldType = Type.GetType("System.Byte[]");
  193. int status = 0;
  194. definedSize = -1;
  195. lobLocator = (OciLobLocator) Parent.Parent.Allocate (OciHandleType.LobLocator);
  196. if (lobLocator == null) {
  197. OciErrorInfo info = ErrorHandle.HandleError ();
  198. throw new OracleException (info.ErrorCode, info.ErrorMessage);
  199. }
  200. value = lobLocator.Handle;
  201. lobLocator.ErrorHandle = ErrorHandle;
  202. lobLocator.Service = ((OciStatementHandle) Parent).Service;
  203. status = OciCalls.OCIDefineByPosPtr (Parent,
  204. out handle,
  205. ErrorHandle,
  206. position + 1,
  207. ref value,
  208. definedSize,
  209. ociType,
  210. ref indicator,
  211. ref rlenp,
  212. IntPtr.Zero,
  213. 0);
  214. definedSize = Int32.MaxValue;
  215. if (status != 0) {
  216. OciErrorInfo info = ErrorHandle.HandleError ();
  217. throw new OracleException (info.ErrorCode, info.ErrorMessage);
  218. }
  219. }
  220. void DefineRaw (int position)
  221. {
  222. ociType = OciDataType.Raw;
  223. fieldType = Type.GetType("System.Byte[]");
  224. value = Marshal.AllocHGlobal (definedSize);
  225. int status = 0;
  226. status = OciCalls.OCIDefineByPos (Parent,
  227. out handle,
  228. ErrorHandle,
  229. position + 1,
  230. value,
  231. definedSize * 2,
  232. ociType,
  233. ref indicator,
  234. ref rlenp,
  235. IntPtr.Zero, 0);
  236. if (status != 0) {
  237. OciErrorInfo info = ErrorHandle.HandleError ();
  238. throw new OracleException (info.ErrorCode, info.ErrorMessage);
  239. }
  240. }
  241. protected override void Dispose (bool disposing)
  242. {
  243. if (!disposed) {
  244. try {
  245. switch (definedType) {
  246. case OciDataType.Clob:
  247. case OciDataType.Blob:
  248. break;
  249. default:
  250. Marshal.FreeHGlobal (value);
  251. break;
  252. }
  253. disposed = true;
  254. } finally {
  255. base.Dispose (disposing);
  256. value = IntPtr.Zero;
  257. }
  258. }
  259. }
  260. public OracleLob GetOracleLob ()
  261. {
  262. return new OracleLob (lobLocator, ociType);
  263. }
  264. public object GetValue ()
  265. {
  266. object tmp;
  267. switch (DataType) {
  268. case OciDataType.VarChar2:
  269. case OciDataType.String:
  270. case OciDataType.VarChar:
  271. case OciDataType.Char:
  272. case OciDataType.CharZ:
  273. case OciDataType.OciString:
  274. case OciDataType.RowIdDescriptor:
  275. case OciDataType.LongVarChar:
  276. byte [] buffer = new byte [Size];
  277. Marshal.Copy (Value, buffer, 0, Size);
  278. // Get length of returned string
  279. int rsize = 0;
  280. IntPtr env = Parent.Parent; // Parent is statement, grandparent is environment
  281. OciCalls.OCICharSetToUnicode (env, null, buffer, out rsize);
  282. // Get string
  283. StringBuilder ret = new StringBuilder(rsize);
  284. OciCalls.OCICharSetToUnicode (env, ret, buffer, out rsize);
  285. return ret.ToString ();
  286. case OciDataType.Integer:
  287. case OciDataType.Number:
  288. case OciDataType.Float:
  289. tmp = Marshal.PtrToStringAnsi (Value, Size);
  290. if (tmp != null)
  291. return Decimal.Parse (String.Copy ((string) tmp));
  292. break;
  293. case OciDataType.Date:
  294. return UnpackDate ();
  295. case OciDataType.Raw:
  296. byte [] raw_buffer = new byte [Size];
  297. Marshal.Copy (Value, raw_buffer, 0, Size);
  298. return raw_buffer;
  299. case OciDataType.Blob:
  300. case OciDataType.Clob:
  301. return GetOracleLob ();
  302. }
  303. return DBNull.Value;
  304. }
  305. internal object GetOracleValue ()
  306. {
  307. object ovalue = GetValue ();
  308. switch (DataType) {
  309. case OciDataType.Raw:
  310. return new OracleBinary ((byte[]) ovalue);
  311. case OciDataType.Date:
  312. return new OracleDateTime ((DateTime) ovalue);
  313. case OciDataType.Blob:
  314. case OciDataType.Clob:
  315. OracleLob lob = (OracleLob) ovalue;
  316. return lob;
  317. case OciDataType.Integer:
  318. case OciDataType.Number:
  319. case OciDataType.Float:
  320. return new OracleNumber ((decimal) ovalue);
  321. case OciDataType.VarChar2:
  322. case OciDataType.String:
  323. case OciDataType.VarChar:
  324. case OciDataType.Char:
  325. case OciDataType.CharZ:
  326. case OciDataType.OciString:
  327. case OciDataType.LongVarChar:
  328. case OciDataType.RowIdDescriptor:
  329. return new OracleString ((string) ovalue);
  330. default:
  331. // TODO: do other types
  332. throw new NotImplementedException ();
  333. }
  334. }
  335. [MonoTODO ("Be able to handle negative dates... i.e. BCE.")]
  336. public DateTime UnpackDate ()
  337. {
  338. byte century = Marshal.ReadByte (value, 0);
  339. byte year = Marshal.ReadByte (value, 1);
  340. byte month = Marshal.ReadByte (value, 2);
  341. byte day = Marshal.ReadByte (value, 3);
  342. byte hour = Marshal.ReadByte (value, 4);
  343. byte minute = Marshal.ReadByte (value, 5);
  344. byte second = Marshal.ReadByte (value, 6);
  345. return new DateTime ((century - 100) * 100 + (year - 100),
  346. month,
  347. day,
  348. hour - 1,
  349. minute - 1,
  350. second - 1);
  351. }
  352. #endregion // Methods
  353. }
  354. }