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