2002-10-03 Miguel de Icaza <miguel@ximian.com>
[mono.git] / web / ado-net
index 54aeb2cfc52f94c74d1ddb44ae89d01dd56352a9..876ca9c71643dff03862043c6e38fd4bf86586ae 100644 (file)
@@ -3,39 +3,52 @@
        The coordinator for the ADO.NET implementation is <a
        href="mailto:rodrigo@ximian.com">Rodrigo Moya</a>, with
        the collaboration of <a href="mailto:danmorg@sc.rr.com">Daniel
-       Morgan</a>.
+       Morgan</a> and <a href="mailto:tim@timcoleman.com">Tim Coleman</a>.
+       
 
 * Action plan
 
        The current plan to implement ADO.NET is as follows:
 
-       <b>Step 1:</b> SqlClient:
+       <b>Step 1:</b> Initial <a href="http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemdatasqlclient.asp?frame=true">System.Data.SqlClient</a> Provider:
 
        <ul>
-               * Implementation of System.Data.SqlClient based on
-                 the <a href="http://www.postgresql.org/idocs/">PostgreSQL C API</a>
-
+               * Initial implementation of System.Data.SqlClient is based on
+                 the <a href="http://www.postgresql.org/idocs/">PostgreSQL C API</a> which is a
+                 client API to the PostgreSQL DBMS.  PostgreSQL was chosen so we could quickly
+                 create and test the System.Data classes.
+                 
                * Once the <a href="http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemdatasqlclient.asp?frame=true">System.Data.SqlClient</a>
                  code is functional and is usable by other people, we willl move it to
-                 System.Data.PostgreSQL, and will convert the existing
+                 Mono.Data.PostgreSQL, and will convert the existing
                  System.Data.SqlClient to be just a wrapper around
-                 System.Data.PostgreSQL.  
+                 Mono.Data.PostgreSQL.  
 
        </ul>
 
        <b>Step 2:</b> <a href="http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemDataOleDb.asp?frame=true">System.Data.OleDb</a> Provider:
                
        <ul>
-               * On Unix systems: System.Data.OleDb will use the
+               * <p>On Unix systems: System.Data.OleDb uses the
                <a href="http://www.gnome-db.org/">LibGDA</a>
                 engine. 
 
-                 LibGDA is a data access engine like ADO/OLE-DB, but for Unix.  It is
-                 used by Gnome-Db and libgnomedb.  There is work under way to get libgda
-                 working under Windows by the Gnome-Db developers.
-
-               * On Windows systems: System.Data.OleDb will use OLE-DB as
-                 its engine.  It may have the option of using libgda too.
+                 <p>LibGDA is a data access engine like ADO/OLE-DB, but for Unix.  The 
+                 GDA in libGDA stands for GNU/GNOME Data Access, but it does not require GNOME.
+                 It only requires glib2 and libxml2.  LibGDA is used by 
+                 libgnomedb, GNOME-DB, and gaSQL.
+                 
+                 <p>There is work under way to get libgda working under 
+                 Windows using Cygwin by the GNOME-DB developers.
+                 
+                 <p>LibGDA has providers for MySQL, PostgreSQL, XML, ODBC,
+                 Oracle, Interbase, Sybase/SQL server (via FreeTDS), IBM DB2,
+                 SQLite and MDB Tools
+                 (MS Access support).
+
+               * On Windows systems: System.Data.OleDb will use libgda as well,
+                 if we can get it working, or OLE-DB as
+                 its engine.
        </ul>
 
        <b>Step 3:</b> <a href="http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemdatasqlclient.asp?frame=true">System.Data.SqlClient</a> Provider:
                  
                  <p>Once Step 1 has been completed and the PostgreSQL
                  provider support has been moved to its own place at 
-                 System.Data.PostgreSQL, we will use 
+                 Mono.Data.PostgreSQL, we will use 
                  <a href="http://www.freetds.org/">FreeTDS</a> as the basis
                  for providing access to Microsoft SQL Server databases.
                  
-                 FreeTDS is a C API for Unix and Windows that implements 
+                 <P>FreeTDS is a C API for Unix and Windows that implements 
                  the TDS (Tabular Data Stream) protocol used in accessing 
