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;
119 public bool HasRows {
121 throw new NotImplementedException ();
131 for (int i = 0; i < gdaResults.Count; i++) {
132 IntPtr obj = (IntPtr) gdaResults[i];
133 libgda.FreeObject (obj);
144 public bool GetBoolean (int ordinal)
148 if (currentResult == -1)
149 throw new InvalidCastException ();
151 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
152 ordinal, currentRow);
153 if (value == IntPtr.Zero)
154 throw new InvalidCastException ();
156 if (libgda.gda_value_get_type (value) != GdaValueType.Boolean)
157 throw new InvalidCastException ();
158 return libgda.gda_value_get_boolean (value);
161 public byte GetByte (int ordinal)
165 if (currentResult == -1)
166 throw new InvalidCastException ();
168 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
169 ordinal, currentRow);
170 if (value == IntPtr.Zero)
171 throw new InvalidCastException ();
173 if (libgda.gda_value_get_type (value) != GdaValueType.Tinyint)
174 throw new InvalidCastException ();
175 return libgda.gda_value_get_tinyint (value);
179 public long GetBytes (int ordinal, long dataIndex, byte[] buffer, int bufferIndex, int length)
181 throw new NotImplementedException ();
184 [EditorBrowsableAttribute (EditorBrowsableState.Never)]
185 public char GetChar (int ordinal)
189 if (currentResult == -1)
190 throw new InvalidCastException ();
192 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
193 ordinal, currentRow);
194 if (value == IntPtr.Zero)
195 throw new InvalidCastException ();
197 if (libgda.gda_value_get_type (value) != GdaValueType.Tinyint)
198 throw new InvalidCastException ();
199 return (char) libgda.gda_value_get_tinyint (value);
203 public long GetChars (int ordinal, long dataIndex, char[] buffer, int bufferIndex, int length)
205 throw new NotImplementedException ();
209 public OleDbDataReader GetData (int ordinal)
211 throw new NotImplementedException ();
214 public string GetDataTypeName (int index)
219 if (currentResult == -1)
223 attrs = libgda.gda_data_model_describe_column ((IntPtr) gdaResults[currentResult],
225 if (attrs == IntPtr.Zero)
228 type = libgda.gda_field_attributes_get_gdatype (attrs);
229 libgda.gda_field_attributes_free (attrs);
231 return libgda.gda_type_to_string (type);
234 public DateTime GetDateTime (int ordinal)
239 if (currentResult == -1)
240 throw new InvalidCastException ();
242 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
243 ordinal, currentRow);
244 if (value == IntPtr.Zero)
245 throw new InvalidCastException ();
247 if (libgda.gda_value_get_type (value) == GdaValueType.Date) {
250 gdt = (GdaDate) Marshal.PtrToStructure (libgda.gda_value_get_date (value),
252 return new DateTime ((int) gdt.year, (int) gdt.month, (int) gdt.day);
253 } else if (libgda.gda_value_get_type (value) == GdaValueType.Time) {
256 gdt = (GdaTime) Marshal.PtrToStructure (libgda.gda_value_get_time (value),
258 return new DateTime (0, 0, 0, (int) gdt.hour, (int) gdt.minute, (int) gdt.second, 0);
259 } else if (libgda.gda_value_get_type (value) == GdaValueType.Timestamp) {
262 gdt = (GdaTimestamp) Marshal.PtrToStructure (libgda.gda_value_get_timestamp (value),
263 typeof (GdaTimestamp));
265 return new DateTime ((int) gdt.year, (int) gdt.month, (int) gdt.day,
266 (int) gdt.hour, (int) gdt.minute, (int) gdt.second,
270 throw new InvalidCastException ();
274 public decimal GetDecimal (int ordinal)
276 throw new NotImplementedException ();
279 public double GetDouble (int ordinal)
283 if (currentResult == -1)
284 throw new InvalidCastException ();
286 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
287 ordinal, currentRow);
288 if (value == IntPtr.Zero)
289 throw new InvalidCastException ();
291 if (libgda.gda_value_get_type (value) != GdaValueType.Double)
292 throw new InvalidCastException ();
293 return libgda.gda_value_get_double (value);
297 public Type GetFieldType (int index)
302 if (currentResult == -1)
303 throw new IndexOutOfRangeException ();
305 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
307 if (value == IntPtr.Zero)
308 throw new IndexOutOfRangeException ();
310 type = libgda.gda_value_get_type (value);
312 case GdaValueType.Bigint : return typeof (long);
313 case GdaValueType.Boolean : return typeof (bool);
314 case GdaValueType.Date : return typeof (DateTime);
315 case GdaValueType.Double : return typeof (double);
316 case GdaValueType.Integer : return typeof (int);
317 case GdaValueType.Single : return typeof (float);
318 case GdaValueType.Smallint : return typeof (byte);
319 case GdaValueType.String : return typeof (string);
320 case GdaValueType.Time : return typeof (DateTime);
321 case GdaValueType.Timestamp : return typeof (DateTime);
322 case GdaValueType.Tinyint : return typeof (byte);
325 return typeof(string); // default
328 public float GetFloat (int ordinal)
332 if (currentResult == -1)
333 throw new InvalidCastException ();
335 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
336 ordinal, currentRow);
337 if (value == IntPtr.Zero)
338 throw new InvalidCastException ();
340 if (libgda.gda_value_get_type (value) != GdaValueType.Single)
341 throw new InvalidCastException ();
342 return libgda.gda_value_get_single (value);
346 public Guid GetGuid (int ordinal)
348 throw new NotImplementedException ();
351 public short GetInt16 (int ordinal)
355 if (currentResult == -1)
356 throw new InvalidCastException ();
358 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
359 ordinal, currentRow);
360 if (value == IntPtr.Zero)
361 throw new InvalidCastException ();
363 if (libgda.gda_value_get_type (value) != GdaValueType.Smallint)
364 throw new InvalidCastException ();
365 return (short) libgda.gda_value_get_smallint (value);
368 public int GetInt32 (int ordinal)
372 if (currentResult == -1)
373 throw new InvalidCastException ();
375 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
376 ordinal, currentRow);
377 if (value == IntPtr.Zero)
378 throw new InvalidCastException ();
380 if (libgda.gda_value_get_type (value) != GdaValueType.Integer)
381 throw new InvalidCastException ();
382 return libgda.gda_value_get_integer (value);
385 public long GetInt64 (int ordinal)
389 if (currentResult == -1)
390 throw new InvalidCastException ();
392 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
393 ordinal, currentRow);
394 if (value == IntPtr.Zero)
395 throw new InvalidCastException ();
397 if (libgda.gda_value_get_type (value) != GdaValueType.Bigint)
398 throw new InvalidCastException ();
399 return libgda.gda_value_get_bigint (value);
402 public string GetName (int index)
404 if (currentResult == -1)
407 return libgda.gda_data_model_get_column_title (
408 (IntPtr) gdaResults[currentResult], index);
411 public int GetOrdinal (string name)
413 if (currentResult == -1)
414 throw new IndexOutOfRangeException ();
416 for (int i = 0; i < FieldCount; i++) {
417 if (GetName (i) == name)
421 throw new IndexOutOfRangeException ();
424 public DataTable GetSchemaTable ()
426 DataTable dataTableSchema = null;
427 // Only Results from SQL SELECT Queries
428 // get a DataTable for schema of the result
429 // otherwise, DataTable is null reference
430 if(this.FieldCount > 0) {
433 GdaValueType gdaType;
436 if (currentResult == -1) {
437 // FIXME: throw an exception?
438 Console.WriteLine("Error: current result -1");
442 dataTableSchema = new DataTable ();
444 dataTableSchema.Columns.Add ("ColumnName", typeof (string));
445 dataTableSchema.Columns.Add ("ColumnOrdinal", typeof (int));
446 dataTableSchema.Columns.Add ("ColumnSize", typeof (int));
447 dataTableSchema.Columns.Add ("NumericPrecision", typeof (int));
448 dataTableSchema.Columns.Add ("NumericScale", typeof (int));
449 dataTableSchema.Columns.Add ("IsUnique", typeof (bool));
450 dataTableSchema.Columns.Add ("IsKey", typeof (bool));
451 DataColumn dc = dataTableSchema.Columns["IsKey"];
452 dc.AllowDBNull = true; // IsKey can have a DBNull
453 dataTableSchema.Columns.Add ("BaseCatalogName", typeof (string));
454 dataTableSchema.Columns.Add ("BaseColumnName", typeof (string));
455 dataTableSchema.Columns.Add ("BaseSchemaName", typeof (string));
456 dataTableSchema.Columns.Add ("BaseTableName", typeof (string));
457 dataTableSchema.Columns.Add ("DataType", typeof(Type));
458 dataTableSchema.Columns.Add ("AllowDBNull", typeof (bool));
459 dataTableSchema.Columns.Add ("ProviderType", typeof (int));
460 dataTableSchema.Columns.Add ("IsAliased", typeof (bool));
461 dataTableSchema.Columns.Add ("IsExpression", typeof (bool));
462 dataTableSchema.Columns.Add ("IsIdentity", typeof (bool));
463 dataTableSchema.Columns.Add ("IsAutoIncrement", typeof (bool));
464 dataTableSchema.Columns.Add ("IsRowVersion", typeof (bool));
465 dataTableSchema.Columns.Add ("IsHidden", typeof (bool));
466 dataTableSchema.Columns.Add ("IsLong", typeof (bool));
467 dataTableSchema.Columns.Add ("IsReadOnly", typeof (bool));
473 for (int i = 0; i < this.FieldCount; i += 1 ) {
475 schemaRow = dataTableSchema.NewRow ();
477 attrs = libgda.gda_data_model_describe_column ((IntPtr) gdaResults[currentResult],
479 if (attrs == IntPtr.Zero){
480 // FIXME: throw exception
481 Console.WriteLine("Error: attrs null");
485 gdaType = libgda.gda_field_attributes_get_gdatype (attrs);
486 columnSize = libgda.gda_field_attributes_get_defined_size (attrs);
487 libgda.gda_field_attributes_free (attrs);
489 schemaRow["ColumnName"] = this.GetName(i);
490 schemaRow["ColumnOrdinal"] = i + 1;
492 schemaRow["ColumnSize"] = (int) columnSize;
493 schemaRow["NumericPrecision"] = 0;
494 schemaRow["NumericScale"] = 0;
495 // TODO: need to get KeyInfo
496 //if((cmdBehavior & CommandBehavior.KeyInfo) == CommandBehavior.KeyInfo) {
497 // bool IsUnique, IsKey;
498 // GetKeyInfo(field[i].Name, out IsUnique, out IsKey);
501 schemaRow["IsUnique"] = false;
502 schemaRow["IsKey"] = DBNull.Value;
504 schemaRow["BaseCatalogName"] = "";
506 schemaRow["BaseColumnName"] = this.GetName(i);
507 schemaRow["BaseSchemaName"] = "";
508 schemaRow["BaseTableName"] = "";
510 schemaRow["DataType"] = this.GetFieldType(i);
\r
512 schemaRow["AllowDBNull"] = false;
514 schemaRow["ProviderType"] = (int) gdaType;
515 schemaRow["IsAliased"] = false;
516 schemaRow["IsExpression"] = false;
517 schemaRow["IsIdentity"] = false;
518 schemaRow["IsAutoIncrement"] = false;
519 schemaRow["IsRowVersion"] = false;
520 schemaRow["IsHidden"] = false;
521 schemaRow["IsLong"] = false;
522 schemaRow["IsReadOnly"] = false;
524 schemaRow.AcceptChanges();
526 dataTableSchema.Rows.Add (schemaRow);
529 #if DEBUG_OleDbDataReader
530 Console.WriteLine("********** DEBUG Table Schema BEGIN ************");
531 foreach (DataRow myRow in dataTableSchema.Rows) {
\r
532 foreach (DataColumn myCol in dataTableSchema.Columns)
\r
533 Console.WriteLine(myCol.ColumnName + " = " + myRow[myCol]);
\r
534 Console.WriteLine();
\r
536 Console.WriteLine("********** DEBUG Table Schema END ************");
537 #endif // DEBUG_OleDbDataReader
541 return dataTableSchema;
544 public string GetString (int ordinal)
548 if (currentResult == -1)
549 throw new InvalidCastException ();
551 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
552 ordinal, currentRow);
553 if (value == IntPtr.Zero)
554 throw new InvalidCastException ();
556 if (libgda.gda_value_get_type (value) != GdaValueType.String)
557 throw new InvalidCastException ();
558 return libgda.gda_value_get_string (value);
562 public TimeSpan GetTimeSpan (int ordinal)
564 throw new NotImplementedException ();
567 public object GetValue (int ordinal)
572 if (currentResult == -1)
573 throw new IndexOutOfRangeException ();
575 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
576 ordinal, currentRow);
577 if (value == IntPtr.Zero)
578 throw new IndexOutOfRangeException ();
580 type = libgda.gda_value_get_type (value);
582 case GdaValueType.Bigint : return GetInt64 (ordinal);
583 case GdaValueType.Boolean : return GetBoolean (ordinal);
584 case GdaValueType.Date : return GetDateTime (ordinal);
585 case GdaValueType.Double : return GetDouble (ordinal);
586 case GdaValueType.Integer : return GetInt32 (ordinal);
587 case GdaValueType.Single : return GetFloat (ordinal);
588 case GdaValueType.Smallint : return GetByte (ordinal);
589 case GdaValueType.String : return GetString (ordinal);
590 case GdaValueType.Time : return GetDateTime (ordinal);
591 case GdaValueType.Timestamp : return GetDateTime (ordinal);
592 case GdaValueType.Tinyint : return GetByte (ordinal);
595 return (object) libgda.gda_value_stringify (value);
599 public int GetValues (object[] values)
601 throw new NotImplementedException ();
605 IDataReader IDataRecord.GetData (int ordinal)
607 throw new NotImplementedException ();
610 IEnumerator IEnumerable.GetEnumerator ()
612 return new DbEnumerator (this);
615 public bool IsDBNull (int ordinal)
619 if (currentResult == -1)
620 throw new IndexOutOfRangeException ();
622 value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
623 ordinal, currentRow);
624 if (value == IntPtr.Zero)
625 throw new IndexOutOfRangeException ();
627 return libgda.gda_value_is_null (value);
630 public bool NextResult ()
632 int i = currentResult + 1;
633 if (i >= 0 && i < gdaResults.Count) {
643 if (currentResult < 0 ||
644 currentResult >= gdaResults.Count)
649 libgda.gda_data_model_get_n_rows ((IntPtr) gdaResults[currentResult]))
659 private void Dispose (bool disposing) {
660 if (!this.disposed) {
662 // release any managed resources
665 // release any unmanaged resources
666 if (gdaResults != null) {
675 this.disposed = true;
679 void IDisposable.Dispose() {
687 #endregion // Destructors