2002-08-18 Rodrigo Moya <rodrigo@ximian.com>
[mono.git] / mcs / class / System.Data / System.Data.OleDb / OleDbDataReader.cs
index 3e96f4fe5c64ad7c5dfbd38b1d0dc2f7f07fc2f1..4375949eb9deb5ad8ac89002533beeaedfa4cea4 100644 (file)
@@ -13,6 +13,7 @@ using System.Collections;
 using System.ComponentModel;
 using System.Data;
 using System.Data.Common;
+using System.Runtime.InteropServices;
 
 namespace System.Data.OleDb
 {
@@ -24,6 +25,7 @@ namespace System.Data.OleDb
                private bool open;
                private ArrayList gdaResults;
                private int currentResult;
+               private int currentRow;
 
                #endregion
 
@@ -33,9 +35,12 @@ namespace System.Data.OleDb
                {
                        this.command = command;
                        open = true;
-                       gdaResults = results;
+                       if (results != null)
+                               gdaResults = results;
+                       else
+                               gdaResults = new ArrayList ();
                        currentResult = -1;
-                       command.OpenReader(this);
+                       currentRow = -1;
                }
 
                #endregion
@@ -44,60 +49,119 @@ namespace System.Data.OleDb
 
                public int Depth {
                        [MonoTODO]
-                       get { throw new NotImplementedException (); }
+                       get {
+                               throw new NotImplementedException ();
+                       }
                }
 
                public int FieldCount {
-                       [MonoTODO]
-                       get { throw new NotImplementedException (); }
+                       get {
+                               if (currentResult < 0 ||
+                                   currentResult >= gdaResults.Count)
+                                       return 0;
+
+                               return libgda.gda_data_model_get_n_columns (
+                                       (IntPtr) gdaResults[currentResult]);
+                       }
                }
 
                public bool IsClosed {
-                       [MonoTODO]
-                       get { throw new NotImplementedException (); }
+                       get {
+                               return !open;
+                       }
                }
 
                public object this[string name] {
                        [MonoTODO]
-                       get { throw new NotImplementedException (); }
+                       get {
+                               throw new NotImplementedException ();
+                       }
                }
 
                public object this[int index] {
-                       [MonoTODO]
-                       get { throw new NotImplementedException (); }
+                       get {
+                               return (object) GetValue (index);
+                       }
                }
 
                public int RecordsAffected {
-                       [MonoTODO]
-                       get { throw new NotImplementedException (); }
+                       get {
+                               int total_rows;
+                               
+                               if (currentResult < 0 ||
+                                   currentResult >= gdaResults.Count)
+                                       return 0;
+
+                               total_rows = libgda.gda_data_model_get_n_rows (
+                                       (IntPtr) gdaResults[currentResult]);
+                               if (total_rows > 0) {
+                                       if (FieldCount > 0) {
+                                               // It's a SELECT statement
+                                               return -1;
+                                       }
+                               }
+
+                               return FieldCount > 0 ? -1 : total_rows;
+                       }
                }
 
                #endregion
 
                #region Methods
 
-               [MonoTODO]
                public void Close ()
                {
-                       throw new NotImplementedException ();
+                       for (int i = 0; i < gdaResults.Count; i++) {
+                               IntPtr obj = (IntPtr) gdaResults[i];
+                               libgda.FreeObject (obj);
+                               gdaResults = null;
+                       }
+
+                       gdaResults.Clear ();
+                       
+                       open = false;
+                       currentResult = -1;
+                       currentRow = -1;
                }
 
-               [MonoTODO]
                ~OleDbDataReader ()
                {
-                       throw new NotImplementedException ();
+                       if (open)
+                               Close ();
                }
 
-               [MonoTODO]
                public bool GetBoolean (int ordinal)
                {
-                       throw new NotImplementedException ();
+                       IntPtr value;
+
+                       if (currentResult == -1)
+                               throw new InvalidCastException ();
+
+                       value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
+                                                                   ordinal, currentRow);
+                       if (value == IntPtr.Zero)
+                               throw new InvalidCastException ();
+                       
+                       if (libgda.gda_value_get_vtype (value) != GdaValueType.Boolean)
+                               throw new InvalidCastException ();
+                       return libgda.gda_value_get_boolean (value);
                }
 
-               [MonoTODO]
                public byte GetByte (int ordinal)
                {
-                       throw new NotImplementedException ();
+                       IntPtr value;
+
+                       if (currentResult == -1)
+                               throw new InvalidCastException ();
+
+                       value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
+                                                                   ordinal, currentRow);
+                       if (value == IntPtr.Zero)
+                               throw new InvalidCastException ();
+                       
+                       if (libgda.gda_value_get_vtype (value) != GdaValueType.Tinyint)
+                               throw new InvalidCastException ();
+                       return libgda.gda_value_get_tinyint (value);
                }
 
                [MonoTODO]