-                 Microsoft SQL Server and Sybase databases.
+                 Microsoft SQL Server and Sybase databases.  A .NET Data Provider could be
+                 created for Sybase databases as well, but this would be put in Mono.Data.Sybase.
        </ul>
 
        <b>Step 4:</b> <a href="http://msdn.microsoft.com/downloads/sample.asp?url=/MSDN-FILES/027/001/668/msdncompositedoc.xml&frame=true">System.Data.Odbc</a> Provider:
        <ul>
                * We will create a .NET Managaed Provider for ODBC
                  in System.Data.Odbc for those using ODBC.
-                 On Unix and Windows, <a href="http://www.unixodbc.org/">unixODBC</a> will be used.
+                 On Unix and Windows, <a href="http://www.unixodbc.org/">unixODBC</a> mabye used.
+                 iODBC is an alternative to using unixODBC.
+                 
+                 <p>unixODBC works on Unix and Windows.  Well, I have not actually 
+                 used it on Cygwin, but it does build and install without problems.  
                  
-                 unixODBC works on Unix and Windows.  Providers exist for
+                 <p>unixODBC has providers for:
                  Oracle, Microsoft SQL Server and Sybase via FreeTDS, 
-                 MySQL, PostgreSQL, IBM DB2, Interbase, and others.
+                 MySQL, PostgreSQL, Informix, IBM DB2 (Universal Database), 
+                 Interbase, miniSQL (mSQL), AdabasD, Empress, YARD SQL, and others.
                  
        </ul>
 
        <b>Step 5:</b> Other System.Data providers:
 
        <ul>
-               * The idea in Microsoft .NET System.Data seems to be to have
-                 a managed provider for each supported DBMS. So, apart
-                 from System.Data.OleDb (generic) and System.Data.SqlClient,
-                 we'll need to have System.Data.MySQL,
-                 System.Data.Oracle, and System.Data.PostgreSQL. Others,
+               * <p>The idea in Microsoft .NET System.Data is to have
+                 a managed provider for each supported DBMS.  System.Data.SqlClient
+                 for Microsoft SQL Server.  
+                 System.Data.OracleClient for Oracle 8i and 9i.
+
+                 <p>We will need to have Mono.Data.MySQL, Mono.Data.PostgreSQL,
+                 Mono.Data.DB2, and Mono.Data.miniSQL. Others,
                  of course, are welcomed.
+                                 
+                 <p>System.Data has been designed so 
+                 non-database providers can be created too.              
        </ul>
        
 * Current Status
 
-       <p>We are still working on Step 1, but we are planning the other steps.
+       <p>We are working on Steps 1, 2, and 5.  We have only just begun on
+       steps 2 and 5 though.  We still have tons and tons of stuff to do.
        If you have any ideas, let us know.
        
+       <p>For Step 1, the PostgreSQL is starting to come together - it 
+       still needs a lot of work.
+       
+       <p>For Step 2, Rodrigo Moya has been working on System.Data.OleDb which uses libgda
+       which is an OLE-DB/ADO data access for Unix.  The C-Sharp bindings to libgda
+       currently work - meaning they can compile, run, and you can connect to a
+       PostgreSQL database via libgda via the C-Sharp bindings to libgda.  Basic
+       functionality (execution of commands, data retrieval, transactions, etc) are
+       now working. Current focus is on filling up the missing pieces (Data adapters
+       mainly).
+       
+       <p>For Step 3, we need someone to start the FreeTDS .NET Data Provider so
+       we can have data access to Microsoft SQL Server and Sybase databases, or either
+       add the support in libgda.
+       
+       <p>For Step 4, we need someone to start the unixODBC .NET Data Provider, or add
+       the support in libgda.
+       
+       <p>For Step 5, we have just begun creating a Mono.Data .NET Provider - a MySQL
+       .NET Provider that uses the MySQL C Client Library.  This provider is 
+       found in Mono.Data.MySql.  We can currently connect and do a SQL INSERT and insert
+       a row into a MySQL database.  However, it currently only works on Cygwin because
+       the MySQL client library libmySQL.dll is different 
+       from the library on Linux libmysqlclient.dll.  Another problem, mysql thread functions
+       do not load for some reason.  Also, the provider only runs if you use "mint" (the Mono
+       runtime interpreter).  It does not work on "mono" (the Mono Just-In-Time compiler).
+       The C# Bindings to MySQL are thanks to Brad Meril.
+               
        <p>We are able to do simple CREATE TABLE, DROP TABLE, UPDATE, INSERT, and
        DELETE SQL commands using the ExecuteNonQuery method in SqlCommand.  
        
