2002-05-03 Daniel Morgan <danmorg@sc.rr.com>
authorDaniel Morgan <monodanmorg@yahoo.com>
Fri, 3 May 2002 05:16:20 +0000 (05:16 -0000)
committerDaniel Morgan <monodanmorg@yahoo.com>
Fri, 3 May 2002 05:16:20 +0000 (05:16 -0000)
* Test/TestExecuteScalar.cs: added test for
method ExecuteScalar in class SqlCommand.

* System.Data/DataColumnCollection.cs - it should
inherit properties from base InternalDataCollectionBase
and use them instead of overriding them, such as, List.

* System.Data/DataColumn.cs
* System.Data/DataTable.cs: tweaks to retrieve
meta data from the database

* System.Data.SqlClient/PostgresLibrary.cs -
added method OidToType to convert PostgreSQL oid type
to System.Type.  Renamed method OidTypeToSystem
to ConvertPgTypeToSystem for converting the data value
from a PostgreSQL type to a .NET System type.

* System.Data.SqlClient/SqlCommand.cs: implemented
method ExecuteReader which returns a SqlDataReader
for a light forward only read only result set.
It works on types int4 ==> Int32 and
varchar ==> String.  Other types
will come later.

* System.Data.SqlClient/SqlConnection.cs: added comment

* System.Data.SqlClient/SqlDataReader.cs: implemented
class.  It works, but still lots to do.

* Test/ReadPostgresData.cs: stuff

* Test/TestSqlDataReader.cs: updated test for SqlDataReader
to display meta data and the data

svn path=/trunk/mcs/; revision=4247

19 files changed:
mcs/class/Mono.Data.PostgreSqlClient/Mono.Data.PostgreSqlClient/PgSqlCommand.cs
mcs/class/Mono.Data.PostgreSqlClient/Mono.Data.PostgreSqlClient/PgSqlConnection.cs
mcs/class/Mono.Data.PostgreSqlClient/Mono.Data.PostgreSqlClient/PgSqlDataReader.cs
mcs/class/Mono.Data.PostgreSqlClient/Mono.Data.PostgreSqlClient/PostgresLibrary.cs
mcs/class/Mono.Data.PostgreSqlClient/PgSqlCommand.cs
mcs/class/Mono.Data.PostgreSqlClient/PgSqlConnection.cs
mcs/class/Mono.Data.PostgreSqlClient/PgSqlDataReader.cs
mcs/class/Mono.Data.PostgreSqlClient/PostgresLibrary.cs
mcs/class/System.Data/ChangeLog
mcs/class/System.Data/System.Data.SqlClient/PostgresLibrary.cs
mcs/class/System.Data/System.Data.SqlClient/SqlCommand.cs
mcs/class/System.Data/System.Data.SqlClient/SqlConnection.cs
mcs/class/System.Data/System.Data.SqlClient/SqlDataReader.cs
mcs/class/System.Data/System.Data/DataColumn.cs
mcs/class/System.Data/System.Data/DataColumnCollection.cs
mcs/class/System.Data/System.Data/DataTable.cs
mcs/class/System.Data/Test/ReadPostgresData.cs
mcs/class/System.Data/Test/TestExecuteScalar.cs [new file with mode: 0644]
mcs/class/System.Data/Test/TestSqlDataReader.cs

index 0ae881fcfd1ede19fdbc33fa040e95278ed429de..765684032130d4042163935c8c19ed151e560160 100644 (file)
@@ -158,7 +158,7 @@ namespace System.Data.SqlClient
                [MonoTODO]
                SqlDataReader ExecuteReader ()
                {
-                       throw new NotImplementedException ();   
+                       return ExecuteReader(CommandBehavior.Default);
                }
 
                [MonoTODO]
@@ -171,7 +171,104 @@ namespace System.Data.SqlClient
                [MonoTODO]
                public SqlDataReader ExecuteReader (CommandBehavior behavior)
                {
-                       throw new NotImplementedException ();
+                       // FIXME: currently only works for a 
+                       //        single result set
+                       //        ExecuteReader can be used 
+                       //        for multiple result sets
+                       SqlDataReader dataReader = null;
+                       
+                       IntPtr pgResult; // PGresult
+                       ExecStatusType execStatus;      
+
+                       if(conn.State != ConnectionState.Open)
+                               throw new InvalidOperationException(
+                                       "ConnnectionState is not Open");
+
+                       // FIXME: PQexec blocks 
+                       // while PQsendQuery is non-blocking
+                       // which is better to use?
+                       // int PQsendQuery(PGconn *conn,
+                       //        const char *query);
+
+                       // execute SQL command
+                       // uses internal property to get the PGConn IntPtr
+                       pgResult = PostgresLibrary.
+                               PQexec (conn.PostgresConnection, sql);
+
+                       execStatus = PostgresLibrary.
+                               PQresultStatus (pgResult);
+                       
+                       if(execStatus == ExecStatusType.PGRES_TUPLES_OK) {
+                               DataTable dt = null;
+                               int rows, cols;
+                               int[] oids;
+                               
+                               // FIXME: maybe i should move the
+                               //        BuildTableSchema code
+                               //        to the SqlDataReader?
+                               dt = BuildTableSchema(pgResult, 
+                                       out rows, out cols, out oids);
+                               dataReader = new SqlDataReader(this, dt, pgResult,
+                                       rows, cols, oids);
+                       }
+                       else {
+                               String errorMessage;
+                               
+                               errorMessage = PostgresLibrary.
+                                       PQresStatus(execStatus);
+
+                               errorMessage += " " + PostgresLibrary.\r
+                                       PQresultErrorMessage(pgResult);\r
+                               \r
+                               throw new SqlException(0, 0,
+                                       errorMessage, 0, "",
+                                       conn.DataSource, "SqlCommand", 0);\r
+                       }
+                                       
+                       return dataReader;
+               }
+
+               internal DataTable BuildTableSchema (IntPtr pgResult, 
+                                       out int nRows, 
+                                       out int nFields, 
+                                       out int[] oids) {
+
+                       int nCol;
+                       
+                       DataTable dt = new DataTable();
+
+                       nRows = PostgresLibrary.
+                               PQntuples(pgResult);
+
+                       nFields = PostgresLibrary.
+                               PQnfields(pgResult);
+                       
+                       oids = new int[nFields];
+
+                       for(nCol = 0; nCol < nFields; nCol++) {                                         
+                               // get column name
+                               String fieldName;
+                               fieldName = PostgresLibrary.
+                                       PQfname(pgResult, nCol);
+
+                               // get PostgreSQL data type (OID)
+                               oids[nCol] = PostgresLibrary.
+                                       PQftype(pgResult, nCol);
+
+                               int definedSize;
+                               // get defined size of column
+                               definedSize = PostgresLibrary.
+                                       PQfsize(pgResult, nCol);
+                                                               
+                               // build the data column and add it the table
+                               DataColumn dc = new DataColumn(fieldName);
+                               dc.DataType = PostgresHelper.OidToType(oids[nCol]);
+                               dc.MaxLength = definedSize;
+                               dc.SetTable(dt);
+                               
+                               dt.Columns.Add(dc);
+                       }
+                       return dt;
                }
 
                [MonoTODO]