@@ -105,11 +169,22 @@ namespace System.Data.OleDb
                {
                        throw new NotImplementedException ();
                }
-
-               [MonoTODO]
+               
                public char GetChar (int ordinal)
                {
-                       throw new NotImplementedException ();
+                       IntPtr value;
+
+                       if (currentResult == -1)
+                               throw new InvalidCastException ();
+
+                       value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
+                                                                   ordinal, currentRow);
+                       if (value == IntPtr.Zero)
+                               throw new InvalidCastException ();
+                       
+                       if (libgda.gda_value_get_vtype (value) != GdaValueType.Tinyint)
+                               throw new InvalidCastException ();
+                       return (char) libgda.gda_value_get_tinyint (value);
                }
 
                [MonoTODO]
@@ -124,16 +199,63 @@ namespace System.Data.OleDb
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
                public string GetDataTypeName (int index)
                {
-                       throw new NotImplementedException ();
+                       IntPtr attrs;
+                       GdaValueType type;
+
+                       if (currentResult == -1)
+                               return "unknown";
+
+                       
+                       attrs = libgda.gda_data_model_describe_column ((IntPtr) gdaResults[currentResult],
+                                                                      index);
+                       if (attrs == IntPtr.Zero)
+                               return "unknown";
+
+                       type = libgda.gda_field_attributes_get_gdatype (attrs);
+                       libgda.gda_field_attributes_free (attrs);
+                       
+                       return libgda.gda_type_to_string (type);
                }
 
-               [MonoTODO]
                public DateTime GetDateTime (int ordinal)
                {
-                       throw new NotImplementedException ();
+                       IntPtr value;
+                       DateTime dt;
+
+                       if (currentResult == -1)
+                               throw new InvalidCastException ();
+
+                       value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
+                                                                   ordinal, currentRow);
+                       if (value == IntPtr.Zero)
+                               throw new InvalidCastException ();
+                       
+                       if (libgda.gda_value_get_vtype (value) == GdaValueType.Date) {
+                               GdaDate gdt;
+
+                               gdt = (GdaDate) Marshal.PtrToStructure (libgda.gda_value_get_date (value),
+                                                                       typeof (GdaDate));
+                               return new DateTime ((int) gdt.year, (int) gdt.month, (int) gdt.day);
+                       } else if (libgda.gda_value_get_vtype (value) == GdaValueType.Time) {
+                               GdaTime gdt;
+
+                               gdt = (GdaTime) Marshal.PtrToStructure (libgda.gda_value_get_time (value),
+                                                                       typeof (GdaTime));
+                               return new DateTime (0, 0, 0, (int) gdt.hour, (int) gdt.minute, (int) gdt.second, 0);
+                       } else if (libgda.gda_value_get_vtype (value) == GdaValueType.Timestamp) {
+                               GdaTimestamp gdt;
+                               
+                               gdt = (GdaTimestamp) Marshal.PtrToStructure (libgda.gda_value_get_timestamp (value),
+                                                                            typeof (GdaTimestamp));
+
+                               return new DateTime ((int) gdt.year, (int) gdt.month, (int) gdt.day,
+                                                    (int) gdt.hour, (int) gdt.minute, (int) gdt.second,
+                                                    (int) gdt.fraction);
+                       }
+
+                       throw new InvalidCastException ();
                }
 
                [MonoTODO]
@@ -142,10 +264,21 @@ namespace System.Data.OleDb
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
                public double GetDouble (int ordinal)
                {
-                       throw new NotImplementedException ();
+                       IntPtr value;
+
+                       if (currentResult == -1)
+                               throw new InvalidCastException ();
+
+                       value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
+                                                                   ordinal, currentRow);
+                       if (value == IntPtr.Zero)
+                               throw new InvalidCastException ();
+                       
+                       if (libgda.gda_value_get_vtype (value) != GdaValueType.Double)
+                               throw new InvalidCastException ();
+                       return libgda.gda_value_get_double (value);
                }
 
                [MonoTODO]
@@ -154,10 +287,21 @@ namespace System.Data.OleDb
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
                public float GetFloat (int ordinal)
                {
-                       throw new NotImplementedException ();
+                       IntPtr value;
+
+                       if (currentResult == -1)
+                               throw new InvalidCastException ();
+
+                       value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
+                                                                   ordinal, currentRow);
+                       if (value == IntPtr.Zero)
+                               throw new InvalidCastException ();
+                       
+                       if (libgda.gda_value_get_vtype (value) != GdaValueType.Single)
+                               throw new InvalidCastException ();
+                       return libgda.gda_value_get_single (value);
                }
 
                [MonoTODO]
@@ -166,34 +310,77 @@ namespace System.Data.OleDb
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
                public short GetInt16 (int ordinal)
                {
-                       throw new NotImplementedException ();
+                       IntPtr value;
+
+                       if (currentResult == -1)
+                               throw new InvalidCastException ();
+
+                       value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
+                                                                   ordinal, currentRow);
+                       if (value == IntPtr.Zero)
+                               throw new InvalidCastException ();
+                       
+                       if (libgda.gda_value_get_vtype (value) != GdaValueType.Smallint)
+                               throw new InvalidCastException ();
+                       return (short) libgda.gda_value_get_smallint (value);
                }
 
