OracleParameter.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. //
  2. // OracleParameter.cs
  3. //
  4. // Part of the Mono class libraries at
  5. // mcs/class/System.Data.OracleClient/System.Data.OracleClient
  6. //
  7. // Assembly: System.Data.OracleClient.dll
  8. // Namespace: System.Data.OracleClient
  9. //
  10. // Authors:
  11. // Tim Coleman <[email protected]>
  12. // Daniel Moragn <[email protected]>
  13. //
  14. // Copyright (C) Tim Coleman , 2003
  15. // Copyright (C) Daniel Morgan, 2005
  16. //
  17. // Licensed under the MIT/X11 License.
  18. //
  19. using System;
  20. using System.Collections;
  21. using System.ComponentModel;
  22. using System.Data;
  23. using System.Data.OracleClient.Oci;
  24. using System.Globalization;
  25. using System.Runtime.InteropServices;
  26. using System.Text;
  27. namespace System.Data.OracleClient {
  28. [TypeConverter (typeof(OracleParameter.OracleParameterConverter))]
  29. public sealed class OracleParameter : MarshalByRefObject, IDbDataParameter, IDataParameter, ICloneable
  30. {
  31. #region Fields
  32. string name;
  33. OracleType oracleType = OracleType.VarChar;
  34. OciDataType ociType;
  35. int size;
  36. ParameterDirection direction = ParameterDirection.Input;
  37. bool isNullable;
  38. byte precision;
  39. byte scale;
  40. string srcColumn;
  41. DataRowVersion srcVersion;
  42. DbType dbType = DbType.AnsiString;
  43. int offset = 0;
  44. bool sizeSet = false;
  45. object value = DBNull.Value;
  46. OciLobLocator lobLocator = null; // only if Blob or Clob
  47. IntPtr bindOutValue = IntPtr.Zero;
  48. OracleParameterCollection container = null;
  49. OciBindHandle bindHandle;
  50. OciErrorHandle errorHandle;
  51. OracleConnection connection;
  52. int indicator = 0; // TODO: handle indicator to indicate NULL value for OUT parameters
  53. int bindSize = 0;
  54. #endregion // Fields
  55. #region Constructors
  56. // constructor for cloning the object
  57. internal OracleParameter (OracleParameter value) {
  58. this.name = value.name;
  59. this.oracleType = value.oracleType;
  60. this.ociType = value.ociType;
  61. this.size = value.size;
  62. this.direction = value.direction;
  63. this.isNullable = value.isNullable;
  64. this.precision = value.precision;
  65. this.scale = value.scale;
  66. this.srcColumn = value.srcColumn;
  67. this.srcVersion = value.srcVersion;
  68. this.dbType = value.dbType;
  69. this.offset = value.offset;
  70. this.sizeSet = value.sizeSet;
  71. this.value = value.value;
  72. this.lobLocator = value.lobLocator;
  73. }
  74. public OracleParameter ()
  75. : this (String.Empty, OracleType.VarChar, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
  76. {
  77. }
  78. public OracleParameter (string name, object value)
  79. {
  80. this.name = name;
  81. this.value = value;
  82. SourceVersion = DataRowVersion.Current;
  83. InferOracleType (value);
  84. }
  85. public OracleParameter (string name, OracleType dataType)
  86. : this (name, dataType, 0, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
  87. {
  88. }
  89. public OracleParameter (string name, OracleType dataType, int size)
  90. : this (name, dataType, size, ParameterDirection.Input, false, 0, 0, String.Empty, DataRowVersion.Current, null)
  91. {
  92. }
  93. public OracleParameter (string name, OracleType dataType, int size, string srcColumn)
  94. : this (name, dataType, size, ParameterDirection.Input, false, 0, 0, srcColumn, DataRowVersion.Current, null)
  95. {
  96. }
  97. public OracleParameter (string name, OracleType dataType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string srcColumn, DataRowVersion srcVersion, object value)
  98. {
  99. this.name = name;
  100. this.size = size;
  101. this.value = value;
  102. OracleType = dataType;
  103. Direction = direction;
  104. SourceColumn = srcColumn;
  105. SourceVersion = srcVersion;
  106. }
  107. #endregion // Constructors
  108. #region Properties
  109. internal OracleParameterCollection Container {
  110. get { return container; }
  111. set { container = value; }
  112. }
  113. [Browsable (false)]
  114. [RefreshProperties (RefreshProperties.All)]
  115. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  116. public DbType DbType {
  117. get { return dbType; }
  118. set { SetDbType (value); }
  119. }
  120. [DefaultValue (ParameterDirection.Input)]
  121. [RefreshProperties (RefreshProperties.All)]
  122. public ParameterDirection Direction {
  123. get { return direction; }
  124. set { direction = value; }
  125. }
  126. [Browsable (false)]
  127. [DesignOnly (true)]
  128. [DefaultValue (false)]
  129. [EditorBrowsable (EditorBrowsableState.Never)]
  130. public bool IsNullable {
  131. get { return isNullable; }
  132. set { isNullable = value; }
  133. }
  134. [DefaultValue (0)]
  135. [Browsable (false)]
  136. public int Offset {
  137. get { return offset; }
  138. set { offset = value; }
  139. }
  140. [DefaultValue (OracleType.VarChar)]
  141. [RefreshProperties (RefreshProperties.All)]
  142. public OracleType OracleType {
  143. get { return oracleType; }
  144. set { SetOracleType (value); }
  145. }
  146. [DefaultValue ("")]
  147. public string ParameterName {
  148. get { return name; }
  149. set { name = value; }
  150. }
  151. [DefaultValue (0)]
  152. public byte Precision {
  153. get { return precision; }
  154. set { /* NO EFFECT*/ }
  155. }
  156. [DefaultValue (0)]
  157. public byte Scale {
  158. get { return scale; }
  159. set { /* NO EFFECT*/ }
  160. }
  161. [DefaultValue (0)]
  162. public int Size {
  163. get { return size; }
  164. set {
  165. sizeSet = true;
  166. size = value;
  167. }
  168. }
  169. [DefaultValue ("")]
  170. public string SourceColumn {
  171. get { return srcColumn; }
  172. set { srcColumn = value; }
  173. }
  174. [DefaultValue (DataRowVersion.Current)]
  175. public DataRowVersion SourceVersion {
  176. get { return srcVersion; }
  177. set { srcVersion = value; }
  178. }
  179. [DefaultValue (null)]
  180. [RefreshProperties (RefreshProperties.All)]
  181. [TypeConverter (typeof(StringConverter))]
  182. public object Value {
  183. get { return this.value; }
  184. set { this.value = value; }
  185. }
  186. #endregion // Properties
  187. #region Methods
  188. private void AssertSizeIsSet ()
  189. {
  190. switch (ociType) {
  191. case OciDataType.VarChar2:
  192. case OciDataType.String:
  193. case OciDataType.VarChar:
  194. case OciDataType.Char:
  195. case OciDataType.CharZ:
  196. case OciDataType.OciString:
  197. if (!sizeSet)
  198. throw new Exception ("Size must be set.");
  199. break;
  200. default:
  201. break;
  202. }
  203. }
  204. internal void Bind (OciStatementHandle statement, OracleConnection connection)
  205. {
  206. errorHandle = connection.ErrorHandle;
  207. if (bindHandle == null)
  208. bindHandle = new OciBindHandle ((OciHandle) statement);
  209. IntPtr tmpHandle = bindHandle.Handle;
  210. if (Direction != ParameterDirection.Input)
  211. AssertSizeIsSet ();
  212. if (!sizeSet)
  213. size = InferSize ();
  214. bindSize = size;
  215. byte[] bytes = null;
  216. object v = value;
  217. int status = 0;
  218. OciDataType bindType = ociType;
  219. IntPtr bindValue = IntPtr.Zero;
  220. int rsize = 0;
  221. // TODO: handle InputOutput and Return parameters
  222. if (direction == ParameterDirection.Output) {
  223. // TODO: need to figure out how OracleParameter
  224. // which uses OciBindHandle to share code
  225. // with OciDefineHandle
  226. switch(ociType) {
  227. case OciDataType.VarChar2:
  228. case OciDataType.String:
  229. case OciDataType.VarChar:
  230. case OciDataType.Char:
  231. case OciDataType.CharZ:
  232. case OciDataType.OciString:
  233. bindType = OciDataType.Char;
  234. bindSize = size * 2;
  235. bindOutValue = Marshal.AllocHGlobal (bindSize);
  236. break;
  237. case OciDataType.RowIdDescriptor:
  238. size = 10;
  239. bindType = OciDataType.Char;
  240. bindSize = size * 2;
  241. bindOutValue = Marshal.AllocHGlobal (bindSize);
  242. break;
  243. case OciDataType.Date:
  244. bindSize = 7;
  245. bindType = OciDataType.Date;
  246. bindOutValue = Marshal.AllocHGlobal (bindSize);
  247. break;
  248. case OciDataType.Number:
  249. bindSize = 22;
  250. bindType = OciDataType.Char;
  251. bindOutValue = Marshal.AllocHGlobal (bindSize);
  252. break;
  253. case OciDataType.Long:
  254. case OciDataType.LongVarChar:
  255. // LAMESPEC: you don't know size until you get it;
  256. // therefore, you must allocate an insane size
  257. // see OciDefineHandle
  258. bindSize = OciDefineHandle.LongVarCharMaxValue;
  259. bindOutValue = Marshal.AllocHGlobal (bindSize);
  260. bindType = OciDataType.LongVarChar;
  261. break;
  262. case OciDataType.Blob:
  263. case OciDataType.Clob:
  264. bindSize = -1;
  265. lobLocator = (OciLobLocator) connection.Environment.Allocate (OciHandleType.LobLocator);
  266. if (lobLocator == null) {
  267. OciErrorInfo info = connection.ErrorHandle.HandleError ();
  268. throw new OracleException (info.ErrorCode, info.ErrorMessage);
  269. }
  270. value = lobLocator.Handle;
  271. lobLocator.ErrorHandle = connection.ErrorHandle;
  272. lobLocator.Service = statement.Service;
  273. break;
  274. default:
  275. // define other types
  276. throw new NotImplementedException ();
  277. }
  278. bindValue = bindOutValue;
  279. }
  280. else if (v == DBNull.Value || v == null) {
  281. indicator = 0;
  282. bindType = OciDataType.VarChar2;
  283. bindSize = 0;
  284. }
  285. else {
  286. // TODO: do other data types and oracle data types
  287. // should I be using IConvertible to convert?
  288. if (oracleType == OracleType.DateTime) {
  289. string oraDateFormat = connection.GetSessionDateFormat ();
  290. string sysDateFormat = OracleDateTime.ConvertOracleDateFormatToSystemDateTime (oraDateFormat);
  291. string sDate = "";
  292. DateTime dt = DateTime.MinValue;
  293. if (v is String) {
  294. sDate = (string) v;
  295. dt = DateTime.Parse (sDate);
  296. }
  297. else if (v is DateTime)
  298. dt = (DateTime) v;
  299. else if (v is OracleString) {
  300. sDate = (string) v;
  301. dt = DateTime.Parse (sDate);
  302. }
  303. else if (v is OracleDateTime) {
  304. OracleDateTime odt = (OracleDateTime) v;
  305. dt = (DateTime) odt.Value;
  306. }
  307. else
  308. throw new NotImplementedException (); // ?
  309. sDate = dt.ToString (sysDateFormat);
  310. rsize = 0;
  311. // Get size of buffer
  312. OciCalls.OCIUnicodeToCharSet (statement.Parent, null, sDate, out rsize);
  313. // Fill buffer
  314. bytes = new byte[rsize];
  315. OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, sDate, out rsize);
  316. bindType = OciDataType.VarChar2;
  317. //bindValue = Marshal.StringToHGlobalAnsi (sDate);
  318. bindSize = sDate.Length;
  319. }
  320. else if (oracleType == OracleType.Blob) {
  321. bytes = (byte[]) v;
  322. bindType = OciDataType.LongRaw;
  323. bindSize = bytes.Length;
  324. }
  325. else if (oracleType == OracleType.Clob) {
  326. string sv = (string) v;
  327. rsize = 0;
  328. // Get size of buffer
  329. OciCalls.OCIUnicodeToCharSet (statement.Parent, null, sv, out rsize);
  330. // Fill buffer
  331. bytes = new byte[rsize];
  332. OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, sv, out rsize);
  333. bindType = OciDataType.Long;
  334. bindSize = bytes.Length;
  335. }
  336. else if (oracleType == OracleType.Raw) {
  337. byte[] val = v as byte[];
  338. bindValue = Marshal.AllocHGlobal (val.Length);
  339. Marshal.Copy (val, 0, bindValue, val.Length);
  340. bindSize = val.Length;
  341. }
  342. else {
  343. string svalue = v.ToString ();
  344. rsize = 0;
  345. // Get size of buffer
  346. OciCalls.OCIUnicodeToCharSet (statement.Parent, null, svalue, out rsize);
  347. // Fill buffer
  348. bytes = new byte[rsize];
  349. OciCalls.OCIUnicodeToCharSet (statement.Parent, bytes, svalue, out rsize);
  350. //bindValue = Marshal.StringToHGlobalAnsi (value.ToString ());
  351. bindType = OciDataType.VarChar2;
  352. bindSize = v.ToString ().Length;
  353. }
  354. }
  355. if (bytes != null) {
  356. status = OciCalls.OCIBindByNameBytes (statement,
  357. out tmpHandle,
  358. connection.ErrorHandle,
  359. ParameterName,
  360. ParameterName.Length,
  361. bytes,
  362. bindSize,
  363. bindType,
  364. indicator,
  365. IntPtr.Zero,
  366. IntPtr.Zero,
  367. 0,
  368. IntPtr.Zero,
  369. 0);
  370. }
  371. else {
  372. status = OciCalls.OCIBindByName (statement,
  373. out tmpHandle,
  374. connection.ErrorHandle,
  375. ParameterName,
  376. ParameterName.Length,
  377. bindValue,
  378. bindSize,
  379. bindType,
  380. indicator,
  381. IntPtr.Zero,
  382. IntPtr.Zero,
  383. 0,
  384. IntPtr.Zero,
  385. 0);
  386. }
  387. if (status != 0) {
  388. OciErrorInfo info = connection.ErrorHandle.HandleError ();
  389. throw new OracleException (info.ErrorCode, info.ErrorMessage);
  390. }
  391. bindHandle.SetHandle (tmpHandle);
  392. }
  393. object ICloneable.Clone ()
  394. {
  395. return new OracleParameter(this);
  396. }
  397. private void InferOracleType (object value)
  398. {
  399. Type type = value.GetType ();
  400. string exception = String.Format ("The parameter data type of {0} is invalid.", type.Name);
  401. switch (type.FullName) {
  402. case "System.Int64":
  403. SetOracleType (OracleType.Number);
  404. break;
  405. case "System.Boolean":
  406. case "System.Byte":
  407. SetOracleType (OracleType.Byte);
  408. break;
  409. case "System.String":
  410. SetOracleType (OracleType.VarChar);
  411. break;
  412. case "System.DateTime":
  413. SetOracleType (OracleType.DateTime);
  414. break;
  415. case "System.Decimal":
  416. SetOracleType (OracleType.Number);
  417. //scale = ((decimal) value).Scale;
  418. break;
  419. case "System.Double":
  420. SetOracleType (OracleType.Double);
  421. break;
  422. case "System.Byte[]":
  423. case "System.Guid":
  424. SetOracleType (OracleType.Raw);
  425. break;
  426. case "System.Int32":
  427. SetOracleType (OracleType.Int32);
  428. break;
  429. case "System.Single":
  430. SetOracleType (OracleType.Float);
  431. break;
  432. case "System.Int16":
  433. SetOracleType (OracleType.Int16);
  434. break;
  435. default:
  436. throw new ArgumentException (exception);
  437. }
  438. }
  439. private int InferSize ()
  440. {
  441. int newSize = 0;
  442. switch (ociType) {
  443. case OciDataType.VarChar2:
  444. case OciDataType.String:
  445. case OciDataType.VarChar:
  446. case OciDataType.Char:
  447. case OciDataType.CharZ:
  448. case OciDataType.OciString:
  449. case OciDataType.Long:
  450. case OciDataType.LongVarChar:
  451. if (value == null || value == DBNull.Value)
  452. newSize = 0;
  453. else
  454. newSize = value.ToString ().Length;
  455. break;
  456. case OciDataType.RowIdDescriptor:
  457. newSize = 10;
  458. break;
  459. case OciDataType.Integer:
  460. case OciDataType.Number:
  461. case OciDataType.Float:
  462. newSize = 22;
  463. break;
  464. case OciDataType.Date:
  465. newSize = 7;
  466. break;
  467. case OciDataType.Blob:
  468. case OciDataType.Clob:
  469. newSize = -1;
  470. break;
  471. default:
  472. if (value == null || value == DBNull.Value)
  473. newSize = 0;
  474. else
  475. newSize = value.ToString ().Length;
  476. break;
  477. }
  478. sizeSet = true;
  479. return newSize;
  480. }
  481. private void SetDbType (DbType type)
  482. {
  483. string exception = String.Format ("No mapping exists from DbType {0} to a known OracleType.", type);
  484. switch (type) {
  485. case DbType.AnsiString:
  486. oracleType = OracleType.VarChar;
  487. ociType = OciDataType.VarChar;
  488. break;
  489. case DbType.AnsiStringFixedLength:
  490. oracleType = OracleType.Char;
  491. ociType = OciDataType.Char;
  492. break;
  493. case DbType.Binary:
  494. case DbType.Guid:
  495. oracleType = OracleType.Raw;
  496. ociType = OciDataType.Raw;
  497. break;
  498. case DbType.Boolean:
  499. case DbType.Byte:
  500. oracleType = OracleType.Byte;
  501. ociType = OciDataType.Integer;
  502. break;
  503. case DbType.Currency:
  504. case DbType.Decimal:
  505. case DbType.Int64:
  506. oracleType = OracleType.Number;
  507. ociType = OciDataType.Number;
  508. break;
  509. case DbType.Date:
  510. case DbType.DateTime:
  511. case DbType.Time:
  512. oracleType = OracleType.DateTime;
  513. ociType = OciDataType.Char;
  514. break;
  515. case DbType.Double:
  516. oracleType = OracleType.Double;
  517. ociType = OciDataType.Float;
  518. break;
  519. case DbType.Int16:
  520. oracleType = OracleType.Int16;
  521. ociType = OciDataType.Integer;
  522. break;
  523. case DbType.Int32:
  524. oracleType = OracleType.Int32;
  525. ociType = OciDataType.Integer;
  526. break;
  527. case DbType.Object:
  528. oracleType = OracleType.Blob;
  529. ociType = OciDataType.Blob;
  530. break;
  531. case DbType.Single:
  532. oracleType = OracleType.Float;
  533. ociType = OciDataType.Float;
  534. break;
  535. case DbType.String:
  536. oracleType = OracleType.NVarChar;
  537. ociType = OciDataType.VarChar;
  538. break;
  539. case DbType.StringFixedLength:
  540. oracleType = OracleType.NChar;
  541. ociType = OciDataType.Char;
  542. break;
  543. default:
  544. throw new ArgumentException (exception);
  545. }
  546. dbType = type;
  547. }
  548. private void SetOracleType (OracleType type)
  549. {
  550. string exception = String.Format ("No mapping exists from OracleType {0} to a known DbType.", type);
  551. switch (type) {
  552. case OracleType.BFile:
  553. case OracleType.Blob:
  554. dbType = DbType.Binary;
  555. ociType = OciDataType.Blob;
  556. break;
  557. case OracleType.LongRaw:
  558. case OracleType.Raw:
  559. dbType = DbType.Binary;
  560. ociType = OciDataType.Raw;
  561. break;
  562. case OracleType.Byte:
  563. dbType = DbType.Byte;
  564. ociType = OciDataType.Number;
  565. break;
  566. case OracleType.Char:
  567. dbType = DbType.AnsiString;
  568. ociType = OciDataType.Char;
  569. break;
  570. case OracleType.Clob:
  571. dbType = DbType.AnsiString;
  572. ociType = OciDataType.Clob;
  573. break;
  574. case OracleType.LongVarChar:
  575. case OracleType.RowId:
  576. case OracleType.VarChar:
  577. dbType = DbType.AnsiString;
  578. ociType = OciDataType.VarChar;
  579. break;
  580. case OracleType.Cursor:
  581. case OracleType.IntervalDayToSecond:
  582. dbType = DbType.AnsiStringFixedLength;
  583. ociType = OciDataType.Char;
  584. break;
  585. case OracleType.DateTime:
  586. case OracleType.Timestamp:
  587. case OracleType.TimestampLocal:
  588. case OracleType.TimestampWithTZ:
  589. dbType = DbType.DateTime;
  590. ociType = OciDataType.Date;
  591. break;
  592. case OracleType.Double:
  593. dbType = DbType.Double;
  594. ociType = OciDataType.Number;
  595. break;
  596. case OracleType.Float:
  597. dbType = DbType.Single;
  598. ociType = OciDataType.Number;
  599. break;
  600. case OracleType.Int16:
  601. dbType = DbType.Int16;
  602. ociType = OciDataType.Number;
  603. break;
  604. case OracleType.Int32:
  605. case OracleType.IntervalYearToMonth:
  606. dbType = DbType.Int32;
  607. ociType = OciDataType.Number;
  608. break;
  609. case OracleType.NChar:
  610. dbType = DbType.StringFixedLength;
  611. ociType = OciDataType.Char;
  612. break;
  613. case OracleType.NClob:
  614. case OracleType.NVarChar:
  615. dbType = DbType.String;
  616. ociType = OciDataType.Char;
  617. break;
  618. case OracleType.Number:
  619. dbType = DbType.VarNumeric;
  620. ociType = OciDataType.Number;
  621. break;
  622. case OracleType.SByte:
  623. dbType = DbType.SByte;
  624. ociType = OciDataType.Number;
  625. break;
  626. case OracleType.UInt16:
  627. dbType = DbType.UInt16;
  628. ociType = OciDataType.Number;
  629. break;
  630. case OracleType.UInt32:
  631. dbType = DbType.UInt32;
  632. ociType = OciDataType.Number;
  633. break;
  634. default:
  635. throw new ArgumentException (exception);
  636. }
  637. oracleType = type;
  638. }
  639. public override string ToString ()
  640. {
  641. return ParameterName;
  642. }
  643. internal void Update (OracleCommand cmd)
  644. {
  645. // used to update the parameter value
  646. // for Output, the output of InputOutput, and Return parameters
  647. // TODO: handle NULL values by using the indicator variable
  648. // referenced in call to OCIBindByName
  649. value = DBNull.Value;
  650. byte[] buffer = null;
  651. object tmp = null;
  652. switch (ociType) {
  653. case OciDataType.VarChar2:
  654. case OciDataType.String:
  655. case OciDataType.VarChar:
  656. case OciDataType.Char:
  657. case OciDataType.CharZ:
  658. case OciDataType.OciString:
  659. case OciDataType.RowIdDescriptor:
  660. buffer = new byte [Size];
  661. Marshal.Copy (bindOutValue, buffer, 0, Size);
  662. // Get length of returned string
  663. int rsize = 0;
  664. IntPtr env = cmd.Connection.Environment;
  665. OciCalls.OCICharSetToUnicode (env, null, buffer, out rsize);
  666. // Get string
  667. StringBuilder ret = new StringBuilder(rsize);
  668. OciCalls.OCICharSetToUnicode (env, ret, buffer, out rsize);
  669. value = ret.ToString ();
  670. break;
  671. case OciDataType.Integer:
  672. case OciDataType.Number:
  673. case OciDataType.Float:
  674. tmp = Marshal.PtrToStringAnsi (bindOutValue, bindSize);
  675. if (tmp != null)
  676. value = Decimal.Parse (String.Copy ((string) tmp));
  677. break;
  678. case OciDataType.Date:
  679. value = UnpackDate (bindOutValue);
  680. break;
  681. case OciDataType.Blob:
  682. case OciDataType.Clob:
  683. OracleLob lob = new OracleLob (lobLocator, ociType);
  684. lob.connection = connection;
  685. value = lob;
  686. break;
  687. default:
  688. throw new NotImplementedException ();
  689. }
  690. }
  691. // copied from OciDefineHandle
  692. [MonoTODO ("Be able to handle negative dates... i.e. BCE.")]
  693. internal DateTime UnpackDate (IntPtr dateValue)
  694. {
  695. byte century = Marshal.ReadByte (dateValue, 0);
  696. byte year = Marshal.ReadByte (dateValue, 1);
  697. byte month = Marshal.ReadByte (dateValue, 2);
  698. byte day = Marshal.ReadByte (dateValue, 3);
  699. byte hour = Marshal.ReadByte (dateValue, 4);
  700. byte minute = Marshal.ReadByte (dateValue, 5);
  701. byte second = Marshal.ReadByte (dateValue, 6);
  702. return new DateTime ((century - 100) * 100 + (year - 100),
  703. month,
  704. day,
  705. hour - 1,
  706. minute - 1,
  707. second - 1);
  708. }
  709. #endregion // Methods
  710. internal sealed class OracleParameterConverter : ExpandableObjectConverter
  711. {
  712. public OracleParameterConverter ()
  713. {
  714. }
  715. [MonoTODO]
  716. public override bool CanConvertTo (ITypeDescriptorContext context, Type destinationType)
  717. {
  718. throw new NotImplementedException ();
  719. }
  720. [MonoTODO]
  721. public override object ConvertTo (ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
  722. {
  723. throw new NotImplementedException ();
  724. }
  725. }
  726. }
  727. }