DataContainer.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128
  1. //
  2. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining
  5. // a copy of this software and associated documentation files (the
  6. // "Software"), to deal in the Software without restriction, including
  7. // without limitation the rights to use, copy, modify, merge, publish,
  8. // distribute, sublicense, and/or sell copies of the Software, and to
  9. // permit persons to whom the Software is furnished to do so, subject to
  10. // the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be
  13. // included in all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  19. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  20. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  21. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. //
  23. using System;
  24. using System.Collections;
  25. namespace System.Data.Common
  26. {
  27. internal abstract class AbstractDataContainer
  28. {
  29. #region Fields
  30. BitArray _nullValues;
  31. System.Type _type;
  32. DataColumn _column;
  33. #endregion //Fields
  34. #region Properties
  35. internal abstract object this[int index] {
  36. get;
  37. set;
  38. }
  39. internal virtual int Capacity {
  40. get {
  41. return (_nullValues != null) ? _nullValues.Count : 0;
  42. }
  43. set {
  44. if (_nullValues == null) {
  45. _nullValues = new BitArray(value);
  46. }
  47. else {
  48. _nullValues.Length = value;
  49. }
  50. }
  51. }
  52. internal Type Type {
  53. get {
  54. return _type;
  55. }
  56. }
  57. protected DataColumn Column {
  58. get {
  59. return _column;
  60. }
  61. }
  62. #endregion //Properties
  63. #region Methods
  64. internal static AbstractDataContainer CreateInstance(Type type, DataColumn column)
  65. {
  66. AbstractDataContainer container;
  67. switch (Type.GetTypeCode(type)) {
  68. case TypeCode.Int16 :
  69. container = new Int16DataContainer();
  70. break;
  71. case TypeCode.Int32 :
  72. container = new Int32DataContainer();
  73. break;
  74. case TypeCode.Int64 :
  75. container = new Int64DataContainer();
  76. break;
  77. case TypeCode.String :
  78. container = new StringDataContainer();
  79. break;
  80. case TypeCode.Boolean:
  81. container = new BitDataContainer();
  82. break;
  83. case TypeCode.Byte :
  84. container = new ByteDataContainer();
  85. break;
  86. //case TypeCode.Char :
  87. case TypeCode.DateTime :
  88. container = new DateTimeDataContainer();
  89. break;
  90. //case TypeCode.Decimal :
  91. case TypeCode.Double :
  92. container = new DoubleDataContainer();
  93. break;
  94. //case TypeCode.SByte :
  95. case TypeCode.Single :
  96. container = new SingleDataContainer();
  97. break;
  98. //case TypeCode.UInt16 :
  99. //case TypeCode.UInt32 :
  100. //case TypeCode.UInt64 :
  101. default :
  102. container = new ObjectDataContainer();
  103. break;
  104. }
  105. container._type = type;
  106. container._column = column;
  107. return container;
  108. }
  109. internal bool IsNull(int index)
  110. {
  111. return (_nullValues != null) ? _nullValues[index] : true;
  112. }
  113. internal void SetNullBit(int index,bool isNull)
  114. {
  115. _nullValues[index] = isNull;
  116. }
  117. protected void SetNull(int index,bool isNull,bool isDbNull)
  118. {
  119. SetNullBit(index,isDbNull);
  120. // this method must be called after setting the value into value array
  121. // otherwise the dafault value will be overriden
  122. if ( isNull ) {
  123. // set the value to default
  124. CopyValue(Column.Table.DefaultValuesRowIndex,index);
  125. }
  126. }
  127. internal void FillValues(int fromIndex)
  128. {
  129. for(int i=0; i < Capacity; i++) {
  130. CopyValue(fromIndex,i);
  131. _nullValues[i] = _nullValues[fromIndex];
  132. }
  133. }
  134. internal virtual void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
  135. {
  136. _nullValues[toIndex] = fromContainer._nullValues[fromIndex];
  137. }
  138. internal virtual void CopyValue(int fromIndex, int toIndex)
  139. {
  140. _nullValues[toIndex] = _nullValues[fromIndex];
  141. }
  142. internal virtual void SetItemFromDataRecord(int index, IDataRecord record, int field)
  143. {
  144. bool isDbNull = record.IsDBNull(field);
  145. SetNull(index,false,isDbNull);
  146. }
  147. protected bool CheckAndSetNull( int index, IDataRecord record, int field)
  148. {
  149. bool isDbNull = record.IsDBNull(field);
  150. SetNull(index,false,isDbNull);
  151. return isDbNull;
  152. }
  153. protected int CompareNulls(int index1, int index2)
  154. {
  155. bool null1 = IsNull(index1);
  156. bool null2 = IsNull(index2);
  157. if ( null1 ^ null2 ) {
  158. return null1 ? -1 : 1;
  159. }
  160. else {
  161. return 0;
  162. }
  163. }
  164. internal abstract int CompareValues(int index1, int index2);
  165. internal abstract long GetInt64(int index);
  166. #endregion //Methods
  167. sealed class Int16DataContainer : AbstractDataContainer
  168. {
  169. #region Fields
  170. short[] _values;
  171. #endregion //Fields
  172. #region Properties
  173. internal override object this[int index] {
  174. get {
  175. if (IsNull(index)) {
  176. return DBNull.Value;
  177. }
  178. else {
  179. return _values[index];
  180. }
  181. }
  182. set {
  183. bool isDbNull = (value == DBNull.Value);
  184. if (value == null || isDbNull) {
  185. SetValue(index,0);
  186. }
  187. else if( value is short ) {
  188. SetValue(index,(short)value);
  189. }
  190. else {
  191. try {
  192. SetValue(index,Convert.ToInt16(value));
  193. } catch (Exception ex) {
  194. throw new ArgumentException (ex.Message, ex);
  195. }
  196. }
  197. SetNull(index,value == null,isDbNull);
  198. }
  199. }
  200. internal override int Capacity {
  201. set {
  202. base.Capacity = value;
  203. if (_values == null) {
  204. _values = new short[value];
  205. }
  206. else {
  207. short[] tmp = new short[value];
  208. Array.Copy(_values,0,tmp,0,_values.Length);
  209. _values = tmp;
  210. }
  211. }
  212. }
  213. #endregion //Properties
  214. #region Methods
  215. private void SetValue(int index, short value)
  216. {
  217. _values[index] = value;
  218. }
  219. internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
  220. {
  221. // if exception thrown, it should be caught
  222. // in the caller method
  223. if (!CheckAndSetNull ( index, record,field))
  224. SetValue(index,record.GetInt16(field));
  225. }
  226. internal override void CopyValue(int fromIndex, int toIndex)
  227. {
  228. base.CopyValue(fromIndex, toIndex);
  229. _values[toIndex] = _values[fromIndex];
  230. }
  231. internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
  232. {
  233. base.CopyValue(fromContainer, fromIndex, toIndex);
  234. _values[toIndex] = ((Int16DataContainer)fromContainer)._values[fromIndex];
  235. }
  236. internal override int CompareValues(int index1, int index2)
  237. {
  238. short s1 = _values[index1];
  239. short s2 = _values[index2];
  240. if ( s1 == 0 && s2 == 0 ) {
  241. int cn = CompareNulls(index1, index2);
  242. return cn;
  243. }
  244. bool b1 = IsNull(index1);
  245. bool b2 = IsNull(index2);
  246. if ( s1 == 0 && b1 ) {
  247. return -1;
  248. }
  249. if ( s2 == 0 && b2 ) {
  250. return 1;
  251. }
  252. if ( s1 <= s2 ) {
  253. return ( s1 != s2 ) ? -1 : 0;
  254. }
  255. return 1;
  256. }
  257. internal override long GetInt64(int index)
  258. {
  259. return (long) _values[index];
  260. }
  261. #endregion //Methods
  262. }
  263. sealed class Int32DataContainer : AbstractDataContainer
  264. {
  265. #region Fields
  266. int[] _values;
  267. #endregion //Fields
  268. #region Properties
  269. internal override object this[int index] {
  270. get {
  271. if (IsNull(index)) {
  272. return DBNull.Value;
  273. }
  274. else {
  275. return _values[index];
  276. }
  277. }
  278. set {
  279. bool isDbNull = (value == DBNull.Value);
  280. if (value == null || isDbNull) {
  281. SetValue(index,0);
  282. }
  283. else if( value is int ) {
  284. SetValue(index,(int)value);
  285. }
  286. else {
  287. SetValue(index,Convert.ToInt32(value));
  288. }
  289. SetNull(index,value == null,isDbNull);
  290. }
  291. }
  292. internal override int Capacity {
  293. set {
  294. base.Capacity = value;
  295. if (_values == null) {
  296. _values = new int[value];
  297. }
  298. else {
  299. int[] tmp = new int[value];
  300. Array.Copy(_values,0,tmp,0,_values.Length);
  301. _values = tmp;
  302. }
  303. }
  304. }
  305. #endregion //Properties
  306. #region Methods
  307. private void SetValue(int index, int value)
  308. {
  309. _values[index] = value;
  310. }
  311. internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
  312. {
  313. // if exception thrown, it should be caught
  314. // in the caller method
  315. if (!CheckAndSetNull ( index, record,field))
  316. SetValue(index,record.GetInt32(field));
  317. }
  318. internal override void CopyValue(int fromIndex, int toIndex)
  319. {
  320. base.CopyValue(fromIndex, toIndex);
  321. _values[toIndex] = _values[fromIndex];
  322. }
  323. internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
  324. {
  325. base.CopyValue(fromContainer, fromIndex, toIndex);
  326. _values[toIndex] = ((Int32DataContainer)fromContainer)._values[fromIndex];
  327. }
  328. internal override int CompareValues(int index1, int index2)
  329. {
  330. int i1 = _values[index1];
  331. int i2 = _values[index2];
  332. if ( i1 == 0 && i2 == 0 ) {
  333. int cn = CompareNulls(index1, index2);
  334. return cn;
  335. }
  336. bool b1 = IsNull(index1);
  337. bool b2 = IsNull(index2);
  338. if ( i1 == 0 && b1 ) {
  339. return -1;
  340. }
  341. if ( i2 == 0 && b2 ) {
  342. return 1;
  343. }
  344. if ( i1 <= i2 ) {
  345. return ( i1 != i2 ) ? -1 : 0;
  346. }
  347. return 1;
  348. }
  349. internal override long GetInt64(int index)
  350. {
  351. return (long) _values[index];
  352. }
  353. #endregion //Methods
  354. }
  355. sealed class Int64DataContainer : AbstractDataContainer
  356. {
  357. #region Fields
  358. long[] _values;
  359. #endregion //Fields
  360. #region Properties
  361. internal override object this[int index] {
  362. get {
  363. if (IsNull(index)) {
  364. return DBNull.Value;
  365. }
  366. else {
  367. return _values[index];
  368. }
  369. }
  370. set {
  371. bool isDbNull = (value == DBNull.Value);
  372. if (value == null || isDbNull) {
  373. SetValue(index,0);
  374. }
  375. else if( value is long ) {
  376. SetValue(index,(long)value);
  377. }
  378. else {
  379. SetValue(index,Convert.ToInt64(value));
  380. }
  381. SetNull(index,value == null,isDbNull);
  382. }
  383. }
  384. internal override int Capacity {
  385. set {
  386. base.Capacity = value;
  387. if (_values == null) {
  388. _values = new long[value];
  389. }
  390. else {
  391. long[] tmp = new long[value];
  392. Array.Copy(_values,0,tmp,0,_values.Length);
  393. _values = tmp;
  394. }
  395. }
  396. }
  397. #endregion //Properties
  398. #region Methods
  399. private void SetValue(int index, long value)
  400. {
  401. _values[index] = value;
  402. }
  403. internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
  404. {
  405. // if exception thrown, it should be caught
  406. // in the caller method
  407. if (!CheckAndSetNull ( index, record,field))
  408. SetValue(index,record.GetInt64(field));
  409. }
  410. internal override void CopyValue(int fromIndex, int toIndex)
  411. {
  412. base.CopyValue(fromIndex, toIndex);
  413. _values[toIndex] = _values[fromIndex];
  414. }
  415. internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
  416. {
  417. base.CopyValue(fromContainer, fromIndex, toIndex);
  418. _values[toIndex] = ((Int64DataContainer)fromContainer)._values[fromIndex];
  419. }
  420. internal override int CompareValues(int index1, int index2)
  421. {
  422. long l1 = _values[index1];
  423. long l2 = _values[index2];
  424. if ( l1 == 0 || l2 == 0 ) {
  425. int cn = CompareNulls(index1, index2);
  426. if (cn != 0) {
  427. return cn;
  428. }
  429. }
  430. if ( l1 <= l2 ) {
  431. return ( l1 != l2 ) ? -1 : 0;
  432. }
  433. return 1;
  434. }
  435. internal override long GetInt64(int index)
  436. {
  437. return _values[index];
  438. }
  439. #endregion //Methods
  440. }
  441. sealed class SingleDataContainer : AbstractDataContainer
  442. {
  443. #region Fields
  444. float[] _values;
  445. #endregion //Fields
  446. #region Properties
  447. internal override object this[int index] {
  448. get {
  449. if (IsNull(index)) {
  450. return DBNull.Value;
  451. }
  452. else {
  453. return _values[index];
  454. }
  455. }
  456. set {
  457. bool isDbNull = (value == DBNull.Value);
  458. if (value == null || isDbNull) {
  459. SetValue(index,0);
  460. }
  461. else if( value is float ) {
  462. SetValue(index,(float)value);
  463. }
  464. else {
  465. SetValue(index,Convert.ToSingle(value));
  466. }
  467. SetNull(index,value == null,isDbNull);
  468. }
  469. }
  470. internal override int Capacity {
  471. set {
  472. base.Capacity = value;
  473. if (_values == null) {
  474. _values = new float[value];
  475. }
  476. else {
  477. float[] tmp = new float[value];
  478. Array.Copy(_values,0,tmp,0,_values.Length);
  479. _values = tmp;
  480. }
  481. }
  482. }
  483. #endregion //Properties
  484. #region Methods
  485. private void SetValue(int index, float value)
  486. {
  487. _values[index] = value;
  488. }
  489. internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
  490. {
  491. // if exception thrown, it should be caught
  492. // in the caller method
  493. if (!CheckAndSetNull ( index, record,field))
  494. SetValue(index,record.GetFloat(field));
  495. }
  496. internal override void CopyValue(int fromIndex, int toIndex)
  497. {
  498. base.CopyValue(fromIndex, toIndex);
  499. _values[toIndex] = _values[fromIndex];
  500. }
  501. internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
  502. {
  503. base.CopyValue(fromContainer, fromIndex, toIndex);
  504. _values[toIndex] = ((SingleDataContainer)fromContainer)._values[fromIndex];
  505. }
  506. internal override int CompareValues(int index1, int index2)
  507. {
  508. float f1 = _values[index1];
  509. float f2 = _values[index2];
  510. if ( f1 == 0 || f2 == 0 ) {
  511. int cn = CompareNulls(index1, index2);
  512. if (cn != 0) {
  513. return cn;
  514. }
  515. }
  516. if ( f1 <= f2 ) {
  517. return ( f1 != f2 ) ? -1 : 0;
  518. }
  519. return 1;
  520. }
  521. internal override long GetInt64(int index)
  522. {
  523. return Convert.ToInt64(_values[index]);
  524. }
  525. #endregion //Methods
  526. }
  527. sealed class DoubleDataContainer : AbstractDataContainer
  528. {
  529. #region Fields
  530. double[] _values;
  531. #endregion //Fields
  532. #region Properties
  533. internal override object this[int index] {
  534. get {
  535. if (IsNull(index)) {
  536. return DBNull.Value;
  537. }
  538. else {
  539. return _values[index];
  540. }
  541. }
  542. set {
  543. bool isDbNull = (value == DBNull.Value);
  544. if (value == null || isDbNull) {
  545. SetValue(index,0);
  546. }
  547. else if( value is double ) {
  548. SetValue(index,(double)value);
  549. }
  550. else {
  551. SetValue(index,Convert.ToDouble(value));
  552. }
  553. SetNull(index,value == null,isDbNull);
  554. }
  555. }
  556. internal override int Capacity {
  557. set {
  558. base.Capacity = value;
  559. if (_values == null) {
  560. _values = new double[value];
  561. }
  562. else {
  563. double[] tmp = new double[value];
  564. Array.Copy(_values,0,tmp,0,_values.Length);
  565. _values = tmp;
  566. }
  567. }
  568. }
  569. #endregion //Properties
  570. #region Methods
  571. private void SetValue(int index, double value)
  572. {
  573. _values[index] = value;
  574. }
  575. internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
  576. {
  577. // if exception thrown, it should be caught
  578. // in the caller method
  579. if (!CheckAndSetNull ( index, record,field))
  580. SetValue(index,record.GetDouble(field));
  581. }
  582. internal override void CopyValue(int fromIndex, int toIndex)
  583. {
  584. base.CopyValue(fromIndex, toIndex);
  585. _values[toIndex] = _values[fromIndex];
  586. }
  587. internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
  588. {
  589. base.CopyValue(fromContainer, fromIndex, toIndex);
  590. _values[toIndex] = ((DoubleDataContainer)fromContainer)._values[fromIndex];
  591. }
  592. internal override int CompareValues(int index1, int index2)
  593. {
  594. double d1 = _values[index1];
  595. double d2 = _values[index2];
  596. if ( d1 == 0 || d2 == 0 ) {
  597. int cn = CompareNulls(index1, index2);
  598. if (cn != 0) {
  599. return cn;
  600. }
  601. }
  602. if ( d1 <= d2 ) {
  603. return ( d1 != d2 ) ? -1 : 0;
  604. }
  605. return 1;
  606. }
  607. internal override long GetInt64(int index)
  608. {
  609. return Convert.ToInt64(_values[index]);
  610. }
  611. #endregion //Methods
  612. }
  613. sealed class ByteDataContainer : AbstractDataContainer
  614. {
  615. #region Fields
  616. byte[] _values;
  617. #endregion //Fields
  618. #region Properties
  619. internal override object this[int index] {
  620. get {
  621. if (IsNull(index)) {
  622. return DBNull.Value;
  623. }
  624. else {
  625. return _values[index];
  626. }
  627. }
  628. set {
  629. bool isDbNull = (value == DBNull.Value);
  630. if (value == null || isDbNull) {
  631. SetValue(index,0);
  632. }
  633. else if( value is byte ) {
  634. SetValue(index,(byte)value);
  635. }
  636. else {
  637. SetValue(index,Convert.ToByte(value));
  638. }
  639. SetNull(index,value == null,isDbNull);
  640. }
  641. }
  642. internal override int Capacity {
  643. set {
  644. base.Capacity = value;
  645. if (_values == null) {
  646. _values = new byte[value];
  647. }
  648. else {
  649. byte[] tmp = new byte[value];
  650. Array.Copy(_values,0,tmp,0,_values.Length);
  651. _values = tmp;
  652. }
  653. }
  654. }
  655. #endregion //Properties
  656. #region Methods
  657. private void SetValue(int index, byte value)
  658. {
  659. _values[index] = value;
  660. }
  661. internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
  662. {
  663. // if exception thrown, it should be caught
  664. // in the caller method
  665. if (!CheckAndSetNull ( index, record,field))
  666. SetValue(index,record.GetByte(field));
  667. }
  668. internal override void CopyValue(int fromIndex, int toIndex)
  669. {
  670. base.CopyValue(fromIndex, toIndex);
  671. _values[toIndex] = _values[fromIndex];
  672. }
  673. internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
  674. {
  675. base.CopyValue(fromContainer, fromIndex, toIndex);
  676. _values[toIndex] = ((ByteDataContainer)fromContainer)._values[fromIndex];
  677. }
  678. internal override int CompareValues(int index1, int index2)
  679. {
  680. byte b1 = _values[index1];
  681. byte b2 = _values[index2];
  682. if ( b1 == 0 || b2 == 0 ) {
  683. int cn = CompareNulls(index1, index2);
  684. if (cn != 0) {
  685. return cn;
  686. }
  687. }
  688. if ( b1 <= b2 ) {
  689. return ( b1 != b2 ) ? -1 : 0;
  690. }
  691. return 1;
  692. }
  693. internal override long GetInt64(int index)
  694. {
  695. return (long) _values[index];
  696. }
  697. #endregion //Methods
  698. }
  699. sealed class BitDataContainer : AbstractDataContainer
  700. {
  701. #region Fields
  702. bool[] _values;
  703. #endregion //Fields
  704. #region Properties
  705. internal override object this[int index] {
  706. get {
  707. bool isNull = IsNull(index);
  708. if (isNull) {
  709. return DBNull.Value;
  710. }
  711. else {
  712. return _values[index];
  713. }
  714. }
  715. set {
  716. bool isDbNull = (value == DBNull.Value);
  717. if (value == null || isDbNull) {
  718. SetValue(index,false);
  719. }
  720. else if( value is bool ) {
  721. SetValue(index,(bool)value);
  722. }
  723. else {
  724. SetValue(index,Convert.ToBoolean(value));
  725. }
  726. SetNull(index,value == null,isDbNull);
  727. }
  728. }
  729. internal override int Capacity {
  730. set {
  731. base.Capacity = value;
  732. if (_values == null) {
  733. _values = new bool[value];
  734. }
  735. else {
  736. bool[] tmp = new bool[value];
  737. Array.Copy(_values,0,tmp,0,_values.Length);
  738. _values = tmp;
  739. }
  740. }
  741. }
  742. #endregion //Properties
  743. #region Methods
  744. private void SetValue(int index, bool value)
  745. {
  746. _values[index] = value;
  747. }
  748. internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
  749. {
  750. // if exception thrown, it should be caught
  751. // in the caller method
  752. if (!CheckAndSetNull ( index, record,field))
  753. SetValue(index,record.GetBoolean(field));
  754. }
  755. internal override void CopyValue(int fromIndex, int toIndex)
  756. {
  757. base.CopyValue(fromIndex, toIndex);
  758. _values[toIndex] = _values[fromIndex];
  759. }
  760. internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
  761. {
  762. base.CopyValue(fromContainer, fromIndex, toIndex);
  763. _values[toIndex] = ((BitDataContainer)fromContainer)._values[fromIndex];
  764. }
  765. internal override int CompareValues(int index1, int index2)
  766. {
  767. bool b1 = _values[index1];
  768. bool b2 = _values[index2];
  769. if ( b1 ^ b2 ) {
  770. return b1 ? 1 : -1;
  771. }
  772. if ( b1 ) {
  773. return 0;
  774. }
  775. return CompareNulls(index1, index2);
  776. }
  777. internal override long GetInt64(int index)
  778. {
  779. return Convert.ToInt64(_values[index]);
  780. }
  781. #endregion //Methods
  782. }
  783. class ObjectDataContainer : AbstractDataContainer
  784. {
  785. #region Fields
  786. object[] _values;
  787. #endregion //Fields
  788. #region Properties
  789. internal override object this[int index] {
  790. get {
  791. return _values[index];
  792. }
  793. set {
  794. SetValue(index,value);
  795. SetNull(index,value == null,value == DBNull.Value);
  796. }
  797. }
  798. internal override int Capacity {
  799. set {
  800. base.Capacity = value;
  801. if (_values == null) {
  802. _values = new object[value];
  803. }
  804. else {
  805. object[] tmp = new object[value];
  806. Array.Copy(_values,0,tmp,0,_values.Length);
  807. _values = tmp;
  808. }
  809. }
  810. }
  811. #endregion //Properties
  812. #region Methods
  813. protected virtual void SetValue(int index, object value)
  814. {
  815. if(value == null) {
  816. value = Column.DefaultValue;
  817. }
  818. _values[index] = value;
  819. }
  820. internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
  821. {
  822. // if exception thrown, it should be caught
  823. // in the caller metho
  824. SetValue(index,record.GetValue(field));
  825. base.SetItemFromDataRecord(index,record,field);
  826. }
  827. internal override void CopyValue(int fromIndex, int toIndex)
  828. {
  829. base.CopyValue(fromIndex, toIndex);
  830. _values[toIndex] = _values[fromIndex];
  831. }
  832. internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
  833. {
  834. base.CopyValue(fromContainer, fromIndex, toIndex);
  835. _values[toIndex] = ((ObjectDataContainer)fromContainer)._values[fromIndex];
  836. }
  837. internal override int CompareValues(int index1, int index2)
  838. {
  839. object obj1 = _values[index1];
  840. object obj2 = _values[index2];
  841. if(obj1 == obj2) {
  842. return 0;
  843. }
  844. else if (obj1 is IComparable) {
  845. try {
  846. return ((IComparable)obj1).CompareTo(obj2);
  847. }
  848. catch {
  849. //just suppress
  850. }
  851. if (obj2 is IComparable) {
  852. obj2 = Convert.ChangeType(obj2, Type.GetTypeCode(obj1.GetType()));
  853. return ((IComparable)obj1).CompareTo(obj2);
  854. }
  855. }
  856. return String.Compare(obj1.ToString(), obj2.ToString());
  857. }
  858. internal override long GetInt64(int index)
  859. {
  860. return Convert.ToInt64(_values[index]);
  861. }
  862. #endregion //Methods
  863. }
  864. sealed class StringDataContainer : ObjectDataContainer
  865. {
  866. #region Methods
  867. private void SetValue(int index, string value)
  868. {
  869. if (value != null && Column.MaxLength >= 0 && Column.MaxLength < value.Length ) {
  870. throw new ArgumentException("Cannot set column '" + Column.ColumnName + "' to '" + value + "'. The value violates the MaxLength limit of this column.");
  871. }
  872. base.SetValue(index,value);
  873. }
  874. protected override void SetValue(int index, object value)
  875. {
  876. if ( value != null && value != DBNull.Value ) {
  877. if ( value is string ) {
  878. SetValue(index, (string) value);
  879. }
  880. else {
  881. SetValue(index, Convert.ToString(value));
  882. }
  883. return;
  884. }
  885. base.SetValue(index, value);
  886. }
  887. internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
  888. {
  889. // if exception thrown, it should be caught
  890. // in the caller method
  891. if (!CheckAndSetNull ( index, record,field))
  892. SetValue(index,record.GetString(field));
  893. }
  894. internal override int CompareValues(int index1, int index2)
  895. {
  896. bool isNull1 = IsNull(index1);
  897. bool isNull2 = IsNull(index2);
  898. if (isNull1) {
  899. return isNull2 ? 0 : -1;
  900. }
  901. else {
  902. if (isNull2) {
  903. return 1;
  904. }
  905. }
  906. return String.Compare((string)this[index1], (string)this[index2], !Column.Table.CaseSensitive);
  907. }
  908. #endregion //Methods
  909. }
  910. sealed class DateTimeDataContainer : ObjectDataContainer
  911. {
  912. #region Methods
  913. protected override void SetValue(int index, object value)
  914. {
  915. if ( value != null && value != DBNull.Value && !(value is DateTime)) {
  916. value = Convert.ToDateTime(value);
  917. }
  918. base.SetValue(index,value);
  919. }
  920. internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
  921. {
  922. // if exception thrown, it should be caught
  923. // in the caller method
  924. if (!CheckAndSetNull(index,record,field))
  925. base.SetValue(index,record.GetDateTime(field));
  926. }
  927. internal override int CompareValues(int index1, int index2)
  928. {
  929. bool isNull1 = IsNull(index1);
  930. bool isNull2 = IsNull(index2);
  931. if (isNull1) {
  932. return isNull2 ? 0 : -1;
  933. }
  934. else {
  935. if (isNull2) {
  936. return 1;
  937. }
  938. }
  939. return DateTime.Compare((DateTime)this[index1], (DateTime)this[index2]);
  940. }
  941. #endregion //Methods
  942. }
  943. }
  944. }