Added info about new advances
[mono.git] / doc / ado-net
1 * ADO.NET
2
3         The coordinator for the ADO.NET implementation is <a
4         href="mailto:rodrigo@ximian.com">Rodrigo Moya</a>, with
5         the collaboration of <a href="mailto:danmorg@sc.rr.com">Daniel
6         Morgan</a> and <a href="mailto:tim@timcoleman.com">Tim Coleman</a>.
7         
8
9 * Action plan
10
11         The current plan to implement ADO.NET is as follows:
12
13         <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:
14
15         <ul>
16                 * Initial implementation of System.Data.SqlClient is based on
17                   the <a href="http://www.postgresql.org/idocs/">PostgreSQL C API</a> which is a
18                   client API to the PostgreSQL DBMS.  PostgreSQL was chosen so we could quickly
19                   create and test the System.Data classes.
20                   
21                 * Once the <a href="http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemdatasqlclient.asp?frame=true">System.Data.SqlClient</a>
22                   code is functional and is usable by other people, we willl move it to
23                   Mono.Data.PostgreSQL, and will convert the existing
24                   System.Data.SqlClient to be just a wrapper around
25                   Mono.Data.PostgreSQL.  
26
27         </ul>
28
29         <b>Step 2:</b> <a href="http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemDataOleDb.asp?frame=true">System.Data.OleDb</a> Provider:
30                 
31         <ul>
32                 * <p>On Unix systems: System.Data.OleDb uses the
33                 <a href="http://www.gnome-db.org/">LibGDA</a>
34                  engine. 
35
36                   <p>LibGDA is a data access engine like ADO/OLE-DB, but for Unix.  The 
37                   GDA in libGDA stands for GNU/GNOME Data Access, but it does not require GNOME.
38                   It only requires glib2 and libxml2.  LibGDA is used by 
39                   libgnomedb, GNOME-DB, and gaSQL.
40                   
41                   <p>There is work under way to get libgda working under 
42                   Windows using Cygwin by the GNOME-DB developers.
43                   
44                   <p>LibGDA has providers for MySQL, PostgreSQL, XML, ODBC,
45                   Oracle, Interbase, Sybase/SQL server (via FreeTDS), IBM DB2,
46                   SQLite and MDB Tools
47                   (MS Access support).
48
49                 * On Windows systems: System.Data.OleDb will use libgda as well,
50                   if we can get it working, or OLE-DB as
51                   its engine.
52         </ul>
53
54         <b>Step 3:</b> <a href="http://msdn.microsoft.com/library/en-us/cpref/html/frlrfsystemdatasqlclient.asp?frame=true">System.Data.SqlClient</a> Provider:
55
56         <ul>
57                 * <p>System.Data.SqlClient will then become a managed
58                   provider for Microsoft SQL Server, both on Windows and
59                   Linux, to be compatible with applications written
60                   for the Microsoft .NET Development Framework.
61                   
62                   <p>Once Step 1 has been completed and the PostgreSQL
63                   provider support has been moved to its own place at 
64                   Mono.Data.PostgreSQL, we will use 
65                   <a href="http://www.freetds.org/">FreeTDS</a> as the basis
66                   for providing access to Microsoft SQL Server databases.
67                   
68                   <P>FreeTDS is a C API for Unix and Windows that implements 
69                   the TDS (Tabular Data Stream) protocol used in accessing 
70                   Microsoft SQL Server and Sybase databases.  A .NET Data Provider could be
71                   created for Sybase databases as well, but this would be put in Mono.Data.Sybase.
72         </ul>
73
74         <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:
75         
76         <ul>
77                 * We will create a .NET Managaed Provider for ODBC
78                   in System.Data.Odbc for those using ODBC.
79                   On Unix and Windows, <a href="http://www.unixodbc.org/">unixODBC</a> mabye used.
80                   iODBC is an alternative to using unixODBC.
81                   
82                   <p>unixODBC works on Unix and Windows.  Well, I have not actually 
83                   used it on Cygwin, but it does build and install without problems.  
84                   
85                   <p>unixODBC has providers for:
86                   Oracle, Microsoft SQL Server and Sybase via FreeTDS, 
87                   MySQL, PostgreSQL, Informix, IBM DB2 (Universal Database), 
88                   Interbase, miniSQL (mSQL), AdabasD, Empress, YARD SQL, and others.
89                   
90         </ul>
91
92         <b>Step 5:</b> Other System.Data providers:
93
94         <ul>
95                 * <p>The idea in Microsoft .NET System.Data is to have
96                   a managed provider for each supported DBMS.  System.Data.SqlClient
97                   for Microsoft SQL Server.  
98                   System.Data.OracleClient for Oracle 8i and 9i.
99
100                   <p>We will need to have Mono.Data.MySQL, Mono.Data.PostgreSQL,
101                   Mono.Data.DB2, and Mono.Data.miniSQL. Others,
102                   of course, are welcomed.
103                                   
104                   <p>System.Data has been designed so 
105                   non-database providers can be created too.              
106         </ul>
107         
108 * Current Status
109
110         <p>We are working on Steps 1, 2, and 5.  We have only just begun on
111         steps 2 and 5 though.  We still have tons and tons of stuff to do.
112         If you have any ideas, let us know.
113         
114         <p>For Step 1, the PostgreSQL is starting to come together - it 
115         still needs a lot of work.
116         
117         <p>For Step 2, Rodrigo Moya has been working on System.Data.OleDb which uses libgda
118         which is an OLE-DB/ADO data access for Unix.  The C-Sharp bindings to libgda
119         currently work - meaning they can compile, run, and you can connect to a
120         PostgreSQL database via libgda via the C-Sharp bindings to libgda.  Basic
121         functionality (execution of commands, data retrieval, transactions, etc) are
122         now working. Current focus is on filling up the missing pieces (Data adapters
123         mainly).
124         
125         <p>For Step 3, we need someone to start the FreeTDS .NET Data Provider so
126         we can have data access to Microsoft SQL Server and Sybase databases, or either
127         add the support in libgda.
128         
129         <p>For Step 4, we need someone to start the unixODBC .NET Data Provider, or add
130         the support in libgda.
131         
132         <p>For Step 5, we have just begun creating a Mono.Data .NET Provider - a MySQL
133         .NET Provider that uses the MySQL C Client Library.  This provider is 
134         found in Mono.Data.MySql.  We can currently connect and do a SQL INSERT and insert
135         a row into a MySQL database.  However, it currently only works on Cygwin because
136         the MySQL client library libmySQL.dll is different 
137         from the library on Linux libmysqlclient.dll.  Another problem, mysql thread functions
138         do not load for some reason.  Also, the provider only runs if you use "mint" (the Mono
139         runtime interpreter).  It does not work on "mono" (the Mono Just-In-Time compiler).
140         The C# Bindings to MySQL are thanks to Brad Meril.
141                 
142         <p>We are able to do simple CREATE TABLE, DROP TABLE, UPDATE, INSERT, and
143         DELETE SQL commands using the ExecuteNonQuery method in SqlCommand.  
144         
145         <p>We can execute multiple queries and do a NextResult() in SqlDataReader()
146         to get the next result set.  
147         
148         <p>We are also able to do simple aggregate functions, 
149         ie, count(), sum(), min(), and max() 
150         in a simple SELECT SQL query using the ExecuteScalar() now.  
151         
152         <p>We are also able to retrieve data with a simple SELECT SQL query 
153         using ExecuteReader() which returns a SqlDataReader.  We are able to
154         use GetSchemaTable() to get the meta data about the table columns.  
155         We are able     to Read() to get each row from the result set.  
156         
157         <p>Here is a sample of code that is based on PostgresTest.cs and
158         TestSqlDataReader.cs tests:
159 <pre>
160  
161  static void SelectData (IDbConnection cnc) {
162         
163         IDbCommand selectCommand = cnc.CreateCommand();
164         IDataReader reader;
165
166         selectCommand.CommandType = CommandType.Text;
167         selectCommand.CommandText = 
168                 "select * from pg_user;" + \r
169                 "select * from pg_tables;" + \r
170                 "select * from pg_database";\r
171
172         reader = selectCommand.ExecuteReader ();
173
174         do {\r
175                 // get the DataTable that holds\r
176                 // the schema\r
177                 DataTable dt = rdr.GetSchemaTable();\r
178 \r
179                 if(rdr.RecordsAffected != -1) {\r
180                         // Results for \r
181                         // SQL INSERT, UPDATE, DELETE Commands \r
182                         // have RecordsAffected >= 0\r
183                         Console.WriteLine("Result is from a SQL Command (INSERT,UPDATE,DELETE).  Records Affected: " + rdr.RecordsAffected);\r
184                 }\r
185                 else if (dt == null)\r
186                                 Console.WriteLine("Result is from a SQL Command not (INSERT,UPDATE,DELETE).   Records Affected: " + rdr.RecordsAffected);\r
187                 else {\r
188                         // Results for\r
189                         // SQL not INSERT, UPDATE, nor DELETE\r
190                         // have RecordsAffected = -1\r
191                         Console.WriteLine("Result is from a SQL SELECT Query.  Records Affected: " + rdr.RecordsAffected);\r
192                 \r
193                         // Results for a SQL Command (CREATE TABLE, SET, etc)\r
194                         // will have a null reference returned from GetSchemaTable()\r
195                         // \r
196                         // Results for a SQL SELECT Query\r
197                         // will have a DataTable returned from GetSchemaTable()\r
198 \r
199                         results++;\r
200                         Console.WriteLine("Result Set " + results + "...");\r
201                                                 \r
202                         // number of columns in the table\r
203                         Console.WriteLine("   Total Columns: " +\r
204                                 dt.Columns.Count);\r
205 \r
206                         // display the schema\r
207                         foreach (DataRow schemaRow in dt.Rows) {\r
208                                 foreach (DataColumn schemaCol in dt.Columns)\r
209                                         Console.WriteLine(schemaCol.ColumnName + \r
210                                                 " = " + \r
211                                                 schemaRow[schemaCol]);\r
212                                 Console.WriteLine();\r
213                         }\r
214 \r
215                         int nRows = 0;\r
216                         string output, metadataValue, dataValue;\r
217                         // Read and display the rows\r
218                         Console.WriteLine("Gonna do a Read() now...");\r
219                         while(rdr.Read()) {\r
220                                 Console.WriteLine("   Row " + nRows + ": ");\r
221                                         \r
222                                 for(c = 0; c < rdr.FieldCount; c++) {\r
223                                         // column meta data \r
224                                         DataRow dr = dt.Rows[c];\r
225                                         metadataValue = \r
226                                                 "    Col " + \r
227                                                 c + ": " + \r
228                                                 dr["ColumnName"];\r
229                                                 \r
230                                         // column data\r
231                                         if(rdr.IsDBNull(c) == true)\r
232                                                 dataValue = " is NULL";\r
233                                         else\r
234                                                 dataValue = \r
235                                                         ": " + \r
236                                                         rdr.GetValue(c);\r
237                                 \r
238                                         // display column meta data and data\r
239                                         output = metadataValue + dataValue;                                     \r
240                                         Console.WriteLine(output);\r
241                                 }\r
242                                 nRows++;\r
243                         }\r
244                         Console.WriteLine("   Total Rows: " + \r
245                                 nRows);\r
246                 }       \r
247         } while(rdr.NextResult());\r
248         Console.WriteLine("Total Result sets: " + results);\r
249                         \r
250         rdr.Close();\r
251  }
252
253 </pre>
254         
255         <p>We are able to get 
256         String data (char, character, text, varchar), Int16 (smallint),
257         Int32 (integer), Int64 (bigint), DateTime (time, date, timestamp),
258         Boolean (boolean), Single (float), and Double (double).
259         More data types will come later.  Note, the types that do work still 
260         need thorough testing.
261         
262         <p>Rows that are returned which contain columns that are NULL are handled now. 
263         The SqlDataReader method IsDBNull() needs to be called to determine 
264         if a field IS NULL before trying to read data from that field.
265         
266         <p>Calling PostgreSQL stored procedures works.  It does not work perfectly.  It may not
267         even work to specification - yet.  If you want to test it yourself, look at
268         TestSqlDataReader.cs or PostgresTest.cs in
269         mcs/class/System.Data/Test.  
270         
271         <p>Below, I have some sample code you can
272         use to call a PostgreSQL stored procedure named "version".  This stored
273         procedure returns a string containing the PostgreSQL server version.  Notice
274         the CommandType is StoredProcedure and the method ExecuteScalar() is called.
275         
276         <p>ExecuteScalar() is a lightweight method in class SqlCommand that only returns
277         one row and one column as one object - even if there is more than row or column.
278         
279 <pre>
280  static string GetDatabaseServerVersion (SqlConnection cnc) 
281  {                       
282         SqlCommand cmd = cnc.CreateCommand ();
283         string data;
284
285         cmd.CommandType = CommandType.StoredProcedure;
286         cmd.CommandText = "version";
287                                                         
288         data = (string) cmd.ExecuteScalar ();
289
290         return data;
291  }
292 </pre>
293                         
294         <p>We have the beginnings of Parameters support PostgreSQL.  Only
295         Input Parameters are currently supported.  Output, Input/Output,
296         and Return parameters still need to be done.
297         
298         <p>A lot of functionality in System.Data is missing, but the 
299         infrastructure is starting to come together.
300         
301         <p>A lot of Exceptions need to be thrown for various exceptions.  However,
302         SqlException, SqlErrorCollection, and SqlError have been partially
303         implemented.
304         
305         <p>Tim Coleman and Rodrigo Moya got the beginnings of the
306         SqlDataAdapter/DataSet/DataTable/DataRow to work.  Currently, 
307         the SqlDataAdapter can Fill() relational data into a DataTable in a DataSet.
308         See the test mcs/class/System.Data/Test/TestSqlDataAdapter.cs to see it in action.
309         Below, I show a snippets from the test:
310         
311 <pre>
312  string connectionString;
313  string sqlQuery;
314  SqlDataAdapter adapter;
315  DataSet dataSet = null;
316
317  connectionString =
318         "host=localhost;" +
319         "dbname=test;" +
320         "user=postgres";
321                                                 
322  sqlQuery = "select * from pg_tables";
323
324  adapter = new SqlDataAdapter (sqlQuery, 
325                         connectionString);
326                                 
327  dataSet = new DataSet ();
328
329  adapter.Fill (dataSet);
330                         
331  if (dataSet != null) {
332         foreach (DataRow row in dataSet.Tables["Table"].Rows)
333                 Console.WriteLine("tablename: " + row["tablename"]);
334  }
335 </pre>  
336         
337         <p>We do need help on the DataSet/DataAdaptor/DataTable/DataRelation/XML 
338         functionality so we     can integrate with 
339         the ASP.NET controls and Windows.Forms controls by allowing the controls to bind 
340         to a data source.  Gonzalo, Gaurav, Leen, Patrik, Duncan, and others are 
341         working very hard on the ASP.NET support. If you want to help, 
342         contact <a href="mailto:gonzalo@ximian.com">Gonzalo Paniagua Javier</a>
343         
344         <P>Need to add XML support in System.Data.  This involves working on
345         the classes: DataSet and XmlDataDocument and the ExecuteXmlReader() in SqlCommand.
346         
347         <p>The System.Data.dll gets built with the rest of the class library.
348         To compile the System.Data.dll assembly separately, you need:
349
350         <b>On Unix</b>
351
352         <ul>
353                 * update your mono sources. Be sure you have latest mcs.exe
354                   and .dll's, since there have been many fixes needed for
355                   compilation on Linux.
356
357                 * compile System.Data.dll:
358 <pre>
359  cd mcs/class/System.Data<br>
360  mcs --target library -o System.Data.dll @list
361 </pre>
362         </ul>
363
364         <b>On Windows</b>
365
366         <ul>
367                 * update your mono sources. Be sure you have latest mcs.exe
368                   and .dll's.  You can use the same method as Linux, 
369                   or you can use NAnt.
370
371                 * To use NAnt:
372
373 <pre>
374  cd mcs/class/System.Data
375  ../../nant/NAnt.exe
376 </pre>
377                         
378                         This will automatically copy the System.Data.dll to Test.
379                         If you need to do a clean for the System.Data.dll assembly,<br><br>
380
381 <pre>                   
382  cd mcs/class/System.Data
383  ../../nant/NAnt.exe clean
384 </pre>
385         </ul>
386
387 * Testing
388
389         <p>In order to test System.Data.SqlClient, you will need to have
390         access to a remote PostgreSQL DBMS, or you will have to install 
391         one locally.  PostgreSQL is the DBMS used for the initial 
392         implementation of System.Data.SqlClient.
393                 
394         <p>Why?  Because it is free software, has a client 
395         library that is easy to use, PostgreSQL is easy to install on
396         Unix and Windows (using the Cygwin install program), not difficult to setup after
397         installation, and it runs under: Linux, 
398         Windows (via cygwin and ipc-daemon), Unix, and
399         others.  This allowed us to create the
400         System.Data functionality in Mono much quicker.
401                 
402         <p>If you plan on using a remote PostgreSQL DBMS Server,
403         than you will need to have the PostgreSQL client software on your
404         local computer that includes libpq.so (pq.dll on Windows).
405         
406         <p>The System.Data tests use this connection string to connect
407         to the PostgreSQL database named "test" at host "localhost" as
408         user "postgres".
409
410 <pre>
411 "host=localhost;dbname=test;user=postgres"
412 </pre>
413                 
414         <p>Installation instructions for PostgreSQL DBMS:
415
416         <b>On Unix</b>
417
418         <ul>
419                 * Read the PostgreSQL Installation Instructions 
420                 at \usr\doc\postgresql-x.x.x\html\installation.html
421                 
422                 * Depending on your Unix system, 
423                 PostgreSQL maybe already installed, a database user 'postgres' created, 
424                 a linux user 'postgres' created and initdb ran.  Or maybe not.
425
426 <pre>
427  su\r
428  adduser postgres\r
429  mkdir /usr/local/pgsql/data\r
430  chown postgres /usr/local/pgsql/data\r
431  su - postgres\r
432  initdb -D /usr/local/pgsql/data\r
433  postmaster -i -D /usr/local/pgsql/data\r
434  createdb test\r
435  psql test
436 </pre>
437         
438                 * Make sure you have a database user named postgres.  It is best to install
439                 the PostgreSQL DBMS under linux user postgres.  When you run the postmaster,
440                 run it under the user postgres as well.  If this was not done, then you
441                 will need to create a user named postgres for the System.Data tests.
442
443                 * If you already installed PostgeSQL and you do not have a database
444                 user named postgres, then you can create user postgres using psql:
445                 
446 <pre>           
447 psql test
448 create user postgres with password 'fun2db';
449 </pre>
450                                 
451                 * The postmaster must be run with -i option.
452                 
453                 * In the /usr/local/pgsql/data/pg_hba.conf file, you need
454                 to have the AUTH_TYPE set to md5.  You can read more on this at
455                 /usr/doc/postgresql-7.2.1/html/client-authentication.html 
456                 or wherever your
457                 PostgreSQL html docs are located.  See the 2nd line below,
458                 host 127.0.0.1 has an AUTH_TYPE md5 in pg_hba.conf.
459                 
460 <pre>
461  # TYPE     DATABASE    IP_ADDRESS    MASK               AUTH_TYPE
462
463  local      all                                          trust
464  host       all         127.0.0.1     255.255.255.255    md5
465 </pre>
466
467         * If you can not find your PostgreSQL documentation locally or you 
468         did not install it, then you 
469         can get it <a href="http://www.postgresql.org/idocs/">here</a>.
470
471         </ul>
472
473         <b>On Windows</b>
474
475         <ul>
476                 * Use the <a href="http://www.cygwin.com/">Cygwin</a> installer to 
477                   install the PostgreSQL DBMS.  It is
478                   found in the database category.
479                   
480                 * <p>Read the file postgres-x.x.README at /usr/doc/Cygwin and read 
481                   the requirements to install PostgreSQL.  Those requirements
482                   are included with cygwin except cygipc.  A default installtion
483                   of cygwin does not install everything you will need, so on the 
484                   safe side, just include everything when installing cygwin.
485                 
486                 * <p>The -x.x in postgres-x.x is the version of your PostgreSQL DBMS.
487                 
488                 * <p>Once Cygwin has installed the PostgreSQL DBMS on your computer,
489                   read the file FAQ_MSWIN which is available 
490                   in /usr/doc/postgres-x.x 
491                                   
492                 * <p>Important notes from this file are:
493                   
494                   <ul>
495                                 <p><b>2.</b> - Install the latest <a href="http://www.neuro.gatech.edu/users/cwilson/cygutils/OBSOLETE/V1.1/cygipc/index.html">CygIPC</a> package.
496                                                   
497                                 <p>The cygipc package contains the ipc-daemon you will need 
498                                 to run before you can
499                                 run the PostgreSQL DBMS Server daemon (postmaster) or run
500                                 initdb which initializes the PostgreSQL database.
501                           
502                                 <p><b>3.</b>  The Cygwin bin directory has to be placed in 
503                                 the path before the Windows program directories, 
504                                 for example, C:\cygwin\bin 
505                           
506                                 <p><b>My own note.</b>  In the Windows control panel, I set
507                                 the environment variables PATH to my cygwin /usr/local/bin,
508                                 /usr/bin, and /bin.  I also set my LD_LIBRARY_PATH to 
509                                 /usr/local/lib and /usr/lib.  For example:
510                           
511                                 <p>
512 <pre>
513 PATH=c:\cygwin\usr\local\bin;c:\cygwin\usr\bin;c:\cygwin\bin;
514 LD_LIBRARY_PATH=c:\cygwin\usr\local\lib;c:\cygwin\usr\lib;
515 </pre>
516                                                           
517                                 <p><b>4.</b> Start the ipc-daemon that came with the cygipc 
518                                 package.  There
519                                 are two ways to do this: run it from the command line as:
520                           
521                                 <p>
522 <pre>
523 ipc-daemon &
524 </pre>                    
525                                 <p>or you can set it up as a Windows service.  See the 
526                                 file cygrunsrv.README at /usr/doc/Cygwin on how to do this
527                                 for ipc-daemon and postmaster.  Note the
528                                 troubleshooting section at the end of 
529                                 the cygrunsrv.README file.
530                           
531                                 <p>To install ipc-daemon as a service, 
532                                 you just have to run
533                           
534                                 <p>
535 <pre>
536 ipc-daemon --install-as-service' (--remove-as-service) 
537 </pre>
538                           
539                                 <p>and then run
540                           
541 <pre>
542 net start ipc-daemon
543 </pre>
544                         </ul>
545                           
546                         <p>Read the installation.html file 
547                         at /usr/doc/postgresql-x.x/html/installation.html
548                 
549                         <p>You will see in this file that you will need to 
550                         run the following commands:
551                   
552                         <p>
553 <pre>
554 mkdir /usr/local/pgsql/data\r
555 initdb -D /usr/local/pgsql/data\r
556 postmaster -D /usr/local/pgsql/data\r
557 createdb test\r
558 psql test               
559 </pre>
560                   
561                         <p>When you need to connect to the database, 
562                         you will need ipc-daemon and postmaster running.  Start ipc-daemon
563                         before any of the command above.  If you restart your computer, you
564                         need to start ipc-daemon and postmaster either manually or as a 
565                         service.
566                   
567                         <p>psql is a command-line PostgreSQL client tool to 
568                         enter and run SQL commands and queries.
569                   
570                         <p>If there is no database user named postgres, create a user named
571                         postgres with the following SQL command in the client tool psql:
572                   
573                         <p>
574 <pre>
575 psql test
576 create user postgres with password 'fun2db';
577 </pre>
578                         <p>The only reason I say this is so you can easily use the System.Data tests
579                         without having to change the database, userid, etc.
580         </ul>
581         
582         <p>In the path mcs/class/System.Data/Test
583         there is a PostgreSQL test program named
584         PostgreTest.cs.  Thanks goes to Gonzalo for creating the original
585         PostgreSQL test.
586         
587         <p>To use it to test System.Data, you
588         modify the file to your PostgreSQL database
589         connection requirements:
590
591         <p>
592         <ul>
593                 <li><b>dbname</b> database, ie., test</li>
594                 <li><b>host</b> hostname of the PostgreSQL DBMS Server to connect to, ie., localhost</li>
595                 <li><b>user</b> username, ie., someuser</li>
596                 <li><b>password</b> password, ie., mypass1234</li>
597         </ul>
598         
599         <p>The connection string is in OLE-DB connection string format.  Internally,
600         SqlConnection converts this to the PostgreSQL connection string format.
601         
602         <p>
603 <pre>
604     OLE-DB: "host=localhost;dbname=test;user=joe;password=smoe"
605 PostgreSQL: "host=localhost dbname=test user=joe password=smoe"
606 </pre>
607
608         <p>
609         Note that OLE-DB includes the semicolons while PostgreSQL's connection
610         string does not.
611
612         <p>
613     To compile the PostgresTest.cs program, do:
614     
615     <p>
616 <pre>
617 mcs PostgresTest.cs -r System.Data.dll
618 </pre>
619     
620     <p>
621     To run using mint, do:
622     
623     <p>
624 <pre>
625 mint PostgresTest.exe
626 </pre>
627     
628     <p>
629     To run using mono, do:
630 <pre>
631 mono PostgresTest.exe
632 </pre>
633     
634     <p>Below, I show how the output from PostgresTest.  I have omitted a lot
635     of the meta data for the columns except two columns.  The classes
636     used were from System.Data.SqlClient and were used to connect to a
637     PostgreSQL database and retrieve data.
638
639 <p>
640 <pre>   
641 \r
642 danmorg@DANPC ~/mono/mcs/class/System.Data/Test\r
643 $ mcs PostgresTest.cs -r System.Data.dll\r
644 \r
645 danmorg@DANPC ~/mono/mcs/class/System.Data/Test\r
646 $ mono PostgresTest.exe\r
647         Postgres provider specific tests...\r
648 \r
649                 Drop table:\r
650 Error (don't worry about this one)SqlError:PGRES_FATAL_ERROR ERROR:  table "mono\r
651 _postgres_test" does not exist\r
652  <Stack Trace>\r
653 \r
654                 Create table with all supported types:\r
655 OK\r
656                 Insert values for all known types:\r
657 OK\r
658                 Update values:\r
659 OK\r
660                 Insert values for all known types:\r
661 OK\r
662 Aggregate: count(*)\r
663 Agg Result: 2\r
664 Aggregate: min(text_value)\r
665 Agg Result: This is a text\r
666 Aggregate: max(int4_value)\r
667 Agg Result: 1048000\r
668 Aggregate: sum(int4_value)\r
669 Agg Result: 1048003\r
670                 Select values from the database:\r
671 Result is from a SELECT SQL Query.  Records Affected: -1\r
672 Result Set 1...\r
673    Total Columns: 28\r
674 ColumnName = boolean_value\r
675 ColumnOrdinal = 1\r
676 ColumnSize = 1\r
677 NumericPrecision = 0\r
678 NumericScale = 0\r
679 IsUnique = False\r
680 IsKey =\r
681 BaseCatalogName =\r
682 BaseColumnName = boolean_value\r
683 BaseSchemaName =\r
684 BaseTableName =\r
685 DataType = System.Boolean\r
686 AllowDBNull = False\r
687 ProviderType = 16\r
688 IsAliased = False\r
689 IsExpression = False\r
690 IsIdentity = False\r
691 IsAutoIncrement = False\r
692 IsRowVersion = False\r
693 IsHidden = False\r
694 IsLong = False\r
695 IsReadOnly = False\r
696 \r
697  ...\r
698 \r
699  ColumnName = null_timestamp_value\r
700  ColumnOrdinal = 28\r
701  ColumnSize = 8\r
702  NumericPrecision = 0\r
703  NumericScale = 0\r
704  IsUnique = False\r
705  IsKey =\r
706  BaseCatalogName =\r
707  BaseColumnName = null_timestamp_value\r
708  BaseSchemaName =\r
709  BaseTableName =\r
710  DataType = System.DateTime\r
711  AllowDBNull = False\r
712  ProviderType = 1184\r
713  IsAliased = False\r
714  IsExpression = False\r
715  IsIdentity = False\r
716  IsAutoIncrement = False\r
717  IsRowVersion = False\r
718  IsHidden = False\r
719  IsLong = False\r
720  IsReadOnly = False\r
721 \r
722  Gonna do a Read() now...\r
723    Row 0:\r
724     Col 0: boolean_value: False\r
725     Col 1: int2_value: 5\r
726     Col 2: int4_value: 3\r
727     Col 3: bigint_value: 9\r
728     Col 4: float_value: 3.141590\r
729     Col 5: double_value: 3.14159\r
730     Col 6: numeric_value: 123456789012.345\r
731     Col 7: char_value: Mono.Data!\r
732     Col 8: varchar_value: It was not me!\r
733     Col 9: text_value: We got data!\r
734     Col 10: point_value: (1,0)\r
735     Col 11: time_value: 01/01/1 21:13:14\r
736     Col 12: date_value: 02/29/2000 00:00:00\r
737     Col 13: timestamp_value: 02/29/2004 14:00:11\r
738     Col 14: null_boolean_value is NULL\r
739     Col 15: null_int2_value is NULL\r
740     Col 16: null_int4_value is NULL\r
741     Col 17: null_bigint_value is NULL\r
742     Col 18: null_float_value is NULL\r
743     Col 19: null_double_value is NULL\r
744     Col 20: null_numeric_value is NULL\r
745     Col 21: null_char_value is NULL\r
746     Col 22: null_varchar_value is NULL\r
747     Col 23: null_text_value is NULL\r
748     Col 24: null_point_value is NULL\r
749     Col 25: null_time_value is NULL\r
750     Col 26: null_date_value is NULL\r
751     Col 27: null_timestamp_value is NULL\r
752    Row 1:\r
753     Col 0: boolean_value: True\r
754     Col 1: int2_value: -22\r
755     Col 2: int4_value: 1048000\r
756     Col 3: bigint_value: 123456789012345\r
757     Col 4: float_value: 3.141590\r
758     Col 5: double_value: 3.14159\r
759     Col 6: numeric_value: 123456789012.345\r
760     Col 7: char_value: This is a char\r
761     Col 8: varchar_value: This is a varchar\r
762     Col 9: text_value: This is a text\r
763     Col 10: point_value: (1,0)\r
764     Col 11: time_value: 01/01/1 21:13:14\r
765     Col 12: date_value: 02/29/2000 00:00:00\r
766     Col 13: timestamp_value: 02/29/2004 14:00:11\r
767     Col 14: null_boolean_value is NULL\r
768     Col 15: null_int2_value is NULL\r
769     Col 16: null_int4_value is NULL\r
770     Col 17: null_bigint_value is NULL\r
771     Col 18: null_float_value is NULL\r
772     Col 19: null_double_value is NULL\r
773     Col 20: null_numeric_value is NULL\r
774     Col 21: null_char_value is NULL\r
775     Col 22: null_varchar_value is NULL\r
776     Col 23: null_text_value is NULL\r
777     Col 24: null_point_value is NULL\r
778     Col 25: null_time_value is NULL\r
779     Col 26: null_date_value is NULL\r
780     Col 27: null_timestamp_value is NULL\r
781    Total Rows Retrieved: 2\r
782  Total Result sets: 1\r
783                 Call ExecuteReader with a SQL Command. (Not INSERT,UPDATE,DELETE\r
784  ).\r
785  Result is from a SQL Command not (INSERT,UPDATE,DELETE).   Records Affected: -1\r
786  Total Result sets: 0\r
787                 Call ExecuteReader with a SQL Command. (Is INSERT,UPDATE,DELETE)\r
788  .\r
789  Result is from a SQL Command (INSERT,UPDATE,DELETE).  Records Affected: 1\r
790  Total Result sets: 0\r
791                 Calling stored procedure version()\r
792  Result: PostgreSQL 7.2.1 on i686-pc-cygwin, compiled by GCC 2.95.3-5\r
793  Database Server Version: PostgreSQL 7.2.1 on i686-pc-cygwin, compiled by GCC 2.9\r
794  5.3-5\r
795  Clean up...\r
796                 Drop table...\r
797  OK\r
798  RESULT: 0\r
799 \r
800 </pre>\r
801 \r