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