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