2 // System.Data.OleDb.OleDbDataReader
5 // Rodrigo Moya (rodrigo@ximian.com)
6 // Tim Coleman (tim@timcoleman.com)
8 // Copyright (C) Rodrigo Moya, 2002
9 // Copyright (C) Tim Coleman, 2002
12 using System.Collections;
13 using System.ComponentModel;
15 using System.Data.Common;
16 using System.Runtime.InteropServices;
18 namespace System.Data.OleDb
20 public sealed class OleDbDataReader : MarshalByRefObject, IDataReader, IDisposable, IDataRecord, IEnumerable
24 private OleDbCommand command;
26 private ArrayList gdaResults;
27 private int currentResult;
28 private int currentRow;
29 private bool disposed = false;
35 internal OleDbDataReader (OleDbCommand command, ArrayList results)
37 this.command = command;
42 gdaResults = new ArrayList ();
53 return 0; // no nested selects supported
57 public int FieldCount {
59 if (currentResult < 0 ||
60 currentResult >= gdaResults.Count)
63 return libgda.gda_data_model_get_n_columns (
64 (IntPtr) gdaResults[currentResult]);
68 public bool IsClosed {
74 public object this[string name] {
78 if (currentResult == -1)
79 throw new InvalidOperationException ();
81 pos = libgda.gda_data_model_get_column_position (
82 (IntPtr) gdaResults[currentResult],
85 throw new IndexOutOfRangeException ();
91 public object this[int index] {
93 return (object) GetValue (index);
97 public int RecordsAffected {
101 if (currentResult < 0 ||
102 currentResult >= gdaResults.Count)
105 total_rows = libgda.gda_data_model_get_n_rows (
106 (IntPtr) gdaResults[currentResult]);
107 if (total_rows > 0) {
108 if (FieldCount > 0) {
109 // It's a SELECT statement
114 return FieldCount > 0 ? -1 : total_rows;
124 for (int i = 0; i < gdaResults.Count; i++) {
125 IntPtr obj = (IntPtr) gdaResults[i];
126 libgda.FreeObject (obj);
137 public bool GetBoolean (int ordinal)
141 if (currentResult == -1)
142 throw new InvalidCastException ();
144 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
145 ordinal, currentRow);
146 if (value == IntPtr.Zero)
147 throw new InvalidCastException ();
149 if (libgda.gda_value_get_type (value) != GdaValueType.Boolean)
150 throw new InvalidCastException ();
151 return libgda.gda_value_get_boolean (value);
154 public byte GetByte (int ordinal)
158 if (currentResult == -1)
159 throw new InvalidCastException ();
161 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
162 ordinal, currentRow);
163 if (value == IntPtr.Zero)
164 throw new InvalidCastException ();
166 if (libgda.gda_value_get_type (value) != GdaValueType.Tinyint)
167 throw new InvalidCastException ();
168 return libgda.gda_value_get_tinyint (value);
172 public long GetBytes (int ordinal, long dataIndex, byte[] buffer, int bufferIndex, int length)
174 throw new NotImplementedException ();
177 public char GetChar (int ordinal)
181 if (currentResult == -1)
182 throw new InvalidCastException ();
184 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
185 ordinal, currentRow);
186 if (value == IntPtr.Zero)
187 throw new InvalidCastException ();
189 if (libgda.gda_value_get_type (value) != GdaValueType.Tinyint)
190 throw new InvalidCastException ();
191 return (char) libgda.gda_value_get_tinyint (value);
195 public long GetChars (int ordinal, long dataIndex, char[] buffer, int bufferIndex, int length)
197 throw new NotImplementedException ();
201 public OleDbDataReader GetData (int ordinal)
203 throw new NotImplementedException ();
206 public string GetDataTypeName (int index)
211 if (currentResult == -1)
215 attrs = libgda.gda_data_model_describe_column ((IntPtr) gdaResults[currentResult],
217 if (attrs == IntPtr.Zero)
220 type = libgda.gda_field_attributes_get_gdatype (attrs);
221 libgda.gda_field_attributes_free (attrs);
223 return libgda.gda_type_to_string (type);
226 public DateTime GetDateTime (int ordinal)
231 if (currentResult == -1)
232 throw new InvalidCastException ();
234 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
235 ordinal, currentRow);
236 if (value == IntPtr.Zero)
237 throw new InvalidCastException ();
239 if (libgda.gda_value_get_type (value) == GdaValueType.Date) {
242 gdt = (GdaDate) Marshal.PtrToStructure (libgda.gda_value_get_date (value),
244 return new DateTime ((int) gdt.year, (int) gdt.month, (int) gdt.day);
245 } else if (libgda.gda_value_get_type (value) == GdaValueType.Time) {
248 gdt = (GdaTime) Marshal.PtrToStructure (libgda.gda_value_get_time (value),
250 return new DateTime (0, 0, 0, (int) gdt.hour, (int) gdt.minute, (int) gdt.second, 0);
251 } else if (libgda.gda_value_get_type (value) == GdaValueType.Timestamp) {
254 gdt = (GdaTimestamp) Marshal.PtrToStructure (libgda.gda_value_get_timestamp (value),
255 typeof (GdaTimestamp));
257 return new DateTime ((int) gdt.year, (int) gdt.month, (int) gdt.day,
258 (int) gdt.hour, (int) gdt.minute, (int) gdt.second,
262 throw new InvalidCastException ();
266 public decimal GetDecimal (int ordinal)
268 throw new NotImplementedException ();
271 public double GetDouble (int ordinal)
275 if (currentResult == -1)
276 throw new InvalidCastException ();
278 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
279 ordinal, currentRow);
280 if (value == IntPtr.Zero)
281 throw new InvalidCastException ();
283 if (libgda.gda_value_get_type (value) != GdaValueType.Double)
284 throw new InvalidCastException ();
285 return libgda.gda_value_get_double (value);
289 public Type GetFieldType (int index)
294 if (currentResult == -1)
295 throw new IndexOutOfRangeException ();
297 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
299 if (value == IntPtr.Zero)
300 throw new IndexOutOfRangeException ();
302 type = libgda.gda_value_get_type (value);
304 case GdaValueType.Bigint : return typeof (long);
305 case GdaValueType.Boolean : return typeof (bool);
306 case GdaValueType.Date : return typeof (DateTime);
307 case GdaValueType.Double : return typeof (double);
308 case GdaValueType.Integer : return typeof (int);
309 case GdaValueType.Single : return typeof (float);
310 case GdaValueType.Smallint : return typeof (byte);
311 case GdaValueType.String : return typeof (string);
312 case GdaValueType.Time : return typeof (DateTime);
313 case GdaValueType.Timestamp : return typeof (DateTime);
314 case GdaValueType.Tinyint : return typeof (byte);
317 return typeof(string); // default
320 public float GetFloat (int ordinal)
324 if (currentResult == -1)
325 throw new InvalidCastException ();
327 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
328 ordinal, currentRow);
329 if (value == IntPtr.Zero)
330 throw new InvalidCastException ();
332 if (libgda.gda_value_get_type (value) != GdaValueType.Single)
333 throw new InvalidCastException ();
334 return libgda.gda_value_get_single (value);
338 public Guid GetGuid (int ordinal)
340 throw new NotImplementedException ();
343 public short GetInt16 (int ordinal)
347 if (currentResult == -1)
348 throw new InvalidCastException ();
350 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
351 ordinal, currentRow);
352 if (value == IntPtr.Zero)
353 throw new InvalidCastException ();
355 if (libgda.gda_value_get_type (value) != GdaValueType.Smallint)
356 throw new InvalidCastException ();
357 return (short) libgda.gda_value_get_smallint (value);
360 public int GetInt32 (int ordinal)
364 if (currentResult == -1)
365 throw new InvalidCastException ();
367 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
368 ordinal, currentRow);
369 if (value == IntPtr.Zero)
370 throw new InvalidCastException ();
372 if (libgda.gda_value_get_type (value) != GdaValueType.Integer)
373 throw new InvalidCastException ();
374 return libgda.gda_value_get_integer (value);
377 public long GetInt64 (int ordinal)
381 if (currentResult == -1)
382 throw new InvalidCastException ();
384 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
385 ordinal, currentRow);
386 if (value == IntPtr.Zero)
387 throw new InvalidCastException ();
389 if (libgda.gda_value_get_type (value) != GdaValueType.Bigint)
390 throw new InvalidCastException ();
391 return libgda.gda_value_get_bigint (value);
394 public string GetName (int index)
396 if (currentResult == -1)
399 return libgda.gda_data_model_get_column_title (
400 (IntPtr) gdaResults[currentResult], index);
403 public int GetOrdinal (string name)
405 if (currentResult == -1)
406 throw new IndexOutOfRangeException ();
408 for (int i = 0; i < FieldCount; i++) {
409 if (GetName (i) == name)
413 throw new IndexOutOfRangeException ();
416 public DataTable GetSchemaTable ()
418 DataTable dataTableSchema = null;
419 // Only Results from SQL SELECT Queries
420 // get a DataTable for schema of the result
421 // otherwise, DataTable is null reference
422 if(this.FieldCount > 0) {
425 GdaValueType gdaType;
428 if (currentResult == -1) {
429 // FIXME: throw an exception?
430 Console.WriteLine("Error: current result -1");
434 dataTableSchema = new DataTable ();
436 dataTableSchema.Columns.Add ("ColumnName", typeof (string));
437 dataTableSchema.Columns.Add ("ColumnOrdinal", typeof (int));
438 dataTableSchema.Columns.Add ("ColumnSize", typeof (int));
439 dataTableSchema.Columns.Add ("NumericPrecision", typeof (int));
440 dataTableSchema.Columns.Add ("NumericScale", typeof (int));
441 dataTableSchema.Columns.Add ("IsUnique", typeof (bool));
442 dataTableSchema.Columns.Add ("IsKey", typeof (bool));
443 DataColumn dc = dataTableSchema.Columns["IsKey"];
444 dc.AllowDBNull = true; // IsKey can have a DBNull
445 dataTableSchema.Columns.Add ("BaseCatalogName", typeof (string));
446 dataTableSchema.Columns.Add ("BaseColumnName", typeof (string));
447 dataTableSchema.Columns.Add ("BaseSchemaName", typeof (string));
448 dataTableSchema.Columns.Add ("BaseTableName", typeof (string));
449 dataTableSchema.Columns.Add ("DataType", typeof(Type));
450 dataTableSchema.Columns.Add ("AllowDBNull", typeof (bool));
451 dataTableSchema.Columns.Add ("ProviderType", typeof (int));
452 dataTableSchema.Columns.Add ("IsAliased", typeof (bool));
453 dataTableSchema.Columns.Add ("IsExpression", typeof (bool));
454 dataTableSchema.Columns.Add ("IsIdentity", typeof (bool));
455 dataTableSchema.Columns.Add ("IsAutoIncrement", typeof (bool));
456 dataTableSchema.Columns.Add ("IsRowVersion", typeof (bool));
457 dataTableSchema.Columns.Add ("IsHidden", typeof (bool));
458 dataTableSchema.Columns.Add ("IsLong", typeof (bool));
459 dataTableSchema.Columns.Add ("IsReadOnly", typeof (bool));
465 for (int i = 0; i < this.FieldCount; i += 1 ) {
467 schemaRow = dataTableSchema.NewRow ();
469 attrs = libgda.gda_data_model_describe_column ((IntPtr) gdaResults[currentResult],
471 if (attrs == IntPtr.Zero){
472 // FIXME: throw exception
473 Console.WriteLine("Error: attrs null");
477 gdaType = libgda.gda_field_attributes_get_gdatype (attrs);
478 columnSize = libgda.gda_field_attributes_get_defined_size (attrs);
479 libgda.gda_field_attributes_free (attrs);
481 schemaRow["ColumnName"] = this.GetName(i);
482 schemaRow["ColumnOrdinal"] = i + 1;
484 schemaRow["ColumnSize"] = (int) columnSize;
485 schemaRow["NumericPrecision"] = 0;
486 schemaRow["NumericScale"] = 0;
487 // TODO: need to get KeyInfo
488 //if((cmdBehavior & CommandBehavior.KeyInfo) == CommandBehavior.KeyInfo) {
489 // bool IsUnique, IsKey;
490 // GetKeyInfo(field[i].Name, out IsUnique, out IsKey);
493 schemaRow["IsUnique"] = false;
494 schemaRow["IsKey"] = DBNull.Value;
496 schemaRow["BaseCatalogName"] = "";
498 schemaRow["BaseColumnName"] = this.GetName(i);
499 schemaRow["BaseSchemaName"] = "";
500 schemaRow["BaseTableName"] = "";
502 schemaRow["DataType"] = this.GetFieldType(i);
\r
504 schemaRow["AllowDBNull"] = false;
506 schemaRow["ProviderType"] = (int) gdaType;
507 schemaRow["IsAliased"] = false;
508 schemaRow["IsExpression"] = false;
509 schemaRow["IsIdentity"] = false;
510 schemaRow["IsAutoIncrement"] = false;
511 schemaRow["IsRowVersion"] = false;
512 schemaRow["IsHidden"] = false;
513 schemaRow["IsLong"] = false;
514 schemaRow["IsReadOnly"] = false;
516 schemaRow.AcceptChanges();
518 dataTableSchema.Rows.Add (schemaRow);
521 #if DEBUG_OleDbDataReader
522 Console.WriteLine("********** DEBUG Table Schema BEGIN ************");
523 foreach (DataRow myRow in dataTableSchema.Rows) {
\r
524 foreach (DataColumn myCol in dataTableSchema.Columns)
\r
525 Console.WriteLine(myCol.ColumnName + " = " + myRow[myCol]);
\r
526 Console.WriteLine();
\r
528 Console.WriteLine("********** DEBUG Table Schema END ************");
529 #endif // DEBUG_OleDbDataReader
533 return dataTableSchema;
536 public string GetString (int ordinal)
540 if (currentResult == -1)
541 throw new InvalidCastException ();
543 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
544 ordinal, currentRow);
545 if (value == IntPtr.Zero)
546 throw new InvalidCastException ();
548 if (libgda.gda_value_get_type (value) != GdaValueType.String)
549 throw new InvalidCastException ();
550 return libgda.gda_value_get_string (value);
554 public TimeSpan GetTimeSpan (int ordinal)
556 throw new NotImplementedException ();
559 public object GetValue (int ordinal)
564 if (currentResult == -1)
565 throw new IndexOutOfRangeException ();
567 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
568 ordinal, currentRow);
569 if (value == IntPtr.Zero)
570 throw new IndexOutOfRangeException ();
572 type = libgda.gda_value_get_type (value);
574 case GdaValueType.Bigint : return GetInt64 (ordinal);
575 case GdaValueType.Boolean : return GetBoolean (ordinal);
576 case GdaValueType.Date : return GetDateTime (ordinal);
577 case GdaValueType.Double : return GetDouble (ordinal);
578 case GdaValueType.Integer : return GetInt32 (ordinal);
579 case GdaValueType.Single : return GetFloat (ordinal);
580 case GdaValueType.Smallint : return GetByte (ordinal);
581 case GdaValueType.String : return GetString (ordinal);
582 case GdaValueType.Time : return GetDateTime (ordinal);
583 case GdaValueType.Timestamp : return GetDateTime (ordinal);
584 case GdaValueType.Tinyint : return GetByte (ordinal);
587 return (object) libgda.gda_value_stringify (value);
591 public int GetValues (object[] values)
593 throw new NotImplementedException ();
597 IDataReader IDataRecord.GetData (int ordinal)
599 throw new NotImplementedException ();
602 IEnumerator IEnumerable.GetEnumerator ()
604 return new DbEnumerator (this);
607 public bool IsDBNull (int ordinal)
611 if (currentResult == -1)
612 throw new IndexOutOfRangeException ();
614 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
615 ordinal, currentRow);
616 if (value == IntPtr.Zero)
617 throw new IndexOutOfRangeException ();
619 return libgda.gda_value_is_null (value);
622 public bool NextResult ()
624 int i = currentResult + 1;
625 if (i >= 0 && i < gdaResults.Count) {
635 if (currentResult < 0 ||
636 currentResult >= gdaResults.Count)
641 libgda.gda_data_model_get_n_rows ((IntPtr) gdaResults[currentResult]))
651 private void Dispose (bool disposing) {
652 if (!this.disposed) {
654 // release any managed resources
657 // release any unmanaged resources
658 if (gdaResults != null) {
667 this.disposed = true;
671 void IDisposable.Dispose() {
679 #endregion // Destructors