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