@@ -247,7 +344,7 @@ namespace System.Data.SqlClient
                                                nRow, nCol);
                                                
                                        obj = PostgresHelper.
-                                               OidTypeToSystem (oid, value);
+                                               ConvertPgTypeToSystem (oid, value);
                                }
 
                                // close result set
index 9b0ab2280f9208300c0f332bf6adf86e16e21802..40271d16ddf1cc89e8f9ec357e42e398f29ee892 100644 (file)
@@ -74,8 +74,12 @@ namespace System.Data.SqlClient
                // support SSL. Set to 0 (default) to 
                // negotiate with server. 
 
-               ConnectionState conState = ConnectionState.Closed;
-
+               private ConnectionState conState = ConnectionState.Closed;
+               private bool dataReaderOpen = false;
+               // FIXME: if true, throw an exception if SqlConnection 
+               //        is used used for anything other than reading
+               //        data using SqlDataReader
+               
                #endregion // Fields
 
                #region Constructors
index 5e3fb572db6862b5abd39eff73794f16803ddd20..0d6aa94bc23b0b3061a0c515589d18bfaea5e80f 100644 (file)
@@ -26,22 +26,52 @@ namespace System.Data.SqlClient
        {
                #region Fields
 
-               private DataTable table = null;
+               private SqlCommand cmd;
+               private DataTable table;
+
+               private object[] fields;
+               private int[] oid; // PostgreSQL Type
+                               
+               private bool open = false;
+               IntPtr pgResult; // PGresult
+               private int rows;
+               private int cols;
+
+               private int currentRow = -1; // no Read() has been done yet
 
                #endregion // Fields
 
+               #region Constructors
+
+               internal SqlDataReader (SqlCommand sqlCmd, 
+                       DataTable dataTableSchema, IntPtr pg_result,
+                       int rowCount, int fieldCount, int[] oids) {
+
+                       cmd = sqlCmd;
+                       table = dataTableSchema;
+                       pgResult = pg_result;
+                       rows = rowCount;
+                       cols = fieldCount;
+                       oid = oids;
+               }
+
+               #endregion
+
                #region Public Methods
 
                [MonoTODO]
                public void Close()
                {
-                       throw new NotImplementedException ();
+                       // close result set
+                       PostgresLibrary.PQclear (pgResult);
+
+                       // TODO: change busy state on SqlConnection to not busy
                }
 
                [MonoTODO]
                public DataTable GetSchemaTable()
                {
-                       throw new NotImplementedException ();
+                       return table;
                }
 
                [MonoTODO]
@@ -53,7 +83,38 @@ namespace System.Data.SqlClient
                [MonoTODO]
                public bool Read()
                {
-                       throw new NotImplementedException ();
+                       string value;
+                       fields = new object[cols]; // re-init row
+
+                       if(currentRow < rows - 1)  {
+                               currentRow++;
+                               int c;
+                               for(c = 0; c < cols; c++) {
+
+                                       // get data value
+                                       value = PostgresLibrary.
+                                               PQgetvalue(
+                                               pgResult,
+                                               currentRow, c);
+
+                                       int columnIsNull;
+                                       // is column NULL?
+                                       columnIsNull = PostgresLibrary.
+                                               PQgetisnull(pgResult,
+                                               currentRow, c);
+
+                                       int actualLength;
+                                       // get Actual Length
+                                       actualLength = PostgresLibrary.
+                                               PQgetlength(pgResult,
+                                               currentRow, c);
+                                               
+                                       fields[c] = PostgresHelper.
+                                               ConvertPgTypeToSystem (oid[c], value);
+                               }
+                               return true;
+                       }
+                       return false; // EOF
                }
 
                [MonoTODO]
@@ -135,25 +196,25 @@ namespace System.Data.SqlClient
                [MonoTODO]
                public short GetInt16(int i)
                {
-                       throw new NotImplementedException ();
+                       return (short) fields[i];
                }
 
                [MonoTODO]
                public int GetInt32(int i)
                {
-                       throw new NotImplementedException ();
+                       return (int) fields[i];
                }
 
                [MonoTODO]
                public long GetInt64(int i)
                {
-                       throw new NotImplementedException ();
+                       return (long) fields[i];
                }
 
                [MonoTODO]
                public string GetName(int i)
                {
-                       throw new NotImplementedException ();
+                       return table.Columns[i].ColumnName;
                }
 
                [MonoTODO]
@@ -165,13 +226,13 @@ namespace System.Data.SqlClient
                [MonoTODO]
                public string GetString(int i)
                {
-                       throw new NotImplementedException ();
+                       return (string) fields[i];
                }
 
                [MonoTODO]
                public object GetValue(int i)
                {
-                       throw new NotImplementedException ();
+                       return fields[i];
                }
 
                [MonoTODO]
@@ -237,14 +298,35 @@ namespace System.Data.SqlClient
                public int FieldCount {
                        [MonoTODO]
                        get { 
-                               throw new NotImplementedException ();
+                               return cols;
                        }
                }
 
                public object this[string name] {
                        [MonoTODO]
                        get { 
-                               throw new NotImplementedException ();
+                               int i;
+                               for(i = 0; i < cols; i ++) {
+                                       if(table.Columns[i].ColumnName.Equals(name)) {
+                                               return fields[i];
+                                       }
+
+                               }
+                               
+                               if(i == cols) {
+                                       for(i = 0; i < cols; i++) {
+                                               string ta;
+                                               string n;
+                                               
+                                               ta = table.Columns[i].ColumnName.ToUpper();
+                                               n = name.ToUpper();
+                                               
+                                               if(ta.Equals(n)) {
+                                                       return fields[i];
+                                               }
+                                       }
+                               }
+                               throw new MissingFieldException("Missing field: " + name);
                        }
                }
 
@@ -252,7 +334,7 @@ namespace System.Data.SqlClient
                        [MonoTODO]
                        get 
                        { 
-                               throw new NotImplementedException ();
+                               return fields[i];
                        }
                }
 
