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