+       <p>We can execute multiple queries and do a NextResult() in SqlDataReader()
+       to get the next result set.  
+       
        <p>We are also able to do simple aggregate functions, 
        ie, count(), sum(), min(), and max() 
        in a simple SELECT SQL query using the ExecuteScalar() now.  
        <p>We are also able to retrieve data with a simple SELECT SQL query 
        using ExecuteReader() which returns a SqlDataReader.  We are able to
        use GetSchemaTable() to get the meta data about the table columns.  
-       We are able     to Read() to get each row from the result set.  We are able to get 
-       String data (char, bpchar (character), text, varchar), Int16 (int2 or smallint),
-       Int32 (int4 or integer), Int64 (int8 or bigint), DateTime (time, date, timestamp),
+       We are able     to Read() to get each row from the result set.  
+       
+       <p>Here is a sample of code that is based on PostgresTest.cs and
+       TestSqlDataReader.cs tests:
+<pre>
+ static void SelectData (IDbConnection cnc) {
+       
+       IDbCommand selectCommand = cnc.CreateCommand();
+       IDataReader reader;
+
+       selectCommand.CommandType = CommandType.Text;
+       selectCommand.CommandText = 
+               "select * from pg_user;" + \r
+               "select * from pg_tables;" + \r
+               "select * from pg_database";\r
+
+       reader = selectCommand.ExecuteReader ();
+
+       do {\r
+               // get the DataTable that holds\r
+               // the schema\r
+               DataTable dt = rdr.GetSchemaTable();\r
+\r
+               if(rdr.RecordsAffected != -1) {\r
+                       // Results for \r
+                       // SQL INSERT, UPDATE, DELETE Commands \r
+                       // have RecordsAffected >= 0\r
+                       Console.WriteLine("Result is from a SQL Command (INSERT,UPDATE,DELETE).  Records Affected: " + rdr.RecordsAffected);\r
+               }\r
+               else if (dt == null)\r
+                               Console.WriteLine("Result is from a SQL Command not (INSERT,UPDATE,DELETE).   Records Affected: " + rdr.RecordsAffected);\r
+               else {\r
+                       // Results for\r
+                       // SQL not INSERT, UPDATE, nor DELETE\r
+                       // have RecordsAffected = -1\r
+                       Console.WriteLine("Result is from a SQL SELECT Query.  Records Affected: " + rdr.RecordsAffected);\r
+               \r
+                       // Results for a SQL Command (CREATE TABLE, SET, etc)\r
+                       // will have a null reference returned from GetSchemaTable()\r
+                       // \r
+                       // Results for a SQL SELECT Query\r
+                       // will have a DataTable returned from GetSchemaTable()\r
+\r
+                       results++;\r
+                       Console.WriteLine("Result Set " + results + "...");\r
+                                               \r
+                       // number of columns in the table\r
+                       Console.WriteLine("   Total Columns: " +\r
+                               dt.Columns.Count);\r
+\r
+                       // display the schema\r
+                       foreach (DataRow schemaRow in dt.Rows) {\r
+                               foreach (DataColumn schemaCol in dt.Columns)\r
+                                       Console.WriteLine(schemaCol.ColumnName + \r
+                                               " = " + \r
+                                               schemaRow[schemaCol]);\r
+                               Console.WriteLine();\r
+                       }\r
+\r
+                       int nRows = 0;\r
+                       string output, metadataValue, dataValue;\r
+                       // Read and display the rows\r
+                       Console.WriteLine("Gonna do a Read() now...");\r
+                       while(rdr.Read()) {\r
+                               Console.WriteLine("   Row " + nRows + ": ");\r
+                                       \r
+                               for(c = 0; c < rdr.FieldCount; c++) {\r
+                                       // column meta data \r
+                                       DataRow dr = dt.Rows[c];\r
+                                       metadataValue = \r
+                                               "    Col " + \r
+                                               c + ": " + \r
+                                               dr["ColumnName"];\r
+                                               \r
+                                       // column data\r
+                                       if(rdr.IsDBNull(c) == true)\r
+                                               dataValue = " is NULL";\r
+                                       else\r
+                                               dataValue = \r
+                                                       ": " + \r
+                                                       rdr.GetValue(c);\r
+                               \r
+                                       // display column meta data and data\r
+                                       output = metadataValue + dataValue;                                     \r
+                                       Console.WriteLine(output);\r
+                               }\r
+                               nRows++;\r
+                       }\r
+                       Console.WriteLine("   Total Rows: " + \r
+                               nRows);\r
+               }       \r
+       } while(rdr.NextResult());\r
+       Console.WriteLine("Total Result sets: " + results);\r
+                       \r
+       rdr.Close();\r
+ }
+
+</pre>
+       
+       <p>We are able to get 
+       String data (char, character, text, varchar), Int16 (smallint),
+       Int32 (integer), Int64 (bigint), DateTime (time, date, timestamp),
        Boolean (boolean), Single (float), and Double (double).
