Copied remotely
[mono.git] / mcs / class / System.Data / System.Data.OleDb / OleDbDataReader.cs
1 //
2 // System.Data.OleDb.OleDbDataReader
3 //
4 // Author:
5 //   Rodrigo Moya (rodrigo@ximian.com)
6 //   Tim Coleman (tim@timcoleman.com)
7 //
8 // Copyright (C) Rodrigo Moya, 2002
9 // Copyright (C) Tim Coleman, 2002
10 //
11
12 //
13 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34
35 using System.Collections;
36 using System.ComponentModel;
37 using System.Data;
38 using System.Data.Common;
39 using System.Runtime.InteropServices;
40
41 namespace System.Data.OleDb
42 {
43         public sealed class OleDbDataReader : MarshalByRefObject, IDataReader, IDisposable, IDataRecord, IEnumerable
44         {
45                 #region Fields
46                 
47                 private OleDbCommand command;
48                 private bool open;
49                 private ArrayList gdaResults;
50                 private int currentResult;
51                 private int currentRow;
52                 private bool disposed = false;
53
54                 #endregion
55
56                 #region Constructors
57
58                 internal OleDbDataReader (OleDbCommand command, ArrayList results) 
59                 {
60                         this.command = command;
61                         open = true;
62                         if (results != null)
63                                 gdaResults = results;
64                         else
65                                 gdaResults = new ArrayList ();
66                         currentResult = -1;
67                         currentRow = -1;
68                 }
69
70                 #endregion
71
72                 #region Properties
73
74                 public int Depth {
75                         get {
76                                 return 0; // no nested selects supported
77                         }
78                 }
79
80                 public int FieldCount {
81                         get {
82                                 if (currentResult < 0 ||
83                                     currentResult >= gdaResults.Count)
84                                         return 0;
85
86                                 return libgda.gda_data_model_get_n_columns (
87                                         (IntPtr) gdaResults[currentResult]);
88                         }
89                 }
90
91                 public bool IsClosed {
92                         get {
93                                 return !open;
94                         }
95                 }
96
97                 public object this[string name] {
98                         get {
99                                 int pos;
100
101                                 if (currentResult == -1)
102                                         throw new InvalidOperationException ();
103
104                                 pos = libgda.gda_data_model_get_column_position (
105                                         (IntPtr) gdaResults[currentResult],
106                                         name);
107                                 if (pos == -1)
108                                         throw new IndexOutOfRangeException ();
109
110                                 return this[pos];
111                         }
112                 }
113
114                 public object this[int index] {
115                         get {
116                                 return (object) GetValue (index);
117                         }
118                 }
119
120                 public int RecordsAffected {
121                         get {
122                                 int total_rows;
123                                 
124                                 if (currentResult < 0 ||
125                                     currentResult >= gdaResults.Count)
126                                         return 0;
127
128                                 total_rows = libgda.gda_data_model_get_n_rows (
129                                         (IntPtr) gdaResults[currentResult]);
130                                 if (total_rows > 0) {
131                                         if (FieldCount > 0) {
132                                                 // It's a SELECT statement
133                                                 return -1;
134                                         }
135                                 }
136
137                                 return FieldCount > 0 ? -1 : total_rows;
138                         }
139                 }
140                 
141                 [MonoTODO]
142                 public bool HasRows {
143                         get {
144                                 throw new NotImplementedException ();
145                         }
146                 }
147
148                 #endregion
149
150                 #region Methods
151
152                 public void Close ()
153                 {
154                         for (int i = 0; i < gdaResults.Count; i++) {
155                                 IntPtr obj = (IntPtr) gdaResults[i];
156                                 libgda.FreeObject (obj);
157                         }
158
159                         gdaResults.Clear ();
160                         gdaResults = null;
161                         
162                         open = false;
163                         currentResult = -1;
164                         currentRow = -1;
165                 }
166
167                 public bool GetBoolean (int ordinal)
168                 {
169                         IntPtr value;
170
171                         if (currentResult == -1)
172                                 throw new InvalidCastException ();
173
174                         value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
175                                                                     ordinal, currentRow);
176                         if (value == IntPtr.Zero)
177                                 throw new InvalidCastException ();
178                         
179                         if (libgda.gda_value_get_type (value) != GdaValueType.Boolean)
180                                 throw new InvalidCastException ();
181                         return libgda.gda_value_get_boolean (value);
182                 }
183
184                 public byte GetByte (int ordinal)
185                 {
186                         IntPtr value;
187
188                         if (currentResult == -1)
189                                 throw new InvalidCastException ();
190
191                         value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
192                                                                     ordinal, currentRow);
193                         if (value == IntPtr.Zero)
194                                 throw new InvalidCastException ();
195                         
196                         if (libgda.gda_value_get_type (value) != GdaValueType.Tinyint)
197                                 throw new InvalidCastException ();
198                         return libgda.gda_value_get_tinyint (value);
199                 }
200
201                 [MonoTODO]
202                 public long GetBytes (int ordinal, long dataIndex, byte[] buffer, int bufferIndex, int length)
203                 {
204                         throw new NotImplementedException ();
205                 }
206                 
207                 [EditorBrowsableAttribute (EditorBrowsableState.Never)]
208                 public char GetChar (int ordinal)
209                 {
210                         IntPtr value;
211
212                         if (currentResult == -1)
213                                 throw new InvalidCastException ();
214
215                         value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
216                                                                     ordinal, currentRow);
217                         if (value == IntPtr.Zero)
218                                 throw new InvalidCastException ();
219                         
220                         if (libgda.gda_value_get_type (value) != GdaValueType.Tinyint)
221                                 throw new InvalidCastException ();
222                         return (char) libgda.gda_value_get_tinyint (value);
223                 }
224
225                 [MonoTODO]
226                 public long GetChars (int ordinal, long dataIndex, char[] buffer, int bufferIndex, int length)
227                 {
228                         throw new NotImplementedException ();
229                 }
230
231                 [MonoTODO]
232                 public OleDbDataReader GetData (int ordinal)
233                 {
234                         throw new NotImplementedException ();
235                 }
236
237                 public string GetDataTypeName (int index)
238                 {
239                         IntPtr attrs;
240                         GdaValueType type;
241
242                         if (currentResult == -1)
243                                 return "unknown";
244
245                         
246                         attrs = libgda.gda_data_model_describe_column ((IntPtr) gdaResults[currentResult],
247                                                                        index);
248                         if (attrs == IntPtr.Zero)
249                                 return "unknown";
250
251                         type = libgda.gda_field_attributes_get_gdatype (attrs);
252                         libgda.gda_field_attributes_free (attrs);
253                         
254                         return libgda.gda_type_to_string (type);
255                 }
256
257                 public DateTime GetDateTime (int ordinal)
258                 {
259                         IntPtr value;
260                         DateTime dt;
261
262                         if (currentResult == -1)
263                                 throw new InvalidCastException ();
264
265                         value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
266                                                                     ordinal, currentRow);
267                         if (value == IntPtr.Zero)
268                                 throw new InvalidCastException ();
269                         
270                         if (libgda.gda_value_get_type (value) == GdaValueType.Date) {
271                                 GdaDate gdt;
272
273                                 gdt = (GdaDate) Marshal.PtrToStructure (libgda.gda_value_get_date (value),
274                                                                         typeof (GdaDate));
275                                 return new DateTime ((int) gdt.year, (int) gdt.month, (int) gdt.day);
276                         } else if (libgda.gda_value_get_type (value) == GdaValueType.Time) {
277                                 GdaTime gdt;
278
279                                 gdt = (GdaTime) Marshal.PtrToStructure (libgda.gda_value_get_time (value),
280                                                                         typeof (GdaTime));
281                                 return new DateTime (0, 0, 0, (int) gdt.hour, (int) gdt.minute, (int) gdt.second, 0);
282                         } else if (libgda.gda_value_get_type (value) == GdaValueType.Timestamp) {
283                                 GdaTimestamp gdt;
284                                 
285                                 gdt = (GdaTimestamp) Marshal.PtrToStructure (libgda.gda_value_get_timestamp (value),
286                                                                              typeof (GdaTimestamp));
287
288                                 return new DateTime ((int) gdt.year, (int) gdt.month, (int) gdt.day,
289                                                      (int) gdt.hour, (int) gdt.minute, (int) gdt.second,
290                                                      (int) gdt.fraction);
291                         }
292
293                         throw new InvalidCastException ();
294                 }
295
296                 [MonoTODO]
297                 public decimal GetDecimal (int ordinal)
298                 {
299                         throw new NotImplementedException ();
300                 }
301
302                 public double GetDouble (int ordinal)
303                 {
304                         IntPtr value;
305
306                         if (currentResult == -1)
307                                 throw new InvalidCastException ();
308
309                         value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
310                                                                     ordinal, currentRow);
311                         if (value == IntPtr.Zero)
312                                 throw new InvalidCastException ();
313                         
314                         if (libgda.gda_value_get_type (value) != GdaValueType.Double)
315                                 throw new InvalidCastException ();
316                         return libgda.gda_value_get_double (value);
317                 }
318
319                 [MonoTODO]
320                 public Type GetFieldType (int index)
321                 {
322                         IntPtr value;
323                         GdaValueType type;
324
325                         if (currentResult == -1)
326                                 throw new IndexOutOfRangeException ();
327
328                         value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
329                                 index, currentRow);
330                         if (value == IntPtr.Zero)
331                                 throw new IndexOutOfRangeException ();
332
333                         type = libgda.gda_value_get_type (value);
334                         switch (type) {
335                         case GdaValueType.Bigint : return typeof (long);
336                         case GdaValueType.Boolean : return typeof (bool);
337                         case GdaValueType.Date : return typeof (DateTime);
338                         case GdaValueType.Double : return typeof (double);
339                         case GdaValueType.Integer : return typeof (int);
340                         case GdaValueType.Single : return typeof (float);
341                         case GdaValueType.Smallint : return typeof (byte);
342                         case GdaValueType.String : return typeof (string);
343                         case GdaValueType.Time : return typeof (DateTime);
344                         case GdaValueType.Timestamp : return typeof (DateTime);
345                         case GdaValueType.Tinyint : return typeof (byte);
346                         }
347
348                         return typeof(string); // default
349                 }
350
351                 public float GetFloat (int ordinal)
352                 {
353                         IntPtr value;
354
355                         if (currentResult == -1)
356                                 throw new InvalidCastException ();
357
358                         value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
359                                                                     ordinal, currentRow);
360                         if (value == IntPtr.Zero)
361                                 throw new InvalidCastException ();
362                         
363                         if (libgda.gda_value_get_type (value) != GdaValueType.Single)
364                                 throw new InvalidCastException ();
365                         return libgda.gda_value_get_single (value);
366                 }
367
368                 [MonoTODO]
369                 public Guid GetGuid (int ordinal)
370                 {
371                         throw new NotImplementedException ();
372                 }
373
374                 public short GetInt16 (int ordinal)
375                 {
376                         IntPtr value;
377
378                         if (currentResult == -1)
379                                 throw new InvalidCastException ();
380
381                         value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
382                                                                     ordinal, currentRow);
383                         if (value == IntPtr.Zero)
384                                 throw new InvalidCastException ();
385                         
386                         if (libgda.gda_value_get_type (value) != GdaValueType.Smallint)
387                                 throw new InvalidCastException ();
388                         return (short) libgda.gda_value_get_smallint (value);
389                 }
390
391                 public int GetInt32 (int ordinal)
392                 {
393                         IntPtr value;
394
395                         if (currentResult == -1)
396                                 throw new InvalidCastException ();
397
398                         value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
399                                                                     ordinal, currentRow);
400                         if (value == IntPtr.Zero)
401                                 throw new InvalidCastException ();
402                         
403                         if (libgda.gda_value_get_type (value) != GdaValueType.Integer)
404                                 throw new InvalidCastException ();
405                         return libgda.gda_value_get_integer (value);
406                 }
407
408                 public long GetInt64 (int ordinal)
409                 {
410                         IntPtr value;
411
412                         if (currentResult == -1)
413                                 throw new InvalidCastException ();
414
415                         value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
416                                                                     ordinal, currentRow);
417                         if (value == IntPtr.Zero)
418                                 throw new InvalidCastException ();
419                         
420                         if (libgda.gda_value_get_type (value) != GdaValueType.Bigint)
421                                 throw new InvalidCastException ();
422                         return libgda.gda_value_get_bigint (value);
423                 }
424
425                 public string GetName (int index)
426                 {
427                         if (currentResult == -1)
428                                 return null;
429
430                         return libgda.gda_data_model_get_column_title (
431                                 (IntPtr) gdaResults[currentResult], index);
432                 }
433
434                 public int GetOrdinal (string name)
435                 {
436                         if (currentResult == -1)
437                                 throw new IndexOutOfRangeException ();
438
439                         for (int i = 0; i < FieldCount; i++) {
440                                 if (GetName (i) == name)
441                                         return i;
442                         }
443
444                         throw new IndexOutOfRangeException ();
445                 }
446
447                 public DataTable GetSchemaTable ()
448                 {
449                         DataTable dataTableSchema = null;
450                         // Only Results from SQL SELECT Queries 
451                         // get a DataTable for schema of the result
452                         // otherwise, DataTable is null reference
453                         if(this.FieldCount > 0) {
454
455                                 IntPtr attrs;
456                                 GdaValueType gdaType;
457                                 long columnSize = 0;
458
459                                 if (currentResult == -1) {
460                                         // FIXME: throw an exception?
461 #if DEBUG_OleDbDataReader
462                                         Console.WriteLine("Error: current result -1");
463 #endif
464                                         return null;
465                                 }
466                                                 
467                                 dataTableSchema = new DataTable ();
468                                 
469                                 dataTableSchema.Columns.Add ("ColumnName", typeof (string));
470                                 dataTableSchema.Columns.Add ("ColumnOrdinal", typeof (int));
471                                 dataTableSchema.Columns.Add ("ColumnSize", typeof (int));
472                                 dataTableSchema.Columns.Add ("NumericPrecision", typeof (int));
473                                 dataTableSchema.Columns.Add ("NumericScale", typeof (int));
474                                 dataTableSchema.Columns.Add ("IsUnique", typeof (bool));
475                                 dataTableSchema.Columns.Add ("IsKey", typeof (bool));
476                                 DataColumn dc = dataTableSchema.Columns["IsKey"];
477                                 dc.AllowDBNull = true; // IsKey can have a DBNull
478                                 dataTableSchema.Columns.Add ("BaseCatalogName", typeof (string));
479                                 dataTableSchema.Columns.Add ("BaseColumnName", typeof (string));
480                                 dataTableSchema.Columns.Add ("BaseSchemaName", typeof (string));
481                                 dataTableSchema.Columns.Add ("BaseTableName", typeof (string));
482                                 dataTableSchema.Columns.Add ("DataType", typeof(Type));
483                                 dataTableSchema.Columns.Add ("AllowDBNull", typeof (bool));
484                                 dataTableSchema.Columns.Add ("ProviderType", typeof (int));
485                                 dataTableSchema.Columns.Add ("IsAliased", typeof (bool));
486                                 dataTableSchema.Columns.Add ("IsExpression", typeof (bool));
487                                 dataTableSchema.Columns.Add ("IsIdentity", typeof (bool));
488                                 dataTableSchema.Columns.Add ("IsAutoIncrement", typeof (bool));
489                                 dataTableSchema.Columns.Add ("IsRowVersion", typeof (bool));
490                                 dataTableSchema.Columns.Add ("IsHidden", typeof (bool));
491                                 dataTableSchema.Columns.Add ("IsLong", typeof (bool));
492                                 dataTableSchema.Columns.Add ("IsReadOnly", typeof (bool));
493 \r
494                                 DataRow schemaRow;
495                                 DbType dbType;
496                                 Type typ;
497                                                                 
498                                 for (int i = 0; i < this.FieldCount; i += 1 ) {
499                                         
500                                         schemaRow = dataTableSchema.NewRow ();
501
502                                         attrs = libgda.gda_data_model_describe_column ((IntPtr) gdaResults[currentResult],
503                                                 i);
504                                         if (attrs == IntPtr.Zero){
505                                                 // FIXME: throw exception
506 #if DEBUG_OleDbDataReader
507                                                 Console.WriteLine("Error: attrs null");
508 #endif
509                                                 return null;
510                                         }
511
512                                         gdaType = libgda.gda_field_attributes_get_gdatype (attrs);
513                                         columnSize = libgda.gda_field_attributes_get_defined_size (attrs);
514                                         libgda.gda_field_attributes_free (attrs);
515                                                                                 
516                                         schemaRow["ColumnName"] = this.GetName(i);
517                                         schemaRow["ColumnOrdinal"] = i + 1;
518                                         
519                                         schemaRow["ColumnSize"] = (int) columnSize;
520                                         schemaRow["NumericPrecision"] = 0;
521                                         schemaRow["NumericScale"] = 0;
522                                         // TODO: need to get KeyInfo
523                                         //if((cmdBehavior & CommandBehavior.KeyInfo) == CommandBehavior.KeyInfo) {
524                                                 // bool IsUnique, IsKey;
525                                                 // GetKeyInfo(field[i].Name, out IsUnique, out IsKey);
526                                         //}
527                                         //else {
528                                                 schemaRow["IsUnique"] = false;
529                                                 schemaRow["IsKey"] = DBNull.Value;
530                                         //}
531                                         schemaRow["BaseCatalogName"] = "";
532                                         
533                                         schemaRow["BaseColumnName"] = this.GetName(i);
534                                         schemaRow["BaseSchemaName"] = "";
535                                         schemaRow["BaseTableName"] = "";
536
537                                         schemaRow["DataType"] = this.GetFieldType(i);\r
538
539                                         schemaRow["AllowDBNull"] = false;
540                                         
541                                         schemaRow["ProviderType"] = (int) gdaType;
542                                         schemaRow["IsAliased"] = false;
543                                         schemaRow["IsExpression"] = false;
544                                         schemaRow["IsIdentity"] = false;
545                                         schemaRow["IsAutoIncrement"] = false;
546                                         schemaRow["IsRowVersion"] = false;
547                                         schemaRow["IsHidden"] = false;
548                                         schemaRow["IsLong"] = false;
549                                         schemaRow["IsReadOnly"] = false;
550                                         
551                                         schemaRow.AcceptChanges();
552                                         
553                                         dataTableSchema.Rows.Add (schemaRow);
554                                 }
555                                 
556 #if DEBUG_OleDbDataReader
557                                 Console.WriteLine("********** DEBUG Table Schema BEGIN ************");
558                                 foreach (DataRow myRow in dataTableSchema.Rows) {\r
559                                         foreach (DataColumn myCol in dataTableSchema.Columns)\r
560                                                 Console.WriteLine(myCol.ColumnName + " = " + myRow[myCol]);\r
561                                         Console.WriteLine();\r
562                                 }
563                                 Console.WriteLine("********** DEBUG Table Schema END ************");
564 #endif // DEBUG_OleDbDataReader
565
566                         }
567                         
568                         return dataTableSchema;
569                 }
570
571                 public string GetString (int ordinal)
572                 {
573                         IntPtr value;
574
575                         if (currentResult == -1)
576                                 throw new InvalidCastException ();
577
578                         value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
579                                                                     ordinal, currentRow);
580                         if (value == IntPtr.Zero)
581                                 throw new InvalidCastException ();
582                         
583                         if (libgda.gda_value_get_type (value) != GdaValueType.String)
584                                 throw new InvalidCastException ();
585                         return libgda.gda_value_get_string (value);
586                 }
587
588                 [MonoTODO]
589                 public TimeSpan GetTimeSpan (int ordinal)
590                 {
591                         throw new NotImplementedException ();
592                 }
593
594                 public object GetValue (int ordinal)
595                 {
596                         IntPtr value;
597                         GdaValueType type;
598
599                         if (currentResult == -1)
600                                 throw new IndexOutOfRangeException ();
601
602                         value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
603                                                                     ordinal, currentRow);
604                         if (value == IntPtr.Zero)
605                                 throw new IndexOutOfRangeException ();
606
607                         type = libgda.gda_value_get_type (value);
608                         switch (type) {
609                         case GdaValueType.Bigint : return GetInt64 (ordinal);
610                         case GdaValueType.Boolean : return GetBoolean (ordinal);
611                         case GdaValueType.Date : return GetDateTime (ordinal);
612                         case GdaValueType.Double : return GetDouble (ordinal);
613                         case GdaValueType.Integer : return GetInt32 (ordinal);
614                         case GdaValueType.Single : return GetFloat (ordinal);
615                         case GdaValueType.Smallint : return GetByte (ordinal);
616                         case GdaValueType.String : return GetString (ordinal);
617                         case GdaValueType.Time : return GetDateTime (ordinal);
618                         case GdaValueType.Timestamp : return GetDateTime (ordinal);
619                         case GdaValueType.Tinyint : return GetByte (ordinal);
620                         }
621
622                         return (object) libgda.gda_value_stringify (value);
623                 }
624
625                 [MonoTODO]
626                 public int GetValues (object[] values)
627                 {
628                         throw new NotImplementedException ();
629                 }
630
631                 [MonoTODO]
632                 IDataReader IDataRecord.GetData (int ordinal)
633                 {
634                         throw new NotImplementedException ();
635                 }
636
637                 IEnumerator IEnumerable.GetEnumerator ()
638                 {
639                         return new DbEnumerator (this);
640                 }
641
642                 public bool IsDBNull (int ordinal)
643                 {
644                         IntPtr value;
645
646                         if (currentResult == -1)
647                                 throw new IndexOutOfRangeException ();
648
649                         value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
650                                                                     ordinal, currentRow);
651                         if (value == IntPtr.Zero)
652                                 throw new IndexOutOfRangeException ();
653
654                         return libgda.gda_value_is_null (value);
655                 }
656
657                 public bool NextResult ()
658                 {
659                         int i = currentResult + 1;
660                         if (i >= 0 && i < gdaResults.Count) {
661                                 currentResult++;
662                                 return true;
663                         }
664
665                         return false;
666                 }
667
668                 public bool Read ()
669                 {
670                         if (currentResult < 0 ||
671                             currentResult >= gdaResults.Count)
672                                 return false;
673
674                         currentRow++;
675                         if (currentRow <
676                             libgda.gda_data_model_get_n_rows ((IntPtr) gdaResults[currentResult]))
677                                 return true;
678
679                         return false;
680                 }
681
682                 #endregion
683
684                 #region Destructors
685
686                 private void Dispose (bool disposing) {
687                         if (!this.disposed) {
688                                 if (disposing) {
689                                         // release any managed resources
690                                         command = null;
691                                 }
692                                 // release any unmanaged resources
693                                 if (gdaResults != null) {
694                                         gdaResults.Clear ();
695                                         gdaResults = null;
696                                 }
697
698                                 // close any handles
699                                 if (open)
700                                         Close ();
701
702                                 this.disposed = true;   
703                         }
704                 }
705
706                 void IDisposable.Dispose() {
707                         Dispose (true);
708                 }
709
710                 ~OleDbDataReader() {
711                         Dispose (false);
712                 }
713
714                 #endregion // Destructors
715
716         }
717 }