index 7f5d1a6141fcc808b1d64af6af71bc363000d3cf..9479e23ef403c41c28aef069dd0cf3a9561491d9 100644 (file)
@@ -57,7 +57,13 @@ namespace System.Data.SqlClient
 
        sealed internal class PostgresHelper {
 
-               public static object OidTypeToSystem (int oid, String value) {
+               /// <summary>\r
+               /// Convert a PostgreSQL Type to a .NET System type.\r
+               /// </summary>\r
+               /// <param name="oid"></param>\r
+               /// <param name="value"></param>\r
+               /// <returns></returns>
+               public static object ConvertPgTypeToSystem (int oid, String value) {
                        object obj = null;
 
                        // FIXME: more types need 
@@ -66,10 +72,10 @@ namespace System.Data.SqlClient
                        //        to .NET System.<type>
 
                        switch(oid) {
-                       case 1023: // varchar
+                       case 1043: // varchar
                        case 25: // text
                        case 18: // char
-                               obj = (object) value; // String
+                               obj = (object) String.Copy(value); 
                                break;
                        case 16: // bool
                                obj = (object) Boolean.Parse(value);
@@ -83,11 +89,53 @@ namespace System.Data.SqlClient
                        case 20: // int8\r
                                obj = (object) Int64.Parse(value);\r
                                break;\r
+                       default:\r
+                               throw new NotImplementedException(\r
+                                       "PGNI1: PostgreSQL oid data type " + oid +\r
+                                       " not mapped to .NET System data type.");\r
                        }
 
                        return obj;
                }
+               
+               /// <summary>\r
+               /// Convert the PostgreSQL Type oid to the .NET System.Type.\r
+               /// </summary>\r
+               /// <param name="oid"></param>\r
+               /// <returns></returns>
+               public static Type OidToType (int oid) {
+                       // FIXME: more types need 
+                       //        to be mapped
+                       //        from PostgreSQL oid type
+                       //        to .NET System.<type>
 
+                       Type typ = null;
+
+                       switch(oid) {
+                       case 1043: // varchar
+                       case 25: // text
+                       case 18: // char
+                               typ = typeof(String);
+                               break;
+                       case 16: // bool
+                               typ = typeof(Boolean);
+                               break;
+                       case 21: // int2\r
+                               typ = typeof(Int16);\r
+                               break;\r
+                       case 23: // int4\r
+                               typ = typeof(Int32);\r
+                               break;\r
+                       case 20: // int8\r
+                               typ = typeof(Int64);\r
+                               break;\r
+                       default:\r
+                               throw new NotImplementedException(\r
+                                       "PGNI2: PostgreSQL oid type " + oid +\r
+                                       " not mapped to .NET System Type.");\r
+                       }
+                       return typ;
+               }
        }
 
        sealed internal class PostgresLibrary
index 0ae881fcfd1ede19fdbc33fa040e95278ed429de..765684032130d4042163935c8c19ed151e560160 100644 (file)
@@ -158,7 +158,7 @@ namespace System.Data.SqlClient
                [MonoTODO]
                SqlDataReader ExecuteReader ()
                {
-                       throw new NotImplementedException ();   
+                       return ExecuteReader(CommandBehavior.Default);
                }
 
                [MonoTODO]
@@ -171,7 +171,104 @@ namespace System.Data.SqlClient
                [MonoTODO]
                public SqlDataReader ExecuteReader (CommandBehavior behavior)
                {
-                       throw new NotImplementedException ();
+                       // FIXME: currently only works for a 
+                       //        single result set
+                       //        ExecuteReader can be used 
+                       //        for multiple result sets
+                       SqlDataReader dataReader = null;
+                       
+                       IntPtr pgResult; // PGresult
+                       ExecStatusType execStatus;      
+
+                       if(conn.State != ConnectionState.Open)
+                               throw new InvalidOperationException(
+                                       "ConnnectionState is not Open");
+
+                       // FIXME: PQexec blocks 
+                       // while PQsendQuery is non-blocking
+                       // which is better to use?
+                       // int PQsendQuery(PGconn *conn,
+                       //        const char *query);
+
+                       // execute SQL command
+                       // uses internal property to get the PGConn IntPtr
+                       pgResult = PostgresLibrary.
+                               PQexec (conn.PostgresConnection, sql);
+
+                       execStatus = PostgresLibrary.
+                               PQresultStatus (pgResult);
+                       
+                       if(execStatus == ExecStatusType.PGRES_TUPLES_OK) {
+                               DataTable dt = null;
+                               int rows, cols;
+                               int[] oids;
+                               
+                               // FIXME: maybe i should move the
+                               //        BuildTableSchema code
+                               //        to the SqlDataReader?
+                               dt = BuildTableSchema(pgResult, 
+                                       out rows, out cols, out oids);
+                               dataReader = new SqlDataReader(this, dt, pgResult,
+                                       rows, cols, oids);
+                       }
+                       else {
+                               String errorMessage;
+                               
+                               errorMessage = PostgresLibrary.
+                                       PQresStatus(execStatus);
+
+                               errorMessage += " " + PostgresLibrary.\r
+                                       PQresultErrorMessage(pgResult);\r
+                               \r
+                               throw new SqlException(0, 0,
+                                       errorMessage, 0, "",
+                                       conn.DataSource, "SqlCommand", 0);\r
+                       }
+                                       
+                       return dataReader;
+               }
+
+               internal DataTable BuildTableSchema (IntPtr pgResult, 
+                                       out int nRows, 
+                                       out int nFields, 
+                                       out int[] oids) {
+
+                       int nCol;
+                       
+                       DataTable dt = new DataTable();
+
+                       nRows = PostgresLibrary.
+                               PQntuples(pgResult);
+
+                       nFields = PostgresLibrary.
+                               PQnfields(pgResult);
+                       
+                       oids = new int[nFields];
+
+                       for(nCol = 0; nCol < nFields; nCol++) {                                         
+                               // get column name
+                               String fieldName;
+                               fieldName = PostgresLibrary.
+                                       PQfname(pgResult, nCol);
+
+                               // get PostgreSQL data type (OID)
+                               oids[nCol] = PostgresLibrary.
+                                       PQftype(pgResult, nCol);
+
+                               int definedSize;
+                               // get defined size of column
+                               definedSize = PostgresLibrary.
+                                       PQfsize(pgResult, nCol);
+                                                               
+                               // build the data column and add it the table
+                               DataColumn dc = new DataColumn(fieldName);
+                               dc.DataType = PostgresHelper.OidToType(oids[nCol]);
+                               dc.MaxLength = definedSize;
+                               dc.SetTable(dt);
+                               
+                               dt.Columns.Add(dc);
+                       }
+                       return dt;
                }
 
                [MonoTODO]
@@ -247,7 +344,7 @@ namespace System.Data.SqlClient
                                                nRow, nCol);
                                                
                                        obj = PostgresHelper.
-                                               OidTypeToSystem (oid, value);
+                                               ConvertPgTypeToSystem (oid, value);
                                }
 
                                // close result set
index 9b0ab2280f9208300c0f332bf6adf86e16e21802..40271d16ddf1cc89e8f9ec357e42e398f29ee892 100644 (file)
@@ -74,8 +74,12 @@ namespace System.Data.SqlClient
                // support SSL. Set to 0 (default) to 
                // negotiate with server. 
 
-               ConnectionState conState = ConnectionState.Closed;
-
+               private ConnectionState conState = ConnectionState.Closed;
+               private bool dataReaderOpen = false;
+               // FIXME: if true, throw an exception if SqlConnection 
+               //        is used used for anything other than reading
+               //        data using SqlDataReader
+               
                #endregion // Fields
 
                #region Constructors
