This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[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                                                 SetValue(index,Convert.ToInt16(value));
222                                         }
223                                         SetNull(index,value == null,isDbNull);
224                                 }
225                         }
226
227                         internal override int Capacity {
228                                 set {
229                                         base.Capacity = value;
230                                         if (_values == null) {
231                                                 _values = new short[value];
232                                         }
233                                         else {
234                                                 short[] tmp = new short[value];
235                                                 Array.Copy(_values,0,tmp,0,_values.Length);
236                                                 _values = tmp;
237                                         }
238                                 }
239                         }
240
241                         #endregion //Properties
242
243                         #region Methods
244                         
245                         private void SetValue(int index, short value)
246                         {
247                                 _values[index] = value;
248                         }
249
250                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
251                         {
252                                 // if exception thrown, it should be caught 
253                                 // in the  caller method
254                                 if (!CheckAndSetNull ( index, record,field))
255                                         SetValue(index,record.GetInt16(field));
256                         }
257
258                         internal override void CopyValue(int fromIndex, int toIndex)
259                         {
260                                 base.CopyValue(fromIndex, toIndex);
261                                 _values[toIndex] = _values[fromIndex];
262                         }
263
264                         internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
265                         {
266                                 base.CopyValue(fromContainer, fromIndex, toIndex);
267                                 _values[toIndex] = ((Int16DataContainer)fromContainer)._values[fromIndex];
268                         }
269
270                         internal override int CompareValues(int index1, int index2)
271                         {
272                                 short s1 = _values[index1];
273                                 short s2 = _values[index2];
274
275                                 if ( s1 == 0 && s2 == 0 ) {
276                                         int cn = CompareNulls(index1, index2);
277                                         return cn;
278                                 }
279
280                                 bool b1 = IsNull(index1);
281                                 bool b2 = IsNull(index2);
282                                 
283                                 if ( s1 == 0 && b1 ) {
284                                         return -1;
285                                 }
286
287                                 if ( s2 == 0 && b2 ) {
288                                         return 1;
289                                 }
290
291                                 if ( s1 <= s2 ) {
292                                         return ( s1 != s2 ) ? -1 : 0;
293                                 }
294                                 return 1;
295                         }
296
297                         internal override long GetInt64(int index)
298                         {
299                                 return (long) _values[index];
300                         }
301
302                         #endregion //Methods
303                 }
304
305                 sealed class Int32DataContainer : AbstractDataContainer
306                 {
307                         #region Fields
308                 
309                         int[] _values;
310
311                         #endregion //Fields
312
313                         #region Properties
314
315                         internal override object this[int index] {
316                                 get {
317                                         if (IsNull(index)) {
318                                                 return DBNull.Value;
319                                         }
320                                         else {
321                                                 return _values[index];
322                                         }
323                                 }
324                                 set {
325                                         bool isDbNull = (value ==  DBNull.Value);
326                                         if (value == null || isDbNull) {
327                                                 SetValue(index,0);
328                                         }
329                                         else if( value is int ) {
330                                                 SetValue(index,(int)value);
331                                         }
332                                         else {
333                                                 SetValue(index,Convert.ToInt32(value));
334                                         }
335                                         SetNull(index,value == null,isDbNull);
336                                 }
337                         }
338
339                         internal override int Capacity {
340                                 set {
341                                         base.Capacity = value;
342                                         if (_values == null) {
343                                                 _values = new int[value];
344                                         }
345                                         else {
346                                                 int[] tmp = new int[value];
347                                                 Array.Copy(_values,0,tmp,0,_values.Length);
348                                                 _values = tmp;
349                                         }
350                                 }
351                         }
352
353                         #endregion //Properties
354
355                         #region Methods
356                         
357                         private void SetValue(int index, int value)
358                         {
359                                 _values[index] = value;
360                         }
361
362                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
363                         {
364                                 // if exception thrown, it should be caught 
365                                 // in the  caller method
366                                 if (!CheckAndSetNull ( index, record,field))
367                                         SetValue(index,record.GetInt32(field));
368                         }
369
370                         internal override void CopyValue(int fromIndex, int toIndex)
371                         {
372                                 base.CopyValue(fromIndex, toIndex);
373                                 _values[toIndex] = _values[fromIndex];
374                         }
375
376                         internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
377                         {
378                                 base.CopyValue(fromContainer, fromIndex, toIndex);
379                                 _values[toIndex] = ((Int32DataContainer)fromContainer)._values[fromIndex];
380                         }
381
382                         internal override int CompareValues(int index1, int index2)
383                         {
384                                 int i1 = _values[index1];
385                                 int i2 = _values[index2];
386
387                                 if ( i1 == 0 && i2 == 0 ) {
388                                         int cn = CompareNulls(index1, index2);
389                                         return cn;
390                                 }
391
392                                 bool b1 = IsNull(index1);
393                                 bool b2 = IsNull(index2);
394                                 
395                                 if ( i1 == 0 && b1 ) {
396                                         return -1;
397                                 }
398
399                                 if ( i2 == 0 && b2 ) {
400                                         return 1;
401                                 }
402
403                                 if ( i1 <= i2 ) {
404                                         return ( i1 != i2 ) ? -1 : 0;
405                                 }
406                                 return 1;
407                         }
408
409                         internal override long GetInt64(int index)
410                         {
411                                 return (long) _values[index];
412                         }
413
414                         #endregion //Methods
415                 }
416
417                 sealed class Int64DataContainer : AbstractDataContainer
418                 {
419                         #region Fields
420                 
421                         long[] _values;
422
423                         #endregion //Fields
424
425                         #region Properties
426
427                         internal override object this[int index] {
428                                 get {
429                                         if (IsNull(index)) {
430                                                 return DBNull.Value;
431                                         }
432                                         else {
433                                                 return _values[index];
434                                         }
435                                 }
436                                 set {
437                                         bool isDbNull = (value ==  DBNull.Value);
438                                         if (value == null || isDbNull) {
439                                                 SetValue(index,0);
440                                         }
441                                         else if( value is long ) {
442                                                 SetValue(index,(long)value);
443                                         }
444                                         else {
445                                                 SetValue(index,Convert.ToInt64(value));
446                                         }
447                                         SetNull(index,value == null,isDbNull);
448                                 }
449                         }
450
451                         internal override int Capacity {
452                                 set {
453                                         base.Capacity = value;
454                                         if (_values == null) {
455                                                 _values = new long[value];
456                                         }
457                                         else {
458                                                 long[] tmp = new long[value];
459                                                 Array.Copy(_values,0,tmp,0,_values.Length);
460                                                 _values = tmp;
461                                         }
462                                 }
463                         }
464
465                         #endregion //Properties
466
467                         #region Methods
468                         
469                         private void SetValue(int index, long value)
470                         {
471                                 _values[index] = value;
472                         }
473
474                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
475                         {
476                                 // if exception thrown, it should be caught 
477                                 // in the  caller method
478                                 if (!CheckAndSetNull ( index, record,field))
479                                         SetValue(index,record.GetInt64(field));
480                         }
481
482                         internal override void CopyValue(int fromIndex, int toIndex)
483                         {
484                                 base.CopyValue(fromIndex, toIndex);
485                                 _values[toIndex] = _values[fromIndex];
486                         }
487
488                         internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
489                         {
490                                 base.CopyValue(fromContainer, fromIndex, toIndex);
491                                 _values[toIndex] = ((Int64DataContainer)fromContainer)._values[fromIndex];
492                         }
493
494                         internal override int CompareValues(int index1, int index2)
495                         {
496                                 long l1 = _values[index1];
497                                 long l2 = _values[index2];
498
499                                 if ( l1 == 0 || l2 == 0 ) {
500                                         int cn = CompareNulls(index1, index2);
501                                         if (cn != 0) {
502                                                 return cn;
503                                         }
504                                 }
505
506                                 if ( l1 <= l2 ) {
507                                         return ( l1 != l2 ) ? -1 : 0;
508                                 }
509                                 return 1;
510                         }
511
512                         internal override long GetInt64(int index)
513                         {
514                                 return _values[index];
515                         }
516
517                         #endregion //Methods
518                 }
519
520                 sealed class SingleDataContainer : AbstractDataContainer
521                 {
522                         #region Fields
523                 
524                         float[] _values;
525
526                         #endregion //Fields
527
528                         #region Properties
529
530                         internal override object this[int index] {
531                                 get {
532                                         if (IsNull(index)) {
533                                                 return DBNull.Value;
534                                         }
535                                         else {
536                                                 return _values[index];
537                                         }
538                                 }
539                                 set {
540                                         bool isDbNull = (value ==  DBNull.Value);
541                                         if (value == null || isDbNull) {
542                                                 SetValue(index,0);
543                                         }
544                                         else if( value is float ) {
545                                                 SetValue(index,(float)value);
546                                         }
547                                         else {
548                                                 SetValue(index,Convert.ToSingle(value));
549                                         }
550                                         SetNull(index,value == null,isDbNull);
551                                 }
552                         }
553
554                         internal override int Capacity {
555                                 set {
556                                         base.Capacity = value;
557                                         if (_values == null) {
558                                                 _values = new float[value];
559                                         }
560                                         else {
561                                                 float[] tmp = new float[value];
562                                                 Array.Copy(_values,0,tmp,0,_values.Length);
563                                                 _values = tmp;
564                                         }
565                                 }
566                         }
567
568                         #endregion //Properties
569
570                         #region Methods
571                         
572                         private void SetValue(int index, float value)
573                         {
574                                 _values[index] = value;
575                         }
576
577                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
578                         {
579                                 // if exception thrown, it should be caught 
580                                 // in the  caller method
581                                 if (!CheckAndSetNull ( index, record,field))
582                                         SetValue(index,record.GetFloat(field));
583                         }
584
585                         internal override void CopyValue(int fromIndex, int toIndex)
586                         {
587                                 base.CopyValue(fromIndex, toIndex);
588                                 _values[toIndex] = _values[fromIndex];
589                         }
590
591                         internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
592                         {
593                                 base.CopyValue(fromContainer, fromIndex, toIndex);
594                                 _values[toIndex] = ((SingleDataContainer)fromContainer)._values[fromIndex];
595                         }
596
597                         internal override int CompareValues(int index1, int index2)
598                         {
599                                 float f1 = _values[index1];
600                                 float f2 = _values[index2];
601
602                                 if ( f1 == 0 || f2 == 0 ) {
603                                         int cn = CompareNulls(index1, index2);
604                                         if (cn != 0) {
605                                                 return cn;
606                                         }
607                                 }
608
609                                 if ( f1 <= f2 ) {
610                                         return ( f1 != f2 ) ? -1 : 0;
611                                 }
612                                 return 1;
613                         }
614
615                         internal override long GetInt64(int index)
616                         {
617                                 return Convert.ToInt64(_values[index]);
618                         }
619
620                         #endregion //Methods
621                 }
622
623                 sealed class DoubleDataContainer : AbstractDataContainer
624                 {
625                         #region Fields
626                 
627                         double[] _values;
628
629                         #endregion //Fields
630
631                         #region Properties
632
633                         internal override object this[int index] {
634                                 get {
635                                         if (IsNull(index)) {
636                                                 return DBNull.Value;
637                                         }
638                                         else {
639                                                 return _values[index];
640                                         }
641                                 }
642                                 set {
643                                         bool isDbNull = (value ==  DBNull.Value);
644                                         if (value == null || isDbNull) {
645                                                 SetValue(index,0);
646                                         }
647                                         else if( value is double ) {
648                                                 SetValue(index,(double)value);
649                                         }
650                                         else {
651                                                 SetValue(index,Convert.ToDouble(value));
652                                         }
653                                         SetNull(index,value == null,isDbNull);
654                                 }
655                         }
656
657                         internal override int Capacity {
658                                 set {
659                                         base.Capacity = value;
660                                         if (_values == null) {
661                                                 _values = new double[value];
662                                         }
663                                         else {
664                                                 double[] tmp = new double[value];
665                                                 Array.Copy(_values,0,tmp,0,_values.Length);
666                                                 _values = tmp;
667                                         }
668                                 }
669                         }
670
671                         #endregion //Properties
672
673                         #region Methods
674                         
675                         private void SetValue(int index, double value)
676                         {
677                                 _values[index] = value;
678                         }
679
680                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
681                         {
682                                 // if exception thrown, it should be caught 
683                                 // in the  caller method
684                                 if (!CheckAndSetNull ( index, record,field))
685                                         SetValue(index,record.GetDouble(field));
686                         }
687
688                         internal override void CopyValue(int fromIndex, int toIndex)
689                         {
690                                 base.CopyValue(fromIndex, toIndex);
691                                 _values[toIndex] = _values[fromIndex];
692                         }
693
694                         internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
695                         {
696                                 base.CopyValue(fromContainer, fromIndex, toIndex);
697                                 _values[toIndex] = ((DoubleDataContainer)fromContainer)._values[fromIndex];
698                         }
699
700                         internal override int CompareValues(int index1, int index2)
701                         {
702                                 double d1 = _values[index1];
703                                 double d2 = _values[index2];
704
705                                 if ( d1 == 0 || d2 == 0 ) {
706                                         int cn = CompareNulls(index1, index2);
707                                         if (cn != 0) {
708                                                 return cn;
709                                         }
710                                 }
711
712                                 if ( d1 <= d2 ) {
713                                         return ( d1 != d2 ) ? -1 : 0;
714                                 }
715                                 return 1;
716                         }
717
718                         internal override long GetInt64(int index)
719                         {
720                                 return Convert.ToInt64(_values[index]);
721                         }
722
723                         #endregion //Methods
724                 }
725
726                 sealed class ByteDataContainer : AbstractDataContainer
727                 {
728                         #region Fields
729                 
730                         byte[] _values;
731
732                         #endregion //Fields
733
734                         #region Properties
735
736                         internal override object this[int index] {
737                                 get {
738                                         if (IsNull(index)) {
739                                                 return DBNull.Value;
740                                         }
741                                         else {
742                                                 return _values[index];
743                                         }
744                                 }
745                                 set {
746                                         bool isDbNull = (value ==  DBNull.Value);
747                                         if (value == null || isDbNull) {
748                                                 SetValue(index,0);
749                                         }
750                                         else if( value is byte ) {
751                                                 SetValue(index,(byte)value);
752                                         }
753                                         else {
754                                                 SetValue(index,Convert.ToByte(value));
755                                         }
756                                         SetNull(index,value == null,isDbNull);
757                                 }
758                         }
759
760                         internal override int Capacity {
761                                 set {
762                                         base.Capacity = value;
763                                         if (_values == null) {
764                                                 _values = new byte[value];
765                                         }
766                                         else {
767                                                 byte[] tmp = new byte[value];
768                                                 Array.Copy(_values,0,tmp,0,_values.Length);
769                                                 _values = tmp;
770                                         }
771                                 }
772                         }
773
774                         #endregion //Properties
775
776                         #region Methods
777                         
778                         private void SetValue(int index, byte value)
779                         {
780                                 _values[index] = value;
781                         }
782
783                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
784                         {
785                                 // if exception thrown, it should be caught 
786                                 // in the  caller method
787                                 if (!CheckAndSetNull ( index, record,field))
788                                         SetValue(index,record.GetByte(field));
789                         }
790
791                         internal override void CopyValue(int fromIndex, int toIndex)
792                         {
793                                 base.CopyValue(fromIndex, toIndex);
794                                 _values[toIndex] = _values[fromIndex];
795                         }
796
797                         internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
798                         {
799                                 base.CopyValue(fromContainer, fromIndex, toIndex);
800                                 _values[toIndex] = ((ByteDataContainer)fromContainer)._values[fromIndex];
801                         }
802
803                         internal override int CompareValues(int index1, int index2)
804                         {
805                                 byte b1 = _values[index1];
806                                 byte b2 = _values[index2];
807
808                                 if ( b1 == 0 || b2 == 0 ) {
809                                         int cn = CompareNulls(index1, index2);
810                                         if (cn != 0) {
811                                                 return cn;
812                                         }
813                                 }
814
815                                 if ( b1 <= b2 ) {
816                                         return ( b1 != b2 ) ? -1 : 0;
817                                 }
818                                 return 1;
819                         }
820
821                         internal override long GetInt64(int index)
822                         {
823                                 return (long) _values[index];
824                         }
825
826                         #endregion //Methods
827                 }
828
829                 sealed class BitDataContainer : AbstractDataContainer
830                 {
831                         #region Fields
832                 
833                         bool[] _values;
834
835                         #endregion //Fields
836
837                         #region Properties
838
839                         internal override object this[int index] {
840                                 get {
841                                         bool isNull = IsNull(index);
842                                         if (isNull) {
843                                                 return DBNull.Value;
844                                         }
845                                         else {
846                                                 return _values[index];
847                                         }
848                                 }
849                                 set {
850                                         bool isDbNull = (value ==  DBNull.Value);
851                                         if (value == null || isDbNull) {
852                                                 SetValue(index,false);
853                                         }
854                                         else if( value is bool ) {
855                                                 SetValue(index,(bool)value);
856                                         }
857                                         else {
858                                                 SetValue(index,Convert.ToBoolean(value));
859                                         }
860                                         SetNull(index,value == null,isDbNull);
861                                 }
862                         }
863
864                         internal override int Capacity {
865                                 set {
866                                         base.Capacity = value;
867                                         if (_values == null) {
868                                                 _values = new bool[value];
869                                         }
870                                         else {
871                                                 bool[] tmp = new bool[value];
872                                                 Array.Copy(_values,0,tmp,0,_values.Length);
873                                                 _values = tmp;
874                                         }
875                                 }
876                         }
877
878                         #endregion //Properties
879
880                         #region Methods
881                         
882                         private void SetValue(int index, bool value)
883                         {
884                                 _values[index] = value;
885                         }
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.GetBoolean(field));
893                         }
894
895                         internal override void CopyValue(int fromIndex, int toIndex)
896                         {
897                                 base.CopyValue(fromIndex, toIndex);
898                                 _values[toIndex] = _values[fromIndex];
899                         }
900
901                         internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
902                         {
903                                 base.CopyValue(fromContainer, fromIndex, toIndex);
904                                 _values[toIndex] = ((BitDataContainer)fromContainer)._values[fromIndex];
905                         }
906
907                         internal override int CompareValues(int index1, int index2)
908                         {
909                                 bool b1 = _values[index1];
910                                 bool b2 = _values[index2];
911
912                                 if ( b1 ^ b2 ) {
913                                         return b1 ? 1 : -1;
914                                 }
915                                 
916                                 if ( b1 ) {
917                                         return 0;
918                                 }
919
920                                 return CompareNulls(index1, index2);    
921                         }
922
923                         internal override long GetInt64(int index)
924                         {
925                                 return Convert.ToInt64(_values[index]);
926                         }
927
928                         #endregion //Methods
929                 }
930
931                 class ObjectDataContainer : AbstractDataContainer
932                 {
933                         #region Fields
934                 
935                         object[] _values;
936
937                         #endregion //Fields
938
939                         #region Properties
940
941                         internal override object this[int index] {
942                                 get {
943                                         return _values[index];
944                                 }
945                                 set {
946                                         SetValue(index,value);
947                                         SetNull(index,value == null,value == DBNull.Value);
948                                 }
949                         }
950
951                         internal override int Capacity {
952                                 set {
953                                         base.Capacity = value;
954                                         if (_values == null) {
955                                                 _values = new object[value];
956                                         }
957                                         else {
958                                                 object[] tmp = new object[value];
959                                                 Array.Copy(_values,0,tmp,0,_values.Length);
960                                                 _values = tmp;
961                                         }
962                                 }
963                         }
964
965                         #endregion //Properties
966
967                         #region Methods
968                         
969                         protected virtual void SetValue(int index, object value)
970                         {
971                                 if(value == null) {
972                                         value = Column.DefaultValue;
973                                 }
974                                 _values[index] = value;
975                         }
976
977                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
978                         {
979                                 // if exception thrown, it should be caught 
980                                 // in the  caller metho
981                                 SetValue(index,record.GetValue(field));
982                                 base.SetItemFromDataRecord(index,record,field);
983                         }
984
985                         internal override void CopyValue(int fromIndex, int toIndex)
986                         {
987                                 base.CopyValue(fromIndex, toIndex);
988                                 _values[toIndex] = _values[fromIndex];
989                         }
990
991                         internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
992                         {
993                                 base.CopyValue(fromContainer, fromIndex, toIndex);
994                                 _values[toIndex] = ((ObjectDataContainer)fromContainer)._values[fromIndex];
995                         }
996
997                         internal override int CompareValues(int index1, int index2)
998                         {
999                                 object obj1 = _values[index1];
1000                                 object obj2 = _values[index2];
1001                                 if(obj1 == obj2) {
1002                                         return 0;
1003                                 }
1004                                 else if (obj1 is IComparable) {
1005                                         try {
1006                                                 return ((IComparable)obj1).CompareTo(obj2);
1007                                         }
1008                                         catch {
1009                                                 //just suppress
1010                                         }
1011
1012                                         if (obj2 is IComparable) {
1013                                                 obj2 = Convert.ChangeType(obj2, Type.GetTypeCode(obj1.GetType()));
1014                                                 return ((IComparable)obj1).CompareTo(obj2);
1015                                         }
1016                                 }
1017
1018                                 return String.Compare(obj1.ToString(), obj2.ToString());
1019                         }
1020
1021                         internal override long GetInt64(int index)
1022                         {
1023                                 return Convert.ToInt64(_values[index]);
1024                         }
1025
1026                         #endregion //Methods
1027          
1028                 }
1029
1030                 sealed class StringDataContainer : ObjectDataContainer
1031                 {
1032                         #region Methods
1033
1034                         private void SetValue(int index, string value)
1035                         {
1036                                 if (value != null && Column.MaxLength >= 0 && Column.MaxLength < value.Length ) {
1037                                         throw new ArgumentException("Cannot set column '" + Column.ColumnName + "' to '" + value + "'. The value violates the MaxLength limit of this column.");
1038                                 }
1039                                 base.SetValue(index,value);
1040                         }
1041                         
1042                         protected override void SetValue(int index, object value)
1043                         {
1044                                 if ( value != null && value != DBNull.Value ) {
1045                                         if ( value is string ) {
1046                                                 SetValue(index, (string) value);
1047                                         }
1048                                         else {
1049                                                 SetValue(index, Convert.ToString(value));
1050                                         }
1051                                         return;
1052                                 }
1053
1054                                 base.SetValue(index, value);
1055                         }
1056
1057                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
1058                         {
1059                                 // if exception thrown, it should be caught 
1060                                 // in the  caller method
1061                                 if (!CheckAndSetNull ( index, record,field))
1062                                         SetValue(index,record.GetString(field));
1063                         }
1064
1065                         internal override int CompareValues(int index1, int index2)
1066                         {
1067                                 bool isNull1 = IsNull(index1);
1068                                 bool isNull2 = IsNull(index2);
1069
1070                                 if (isNull1) {
1071                                         return isNull2 ? 0 : -1;
1072                                 }
1073                                 else {
1074                                         if (isNull2) {
1075                                                 return 1;
1076                                         }
1077                                 }
1078                                 return String.Compare((string)this[index1], (string)this[index2], !Column.Table.CaseSensitive);
1079                         }
1080
1081                         #endregion //Methods 
1082                 }
1083
1084                 sealed class DateTimeDataContainer : ObjectDataContainer
1085                 {
1086                         #region Methods
1087                         
1088                         protected override void SetValue(int index, object value)
1089                         {
1090                                 if ( value != null && value != DBNull.Value && !(value is DateTime)) {
1091                                         value = Convert.ToDateTime(value);
1092                                 }
1093
1094                                 base.SetValue(index,value);
1095                         }
1096
1097                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
1098                         {
1099                                 // if exception thrown, it should be caught 
1100                                 // in the  caller method
1101                                  if (!CheckAndSetNull(index,record,field))
1102                                         base.SetValue(index,record.GetDateTime(field));
1103                         }
1104
1105                         internal override int CompareValues(int index1, int index2)
1106                         {
1107                                 bool isNull1 = IsNull(index1);
1108                                 bool isNull2 = IsNull(index2);
1109
1110                                 if (isNull1) {
1111                                         return isNull2 ? 0 : -1;
1112                                 }
1113                                 else {
1114                                         if (isNull2) {
1115                                                 return 1;
1116                                         }
1117                                 }
1118                                 return DateTime.Compare((DateTime)this[index1], (DateTime)this[index2]);
1119                         }
1120
1121                         #endregion //Methods 
1122                 }
1123         }
1124 }