2002-11-13 Tim Coleman <tim@timcoleman.com>
[mono.git] / mcs / class / System.Data / Test / SqlTest.cs
1 /* SqlTest.cs - based on PostgresTest.cs
2  * 
3  * Copyright (C) 2002 Gonzalo Paniagua Javier
4  * Copyright (C) 2002 Daniel Morgan
5  * Copyright (C) 2002 Tim Coleman
6  *
7  * ORIGINAL AUTHOR:
8  *      Gonzalo Paniagua Javier <gonzalo@gnome-db.org>
9  * PORTING FROM C TO C# AUTHOR:
10  *      Daniel Morgan <danmorg@sc.rr.com>
11  * PORTING TO SQL SERVER AUTHOR:
12  *      Tim Coleman <tim@timcoleman.com>
13  *
14  * Permission was given from the original author, Gonzalo Paniagua Javier,
15  * to port and include his original work in Mono.
16  * 
17  * The original work falls under the LGPL, but the port to C# falls
18  * under the X11 license.
19  * 
20  * This program is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU General Public License as
22  * published by the Free Software Foundation; either version 2 of the
23  * License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
28  * Library General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public
31  * License along with this program; see the file COPYING.  If not,
32  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
33  * Boston, MA 02111-1307, USA.
34  */
35
36 using System;
37 using System.Data;
38 using System.Data.SqlClient;
39
40 namespace Test.Mono.Data.SqlClient {
41
42         class SqlTest {
43
44                 // execute SQL CREATE TABLE Command using ExecuteNonQuery()
45                 static void CreateTable (IDbConnection cnc) {
46                                                 
47                         IDbCommand createCommand = cnc.CreateCommand();
48         
49                         createCommand.CommandText = 
50                                 "create table mono_sql_test (" +
51                                 "boolean_value bit, " +
52                                 "byte_value tinyint, " +
53                                 "int2_value smallint, " +
54                                 "int4_value integer, " +
55                                 "float_value real, " + 
56                                 "double_value float, " +
57                                 "numeric_value decimal(15, 3), " +
58                                 "char_value char(50), " +
59                                 "nchar_value nchar(50), " +
60                                 "varchar_value varchar(20), " +
61                                 "nvarchar_value nvarchar(20), " +
62                                 "text_value text, " +
63                                 "ntext_value ntext, " +
64                                 "datetime_value datetime, " +
65                                 "null_boolean_value bit, " +
66                                 "null_byte_value tinyint, " +
67                                 "null_int2_value smallint, " +
68                                 "null_int4_value integer, " +
69                                 "null_float_value real, " + 
70                                 "null_double_value float, " +
71                                 "null_numeric_value decimal(15, 3), " +
72                                 "null_char_value char(50), " +
73                                 "null_nchar_value nchar(50), " +
74                                 "null_varchar_value varchar(20), " +
75                                 "null_nvarchar_value nvarchar(20), " +
76                                 "null_text_value text, " +
77                                 "null_ntext_value ntext, " +
78                                 "null_datetime_value datetime " +
79                                 ")";                    
80         
81                         createCommand.ExecuteNonQuery ();
82                 }
83
84                 // execute SQL DROP TABLE Command using ExecuteNonQuery
85                 static void DropTable (IDbConnection cnc) {
86                                  
87                         IDbCommand dropCommand = cnc.CreateCommand ();
88
89                         dropCommand.CommandText =
90                                 "drop table mono_sql_test";
91                                                         
92                         dropCommand.ExecuteNonQuery ();
93                 }
94
95                 // execute stored procedure using ExecuteScalar()
96                 static object CallStoredProcedure (IDbConnection cnc) {
97                                  
98                         IDbCommand callStoredProcCommand = cnc.CreateCommand ();
99                         object data;
100
101                         callStoredProcCommand.CommandType = 
102                                 CommandType.StoredProcedure;
103                         callStoredProcCommand.CommandText =
104                                 "sp_server_info";
105                                                         
106                         data = callStoredProcCommand.ExecuteScalar ();
107
108                         return data;
109                 }
110
111                 // execute SQL INSERT Command using ExecuteNonQuery()
112                 static void InsertData (IDbConnection cnc) {            
113
114                         IDbCommand insertCommand = cnc.CreateCommand();
115                 
116                         insertCommand.CommandText =
117                                 "insert into mono_sql_test (" +
118                                 "boolean_value, " +
119                                 "byte_value, " +
120                                 "int2_value, " +
121                                 "int4_value, " +
122                                 "float_value, " + 
123                                 "double_value, " +
124                                 "numeric_value, " +
125                                 "char_value, " +
126                                 "nchar_value, " +
127                                 "varchar_value, " +
128                                 "nvarchar_value, " +
129                                 "text_value, " +
130                                 "ntext_value, " +
131                                 "datetime_value " +
132                                 ") values (" +
133                                 "@p1, " +
134                                 "@p2, " +
135                                 "@p3, " +
136                                 "@p4, " +
137                                 "@p5, " +
138                                 "@p6, " +
139                                 "@p7, " +
140                                 "@p8, " +
141                                 "@p9, " +
142                                 "@p10, " +
143                                 "@p11, " +
144                                 "@p12, " +
145                                 "@p13, " +
146                                 "@p14 " +
147                                 ")";
148
149                         SqlParameterCollection parameters = ((SqlCommand) insertCommand).Parameters;
150
151                         parameters.Add ("@p1",  SqlDbType.Bit, 1);
152                         parameters.Add ("@p2",  SqlDbType.TinyInt, 1);
153                         parameters.Add ("@p3",  SqlDbType.SmallInt, 2);
154                         parameters.Add ("@p4",  SqlDbType.Int, 4);
155                         parameters.Add ("@p5",  SqlDbType.Real, 4);
156                         parameters.Add ("@p6",  SqlDbType.Float, 8);
157                         parameters.Add ("@p7",  SqlDbType.Decimal, 12);
158                         parameters.Add ("@p8",  SqlDbType.Char, 14);
159                         parameters.Add ("@p9",  SqlDbType.NChar, 16);
160                         parameters.Add ("@p10", SqlDbType.VarChar, 17);
161                         parameters.Add ("@p11", SqlDbType.NVarChar, 19);
162                         parameters.Add ("@p12", SqlDbType.Text, 14);
163                         parameters.Add ("@p13", SqlDbType.NText, 16);
164                         parameters.Add ("@p14", SqlDbType.DateTime, 4);
165
166                         parameters ["@p1"].Value = true;
167                         parameters ["@p2"].Value = 15;
168                         parameters ["@p3"].Value = -22;
169                         parameters ["@p4"].Value = 1048000;
170                         parameters ["@p5"].Value = 3.141592;
171                         parameters ["@p6"].Value = 3.1415926969696;
172                         parameters ["@p7"].Value = 123456789012.345;
173                         parameters ["@p7"].Precision = 15;
174                         parameters ["@p7"].Scale = 3;
175                         parameters ["@p8"].Value = "This is a char";
176                         parameters ["@p9"].Value = "This is an nchar";
177                         parameters ["@p10"].Value = "This is a varchar";
178                         parameters ["@p11"].Value = "This is an nvarchar";
179                         parameters ["@p12"].Value = "This is a text";
180                         parameters ["@p13"].Value = "This is an ntext";
181                         parameters ["@p14"].Value = DateTime.Now;
182
183                         insertCommand.ExecuteNonQuery ();
184                 }
185
186                 // execute a SQL SELECT Query using ExecuteReader() to retrieve
187                 // a IDataReader so we retrieve data
188                 static IDataReader SelectData (IDbConnection cnc) {
189         
190                         IDbCommand selectCommand = cnc.CreateCommand();
191                         IDataReader reader;
192
193                         // FIXME: System.Data classes need to handle NULLs
194                         //        this would be done by System.DBNull ?
195                         // FIXME: System.Data needs to handle more data types
196                         /*
197                         selectCommand.CommandText = 
198                                 "select * " +
199                                 "from mono_postgres_test";
200                         */
201
202                         selectCommand.CommandText = 
203                                 "select " +                             
204                                 "boolean_value, " +
205                                 "byte_value, " +
206                                 "int2_value, " +
207                                 "int4_value, " +
208                                 "float_value, " + 
209                                 "double_value, " +
210                                 "numeric_value, " +
211                                 "char_value, " +
212                                 "nchar_value, " +
213                                 "varchar_value, " +
214                                 "nvarchar_value, " +
215                                 "text_value, " +
216                                 "ntext_value, " +
217                                 "datetime_value, " +
218                                 "null_boolean_value, " +
219                                 "null_byte_value, " +
220                                 "null_int2_value, " +
221                                 "null_int4_value, " +
222                                 "null_float_value, " + 
223                                 "null_double_value, " +
224                                 "null_numeric_value, " +
225                                 "null_char_value, " +
226                                 "null_nchar_value, " +
227                                 "null_varchar_value, " +
228                                 "null_nvarchar_value, " +
229                                 "null_text_value, " +
230                                 "null_ntext_value, " +
231                                 "null_datetime_value " +
232                                 "from mono_sql_test";
233
234
235                         reader = selectCommand.ExecuteReader ();
236
237                         return reader;
238                 }
239
240                 // Tests a SQL Command (INSERT, UPDATE, DELETE)
241                 // executed via ExecuteReader
242                 static IDataReader SelectDataUsingInsertCommand (IDbConnection cnc) {
243         
244                         IDbCommand selectCommand = cnc.CreateCommand();
245                         IDataReader reader;
246
247                         // This is a SQL INSERT Command, not a Query
248                         selectCommand.CommandText =
249                                 "insert into mono_sql_test (" +
250                                 "boolean_value, " +
251                                 "byte_value, " +
252                                 "int2_value, " +
253                                 "int4_value, " +
254                                 "float_value, " + 
255                                 "double_value, " +
256                                 "numeric_value, " +
257                                 "char_value, " +
258                                 "nchar_value, " +
259                                 "varchar_value, " +
260                                 "nvarchar_value, " +
261                                 "text_value, " +
262                                 "ntext_value, " +
263                                 "datetime_value " +
264                                 ") values (" +
265                                 "@p1, " +
266                                 "@p2, " +
267                                 "@p3, " +
268                                 "@p4, " +
269                                 "@p5, " +
270                                 "@p6, " +
271                                 "@p7, " +
272                                 "@p8, " +
273                                 "@p9, " +
274                                 "@p10, " +
275                                 "@p11, " +
276                                 "@p12, " +
277                                 "@p13, " +
278                                 "@p14 " +
279                                 ")";
280
281                         SqlParameterCollection parameters = ((SqlCommand) selectCommand).Parameters;
282
283                         parameters.Add ("@p1",  SqlDbType.Bit, 1);
284                         parameters.Add ("@p2",  SqlDbType.TinyInt, 1);
285                         parameters.Add ("@p3",  SqlDbType.SmallInt, 2);
286                         parameters.Add ("@p4",  SqlDbType.Int, 4);
287                         parameters.Add ("@p5",  SqlDbType.Real, 4);
288                         parameters.Add ("@p6",  SqlDbType.Float, 8);
289                         parameters.Add ("@p7",  SqlDbType.Decimal, 12);
290                         parameters.Add ("@p8",  SqlDbType.Char, 14);
291                         parameters.Add ("@p9",  SqlDbType.NChar, 16);
292                         parameters.Add ("@p10", SqlDbType.VarChar, 17);
293                         parameters.Add ("@p11", SqlDbType.NVarChar, 19);
294                         parameters.Add ("@p12", SqlDbType.Text, 14);
295                         parameters.Add ("@p13", SqlDbType.NText, 16);
296                         parameters.Add ("@p14", SqlDbType.DateTime, 4);
297
298                         parameters ["@p1"].Value = true;
299                         parameters ["@p2"].Value = 15;
300                         parameters ["@p3"].Value = -22;
301                         parameters ["@p4"].Value = 1048000;
302                         parameters ["@p5"].Value = 3.141592;
303                         parameters ["@p6"].Value = 3.1415926969696;
304                         parameters ["@p7"].Value = 123456789012.345;
305                         parameters ["@p7"].Precision = 15;
306                         parameters ["@p7"].Scale = 3;
307                         parameters ["@p8"].Value = "This is a char";
308                         parameters ["@p9"].Value = "This is an nchar";
309                         parameters ["@p10"].Value = "This is a varchar";
310                         parameters ["@p11"].Value = "This is an nvarchar";
311                         parameters ["@p12"].Value = "This is a text";
312                         parameters ["@p13"].Value = "This is an ntext";
313                         parameters ["@p14"].Value = DateTime.Now;
314
315                         reader = selectCommand.ExecuteReader ();
316
317                         return reader;
318                 }
319
320                 // Tests a SQL Command not (INSERT, UPDATE, DELETE)
321                 // executed via ExecuteReader
322                 static IDataReader SelectDataUsingCommand (IDbConnection cnc) {
323         
324                         IDbCommand selectCommand = cnc.CreateCommand();
325                         IDataReader reader;
326
327                         // This is a SQL Command, not a Query
328                         selectCommand.CommandText = 
329                                 "SET FMTONLY OFF";
330
331                         reader = selectCommand.ExecuteReader ();
332
333                         return reader;
334                 }
335
336
337                 // execute an SQL UPDATE Command using ExecuteNonQuery()
338                 static void UpdateData (IDbConnection cnc) {
339         
340                         IDbCommand updateCommand = cnc.CreateCommand();         
341                 
342                         updateCommand.CommandText = 
343                                 "update mono_sql_test " +                               
344                                 "set " +
345                                 "boolean_value    = @p1, " +
346                                 "byte_value       = @p2, " +
347                                 "int2_value       = @p3, " +
348                                 "int4_value       = @p4, " +
349                                 "char_value       = @p5, " +
350                                 "nchar_value      = @p6, " +
351                                 "varchar_value    = @p7, " +
352                                 "nvarchar_value   = @p8, " +
353                                 "text_value       = @p9, " +
354                                 "ntext_value      = @p10 " +
355                                 "where int2_value = @p11";
356
357                         SqlParameterCollection parameters = ((SqlCommand) updateCommand).Parameters;
358
359                         parameters.Add ("@p1",  SqlDbType.Bit, 1);
360                         parameters.Add ("@p2",  SqlDbType.TinyInt, 1);
361                         parameters.Add ("@p3",  SqlDbType.SmallInt, 2);
362                         parameters.Add ("@p4",  SqlDbType.Int, 4);
363                         parameters.Add ("@p5",  SqlDbType.Char, 10);
364                         parameters.Add ("@p6",  SqlDbType.NChar, 10);
365                         parameters.Add ("@p7",  SqlDbType.VarChar, 14);
366                         parameters.Add ("@p8",  SqlDbType.NVarChar, 14);
367                         parameters.Add ("@p9",  SqlDbType.Text, 12);
368                         parameters.Add ("@p10", SqlDbType.NText, 12);
369                         parameters.Add ("@p11", SqlDbType.SmallInt, 2);
370
371                         parameters ["@p1"].Value = false;
372                         parameters ["@p2"].Value = 2;
373                         parameters ["@p3"].Value = 5;
374                         parameters ["@p4"].Value = 3;
375                         parameters ["@p5"].Value = "Mono.Data!";
376                         parameters ["@p6"].Value = "Mono.Data!";
377                         parameters ["@p7"].Value = "It was not me!";
378                         parameters ["@p8"].Value = "It was not me!";
379                         parameters ["@p9"].Value = "We got data!";
380                         parameters ["@p10"].Value = "We got data!";
381                         parameters ["@p11"].Value = -22;
382
383                         updateCommand.ExecuteNonQuery ();               
384                 }
385
386                 // used to do a min(), max(), count(), sum(), or avg()
387                 // execute SQL SELECT Query using ExecuteScalar
388                 static object SelectAggregate (IDbConnection cnc, String agg) {
389         
390                         IDbCommand selectCommand = cnc.CreateCommand();
391                         object data;
392
393                         Console.WriteLine("Aggregate: " + agg);
394
395                         selectCommand.CommandType = CommandType.Text;
396                         selectCommand.CommandText = 
397                                 "select " + agg +
398                                 "from mono_sql_test";
399
400                         data = selectCommand.ExecuteScalar ();
401
402                         Console.WriteLine("Agg Result: " + data);
403
404                         return data;
405                 }
406
407                 // used internally by ReadData() to read each result set
408                 static void ReadResult(IDataReader rdr, DataTable dt) {
409                                                 \r
410                         // number of columns in the table\r
411                         Console.WriteLine("   Total Columns: " +\r
412                                 dt.Rows.Count);\r
413 \r
414                         // display the schema\r
415                         foreach (DataRow schemaRow in dt.Rows) {\r
416                                 foreach (DataColumn schemaCol in dt.Columns)\r
417                                         Console.WriteLine(schemaCol.ColumnName + \r
418                                                 " = " + \r
419                                                 schemaRow[schemaCol]);\r
420                                 Console.WriteLine();\r
421                         }\r
422 \r
423                         int nRows = 0;\r
424                         int c = 0;\r
425                         string output, metadataValue, dataValue;\r
426                         // Read and display the rows\r
427                         Console.WriteLine("Gonna do a Read() now...");\r
428                         while(rdr.Read()) {\r
429                                 Console.WriteLine("   Row " + nRows + ": ");\r
430                                         \r
431                                 for(c = 0; c < rdr.FieldCount; c++) {\r
432                                         // column meta data \r
433                                         DataRow dr = dt.Rows[c];\r
434                                         metadataValue = \r
435                                                 "    Col " + \r
436                                                 c + ": " + \r
437                                                 dr["ColumnName"];\r
438                                                 \r
439                                         // column data\r
440                                         if(rdr.IsDBNull(c) == true)\r
441                                                 dataValue = " is NULL";\r
442                                         else\r
443                                                 dataValue = \r
444                                                         ": " + \r
445                                                         rdr.GetValue(c);\r
446                                         \r
447                                         // display column meta data and data\r
448                                         output = metadataValue + dataValue;                                     \r
449                                         Console.WriteLine(output);\r
450                                 }\r
451                                 nRows++;\r
452                         }\r
453                         Console.WriteLine("   Total Rows Retrieved: " + \r
454                                 nRows); 
455                 }
456
457                 // Used to read data from IDataReader after calling IDbCommand:ExecuteReader()
458                 static void ReadData(IDataReader rdr) {
459
460                         int results = 0;
461                         if(rdr == null) {
462                 
463                                 Console.WriteLine("IDataReader has a Null Reference.");
464                         }
465                         else {
466                                 do {\r
467                                         DataTable dt = rdr.GetSchemaTable();\r
468                                         if(rdr.RecordsAffected != -1) {\r
469                                                 // Results for \r
470                                                 // SQL INSERT, UPDATE, DELETE Commands \r
471                                                 // have RecordsAffected >= 0\r
472                                                 Console.WriteLine("Result is from a SQL Command (INSERT,UPDATE,DELETE).  Records Affected: " + rdr.RecordsAffected);\r
473                                         }\r
474                                         else if(dt == null)\r
475                                                 // Results for\r
476                                                 // SQL Commands not INSERT, UPDATE, nor DELETE\r
477                                                 // have RecordsAffected == -1\r
478                                                 // and GetSchemaTable() returns a null reference\r
479                                                 Console.WriteLine("Result is from a SQL Command not (INSERT,UPDATE,DELETE).   Records Affected: " + rdr.RecordsAffected);\r
480                                         else {\r
481                                                 // Results for\r
482                                                 // SQL SELECT Queries\r
483                                                 // have RecordsAffected = -1\r
484                                                 // and GetSchemaTable() returns a reference to a DataTable\r
485                                                 Console.WriteLine("Result is from a SELECT SQL Query.  Records Affected: " + rdr.RecordsAffected);\r
486                 \r
487                                                 results++;\r
488                                                 Console.WriteLine("Result Set " + results + "...");\r
489 \r
490                                                 ReadResult(rdr, dt);\r
491                                         }\r
492 \r
493                                 } while(rdr.NextResult());\r
494                                 Console.WriteLine("Total Result sets: " + results);\r
495                         \r
496                                 rdr.Close();
497                         }
498                 }
499                 
500                 /* Sql provider tests */
501                 static void DoSqlTest (IDbConnection cnc) {
502
503                         IDataReader reader;
504                         Object oDataValue;
505
506                         Console.WriteLine ("\tSql provider specific tests...\n");
507
508                         /* Drops the mono_sql_test table. */
509                         Console.WriteLine ("\t\tDrop table: ");
510                         try {
511                                 DropTable (cnc);
512                                 Console.WriteLine ("OK");
513                         }
514                         catch (SqlException e) {
515                                 Console.WriteLine("Error (don't worry about this one)" + e);
516                         }
517                         
518                         try {
519                                 /* Creates a table with all supported data types */
520                                 Console.WriteLine ("\t\tCreate table with all supported types: ");
521                                 CreateTable (cnc);
522                                 Console.WriteLine ("OK");
523                                 
524                                 /* Inserts values */
525                                 Console.WriteLine ("\t\tInsert values for all known types: ");
526                                 InsertData (cnc);
527                                 Console.WriteLine ("OK");
528
529                                 /* Update values */
530                                 Console.WriteLine ("\t\tUpdate values: ");
531                                 UpdateData (cnc);
532                                 Console.WriteLine ("OK");
533
534                                 /* Inserts values */
535                                 Console.WriteLine ("\t\tInsert values for all known types: ");
536                                 InsertData (cnc);
537                                 Console.WriteLine ("OK");                       
538
539                                 /* Select aggregates */
540                                 SelectAggregate (cnc, "count(*)");
541                                 // FIXME: still having a problem with avg()
542                                 //        because it returns a decimal.
543                                 //        It may have something to do
544                                 //        with culture not being set
545                                 //        properly.
546                                 //SelectAggregate (cnc, "avg(int4_value)");
547                                 SelectAggregate (cnc, "min(varchar_value)");
548                                 SelectAggregate (cnc, "max(int4_value)");
549                                 SelectAggregate (cnc, "sum(int4_value)");
550
551                                 /* Select values */
552                                 Console.WriteLine ("\t\tSelect values from the database: ");
553                                 reader = SelectData (cnc);
554                                 ReadData(reader);
555
556                                 /* SQL Command via ExecuteReader/SqlDataReader */
557                                 /* Command is not INSERT, UPDATE, or DELETE */
558                                 Console.WriteLine("\t\tCall ExecuteReader with a SQL Command. (Not INSERT,UPDATE,DELETE).");
559                                 reader = SelectDataUsingCommand(cnc);
560                                 ReadData(reader);
561
562                                 /* SQL Command via ExecuteReader/SqlDataReader */
563                                 /* Command is INSERT, UPDATE, or DELETE */
564                                 Console.WriteLine("\t\tCall ExecuteReader with a SQL Command. (Is INSERT,UPDATE,DELETE).");
565                                 reader = SelectDataUsingInsertCommand(cnc);
566                                 ReadData(reader);
567 \r
568                                 // Call a Stored Procedure named Version()\r
569                                 Console.WriteLine("\t\tCalling stored procedure sp_server_info()");\r
570                                 object obj = CallStoredProcedure(cnc);\r
571                                 Console.WriteLine("Result: " + obj);\r
572 \r
573                                 Console.WriteLine("Database Server Version: " + \r
574                                         ((SqlConnection)cnc).ServerVersion);\r
575 \r
576                                 /* Clean up */
577                                 Console.WriteLine ("Clean up...");
578                                 Console.WriteLine ("\t\tDrop table...");
579                                 DropTable (cnc);
580                                 Console.WriteLine("OK");
581                         }
582                         catch(Exception e) {
583                                 Console.WriteLine("Exception caught: " + e);
584                         }
585                 }
586
587                 [STAThread]\r
588                 static void Main(string[] args) {\r
589                         SqlConnection cnc = new SqlConnection ();\r
590 \r
591                         /*\r
592                         string connectionString = 
593                                 "host=hostname;" +
594                                 "dbname=database;" +
595                                 "user=userid;" +
596                                 "password=password";
597                         */\r
598 \r
599                         string connectionString = 
600                                 "Server=localhost;" + 
601                                 "Database=test;" +
602                                 "User ID=sql;" +
603                                 "Password=";
604 \r
605                         cnc.ConnectionString =  connectionString;\r
606 \r
607                         cnc.Open();\r
608                         DoSqlTest(cnc);
609                         cnc.Close();
610                 }
611         }
612 }