index 5e3fb572db6862b5abd39eff73794f16803ddd20..0d6aa94bc23b0b3061a0c515589d18bfaea5e80f 100644 (file)
@@ -26,22 +26,52 @@ namespace System.Data.SqlClient
        {
                #region Fields
 
-               private DataTable table = null;
+               private SqlCommand cmd;
+               private DataTable table;
+
+               private object[] fields;
+               private int[] oid; // PostgreSQL Type
+                               
+               private bool open = false;
+               IntPtr pgResult; // PGresult
+               private int rows;
+               private int cols;
+
+               private int currentRow = -1; // no Read() has been done yet
 
                #endregion // Fields
 
+               #region Constructors
+
+               internal SqlDataReader (SqlCommand sqlCmd, 
+                       DataTable dataTableSchema, IntPtr pg_result,
+                       int rowCount, int fieldCount, int[] oids) {
+
+                       cmd = sqlCmd;
+                       table = dataTableSchema;
+                       pgResult = pg_result;
+                       rows = rowCount;
+                       cols = fieldCount;
+                       oid = oids;
+               }
+
+               #endregion
+
                #region Public Methods
 
                [MonoTODO]
                public void Close()
                {
-                       throw new NotImplementedException ();
+                       // close result set
+                       PostgresLibrary.PQclear (pgResult);
+
+                       // TODO: change busy state on SqlConnection to not busy
                }
 
                [MonoTODO]
                public DataTable GetSchemaTable()
                {
-                       throw new NotImplementedException ();
+                       return table;
                }
 
                [MonoTODO]
@@ -53,7 +83,38 @@ namespace System.Data.SqlClient
                [MonoTODO]
                public bool Read()
                {
-                       throw new NotImplementedException ();
+                       string value;
+                       fields = new object[cols]; // re-init row
+
+                       if(currentRow < rows - 1)  {
+                               currentRow++;
+                               int c;
+                               for(c = 0; c < cols; c++) {
+
+                                       // get data value
+                                       value = PostgresLibrary.
+                                               PQgetvalue(
+                                               pgResult,
+                                               currentRow, c);
+
+                                       int columnIsNull;
+                                       // is column NULL?
+                                       columnIsNull = PostgresLibrary.
+                                               PQgetisnull(pgResult,
+                                               currentRow, c);
+
+                                       int actualLength;
+                                       // get Actual Length
+                                       actualLength = PostgresLibrary.
+                                               PQgetlength(pgResult,
+                                               currentRow, c);
+                                               
+                                       fields[c] = PostgresHelper.
+                                               ConvertPgTypeToSystem (oid[c], value);
+                               }
+                               return true;
+                       }
+                       return false; // EOF
                }
 
                [MonoTODO]
@@ -135,25 +196,25 @@ namespace System.Data.SqlClient
                [MonoTODO]
                public short GetInt16(int i)
                {
-                       throw new NotImplementedException ();
+                       return (short) fields[i];
                }
 
                [MonoTODO]
                public int GetInt32(int i)
                {
-                       throw new NotImplementedException ();
+                       return (int) fields[i];
                }
 
                [MonoTODO]
                public long GetInt64(int i)
                {
-                       throw new NotImplementedException ();
+                       return (long) fields[i];
                }
 
                [MonoTODO]
                public string GetName(int i)
                {
-                       throw new NotImplementedException ();
+                       return table.Columns[i].ColumnName;
                }
 
                [MonoTODO]
@@ -165,13 +226,13 @@ namespace System.Data.SqlClient
                [MonoTODO]
                public string GetString(int i)
                {
-                       throw new NotImplementedException ();
+                       return (string) fields[i];
                }
 
                [MonoTODO]
                public object GetValue(int i)
                {
-                       throw new NotImplementedException ();
+                       return fields[i];
                }
 
                [MonoTODO]
@@ -237,14 +298,35 @@ namespace System.Data.SqlClient
                public int FieldCount {
                        [MonoTODO]
                        get { 
-                               throw new NotImplementedException ();
+                               return cols;
                        }
                }
 
                public object this[string name] {
                        [MonoTODO]
                        get { 
-                               throw new NotImplementedException ();
+                               int i;
+                               for(i = 0; i < cols; i ++) {
+                                       if(table.Columns[i].ColumnName.Equals(name)) {
+                                               return fields[i];
+                                       }
+
+                               }
+                               
+                               if(i == cols) {
+                                       for(i = 0; i < cols; i++) {
+                                               string ta;
+                                               string n;
+                                               
+                                               ta = table.Columns[i].ColumnName.ToUpper();
+                                               n = name.ToUpper();
+                                               
+                                               if(ta.Equals(n)) {
+                                                       return fields[i];
+                                               }
+                                       }
+                               }
+                               throw new MissingFieldException("Missing field: " + name);
                        }
                }
 
@@ -252,7 +334,7 @@ namespace System.Data.SqlClient
                        [MonoTODO]
                        get 
                        { 
-                               throw new NotImplementedException ();
+                               return fields[i];
                        }
                }
 