-       Other More data types will follow later on.
-               
-       <p>Parameters and stored procedures have not been tested and most likely
-       do not work.
+       More data types will come later.  Note, the types that do work still 
+       need thorough testing.
+       
+       <p>Rows that are returned which contain columns that are NULL are handled now. 
+       The SqlDataReader method IsDBNull() needs to be called to determine 
+       if a field IS NULL before trying to read data from that field.
+       
+       <p>Calling PostgreSQL stored procedures works.  It does not work perfectly.  It may not
+       even work to specification - yet.  If you want to test it yourself, look at
+       TestSqlDataReader.cs or PostgresTest.cs in
+       mcs/class/System.Data/Test.  
+       
+       <p>Below, I have some sample code you can
+       use to call a PostgreSQL stored procedure named "version".  This stored
+       procedure returns a string containing the PostgreSQL server version.  Notice
+       the CommandType is StoredProcedure and the method ExecuteScalar() is called.
+       
+       <p>ExecuteScalar() is a lightweight method in class SqlCommand that only returns
+       one row and one column as one object - even if there is more than row or column.
+       
+<pre>
+ static string GetDatabaseServerVersion (SqlConnection cnc) 
+ {                      
+       SqlCommand cmd = cnc.CreateCommand ();
+       string data;
+
+       cmd.CommandType = CommandType.StoredProcedure;
+       cmd.CommandText = "version";
+                                                       
+       data = (string) cmd.ExecuteScalar ();
+
+       return data;
+ }
+</pre>
+                       
+       <p>We have the beginnings of Parameters support PostgreSQL.  Only
+       Input Parameters are currently supported.  Output, Input/Output,
+       and Return parameters still need to be done.
        
        <p>A lot of functionality in System.Data is missing, but the 
        infrastructure is starting to come together.
        
-       <p>Need help on the DataSet/DataAdaptor/DataTable/DataRelation/XML 
+       <p>A lot of Exceptions need to be thrown for various exceptions.  However,
+       SqlException, SqlErrorCollection, and SqlError have been partially
+       implemented.
+       
+       <p>Tim Coleman and Rodrigo Moya got the beginnings of the
+       SqlDataAdapter/DataSet/DataTable/DataRow to work.  Currently, 
+       the SqlDataAdapter can Fill() relational data into a DataTable in a DataSet.
+       See the test mcs/class/System.Data/Test/TestSqlDataAdapter.cs to see it in action.
+       Below, I show a snippets from the test:
+       
+<pre>
+ string connectionString;
+ string sqlQuery;
+ SqlDataAdapter adapter;
+ DataSet dataSet = null;
+
+ connectionString =
+       "host=localhost;" +
+       "dbname=test;" +
+       "user=postgres";
+                                               
+ sqlQuery = "select * from pg_tables";
+
+ adapter = new SqlDataAdapter (sqlQuery, 
+                       connectionString);
+                               
+ dataSet = new DataSet ();
+
+ adapter.Fill (dataSet);
+                       
+ if (dataSet != null) {
+       foreach (DataRow row in dataSet.Tables["Table"].Rows)
+               Console.WriteLine("tablename: " + row["tablename"]);
+ }
+</pre> 
+       
+       <p>We do need help on the DataSet/DataAdaptor/DataTable/DataRelation/XML 
        functionality so we     can integrate with 