-               [MonoTODO]
                public int GetInt32 (int ordinal)
                {
-                       throw new NotImplementedException ();
+                       IntPtr value;
+
+                       if (currentResult == -1)
+                               throw new InvalidCastException ();
+
+                       value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
+                                                                   ordinal, currentRow);
+                       if (value == IntPtr.Zero)
+                               throw new InvalidCastException ();
+                       
+                       if (libgda.gda_value_get_vtype (value) != GdaValueType.Integer)
+                               throw new InvalidCastException ();
+                       return libgda.gda_value_get_integer (value);
                }
 
-               [MonoTODO]
                public long GetInt64 (int ordinal)
                {
-                       throw new NotImplementedException ();
+                       IntPtr value;
+
+                       if (currentResult == -1)
+                               throw new InvalidCastException ();
+
+                       value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
+                                                                   ordinal, currentRow);
+                       if (value == IntPtr.Zero)
+                               throw new InvalidCastException ();
+                       
+                       if (libgda.gda_value_get_vtype (value) != GdaValueType.Bigint)
+                               throw new InvalidCastException ();
+                       return libgda.gda_value_get_bigint (value);
                }
 
-               [MonoTODO]
                public string GetName (int index)
                {
-                       throw new NotImplementedException ();
+                       if (currentResult == -1)
+                               return null;
+
+                       return libgda.gda_data_model_get_column_title (
+                               (IntPtr) gdaResults[currentResult], index);
                }
 
-               [MonoTODO]
                public int GetOrdinal (string name)
                {
-                       throw new NotImplementedException ();
+                       if (currentResult == -1)
+                               throw new IndexOutOfRangeException ();
+
+                       for (int i = 0; i < FieldCount; i++) {
+                               if (GetName (i) == name)
+                                       return i;
+                       }
+
+                       throw new IndexOutOfRangeException ();
                }
 
                [MonoTODO]
@@ -202,10 +389,21 @@ namespace System.Data.OleDb
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
                public string GetString (int ordinal)
                {
-                       throw new NotImplementedException ();
+                       IntPtr value;
+
+                       if (currentResult == -1)
+                               throw new InvalidCastException ();
+
+                       value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
+                                                                   ordinal, currentRow);
+                       if (value == IntPtr.Zero)
+                               throw new InvalidCastException ();
+                       
+                       if (libgda.gda_value_get_vtype (value) != GdaValueType.String)
+                               throw new InvalidCastException ();
+                       return libgda.gda_value_get_string (value);
                }
 
                [MonoTODO]
@@ -214,10 +412,35 @@ namespace System.Data.OleDb
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
                public object GetValue (int ordinal)
                {
-                       throw new NotImplementedException ();
+                       IntPtr value;
+                       GdaValueType type;
+
+                       if (currentResult == -1)
+                               throw new IndexOutOfRangeException ();
+
+                       value = libgda.gda_data_model_get_value_at ((IntPtr) gdaResults[currentResult],
+                                                                   ordinal, currentRow);
+                       if (value == IntPtr.Zero)
+                               throw new IndexOutOfRangeException ();
+
+                       type = libgda.gda_value_get_vtype (value);
+                       switch (type) {
+                       case GdaValueType.Bigint : return GetInt64 (ordinal);
+                       case GdaValueType.Boolean : return GetBoolean (ordinal);
+                       case GdaValueType.Date : return GetDateTime (ordinal);
+                       case GdaValueType.Double : return GetDouble (ordinal);
+                       case GdaValueType.Integer : return GetInt32 (ordinal);
+                       case GdaValueType.Single : return GetFloat (ordinal);
+                       case GdaValueType.Smallint : return GetByte (ordinal);
+                       case GdaValueType.String : return GetString (ordinal);
+                       case GdaValueType.Time : return GetDateTime (ordinal);
+                       case GdaValueType.Timestamp : return GetDateTime (ordinal);
+                       case GdaValueType.Tinyint : return GetByte (ordinal);
+                       }
+
+                       return (object) libgda.gda_value_stringify (value);
                }
 
                [MonoTODO]
@@ -261,10 +484,18 @@ namespace System.Data.OleDb
                        return false;
                }
 
-               [MonoTODO]
                public bool Read ()
                {
-                       throw new NotImplementedException ();
+                       if (currentResult < 0 ||
+                           currentResult >= gdaResults.Count)
+                               return false;
+
+                       currentRow++;
+                       if (currentRow <
+                           libgda.gda_data_model_get_n_rows ((IntPtr) gdaResults[currentResult]))
+                               return true;
+
+                       return false;
                }
 
                #endregion