index 7f5d1a6141fcc808b1d64af6af71bc363000d3cf..9479e23ef403c41c28aef069dd0cf3a9561491d9 100644 (file)
@@ -57,7 +57,13 @@ namespace System.Data.SqlClient
 
        sealed internal class PostgresHelper {
 
-               public static object OidTypeToSystem (int oid, String value) {
+               /// <summary>\r
+               /// Convert a PostgreSQL Type to a .NET System type.\r
+               /// </summary>\r
+               /// <param name="oid"></param>\r
+               /// <param name="value"></param>\r
+               /// <returns></returns>
+               public static object ConvertPgTypeToSystem (int oid, String value) {
                        object obj = null;
 
                        // FIXME: more types need 
@@ -66,10 +72,10 @@ namespace System.Data.SqlClient
                        //        to .NET System.<type>
 
                        switch(oid) {
-                       case 1023: // varchar
+                       case 1043: // varchar
                        case 25: // text
                        case 18: // char
-                               obj = (object) value; // String
+                               obj = (object) String.Copy(value); 
                                break;
                        case 16: // bool
                                obj = (object) Boolean.Parse(value);
@@ -83,11 +89,53 @@ namespace System.Data.SqlClient
                        case 20: // int8\r
                                obj = (object) Int64.Parse(value);\r
                                break;\r
+                       default:\r
+                               throw new NotImplementedException(\r
+                                       "PGNI1: PostgreSQL oid data type " + oid +\r
+                                       " not mapped to .NET System data type.");\r
                        }
 
                        return obj;
                }
+               
+               /// <summary>\r
+               /// Convert the PostgreSQL Type oid to the .NET System.Type.\r
+               /// </summary>\r
+               /// <param name="oid"></param>\r
+               /// <returns></returns>
+               public static Type OidToType (int oid) {
+                       // FIXME: more types need 
+                       //        to be mapped
+                       //        from PostgreSQL oid type
+                       //        to .NET System.<type>
 
+                       Type typ = null;
+
+                       switch(oid) {
+                       case 1043: // varchar
+                       case 25: // text
+                       case 18: // char
+                               typ = typeof(String);
+                               break;
+                       case 16: // bool
+                               typ = typeof(Boolean);
+                               break;
+                       case 21: // int2\r
+                               typ = typeof(Int16);\r
+                               break;\r
+                       case 23: // int4\r
+                               typ = typeof(Int32);\r
+                               break;\r
+                       case 20: // int8\r
+                               typ = typeof(Int64);\r
+                               break;\r
+                       default:\r
+                               throw new NotImplementedException(\r
+                                       "PGNI2: PostgreSQL oid type " + oid +\r
+                                       " not mapped to .NET System Type.");\r
+                       }
+                       return typ;
+               }
        }
 
        sealed internal class PostgresLibrary
index 1f81855517b088aae720d12a6a807581aad10997..4634a6429830aec9d4070bf4fc16c4993ff0e483 100644 (file)
@@ -1,3 +1,39 @@
+2002-05-03  Daniel Morgan <danmorg@sc.rr.com>
+
+       * Test/TestExecuteScalar.cs: added test for 
+       method ExecuteScalar in class SqlCommand.
+       
+       * System.Data/DataColumnCollection.cs - it should
+       inherit properties from base InternalDataCollectionBase
+       and use them instead of overriding them, such as, List.
+       
+       * System.Data/DataColumn.cs
+       * System.Data/DataTable.cs: tweaks to retrieve
+       meta data from the database
+       
+       * System.Data.SqlClient/PostgresLibrary.cs -
+       added method OidToType to convert PostgreSQL oid type 
+       to System.Type.  Renamed method OidTypeToSystem
+       to ConvertPgTypeToSystem for converting the data value
+       from a PostgreSQL type to a .NET System type.
+       
+       * System.Data.SqlClient/SqlCommand.cs: implemented
+       method ExecuteReader which returns a SqlDataReader
+       for a light forward only read only result set. 
+       It works on types int4 ==> Int32 and 
+       varchar ==> String.  Other types
+       will come later.
+       
+       * System.Data.SqlClient/SqlConnection.cs: added comment
+       
+       * System.Data.SqlClient/SqlDataReader.cs: implemented
+       class.  It works, but still lots to do.
+       
+       * Test/ReadPostgresData.cs: stuff
+       
+       * Test/TestSqlDataReader.cs: updated test for SqlDataReader
+       to display meta data and the data
+       
 2002-05-03  Duncan Mak  <duncan@ximian.com>
 
        * TODO: Took out all the Exceptions. They should be all done now.
index 7f5d1a6141fcc808b1d64af6af71bc363000d3cf..9479e23ef403c41c28aef069dd0cf3a9561491d9 100644 (file)
@@ -57,7 +57,13 @@ namespace System.Data.SqlClient
 
        sealed internal class PostgresHelper {
 
-               public static object OidTypeToSystem (int oid, String value) {
+               /// <summary>\r
+               /// Convert a PostgreSQL Type to a .NET System type.\r
+               /// </summary>\r
+               /// <param name="oid"></param>\r
+               /// <param name="value"></param>\r
+               /// <returns></returns>
+               public static object ConvertPgTypeToSystem (int oid, String value) {
                        object obj = null;
 
                        // FIXME: more types need 
@@ -66,10 +72,10 @@ namespace System.Data.SqlClient
                        //        to .NET System.<type>
 
                        switch(oid) {
-                       case 1023: // varchar
+                       case 1043: // varchar
                        case 25: // text
                        case 18: // char
-                               obj = (object) value; // String
+                               obj = (object) String.Copy(value); 
                                break;
                        case 16: // bool
                                obj = (object) Boolean.Parse(value);
@@ -83,11 +89,53 @@ namespace System.Data.SqlClient
                        case 20: // int8\r
                                obj = (object) Int64.Parse(value);\r
                                break;\r
+                       default:\r
+                               throw new NotImplementedException(\r
+                                       "PGNI1: PostgreSQL oid data type " + oid +\r
+                                       " not mapped to .NET System data type.");\r
                        }
 
                        return obj;
                }
+               
+               /// <summary>\r
+               /// Convert the PostgreSQL Type oid to the .NET System.Type.\r
+               /// </summary>\r
+               /// <param name="oid"></param>\r
+               /// <returns></returns>
+               public static Type OidToType (int oid) {
+                       // FIXME: more types need 
+                       //        to be mapped
+                       //        from PostgreSQL oid type
+                       //        to .NET System.<type>
 
+                       Type typ = null;
+
+                       switch(oid) {
+                       case 1043: // varchar
+                       case 25: // text
+                       case 18: // char
+                               typ = typeof(String);
+                               break;
+                       case 16: // bool
+                               typ = typeof(Boolean);
+                               break;
+                       case 21: // int2\r
+                               typ = typeof(Int16);\r
+                               break;\r
+                       case 23: // int4\r
+                               typ = typeof(Int32);\r
+                               break;\r
+                       case 20: // int8\r
+                               typ = typeof(Int64);\r
+                               break;\r
+                       default:\r
+                               throw new NotImplementedException(\r
+                                       "PGNI2: PostgreSQL oid type " + oid +\r
+                                       " not mapped to .NET System Type.");\r
+                       }
+                       return typ;
+               }
        }
 
        sealed internal class PostgresLibrary
index 0ae881fcfd1ede19fdbc33fa040e95278ed429de..765684032130d4042163935c8c19ed151e560160 100644 (file)
@@ -158,7 +158,7 @@ namespace System.Data.SqlClient
                [MonoTODO]
                SqlDataReader ExecuteReader ()
                {
-                       throw new NotImplementedException ();   
+                       return ExecuteReader(CommandBehavior.Default);
                }
 
                [MonoTODO]
@@ -171,7 +171,104 @@ namespace System.Data.SqlClient
                [MonoTODO]
                public SqlDataReader ExecuteReader (CommandBehavior behavior)
                {
-                       throw new NotImplementedException ();
+                       // FIXME: currently only works for a 
+                       //        single result set
+                       //        ExecuteReader can be used 
+                       //        for multiple result sets
+                       SqlDataReader dataReader = null;
+                       
+                       IntPtr pgResult; // PGresult
+                       ExecStatusType execStatus;      
+
+                       if(conn.State != ConnectionState.Open)
+                               throw new InvalidOperationException(
+                                       "ConnnectionState is not Open");
+
+                       // FIXME: PQexec blocks 
+                       // while PQsendQuery is non-blocking
+                       // which is better to use?
+                       // int PQsendQuery(PGconn *conn,
+                       //        const char *query);
+
+                       // execute SQL command
+                       // uses internal property to get the PGConn IntPtr
+                       pgResult = PostgresLibrary.
+                               PQexec (conn.PostgresConnection, sql);
+
+                       execStatus = PostgresLibrary.
+                               PQresultStatus (pgResult);
+                       
+                       if(execStatus == ExecStatusType.PGRES_TUPLES_OK) {
+                               DataTable dt = null;
+                               int rows, cols;
+                               int[] oids;
+                               
+                               // FIXME: maybe i should move the
+                               //        BuildTableSchema code
+                               //        to the SqlDataReader?
+                               dt = BuildTableSchema(pgResult, 
+                                       out rows, out cols, out oids);
+                               dataReader = new SqlDataReader(this, dt, pgResult,
+                                       rows, cols, oids);
+                       }
+                       else {
+                               String errorMessage;
+                               
+                               errorMessage = PostgresLibrary.
+                                       PQresStatus(execStatus);
+
+                               errorMessage += " " + PostgresLibrary.\r
+                                       PQresultErrorMessage(pgResult);\r
+                               \r
+                               throw new SqlException(0, 0,
+                                       errorMessage, 0, "",
+                                       conn.DataSource, "SqlCommand", 0);\r
+                       }
+                                       
+                       return dataReader;
+               }
+
+               internal DataTable BuildTableSchema (IntPtr pgResult, 
+                                       out int nRows, 
+                                       out int nFields, 
+                                       out int[] oids) {
+
+                       int nCol;
+                       
+                       DataTable dt = new DataTable();
+
+                       nRows = PostgresLibrary.
+                               PQntuples(pgResult);
+
+                       nFields = PostgresLibrary.
+                               PQnfields(pgResult);
+                       
+                       oids = new int[nFields];
+
+                       for(nCol = 0; nCol < nFields; nCol++) {                                         
+                               // get column name
+                               String fieldName;
+                               fieldName = PostgresLibrary.
+                                       PQfname(pgResult, nCol);
+
+                               // get PostgreSQL data type (OID)
+                               oids[nCol] = PostgresLibrary.
+                                       PQftype(pgResult, nCol);
+
+                               int definedSize;
+                               // get defined size of column
+                               definedSize = PostgresLibrary.
+                                       PQfsize(pgResult, nCol);
+                                                               
+                               // build the data column and add it the table
+                               DataColumn dc = new DataColumn(fieldName);
+                               dc.DataType = PostgresHelper.OidToType(oids[nCol]);
+                               dc.MaxLength = definedSize;
+                               dc.SetTable(dt);
+                               
+                               dt.Columns.Add(dc);
+                       }
+                       return dt;
                }
 
                [MonoTODO]
@@ -247,7 +344,7 @@ namespace System.Data.SqlClient
                                                nRow, nCol);
                                                
                                        obj = PostgresHelper.
-                                               OidTypeToSystem (oid, value);
+                                               ConvertPgTypeToSystem (oid, value);
                                }
 
                                // close result set