-       the ASP.NET controls and Windows.Forms.  
+       the ASP.NET controls and Windows.Forms controls by allowing the controls to bind 
+       to a data source.  Gonzalo, Gaurav, Leen, Patrik, Duncan, and others are 
+       working very hard on the ASP.NET support. If you want to help, 
+       contact <a href="mailto:gonzalo@ximian.com">Gonzalo Paniagua Javier</a>
        
-       <P>Need to add XML support in System.Data.
+       <P>Need to add XML support in System.Data.  This involves working on
+       the classes: DataSet and XmlDataDocument and the ExecuteXmlReader() in SqlCommand.
        
        <p>The System.Data.dll gets built with the rest of the class library.
        To compile the System.Data.dll assembly separately, you need:
                  compilation on Linux.
 
                * compile System.Data.dll:
-
-                       cd mcs/class/System.Data
-                       mcs --target library -o System.Data.dll @list
+<pre>
+ cd mcs/class/System.Data<br>
+ mcs --target library -o System.Data.dll @list
+</pre>
        </ul>
 
        <b>On Windows</b>
 
        <ul>
                * update your mono sources. Be sure you have latest mcs.exe
-                 and .dll's.  You can use the same method as Linux, or you can use NAnt.
+                 and .dll's.  You can use the same method as Linux, 
+                 or you can use NAnt.
 
                * To use NAnt:
 
-                       cd mcs/class/System.Data
-                       ../../nant/NAnt.exe
+<pre>
+ cd mcs/class/System.Data
+ ../../nant/NAnt.exe
+</pre>
                        
                        This will automatically copy the System.Data.dll to Test.
-                       If you need to do a clean for the System.Data.dll assembly,
-                       cd mcs/class/System.Data and run ../../nant/NAnt.exe clean
+                       If you need to do a clean for the System.Data.dll assembly,<br><br>
+
+<pre>                  
+ cd mcs/class/System.Data
+ ../../nant/NAnt.exe clean
+</pre>
        </ul>
 
 * Testing
        one locally.  PostgreSQL is the DBMS used for the initial 
        implementation of System.Data.SqlClient.
                
-       <p>Why?  Because it is open source, has a client 
-       library that is easy to use, PostgreSQL on Windows is easy to install on
+       <p>Why?  Because it is free software, has a client 
+       library that is easy to use, PostgreSQL is easy to install on
        Unix and Windows (using the Cygwin install program), not difficult to setup after
        installation, and it runs under: Linux, 
        Windows (via cygwin and ipc-daemon), Unix, and
  chown postgres /usr/local/pgsql/data\r
  su - postgres\r
  initdb -D /usr/local/pgsql/data\r
- postmaster -i -D /usr/local/pgsql/data >logfile 2>&1 &\r
+ postmaster -i -D /usr/local/pgsql/data\r
  createdb test\r
  psql test
 </pre>
@@ -214,12 +452,13 @@ create user postgres with password 'fun2db';
                
                * In the /usr/local/pgsql/data/pg_hba.conf file, you need
                to have the AUTH_TYPE set to md5.  You can read more on this at
-               /usr/doc/postgresql-7.2.1/html/client-authentication.html or wherever your
+               /usr/doc/postgresql-7.2.1/html/client-authentication.html 
+               or wherever your
                PostgreSQL html docs are located.  See the 2nd line below,
                host 127.0.0.1 has an AUTH_TYPE md5 in pg_hba.conf.
                
 <pre>
- # TYPE     DATABASE    IP_ADDRESS    MASK               AUTH_TYPE  AUTH_ARGUMENT
+ # TYPE     DATABASE    IP_ADDRESS    MASK               AUTH_TYPE
 
  local      all                                          trust
  host       all         127.0.0.1     255.255.255.255    md5
@@ -234,7 +473,8 @@ create user postgres with password 'fun2db';
        <b>On Windows</b>
 
        <ul>