index 9b0ab2280f9208300c0f332bf6adf86e16e21802..40271d16ddf1cc89e8f9ec357e42e398f29ee892 100644 (file)
@@ -74,8 +74,12 @@ namespace System.Data.SqlClient
                // support SSL. Set to 0 (default) to 
                // negotiate with server. 
 
-               ConnectionState conState = ConnectionState.Closed;
-
+               private ConnectionState conState = ConnectionState.Closed;
+               private bool dataReaderOpen = false;
+               // FIXME: if true, throw an exception if SqlConnection 
+               //        is used used for anything other than reading
+               //        data using SqlDataReader
+               
                #endregion // Fields
 
                #region Constructors
index 5e3fb572db6862b5abd39eff73794f16803ddd20..0d6aa94bc23b0b3061a0c515589d18bfaea5e80f 100644 (file)
@@ -26,22 +26,52 @@ namespace System.Data.SqlClient
        {
                #region Fields
 
-               private DataTable table = null;
+               private SqlCommand cmd;
+               private DataTable table;
+
+               private object[] fields;
+               private int[] oid; // PostgreSQL Type
+                               
+               private bool open = false;
+               IntPtr pgResult; // PGresult
+               private int rows;
+               private int cols;
+
+               private int currentRow = -1; // no Read() has been done yet
 
                #endregion // Fields
 
+               #region Constructors
+
+               internal SqlDataReader (SqlCommand sqlCmd, 
+                       DataTable dataTableSchema, IntPtr pg_result,
+                       int rowCount, int fieldCount, int[] oids) {
+
+                       cmd = sqlCmd;
+                       table = dataTableSchema;
+                       pgResult = pg_result;
+                       rows = rowCount;
+                       cols = fieldCount;
+                       oid = oids;
+               }
+
+               #endregion
+
                #region Public Methods
 
                [MonoTODO]
                public void Close()
                {
-                       throw new NotImplementedException ();
+                       // close result set
+                       PostgresLibrary.PQclear (pgResult);
+
+                       // TODO: change busy state on SqlConnection to not busy
                }
 
                [MonoTODO]
                public DataTable GetSchemaTable()
                {
-                       throw new NotImplementedException ();
+                       return table;
                }
 
                [MonoTODO]
@@ -53,7 +83,38 @@ namespace System.Data.SqlClient
                [MonoTODO]
                public bool Read()
                {
-                       throw new NotImplementedException ();
+                       string value;
+                       fields = new object[cols]; // re-init row
+
+                       if(currentRow < rows - 1)  {
+                               currentRow++;
+                               int c;
+                               for(c = 0; c < cols; c++) {
+
+                                       // get data value
+                                       value = PostgresLibrary.
+                                               PQgetvalue(
+                                               pgResult,
+                                               currentRow, c);
+
+                                       int columnIsNull;
+                                       // is column NULL?
+                                       columnIsNull = PostgresLibrary.
+                                               PQgetisnull(pgResult,
+                                               currentRow, c);
+
+                                       int actualLength;
+                                       // get Actual Length
+                                       actualLength = PostgresLibrary.
+                                               PQgetlength(pgResult,
+                                               currentRow, c);
+                                               
+                                       fields[c] = PostgresHelper.
+                                               ConvertPgTypeToSystem (oid[c], value);
+                               }
+                               return true;
+                       }
+                       return false; // EOF
                }
 
                [MonoTODO]
@@ -135,25 +196,25 @@ namespace System.Data.SqlClient
                [MonoTODO]
                public short GetInt16(int i)
                {
-                       throw new NotImplementedException ();
+                       return (short) fields[i];
                }
 
                [MonoTODO]
                public int GetInt32(int i)
                {
-                       throw new NotImplementedException ();
+                       return (int) fields[i];
                }
 
                [MonoTODO]
                public long GetInt64(int i)
                {
-                       throw new NotImplementedException ();
+                       return (long) fields[i];
                }
 
                [MonoTODO]
                public string GetName(int i)
                {
-                       throw new NotImplementedException ();
+                       return table.Columns[i].ColumnName;
                }
 
                [MonoTODO]
@@ -165,13 +226,13 @@ namespace System.Data.SqlClient
                [MonoTODO]
                public string GetString(int i)
                {
-                       throw new NotImplementedException ();
+                       return (string) fields[i];
                }
 
                [MonoTODO]
                public object GetValue(int i)
                {
-                       throw new NotImplementedException ();
+                       return fields[i];
                }
 
                [MonoTODO]
@@ -237,14 +298,35 @@ namespace System.Data.SqlClient
                public int FieldCount {
                        [MonoTODO]
                        get { 
-                               throw new NotImplementedException ();
+                               return cols;
                        }
                }
 
                public object this[string name] {
                        [MonoTODO]
                        get { 
-                               throw new NotImplementedException ();
+                               int i;
+                               for(i = 0; i < cols; i ++) {
+                                       if(table.Columns[i].ColumnName.Equals(name)) {
+                                               return fields[i];
+                                       }
+
+                               }
+                               
+                               if(i == cols) {
+                                       for(i = 0; i < cols; i++) {
+                                               string ta;
+                                               string n;
+                                               
+                                               ta = table.Columns[i].ColumnName.ToUpper();
+                                               n = name.ToUpper();
+                                               
+                                               if(ta.Equals(n)) {
+                                                       return fields[i];
+                                               }
+                                       }
+                               }
+                               throw new MissingFieldException("Missing field: " + name);
                        }
                }
 
@@ -252,7 +334,7 @@ namespace System.Data.SqlClient
                        [MonoTODO]
                        get 
                        { 
-                               throw new NotImplementedException ();
+                               return fields[i];
                        }
                }
 
index 5f1d24e5c5253d43fca2b072cf9fa32495661e05..d7f1bf55a07c0bdd35a46465662d34cf2987a880 100644 (file)
@@ -55,7 +55,6 @@ namespace System.Data
                public DataColumn(string columnName): this()
                {
                        ColumnName = columnName;
-                       Caption = columnName;
                }
 
                public DataColumn(string columnName, Type dataType): this(columnName)
index 3e238d72b162772625309f98d8f1c46a95556476..616669aaec172413ca43b7ad9817a07385556bfd 100644 (file)
@@ -18,9 +18,6 @@ namespace System.Data
        /// </summary>
        public class DataColumnCollection : InternalDataCollectionBase
        {
-
-               protected new ArrayList list = null;
-               
                // The defaultNameIndex is used to create a default name for a column if one wasn't given.
                private int defaultNameIndex;
 
@@ -30,7 +27,6 @@ namespace System.Data
                // Internal Constructor.  This Class can only be created from other classes in this assembly.
                internal DataColumnCollection(DataTable table):base()
                {
-                       list = new ArrayList();
                        defaultNameIndex = 1;
                        parentTable = table;
                }
@@ -44,7 +40,7 @@ namespace System.Data
                {
                        get
                        {
-                               return (DataColumn)list[index];
+                               return (DataColumn) base.List[index];
                        }
                }
 
@@ -55,7 +51,7 @@ namespace System.Data
                {
                        get
                        {
-                               foreach (DataColumn column in list)
+                               foreach (DataColumn column in base.List)
                                {
                                        if (column.ColumnName == name)
                                        {
@@ -76,7 +72,7 @@ namespace System.Data
                {
                        get
                        {
-                               return list;
+                               return base.List;
                        }
                }
 
@@ -88,7 +84,7 @@ namespace System.Data
                {
                        DataColumn column = new DataColumn("Column" + defaultNameIndex.ToString());
                        CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
-                       list.Add(column);
+                       base.List.Add(column);
                        OnCollectionChanged(e);
                        defaultNameIndex++;
                        return column;
@@ -107,7 +103,7 @@ namespace System.Data
                        else
                        {
                                CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
-                               list.Add(column);
+                               base.List.Add(column);
                                OnCollectionChanged(e);
                                return;
                        }
@@ -136,7 +132,7 @@ namespace System.Data
                                DataColumn column = new DataColumn(columnName);
                                
                                CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
-                               list.Add(column);
+                               base.List.Add(column);
                                OnCollectionChanged(e);
                                return column;
                        }
@@ -164,7 +160,7 @@ namespace System.Data
                        {
                                DataColumn column = new DataColumn(columnName, type);
                                CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
-                               list.Add(column);
+                               base.List.Add(column);
                                OnCollectionChanged(e);
                                return column;
                        }
@@ -193,7 +189,7 @@ namespace System.Data
                        {
                                DataColumn column = new DataColumn(columnName, type, expression);
                                CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
-                               list.Add(column);
+                               base.List.Add(column);
                                OnCollectionChanged(e);
                                return column;
                        }
@@ -278,7 +274,7 @@ namespace System.Data
                        
                        //Check if another column's expression depends on this column.
                        
-                       foreach (DataColumn dataColumn in list)
+                       foreach (DataColumn dataColumn in List)
                        {
                                if (dataColumn.Expression.ToString().IndexOf(column.ColumnName) > 0)
                                {
@@ -296,7 +292,7 @@ namespace System.Data
                public void Clear()
                {
                        CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Refresh, this);
-                       list.Clear();
+                       base.List.Clear();
                        OnCollectionChanged(e);
                        return;
                }
@@ -318,7 +314,7 @@ namespace System.Data
                /// <returns>The index of the column specified by column if it is found; otherwise, -1.</returns>
                public virtual int IndexOf(DataColumn column)
                {
-                       return list.IndexOf(column);
+                       return base.List.IndexOf(column);
                }
 
                /// <summary>
@@ -374,7 +370,7 @@ namespace System.Data
                public void Remove(DataColumn column)
                {
                        CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Remove, this);
-                       list.Remove(column);
+                       base.List.Remove(column);
                        OnCollectionChanged(e);
                        return;
                }
@@ -387,7 +383,7 @@ namespace System.Data
                {
                        DataColumn column = this[name];
                        CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Remove, this);
-                       list.Remove(column);
+                       base.List.Remove(column);
                        OnCollectionChanged(e);
                        return;
                }
@@ -399,7 +395,7 @@ namespace System.Data
                public void RemoveAt(int index)
                {
                        CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Remove, this);
-                       list.RemoveAt(index);
+                       base.List.RemoveAt(index);
                        OnCollectionChanged(e);
                        return;
                }
index ae185c4ec45c91189dcff55e04072abece1d4dfa..026c00c79c925ba3b266bb4dc474a8cef936695a 100644 (file)
@@ -49,8 +49,6 @@ namespace System.Data
                private bool _containsListCollection;
                private string _encodedTableName;
                
-               
-               
                /// <summary>
                /// Initializes a new instance of the DataTable class with no arguments.
                /// </summary>
@@ -582,7 +580,8 @@ namespace System.Data
                /// </summary>
                public DataRow NewRow()
                {
-                       DataRow dataRow = null;
+                       DataRow dataRow = new DataRow();
+                       dataRow.SetTable(this);
                        return dataRow;
                }
 
index 84fb5cea39785d600216f0d2538ea53a34132c1c..9107c62d1e2a9facfede93440b9a79a3bb11f2a7 100644 (file)
@@ -24,7 +24,7 @@ namespace LearnToCreateSqlDataReader
                        object obj = null;
 
                        switch(oid) {
-                       case 1023: // varchar
+                       case 1043: // varchar
                                Console.WriteLine("oid 1023 varchar ==> String found");
                                obj = (object) String.Copy(value); // String
                                break;
@@ -61,6 +61,36 @@ namespace LearnToCreateSqlDataReader
 
                        return obj;
                }
+
+               public static Type OidToType (int oid) {
+                       Type typ = null;
+
+                       switch(oid) {
+                       case 1043: // varchar
+                       case 25: // text
+                       case 18: // char
+                               typ = typeof(String);
+                               break;
+                       case 16: // bool
+                               typ = typeof(Boolean);
+                               break;
+                       case 21: // int2\r
+                               typ = typeof(Int16);\r
+                               break;\r
+                       case 23: // int4\r
+                               typ = typeof(Int32);\r
+                               break;\r
+                       case 20: // int8\r
+                               typ = typeof(Int64);\r
+                               break;\r
+                       default:\r
+                               throw new NotImplementedException(\r
+                                       "PGNI2: PostgreSQL oid type " + oid +\r
+                                       " not mapped to .NET System Type.");\r
+                       }
+                       return typ;
+               }
+
        }
 
        sealed public class PostgresLibrary {
@@ -94,6 +124,7 @@ namespace LearnToCreateSqlDataReader
                        PGRES_FATAL_ERROR
                }
 
+
                [DllImport("pq")]
                public static extern string PQerrorMessage (IntPtr conn);
                // char *PQerrorMessage(const PGconn *conn);
@@ -525,6 +556,20 @@ namespace LearnToCreateSqlDataReader
                        Test();
 
                        TestExecuteScalar();
+
+                       Type t;
+                       int oid;
+
+                       oid = 1043;
+                       t = PostgresHelper.OidToType(oid); // varchar ==> String
+                       Console.WriteLine("OidToType varchar oid: " + oid +
+                               " ==> t: " + t.ToString());
+
+                       oid = 23;
+                       t = PostgresHelper.OidToType(oid);  // int4 ==> Int32
+                       Console.WriteLine("OidToType int4 oid: " + oid +
+                               " ==> t: " + t.ToString());
+
                }
        }
 }