-               * Use the <a href="http://www.cygwin.com/">Cygwin</a> installer to install the PostgreSQL DBMS.  It is
+               * Use the <a href="http://www.cygwin.com/">Cygwin</a> installer to 
+                 install the PostgreSQL DBMS.  It is
                  found in the database category.
                  
                * <p>Read the file postgres-x.x.README at /usr/doc/Cygwin and read 
@@ -274,7 +514,8 @@ PATH=c:\cygwin\usr\local\bin;c:\cygwin\usr\bin;c:\cygwin\bin;
 LD_LIBRARY_PATH=c:\cygwin\usr\local\lib;c:\cygwin\usr\lib;
 </pre>
                                                          
-                               <p><b>4.</b> Start the ipc-daemon that came with the cygipc package.  There
+                               <p><b>4.</b> Start the ipc-daemon that came with the cygipc 
+                               package.  There
                                are two ways to do this: run it from the command line as:
                          
                                <p>
@@ -312,14 +553,16 @@ net start ipc-daemon
 <pre>
 mkdir /usr/local/pgsql/data\r
 initdb -D /usr/local/pgsql/data\r
-postmaster -D /usr/local/pgsql/data >logfile 2>&1 &\r
+postmaster -D /usr/local/pgsql/data\r
 createdb test\r
 psql test              
 </pre>
                  
                        <p>When you need to connect to the database, 
                        you will need ipc-daemon and postmaster running.  Start ipc-daemon
-                       before any of the command above.  
+                       before any of the command above.  If you restart your computer, you
+                       need to start ipc-daemon and postmaster either manually or as a 
+                       service.
                  
                        <p>psql is a command-line PostgreSQL client tool to 
                        enter and run SQL commands and queries.
@@ -388,106 +631,169 @@ mint PostgresTest.exe
 mono PostgresTest.exe
 </pre>
     
-    <p>You should get something like:
+    <p>Below, I show how the output from PostgresTest.  I have omitted a lot
+    of the meta data for the columns except two columns.  The classes
+    used were from System.Data.SqlClient and were used to connect to a
+    PostgreSQL database and retrieve data.
 
 <p>
 <pre>   
- danmorg@DANPC ~/mono/mcs/class/System.Data/Test\r
- $ mcs PostgresTest.cs -r System.Data.dll\r
 \r
- danmorg@DANPC ~/mono/mcs/class/System.Data/Test\r
- $ mono PostgresTest.exe\r
-         Postgres provider specific tests...\r
+danmorg@DANPC ~/mono/mcs/class/System.Data/Test\r
+$ mcs PostgresTest.cs -r System.Data.dll\r
 \r