diff --git a/mcs/class/System.Data/Test/TestExecuteScalar.cs b/mcs/class/System.Data/Test/TestExecuteScalar.cs
new file mode 100644 (file)
index 0000000..96b10ab
--- /dev/null
@@ -0,0 +1,92 @@
+//\r
+// Test/ExecuteScalar.cs\r
+//\r
+// Test the ExecuteScalar method in the \r
+// System.Data.SqlClient.SqlCommand class\r
+//\r
+// ExecuteScalar is meant to be lightweight\r
+// compared to ExecuteReader and only\r
+// returns one column and one row as one object.\r
+//\r
+// It is meant for SELECT SQL statements that\r
+// use an aggregate/group by function, such as,\r
+// count(), sum(), avg(), min(), max(), etc...\r
+// \r
+// The object that is returned you do an\r
+// explicit cast.  For instance, to retrieve a\r
+// Count of rows in a PostgreSQL table, you\r
+// would use "SELECT COUNT(*) FROM SOMETABLE"\r
+// which returns a number of oid type 20 which is \r
+// a PostgreSQL int8 which maps to \r
+// the .NET type System.Int64.  You\r
+// have to explicitly convert this returned object\r
+// to the type you are expecting, such as, an Int64\r
+// is returned for a COUNT().\r
+// would be:\r
+//      Int64 myCount = (Int64) cmd.ExecuteScalar(selectStatement);\r
+//\r
+// Author:\r
+//     Daniel Morgan <danmorg@sc.rr.com>\r
+//\r
+// (C) 2002 Daniel Morgan\r
+//\r
+\r
+using System;\r
+using System.Data;\r
+using System.Data.SqlClient;\r
+\r
+namespace TestSystemDataSqlClient\r
+{\r
+       class TestSqlDataReader\r
+       {\r
+\r
+               static void Test() { \r
+                       SqlConnection con = null;\r
+                       SqlCommand cmd = null;\r
+                                               \r
+                       String connectionString = null;\r
+                       String sql = null;\r
+\r
+                       connectionString = 
+                               "host=localhost;" +
+                               "dbname=test;" +
+                               "user=danmorg;" +
+                               "password=viewsonic";
+                       \r
+                       try {\r
+                               con = new SqlConnection(connectionString);\r
+                               con.Open();\r
+\r
+                               sql =   "select count(*) " + \r
+                                       "from sometable";\r
+                               cmd = new SqlCommand(sql,con);\r
+                               Console.WriteLine("Executing...");\r
+                               Int64 rowCount = (Int64) cmd.ExecuteScalar();\r
+                               Console.WriteLine("Row Count: " + rowCount);\r
+\r
+                               sql =   "select max(tdesc) " + \r
+                                       "from sometable";\r
+                               cmd = new SqlCommand(sql,con);\r
+                               Console.WriteLine("Executing...");\r
+                               String maxValue = (string) cmd.ExecuteScalar();\r
+                               Console.WriteLine("Max Value: " + maxValue);\r
+\r
+                       }\r
+                       catch(Exception e) {\r
+                               Console.WriteLine(e.ToString());\r
+                       }\r
+                       finally {\r
+                               if(con != null)
+                                       if(con.State == ConnectionState.Open)
+                                               con.Close();\r
+                       }\r
+               }\r
+\r
+               [STAThread]\r
+               static void Main(string[] args)\r
+               {\r
+                       Test();\r
+               }\r
+\r
+       }\r
+}\r
index f778ea30179136146c6d86897e614c0e934330a5..3c6b8baddbe77af604498590a4f789c806dd4c8b 100644 (file)
@@ -35,7 +35,7 @@ namespace TestSystemDataSqlClient
                                "user=danmorg;" +
                                "password=viewsonic";
 \r
-                       sql =   "select tid, tdesc " + \r
+                       sql =   "select tid, tdesc, aint4 " + \r
                                "from sometable";\r
                        \r
                        con = new SqlConnection(connectionString);\r
@@ -46,15 +46,38 @@ namespace TestSystemDataSqlClient
 \r
                        cmd = new SqlCommand(sql, con);\r
                        rdr = cmd.ExecuteReader();\r
+\r
+                        // get the DataTable that holds\r
+                       // the schema\r
+                       DataTable dt = rdr.GetSchemaTable();\r
                        \r
-                       // rdr.GetInt32(0)  \r
-                       // rdr.GetString(1)\r
+                       // number of columns in the table\r
+                       Console.WriteLine("dt.Columns.Count: " +\r
+                               dt.Columns.Count);\r
+\r
+                       // display the schema\r
+                       for(int c = 0; c < dt.Columns.Count; c++) {\r
+                               Console.WriteLine("* Column Name: " + \r
+                                       dt.Columns[c].ColumnName);\r
+                               Console.WriteLine("         MaxLength: " +\r
+                                       dt.Columns[c].MaxLength);\r
+                               Console.WriteLine("         Type: " +\r
+                                       dt.Columns[c].DataType);\r
+                       }\r
+\r
+                       // Read and display the rows\r
                        while(rdr.Read()) {\r
-                               Console.WriteLine(\r
-                                       rdr["fname"].ToString() + \r
-                                       ", " + \r
-                                       rdr["lname"].ToString());\r
+                               Console.WriteLine("Row: " +\r
+                                       rdr["tid"].ToString() + ", " + \r
+                                       rdr["tdesc"].ToString() + ", " + \r
+                                       rdr["aint4"].ToString()\r
+                                       );\r
+\r
+                               Console.WriteLine("1:" + rdr.GetString(0));\r
+                               Console.WriteLine("1:" + rdr.GetString(1));\r
+                               Console.WriteLine("2:" + rdr.GetInt32(2));\r
                        }\r
+                       \r
                        rdr.Close();\r
                        con.Close();\r
                }\r