-                 Drop table:\r
- Error (don't worry about this one)SqlError:PGRES_FATAL_ERROR ERROR:  table "mono\r
- _postgres_test" does not exist\r
-  <Stack Trace>\r
+danmorg@DANPC ~/mono/mcs/class/System.Data/Test\r
+$ mono PostgresTest.exe\r
+        Postgres provider specific tests...\r
 \r
-                 Create table with all supported types:\r
- OK\r
-                 Insert values for all known types:\r
- OK\r
-                 Update values:\r
- OK\r
-                 Insert values for all known types:\r
- OK\r
- Aggregate: count(*)\r
- Agg Result: 2\r
- Aggregate: min(text_value)\r
- Agg Result: This is a text\r
- Aggregate: max(int4_value)\r
- Agg Result: 1048000\r
- Aggregate: sum(int4_value)\r
- Agg Result: 1048003\r
-                 Select values from the database:\r
-                 Get Schema.\r
- dt.Columns.Count: 12\r
- * Column Name: boolean_value\r
-          MaxLength: 1\r
-          Type: System.Boolean\r
- * Column Name: int2_value\r
-          MaxLength: 2\r
-          Type: System.Int16\r
- * Column Name: int4_value\r
-          MaxLength: 4\r
-          Type: System.Int32\r
- * Column Name: bigint_value\r
-          MaxLength: 8\r
-          Type: System.Int64\r
- * Column Name: float_value\r
-          MaxLength: 4\r
-          Type: System.Single\r
- * Column Name: double_value\r
-          MaxLength: 8\r
-          Type: System.Double\r
- * Column Name: char_value\r
-          MaxLength: -1\r
-          Type: System.String\r
- * Column Name: varchar_value\r
-          MaxLength: -1\r
-          Type: System.String\r
- * Column Name: text_value\r
-          MaxLength: -1\r
-          Type: System.String\r
- * Column Name: time_value\r
-          MaxLength: 8\r
-          Type: System.DateTime\r
- * Column Name: date_value\r
-          MaxLength: 4\r
-          Type: System.DateTime\r
- * Column Name: timestamp_value\r
-          MaxLength: 8\r
-          Type: System.DateTime\r
- Row 0:\r
-     Col 0: boolean_value: False\r
-     Col 1: int2_value: 5\r
-     Col 2: int4_value: 3\r
-     Col 3: bigint_value: 9\r
-     Col 4: float_value: 3.141590\r
-     Col 5: double_value: 3.141593\r
-     Col 6: char_value: Mono.Data!\r
-     Col 7: varchar_value: It was not me!\r
-     Col 8: text_value: We got data!\r
-     Col 9: time_value: Monday, 01 January 1 21:13:14\r
-     Col 10: date_value: Tuesday, 29 February 2000 00:00:00\r
-     Col 11: timestamp_value: Sunday, 29 February 2004 14:00:11\r
- Row 1:\r
-     Col 0: boolean_value: True\r
-     Col 1: int2_value: -22\r
-     Col 2: int4_value: 1048000\r
-     Col 3: bigint_value: 123456789012345\r
-     Col 4: float_value: 3.141590\r
-     Col 5: double_value: 3.141593\r
-     Col 6: char_value: This is a char\r
-     Col 7: varchar_value: This is a varchar\r
-     Col 8: text_value: This is a text\r
-     Col 9: time_value: Monday, 01 January 1 21:13:14\r
-     Col 10: date_value: Tuesday, 29 February 2000 00:00:00\r
-     Col 11: timestamp_value: Sunday, 29 February 2004 14:00:11\r
- Rows: 2\r
+                Drop table:\r
+Error (don't worry about this one)SqlError:PGRES_FATAL_ERROR ERROR:  table "mono\r
+_postgres_test" does not exist\r
+ <Stack Trace>\r
+\r
+                Create table with all supported types:\r
+OK\r
+                Insert values for all known types:\r
+OK\r
+                Update values:\r
+OK\r
+                Insert values for all known types:\r
+OK\r
+Aggregate: count(*)\r
+Agg Result: 2\r
+Aggregate: min(text_value)\r
+Agg Result: This is a text\r
+Aggregate: max(int4_value)\r
+Agg Result: 1048000\r
+Aggregate: sum(int4_value)\r
+Agg Result: 1048003\r
+                Select values from the database:\r
+Result is from a SELECT SQL Query.  Records Affected: -1\r
+Result Set 1...\r
+   Total Columns: 28\r
+ColumnName = boolean_value\r
+ColumnOrdinal = 1\r
+ColumnSize = 1\r
+NumericPrecision = 0\r
+NumericScale = 0\r
+IsUnique = False\r
+IsKey =\r
+BaseCatalogName =\r
+BaseColumnName = boolean_value\r
+BaseSchemaName =\r
+BaseTableName =\r
+DataType = System.Boolean\r
+AllowDBNull = False\r
+ProviderType = 16\r
+IsAliased = False\r
+IsExpression = False\r
+IsIdentity = False\r
+IsAutoIncrement = False\r
+IsRowVersion = False\r
+IsHidden = False\r
+IsLong = False\r
+IsReadOnly = False\r
+\r
+ ...\r
+\r
+ ColumnName = null_timestamp_value\r
+ ColumnOrdinal = 28\r
+ ColumnSize = 8\r
+ NumericPrecision = 0\r
+ NumericScale = 0\r
+ IsUnique = False\r
+ IsKey =\r
+ BaseCatalogName =\r
+ BaseColumnName = null_timestamp_value\r
+ BaseSchemaName =\r
+ BaseTableName =\r
+ DataType = System.DateTime\r
+ AllowDBNull = False\r
+ ProviderType = 1184\r
+ IsAliased = False\r
+ IsExpression = False\r
+ IsIdentity = False\r
+ IsAutoIncrement = False\r
+ IsRowVersion = False\r
+ IsHidden = False\r
+ IsLong = False\r
+ IsReadOnly = False\r
+\r
+ Gonna do a Read() now...\r
+   Row 0:\r
+    Col 0: boolean_value: False\r
+    Col 1: int2_value: 5\r
+    Col 2: int4_value: 3\r
+    Col 3: bigint_value: 9\r
+    Col 4: float_value: 3.141590\r
+    Col 5: double_value: 3.14159\r
+    Col 6: numeric_value: 123456789012.345\r
+    Col 7: char_value: Mono.Data!\r
+    Col 8: varchar_value: It was not me!\r
+    Col 9: text_value: We got data!\r
+    Col 10: point_value: (1,0)\r
+    Col 11: time_value: 01/01/1 21:13:14\r
+    Col 12: date_value: 02/29/2000 00:00:00\r
+    Col 13: timestamp_value: 02/29/2004 14:00:11\r
+    Col 14: null_boolean_value is NULL\r
+    Col 15: null_int2_value is NULL\r
+    Col 16: null_int4_value is NULL\r
+    Col 17: null_bigint_value is NULL\r
+    Col 18: null_float_value is NULL\r
+    Col 19: null_double_value is NULL\r
+    Col 20: null_numeric_value is NULL\r
+    Col 21: null_char_value is NULL\r
+    Col 22: null_varchar_value is NULL\r
+    Col 23: null_text_value is NULL\r
+    Col 24: null_point_value is NULL\r
+    Col 25: null_time_value is NULL\r
+    Col 26: null_date_value is NULL\r
+    Col 27: null_timestamp_value is NULL\r
+   Row 1:\r
+    Col 0: boolean_value: True\r
+    Col 1: int2_value: -22\r
+    Col 2: int4_value: 1048000\r
+    Col 3: bigint_value: 123456789012345\r
+    Col 4: float_value: 3.141590\r
+    Col 5: double_value: 3.14159\r
+    Col 6: numeric_value: 123456789012.345\r
+    Col 7: char_value: This is a char\r
+    Col 8: varchar_value: This is a varchar\r
+    Col 9: text_value: This is a text\r
+    Col 10: point_value: (1,0)\r
+    Col 11: time_value: 01/01/1 21:13:14\r
+    Col 12: date_value: 02/29/2000 00:00:00\r
+    Col 13: timestamp_value: 02/29/2004 14:00:11\r
+    Col 14: null_boolean_value is NULL\r
+    Col 15: null_int2_value is NULL\r
+    Col 16: null_int4_value is NULL\r
+    Col 17: null_bigint_value is NULL\r
+    Col 18: null_float_value is NULL\r
+    Col 19: null_double_value is NULL\r
+    Col 20: null_numeric_value is NULL\r
+    Col 21: null_char_value is NULL\r
+    Col 22: null_varchar_value is NULL\r
+    Col 23: null_text_value is NULL\r
+    Col 24: null_point_value is NULL\r
+    Col 25: null_time_value is NULL\r
+    Col 26: null_date_value is NULL\r
+    Col 27: null_timestamp_value is NULL\r
+   Total Rows Retrieved: 2\r
+ Total Result sets: 1\r
+                Call ExecuteReader with a SQL Command. (Not INSERT,UPDATE,DELETE\r
+ ).\r
+ Result is from a SQL Command not (INSERT,UPDATE,DELETE).   Records Affected: -1\r
+ Total Result sets: 0\r
+                Call ExecuteReader with a SQL Command. (Is INSERT,UPDATE,DELETE)\r
+ .\r
+ Result is from a SQL Command (INSERT,UPDATE,DELETE).  Records Affected: 1\r
+ Total Result sets: 0\r
+                Calling stored procedure version()\r
+ Result: PostgreSQL 7.2.1 on i686-pc-cygwin, compiled by GCC 2.95.3-5\r
+ Database Server Version: PostgreSQL 7.2.1 on i686-pc-cygwin, compiled by GCC 2.9\r
+ 5.3-5\r
  Clean up...\r
-                 Drop table...\r
+                Drop table...\r
  OK\r
  RESULT: 0\r
 \r