2007-06-06 Nagappan A <anagappan@novell.com>
[mono.git] / mcs / class / System.Data / System.Data.SqlClient / SqlConnection.cs
1 //
2 // System.Data.SqlClient.SqlConnection.cs
3 //
4 // Authors:
5 //   Rodrigo Moya (rodrigo@ximian.com)
6 //   Daniel Morgan (danmorg@sc.rr.com)
7 //   Tim Coleman (tim@timcoleman.com)
8 //   Phillip Jerkins (Phillip.Jerkins@morgankeegan.com)
9 //   Diego Caravana (diego@toth.it)
10 //
11 // Copyright (C) Ximian, Inc 2002
12 // Copyright (C) Daniel Morgan 2002, 2003
13 // Copyright (C) Tim Coleman, 2002, 2003
14 // Copyright (C) Phillip Jerkins, 2003
15 //
16
17 //
18 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
19 //
20 // Permission is hereby granted, free of charge, to any person obtaining
21 // a copy of this software and associated documentation files (the
22 // "Software"), to deal in the Software without restriction, including
23 // without limitation the rights to use, copy, modify, merge, publish,
24 // distribute, sublicense, and/or sell copies of the Software, and to
25 // permit persons to whom the Software is furnished to do so, subject to
26 // the following conditions:
27 // 
28 // The above copyright notice and this permission notice shall be
29 // included in all copies or substantial portions of the Software.
30 // 
31 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 //
39
40 using Mono.Data.Tds;
41 using Mono.Data.Tds.Protocol;
42 using System;
43 using System.Collections;
44 using System.Collections.Specialized;
45 using System.ComponentModel;
46 using System.Data;
47 using System.Data.Common;
48 using System.EnterpriseServices;
49 using System.Globalization;
50 using System.Net;
51 using System.Net.Sockets;
52 using System.Text;
53 using System.Xml;
54
55 namespace System.Data.SqlClient {
56         [DefaultEvent ("InfoMessage")]
57 #if NET_2_0
58         public sealed class SqlConnection : DbConnection, IDbConnection, ICloneable     
59 #else
60         public sealed class SqlConnection : Component, IDbConnection, ICloneable                        
61 #endif // NET_2_0
62         {
63                 #region Fields
64                 bool disposed = false;
65
66                 // The set of SQL connection pools
67                 static TdsConnectionPoolManager sqlConnectionPools = new TdsConnectionPoolManager (TdsVersion.tds70);
68
69                 // The current connection pool
70                 TdsConnectionPool pool;
71
72                 // The connection string that identifies this connection
73                 string connectionString = null;
74
75                 // The transaction object for the current transaction
76                 SqlTransaction transaction = null;
77
78                 // Connection parameters
79                 
80                 TdsConnectionParameters parms = new TdsConnectionParameters ();
81                 NameValueCollection connStringParameters = null;
82                 bool connectionReset;
83                 bool pooling;
84                 string dataSource;
85                 int connectionTimeout;
86                 int minPoolSize;
87                 int maxPoolSize;
88                 int packetSize;
89                 int port = 1433;
90                 bool fireInfoMessageEventOnUserErrors;
91                 bool statisticsEnabled;
92
93                 // The current state
94                 ConnectionState state = ConnectionState.Closed;
95
96                 SqlDataReader dataReader = null;
97                 XmlReader xmlReader = null;
98
99                 // The TDS object
100                 ITds tds;
101
102                 #endregion // Fields
103
104                 #region Constructors
105
106                 public SqlConnection () 
107                         : this (String.Empty)
108                 {
109                 }
110         
111                 public SqlConnection (string connectionString)
112                 {
113                         Init (connectionString);
114                 }
115
116                 private void Init (string connectionString)
117                 {
118                         connectionTimeout       = 15; // default timeout
119                         dataSource              = ""; // default datasource
120                         packetSize              = 8192; // default packetsize
121                         ConnectionString        = connectionString;
122                 }
123                 
124
125                 #endregion // Constructors
126
127                 #region Properties
128
129 #if !NET_2_0
130                 [DataSysDescription ("Information used to connect to a DataSource, such as 'Data Source=x;Initial Catalog=x;Integrated Security=SSPI'.")]
131 #endif
132                 [DefaultValue ("")]
133                 [EditorAttribute ("Microsoft.VSDesigner.Data.SQL.Design.SqlConnectionStringEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
134                 [RecommendedAsConfigurable (true)]      
135                 [RefreshProperties (RefreshProperties.All)]
136                 [MonoTODO("persist security info, encrypt, enlist and , attachdbfilename keyword not implemented")]
137                 public 
138 #if NET_2_0
139                 override
140 #endif // NET_2_0
141                 string ConnectionString {
142                         get { return connectionString; }
143                         set {
144                                 if (state == ConnectionState.Open)
145                                         throw new InvalidOperationException ("Not Allowed to change ConnectionString property while Connection state is OPEN");
146                                 SetConnectionString (value); 
147                         }
148                 }
149         
150 #if !NET_2_0
151                 [DataSysDescription ("Current connection timeout value, 'Connect Timeout=X' in the ConnectionString.")] 
152 #endif
153                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
154                 public 
155 #if NET_2_0
156                 override
157 #endif // NET_2_0
158                 
159                 int ConnectionTimeout {
160                         get { return connectionTimeout; }
161                 }
162
163 #if !NET_2_0
164                 [DataSysDescription ("Current SQL Server database, 'Initial Catalog=X' in the connection string.")]
165 #endif
166                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
167                 public 
168 #if NET_2_0
169                 override
170 #endif // NET_2_0
171                 string Database {
172                         get { 
173                                 if (State == ConnectionState.Open)
174                                         return tds.Database; 
175                                 return parms.Database ;
176                         }
177                 }
178                 
179                 internal SqlDataReader DataReader {
180                         get { return dataReader; }
181                         set { dataReader = value; }
182                 }
183
184 #if !NET_2_0
185                 [DataSysDescription ("Current SqlServer that the connection is opened to, 'Data Source=X' in the connection string. ")]
186 #else
187                 [Browsable(true)]
188 #endif
189                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
190                 public 
191 #if NET_2_0
192                 override
193 #endif // NET_2_0
194                 string DataSource {
195                         get { return dataSource; }
196                 }
197
198 #if !NET_2_0
199                 [DataSysDescription ("Network packet size, 'Packet Size=x' in the connection string.")]
200 #endif
201                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
202                 public int PacketSize {
203                         get {   
204                                 if (State == ConnectionState.Open) 
205                                         return ((Tds)tds).PacketSize ;
206                                 return packetSize; 
207                         }
208                 }
209
210                 [Browsable (false)]
211 #if !NET_2_0
212                 [DataSysDescription ("Version of the SQL Server accessed by the SqlConnection.")]
213 #endif
214                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
215                 public 
216 #if NET_2_0
217                 override
218 #endif // NET_2_0
219                 string ServerVersion {
220                         get { 
221                                 if (state == ConnectionState.Closed)
222                                         throw new InvalidOperationException ("Invalid Operation.The Connection is Closed");
223                                 else
224                                         return tds.ServerVersion; 
225                         }
226                 }
227
228                 [Browsable (false)]
229 #if !NET_2_0
230                 [DataSysDescription ("The ConnectionState indicating whether the connection is open or closed.")]
231 #endif
232                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
233                 public 
234 #if NET_2_0
235                 override
236 #endif // NET_2_0
237                 ConnectionState State {
238                         get { return state; }
239                 }
240
241                 internal ITds Tds {
242                         get { return tds; }
243                 }
244
245                 internal SqlTransaction Transaction {
246                         get { return transaction; }
247                         set { transaction = value; }
248                 }
249
250 #if !NET_2_0
251                 [DataSysDescription ("Workstation Id, 'Workstation ID=x' in the connection string.")]
252 #endif
253                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
254                 public string WorkstationId {
255                         get { return parms.Hostname; }
256                 }
257
258                 internal XmlReader XmlReader {
259                         get { return xmlReader; }
260                         set { xmlReader = value; }
261                 }
262
263 #if NET_2_0
264                 public bool FireInfoMessageEventOnUserErrors { 
265                         get { return fireInfoMessageEventOnUserErrors; } 
266                         set { fireInfoMessageEventOnUserErrors = value; }
267                 }
268                 
269                 [DefaultValue (false)]
270                 public bool StatisticsEnabled { 
271                         get { return statisticsEnabled; } 
272                         set { statisticsEnabled = value; }
273                 }
274 #endif
275                 #endregion // Properties
276
277                 #region Events
278
279 #if !NET_2_0
280                 [DataSysDescription ("Event triggered when messages arrive from the DataSource.")]
281 #endif
282                 public event SqlInfoMessageEventHandler InfoMessage;
283
284 #if !NET_2_0
285                 [DataSysDescription ("Event triggered when the connection changes state.")]
286                 public 
287 #endif // NET_2_0
288                 new event StateChangeEventHandler StateChange;
289
290                 #endregion // Events
291
292                 #region Delegates
293
294                 private void ErrorHandler (object sender, TdsInternalErrorMessageEventArgs e)
295                 {
296                         throw new SqlException (e.Class, e.LineNumber, e.Message, e.Number, e.Procedure, e.Server, "Mono SqlClient Data Provider", e.State);
297                 }
298
299                 private void MessageHandler (object sender, TdsInternalInfoMessageEventArgs e)
300                 {
301                         OnSqlInfoMessage (CreateSqlInfoMessageEvent (e.Errors));
302                 }
303
304                 #endregion // Delegates
305
306                 #region Methods
307                 
308                 internal string GetConnStringKeyValue (params string [] keys)
309                 {
310                         if (connStringParameters == null || connStringParameters.Count == 0)
311                                 return "";
312                         foreach (string key in keys) {
313                                 string value = connStringParameters [key];
314                                 if (value != null)
315                                         return value;
316                         }
317                         
318                         return "";
319                 }
320                 
321
322                 public new SqlTransaction BeginTransaction ()
323                 {
324                         return BeginTransaction (IsolationLevel.ReadCommitted, String.Empty);
325                 }
326
327                 public new SqlTransaction BeginTransaction (IsolationLevel iso)
328                 {
329                         return BeginTransaction (iso, String.Empty);
330                 }
331
332                 public SqlTransaction BeginTransaction (string transactionName)
333                 {
334                         return BeginTransaction (IsolationLevel.ReadCommitted, transactionName);
335                 }
336
337                 public SqlTransaction BeginTransaction (IsolationLevel iso, string transactionName)
338                 {
339                         if (state == ConnectionState.Closed)
340                                 throw new InvalidOperationException ("The connection is not open.");
341                         if (transaction != null)
342                                 throw new InvalidOperationException ("SqlConnection does not support parallel transactions.");
343
344                         if (iso == IsolationLevel.Chaos)
345                                 throw new ArgumentException ("Invalid IsolationLevel parameter: must be ReadCommitted, ReadUncommitted, RepeatableRead, or Serializable.");
346
347                         string isolevel = String.Empty;
348                         switch (iso) {
349                         case IsolationLevel.ReadCommitted:
350                                 isolevel = "READ COMMITTED";
351                                 break;
352                         case IsolationLevel.ReadUncommitted:
353                                 isolevel = "READ UNCOMMITTED";
354                                 break;
355                         case IsolationLevel.RepeatableRead:
356                                 isolevel = "REPEATABLE READ";
357                                 break;
358                         case IsolationLevel.Serializable:
359                                 isolevel = "SERIALIZABLE";
360                                 break;
361                         }
362
363                         tds.Execute (String.Format ("SET TRANSACTION ISOLATION LEVEL {0};BEGIN TRANSACTION {1}", isolevel, transactionName));
364                         
365                         transaction = new SqlTransaction (this, iso);
366                         return transaction;
367                 }
368
369                 public 
370 #if NET_2_0
371                 override
372 #endif // NET_2_0
373          void ChangeDatabase (string database) 
374                 {
375                         if (!IsValidDatabaseName (database))
376                                 throw new ArgumentException (String.Format ("The database name {0} is not valid.", database));
377                         if (state != ConnectionState.Open)
378                                 throw new InvalidOperationException ("The connection is not open.");
379                         tds.Execute (String.Format ("use [{0}]", database));
380                 }
381
382                 private void ChangeState (ConnectionState currentState)
383                 {
384                         ConnectionState originalState = state;
385                         state = currentState;
386                         OnStateChange (CreateStateChangeEvent (originalState, currentState));
387                 }
388
389                 public 
390 #if NET_2_0
391                 override
392 #endif // NET_2_0
393                 void Close () 
394                 {
395                         if (transaction != null && transaction.IsOpen)
396                                 transaction.Rollback ();
397
398                         if (dataReader != null || xmlReader != null) {
399                                 if(tds != null) tds.SkipToEnd ();
400                                 dataReader = null;
401                                 xmlReader = null;
402                         }
403
404                         if (pooling) {
405                                 if(pool != null) pool.ReleaseConnection (tds);
406                         }else
407                                 if(tds != null) tds.Disconnect ();
408
409                         if(tds != null) {
410                                 tds.TdsErrorMessage -= new TdsInternalErrorMessageEventHandler (ErrorHandler);
411                                 tds.TdsInfoMessage -= new TdsInternalInfoMessageEventHandler (MessageHandler);
412                         }
413
414                         ChangeState (ConnectionState.Closed);
415                 }
416
417                 public new SqlCommand CreateCommand () 
418                 {
419                         SqlCommand command = new SqlCommand ();
420                         command.Connection = this;
421                         return command;
422                 }
423                 
424                 private SqlInfoMessageEventArgs CreateSqlInfoMessageEvent (TdsInternalErrorCollection errors)
425                 {
426                         return new SqlInfoMessageEventArgs (errors);
427                 }
428
429                 private StateChangeEventArgs CreateStateChangeEvent (ConnectionState originalState, ConnectionState currentState)
430                 {
431                         return new StateChangeEventArgs (originalState, currentState);
432                 }
433
434                 protected override void Dispose (bool disposing) 
435                 {
436                         if (disposed)
437                                 return;
438
439                         try {
440                                 if (disposing) {
441                                         if (State == ConnectionState.Open) 
442                                                 Close ();
443                                         ConnectionString = "";
444                                         SetDefaultConnectionParameters (this.connStringParameters); 
445                                 }
446                         } finally {
447                                 disposed = true;
448                                 base.Dispose (disposing);
449                         }
450                 }
451
452                 [MonoTODO ("Not sure what this means at present.")]
453                 public 
454                 void EnlistDistributedTransaction (ITransaction transaction)
455                 {
456                         throw new NotImplementedException ();
457                 }
458
459                 object ICloneable.Clone ()
460                 {
461                         return new SqlConnection (ConnectionString);
462                 }
463
464                 IDbTransaction IDbConnection.BeginTransaction ()
465                 {
466                         return BeginTransaction ();
467                 }
468
469                 IDbTransaction IDbConnection.BeginTransaction (IsolationLevel iso)
470                 {
471                         return BeginTransaction (iso);
472                 }
473 #if NET_2_0
474                 protected override DbTransaction BeginDbTransaction (IsolationLevel level)
475                 {
476                         return (DbTransaction)BeginTransaction (level);
477                 }
478
479                 protected override DbCommand CreateDbCommand ()
480                 {
481                         return CreateCommand ();
482                 }
483 #endif
484
485                 IDbCommand IDbConnection.CreateCommand ()
486                 {
487                         return CreateCommand ();
488                 }
489
490                 void IDisposable.Dispose ()
491                 {
492                         Dispose (true);
493                         GC.SuppressFinalize (this);
494                 }
495
496                 public 
497 #if NET_2_0
498                 override
499 #endif // NET_2_0
500                 void Open () 
501                 {
502                         string serverName = "";
503                         if (state == ConnectionState.Open)
504                                 throw new InvalidOperationException ("The Connection is already Open (State=Open)");
505
506                         if (connectionString == null || connectionString.Trim().Length == 0)
507                                 throw new InvalidOperationException ("Connection string has not been initialized.");
508
509                         try {
510                                 if (!pooling) {
511                                         if(!ParseDataSource (dataSource, out port, out serverName))
512                                                 throw new SqlException(20, 0, "SQL Server does not exist or access denied.",  17, "ConnectionOpen (Connect()).", dataSource, parms.ApplicationName, 0);
513                                         tds = new Tds70 (serverName, port, PacketSize, ConnectionTimeout);
514                                 }
515                                 else {
516                                         if(!ParseDataSource (dataSource, out port, out serverName))
517                                                 throw new SqlException(20, 0, "SQL Server does not exist or access denied.",  17, "ConnectionOpen (Connect()).", dataSource, parms.ApplicationName, 0);
518                                         
519                                         TdsConnectionInfo info = new TdsConnectionInfo (serverName, port, packetSize, ConnectionTimeout, minPoolSize, maxPoolSize);
520                                         pool = sqlConnectionPools.GetConnectionPool (connectionString, info);
521                                         tds = pool.GetConnection ();
522                                 }
523                         } catch (TdsTimeoutException e) {
524                                 throw SqlException.FromTdsInternalException ((TdsInternalException) e);
525                         }catch (TdsInternalException e) {
526                                 throw SqlException.FromTdsInternalException (e);
527                         }
528
529                         tds.TdsErrorMessage += new TdsInternalErrorMessageEventHandler (ErrorHandler);
530                         tds.TdsInfoMessage += new TdsInternalInfoMessageEventHandler (MessageHandler);
531
532                         if (!tds.IsConnected) {
533                                 try {
534                                         tds.Connect (parms);
535                                 }
536                                 catch {
537                                         if (pooling)
538                                                 pool.ReleaseConnection (tds);
539                                         throw;
540                                 }
541                         } else if (connectionReset) {
542                                 tds.Reset ();
543                         }
544
545                         disposed = false; // reset this, so using () would call Close ().
546                         ChangeState (ConnectionState.Open);
547                 }
548
549                 private bool ParseDataSource (string theDataSource, out int thePort, out string theServerName) 
550                 {
551                         theServerName = "";
552                         string theInstanceName = "";
553         
554                         if (theDataSource == null)
555                                 throw new ArgumentException("Format of initialization string does not conform to specifications");
556
557                         thePort = 1433; // default TCP port for SQL Server
558                         bool success = true;
559
560                         int idx = 0;
561                         if ((idx = theDataSource.IndexOf (",")) > -1) {
562                                 theServerName = theDataSource.Substring (0, idx);
563                                 string p = theDataSource.Substring (idx + 1);
564                                 thePort = Int32.Parse (p);
565                         }
566                         else if ((idx = theDataSource.IndexOf ("\\")) > -1) {
567                                 theServerName = theDataSource.Substring (0, idx);
568                                 theInstanceName = theDataSource.Substring (idx + 1);
569                                 // do port discovery via UDP port 1434
570                                 port = DiscoverTcpPortViaSqlMonitor (theServerName, theInstanceName);
571                                 if (port == -1)
572                                         success = false;
573                         }
574                         else if (theDataSource == "" || theDataSource == "(local)")
575                                 theServerName = "localhost";
576                         else
577                                 theServerName = theDataSource;
578
579                         return success;
580                 }
581
582                 private bool ConvertIntegratedSecurity (string value)
583                 {
584                         if (value.ToUpper() == "SSPI") 
585                         {
586                                 return true;
587                         }
588
589                         return ConvertToBoolean("integrated security", value);
590                 }
591
592                 private bool ConvertToBoolean(string key, string value)
593                 {
594                         string upperValue = value.ToUpper();
595
596                         if (upperValue == "TRUE" ||upperValue == "YES")
597                         {
598                                 return true;
599                         } 
600                         else if (upperValue == "FALSE" || upperValue == "NO")
601                         {
602                                 return false;
603                         }
604
605                         throw new ArgumentException(string.Format(CultureInfo.InvariantCulture,
606                                 "Invalid value \"{0}\" for key '{1}'.", value, key));
607                 }
608
609                 private int ConvertToInt32(string key, string value)
610                 {
611                         try
612                         {
613                                 return int.Parse(value);
614                         }
615                         catch (Exception ex)
616                         {
617                                 throw new ArgumentException(string.Format(CultureInfo.InvariantCulture,
618                                         "Invalid value \"{0}\" for key '{1}'.", value, key));
619                         }
620                 }
621
622                 private int DiscoverTcpPortViaSqlMonitor(string ServerName, string InstanceName) 
623                 {
624                         SqlMonitorSocket msock;
625                         msock = new SqlMonitorSocket (ServerName, InstanceName);
626                         int SqlServerPort = msock.DiscoverTcpPort ();
627                         msock = null;
628                         return SqlServerPort;
629                 }
630         
631                 void SetConnectionString (string connectionString)
632                 {
633                         NameValueCollection parameters = new NameValueCollection ();
634                         SetDefaultConnectionParameters (parameters);
635
636                         if ((connectionString == null) || (connectionString.Trim().Length == 0)) {
637                                 this.connectionString = connectionString;
638                                 this.connStringParameters = parameters;
639                                 return;
640                         }
641
642                         connectionString += ";";
643
644                         bool inQuote = false;
645                         bool inDQuote = false;
646                         bool inName = true;
647
648                         string name = String.Empty;
649                         string value = String.Empty;
650                         StringBuilder sb = new StringBuilder ();
651
652                         for (int i = 0; i < connectionString.Length; i += 1) {
653                                 char c = connectionString [i];
654                                 char peek;
655                                 if (i == connectionString.Length - 1)
656                                         peek = '\0';
657                                 else
658                                         peek = connectionString [i + 1];
659
660                                 switch (c) {
661                                 case '\'':
662                                         if (inDQuote)
663                                                 sb.Append (c);
664                                         else if (peek.Equals (c)) {
665                                                 sb.Append (c);
666                                                 i += 1;
667                                         }
668                                         else
669                                                 inQuote = !inQuote;
670                                         break;
671                                 case '"':
672                                         if (inQuote)
673                                                 sb.Append (c);
674                                         else if (peek.Equals (c)) {
675                                                 sb.Append (c);
676                                                 i += 1;
677                                         }
678                                         else
679                                                 inDQuote = !inDQuote;
680                                         break;
681                                 case ';':
682                                         if (inDQuote || inQuote)
683                                                 sb.Append (c);
684                                         else {
685                                                 if (name != String.Empty && name != null) {
686                                                         value = sb.ToString ();
687                                                         SetProperties (name.ToUpper ().Trim() , value);
688                                                         parameters [name.ToUpper ().Trim ()] = value.Trim ();
689                                                 }
690                                                 else if (sb.Length != 0)
691                                                         throw new ArgumentException ("Format of initialization string does not conform to specifications");
692                                                 inName = true;
693                                                 name = String.Empty;
694                                                 value = String.Empty;
695                                                 sb = new StringBuilder ();
696                                         }
697                                         break;
698                                 case '=':
699                                         if (inDQuote || inQuote || !inName)
700                                                 sb.Append (c);
701                                         else if (peek.Equals (c)) {
702                                                 sb.Append (c);
703                                                 i += 1;
704
705                                         }
706                                         else {
707                                                 name = sb.ToString ();
708                                                 sb = new StringBuilder ();
709                                                 inName = false;
710                                         }
711                                         break;
712                                 case ' ':
713                                         if (inQuote || inDQuote)
714                                                 sb.Append (c);
715                                         else if (sb.Length > 0 && !peek.Equals (';'))
716                                                 sb.Append (c);
717                                         break;
718                                 default:
719                                         sb.Append (c);
720                                         break;
721                                 }
722                         }
723
724                         connectionString = connectionString.Substring (0 , connectionString.Length-1);
725                         this.connectionString = connectionString;
726                         this.connStringParameters = parameters;
727                 }
728
729                 void SetDefaultConnectionParameters (NameValueCollection parameters)
730                 {
731                         parms.Reset ();
732                         dataSource = "";
733                         connectionTimeout= 15;
734                         connectionReset = true;
735                         pooling = true;
736                         maxPoolSize = 100; 
737                         minPoolSize = 0;
738                         packetSize = 8192; 
739                         
740                         parameters["APPLICATION NAME"] = "Mono SqlClient Data Provider";
741                         parameters["CONNECT TIMEOUT"] = "15";
742                         parameters["CONNECTION LIFETIME"] = "0";
743                         parameters["CONNECTION RESET"] = "true";
744                         parameters["ENLIST"] = "true";
745                         parameters["INTEGRATED SECURITY"] = "false";
746                         parameters["INITIAL CATALOG"] = "";
747                         parameters["MAX POOL SIZE"] = "100";
748                         parameters["MIN POOL SIZE"] = "0";
749                         parameters["NETWORK LIBRARY"] = "dbmssocn";
750                         parameters["PACKET SIZE"] = "8192";
751                         parameters["PERSIST SECURITY INFO"] = "false";
752                         parameters["POOLING"] = "true";
753                         parameters["WORKSTATION ID"] = Dns.GetHostName();
754  #if NET_2_0
755                         async = false;
756                         parameters ["ASYNCHRONOUS PROCESSING"] = "false";
757  #endif
758                 }
759                 
760                 private void SetProperties (string name , string value)
761                 {
762
763                         switch (name) 
764                         {
765                         case "APP" :
766                         case "APPLICATION NAME" :
767                                 parms.ApplicationName = value;
768                                 break;
769                         case "ATTACHDBFILENAME" :
770                         case "EXTENDED PROPERTIES" :
771                         case "INITIAL FILE NAME" :
772                                 parms.AttachDBFileName = value;
773                                 break;
774                         case "TIMEOUT" :
775                         case "CONNECT TIMEOUT" :
776                         case "CONNECTION TIMEOUT" :
777                                 int tmpTimeout = ConvertToInt32 ("connection timeout", value);
778                                 if (tmpTimeout < 0)
779                                         throw new ArgumentException ("Invalid CONNECTION TIMEOUT .. Must be an integer >=0 ");
780                                 else 
781                                         connectionTimeout = tmpTimeout;
782                                 break;
783                         case "CONNECTION LIFETIME" :
784                                 break;
785                         case "CONNECTION RESET" :
786                                 connectionReset = ConvertToBoolean ("connection reset", value);
787                                 break;
788                         case "LANGUAGE" :
789                         case "CURRENT LANGUAGE" :
790                                 parms.Language = value;
791                                 break;
792                         case "DATA SOURCE" :
793                         case "SERVER" :
794                         case "ADDRESS" :
795                         case "ADDR" :
796                         case "NETWORK ADDRESS" :
797                                 dataSource = value;
798                                 break;
799                         case "ENCRYPT":
800                                 if (ConvertToBoolean("encrypt", value))
801                                 {
802                                         throw new NotImplementedException("SSL encryption for"
803                                                 + " data sent between client and server is not"
804                                                 + " implemented.");
805                                 }
806                                 break;
807                         case "ENLIST" :
808                                 if (!ConvertToBoolean("enlist", value))
809                                 {
810                                         throw new NotImplementedException("Disabling the automatic"
811                                                 + " enlistment of connections in the thread's current"
812                                                 + " transaction context is not implemented.");
813                                 }
814                                 break;
815                         case "INITIAL CATALOG" :
816                         case "DATABASE" :
817                                 parms.Database = value;
818                                 break;
819                         case "INTEGRATED SECURITY" :
820                         case "TRUSTED_CONNECTION" :
821                                 parms.DomainLogin = ConvertIntegratedSecurity(value);
822                                 break;
823                         case "MAX POOL SIZE" :
824                                 int tmpMaxPoolSize = ConvertToInt32 ("max pool size" , value);
825                                 if (tmpMaxPoolSize < 0)
826                                         throw new ArgumentException ("Invalid MAX POOL SIZE. Must be a intger >= 0");
827                                 else
828                                         maxPoolSize = tmpMaxPoolSize; 
829                                 break;
830                         case "MIN POOL SIZE" :
831                                 int tmpMinPoolSize = ConvertToInt32 ("min pool size" , value);
832                                 if (tmpMinPoolSize < 0)
833                                         throw new ArgumentException ("Invalid MIN POOL SIZE. Must be a intger >= 0");
834                                 else
835                                         minPoolSize = tmpMinPoolSize;
836                                 break;
837 #if NET_2_0     
838                         case "MULTIPLEACTIVERESULTSETS":
839                                 break;
840                         case "ASYNCHRONOUS PROCESSING" :
841                         case "ASYNC" :
842                                 async = ConvertToBoolean (name, value);
843                                 break;
844 #endif  
845                         case "NET" :
846                         case "NETWORK" :
847                         case "NETWORK LIBRARY" :
848                                 if (!value.ToUpper ().Equals ("DBMSSOCN"))
849                                         throw new ArgumentException ("Unsupported network library.");
850                                 break;
851                         case "PACKET SIZE" :
852                                 int tmpPacketSize = ConvertToInt32 ("packet size", value);
853                                 if (tmpPacketSize < 512 || tmpPacketSize > 32767)
854                                         throw new ArgumentException ("Invalid PACKET SIZE. The integer must be between 512 and 32767");
855                                 else
856                                         packetSize = tmpPacketSize;
857                                 break;
858                         case "PASSWORD" :
859                         case "PWD" :
860                                 parms.Password = value;
861                                 break;
862                         case "PERSISTSECURITYINFO" :
863                         case "PERSIST SECURITY INFO" :
864                                 // FIXME : not implemented
865                                 // throw new NotImplementedException ();
866                                 break;
867                         case "POOLING" :
868                                 pooling = ConvertToBoolean("pooling", value);
869                                 break;
870                         case "UID" :
871                         case "USER" :
872                         case "USER ID" :
873                                 parms.User = value;
874                                 break;
875                         case "WSID" :
876                         case "WORKSTATION ID" :
877                                 parms.Hostname = value;
878                                 break;
879                         default :
880                                 throw new ArgumentException("Keyword not supported :"+name);
881                         }
882                 }
883
884                 static bool IsValidDatabaseName (string database)
885                 {
886                         if ( database == null || database.Trim() == String.Empty || database.Length > 128)
887                                 return false ;
888                         
889                         if (database[0] == '"' && database[database.Length] == '"')
890                                 database = database.Substring (1, database.Length - 2);
891                         else if (Char.IsDigit (database[0]))
892                                 return false;
893
894                         if (database[0] == '_')
895                                 return false;
896
897                         foreach (char c  in database.Substring (1, database.Length - 1))
898                                 if (!Char.IsLetterOrDigit (c) && c != '_' && c != '-')
899                                         return false;
900                         return true;
901                 }
902
903                 private void OnSqlInfoMessage (SqlInfoMessageEventArgs value)
904                 {
905                         if (InfoMessage != null)
906                                 InfoMessage (this, value);
907                 }
908
909                 private new void OnStateChange (StateChangeEventArgs value)
910                 {
911                         if (StateChange != null)
912                                 StateChange (this, value);
913                 }
914
915                 private sealed class SqlMonitorSocket : UdpClient 
916                 {
917                         // UDP port that the SQL Monitor listens
918                         private static readonly int SqlMonitorUdpPort = 1434;
919                         //private static readonly string SqlServerNotExist = "SQL Server does not exist or access denied";
920
921                         private string server;
922                         private string instance;
923
924                         internal SqlMonitorSocket (string ServerName, string InstanceName) 
925                                 : base (ServerName, SqlMonitorUdpPort) 
926                         {
927                                 server = ServerName;
928                                 instance = InstanceName;
929                         }
930
931                         internal int DiscoverTcpPort () 
932                         {
933                                 int SqlServerTcpPort;
934                                 Client.Blocking = false;
935                                 // send command to UDP 1434 (SQL Monitor) to get
936                                 // the TCP port to connect to the MS SQL server         
937                                 ASCIIEncoding enc = new ASCIIEncoding ();
938                                 Byte[] rawrq = new Byte [instance.Length + 1];
939                                 rawrq[0] = 4;
940                                 enc.GetBytes (instance, 0, instance.Length, rawrq, 1);
941                                 int bytes = Send (rawrq, rawrq.Length);
942
943                                 if (!Active)
944                                         return -1; // Error
945                                 
946                                 bool result;
947                                 result = Client.Poll (100, SelectMode.SelectRead);
948                                 if (result == false)
949                                         return -1; // Error
950
951                                 if (Client.Available <= 0)
952                                         return -1; // Error
953
954                                 IPEndPoint endpoint = new IPEndPoint (Dns.GetHostByName ("localhost").AddressList [0], 0);
955                                 Byte [] rawrs;
956
957                                 rawrs = Receive (ref endpoint);
958
959                                 string rs = Encoding.ASCII.GetString (rawrs);
960
961                                 string[] rawtokens = rs.Split (';');
962                                 Hashtable data = new Hashtable ();
963                                 for (int i = 0; i < rawtokens.Length / 2 && i < 256; i++) {
964                                         data [rawtokens [i * 2]] = rawtokens [ i * 2 + 1];
965                                 }
966                                 if (!data.ContainsKey ("tcp")) 
967                                         throw new NotImplementedException ("Only TCP/IP is supported.");
968
969                                 SqlServerTcpPort = int.Parse ((string) data ["tcp"]);
970                                 Close ();
971
972                                 return SqlServerTcpPort;
973                         }
974                 }
975
976 #if NET_2_0
977                 struct ColumnInfo {
978                         public string name;
979                         public Type type;
980                         public ColumnInfo (string name, Type type)
981                         {
982                                 this.name = name; this.type = type;
983                         }
984                 }
985
986                 static class ReservedWords
987                 {
988                         static readonly string [] reservedWords =
989                         {
990                                 "ADD", "EXCEPT", "PERCENT", "ALL", "EXEC", "PLAN", "ALTER",
991                                   "EXECUTE", "PRECISION", "AND", "EXISTS", "PRIMARY", "ANY",
992                                   "EXIT", "PRINT", "AS", "FETCH", "PROC", "ASC", "FILE",
993                                   "PROCEDURE", "AUTHORIZATION", "FILLFACTOR", "PUBLIC",
994                                   "BACKUP", "FOR", "RAISERROR", "BEGIN", "FOREIGN", "READ",
995                                   "BETWEEN", "FREETEXT", "READTEXT", "BREAK", "FREETEXTTABLE",
996                                   "RECONFIGURE", "BROWSE", "FROM", "REFERENCES", "BULK",
997                                   "FULL", "REPLICATION", "BY", "FUNCTION", "RESTORE",
998                                   "CASCADE", "GOTO", "RESTRICT", "CASE", "GRANT", "RETURN",
999                                   "CHECK", "GROUP", "REVOKE", "CHECKPOINT", "HAVING", "RIGHT",
1000                                   "CLOSE", "HOLDLOCK", "ROLLBACK", "CLUSTERED", "IDENTITY",
1001                                   "ROWCOUNT", "COALESCE", "IDENTITY_INSERT", "ROWGUIDCOL",
1002                                   "COLLATE", "IDENTITYCOL", "RULE", "COLUMN", "IF", "SAVE",
1003                                   "COMMIT", "IN", "SCHEMA", "COMPUTE", "INDEX", "SELECT",
1004                                   "CONSTRAINT", "INNER", "SESSION_USER", "CONTAINS", "INSERT",
1005                                   "SET", "CONTAINSTABLE", "INTERSECT", "SETUSER", "CONTINUE",
1006                                   "INTO", "SHUTDOWN", "CONVERT", "IS", "SOME", "CREATE",
1007                                   "JOIN", "STATISTICS", "CROSS", "KEY", "SYSTEM_USER",
1008                                   "CURRENT", "KILL", "TABLE", "CURRENT_DATE", "LEFT",
1009                                   "TEXTSIZE", "CURRENT_TIME", "LIKE", "THEN",
1010                                   "CURRENT_TIMESTAMP", "LINENO", "TO", "CURRENT_USER", "LOAD",
1011                                   "TOP", "CURSOR", "NATIONAL", "TRAN", "DATABASE", "NOCHECK",
1012                                   "TRANSACTION", "DBCC", "NONCLUSTERED", "TRIGGER",
1013                                   "DEALLOCATE", "NOT", "TRUNCATE", "DECLARE", "NULL",
1014                                   "TSEQUAL", "DEFAULT", "NULLIF", "UNION", "DELETE", "OF",
1015                                   "UNIQUE", "DENY", "OFF", "UPDATE", "DESC", "OFFSETS",
1016                                   "UPDATETEXT", "DISK", "ON", "USE", "DISTINCT", "OPEN",
1017                                   "USER", "DISTRIBUTED", "OPENDATASOURCE", "VALUES", "DOUBLE",
1018                                   "OPENQUERY", "VARYING", "DROP", "OPENROWSET", "VIEW",
1019                                   "DUMMY", "OPENXML", "WAITFOR", "DUMP", "OPTION", "WHEN",
1020                                   "ELSE", "OR", "WHERE", "END", "ORDER", "WHILE", "ERRLVL",
1021                                   "OUTER", "WITH", "ESCAPE", "OVER", "WRITETEXT", "ABSOLUTE",
1022                                   "FOUND", "PRESERVE", "ACTION", "FREE", "PRIOR", "ADMIN",
1023                                   "GENERAL", "PRIVILEGES", "AFTER", "GET", "READS",
1024                                   "AGGREGATE", "GLOBAL", "REAL", "ALIAS", "GO", "RECURSIVE",
1025                                   "ALLOCATE", "GROUPING", "REF", "ARE", "HOST", "REFERENCING",
1026                                   "ARRAY", "HOUR", "RELATIVE", "ASSERTION", "IGNORE", "RESULT",
1027                                   "AT", "IMMEDIATE", "RETURNS", "BEFORE", "INDICATOR", "ROLE",
1028                                   "BINARY", "INITIALIZE", "ROLLUP", "BIT", "INITIALLY",
1029                                   "ROUTINE", "BLOB", "INOUT", "ROW", "BOOLEAN", "INPUT",
1030                                   "ROWS", "BOTH", "INT", "SAVEPOINT", "BREADTH", "INTEGER",
1031                                   "SCROLL", "CALL", "INTERVAL", "SCOPE", "CASCADED",
1032                                   "ISOLATION", "SEARCH", "CAST", "ITERATE", "SECOND",
1033                                   "CATALOG", "LANGUAGE", "SECTION", "CHAR", "LARGE",
1034                                   "SEQUENCE", "CHARACTER", "LAST", "SESSION", "CLASS",
1035                                   "LATERAL", "SETS", "CLOB", "LEADING", "SIZE", "COLLATION",
1036                                   "LESS", "SMALLINT", "COMPLETION", "LEVEL", "SPACE",
1037                                   "CONNECT", "LIMIT", "SPECIFIC", "CONNECTION", "LOCAL",
1038                                   "SPECIFICTYPE", "CONSTRAINTS", "LOCALTIME", "SQL",
1039                                   "CONSTRUCTOR", "LOCALTIMESTAMP", "SQLEXCEPTION",
1040                                   "CORRESPONDING", "LOCATOR", "SQLSTATE", "CUBE", "MAP",
1041                                   "SQLWARNING", "CURRENT_PATH", "MATCH", "START",
1042                                   "CURRENT_ROLE", "MINUTE", "STATE", "CYCLE", "MODIFIES",
1043                                   "STATEMENT", "DATA", "MODIFY", "STATIC", "DATE", "MODULE",
1044                                   "STRUCTURE", "DAY", "MONTH", "TEMPORARY", "DEC", "NAMES",
1045                                   "TERMINATE", "DECIMAL", "NATURAL", "THAN", "DEFERRABLE",
1046                                   "NCHAR", "TIME", "DEFERRED", "NCLOB", "TIMESTAMP", "DEPTH",
1047                                   "NEW", "TIMEZONE_HOUR", "DEREF", "NEXT", "TIMEZONE_MINUTE",
1048                                   "DESCRIBE", "NO", "TRAILING", "DESCRIPTOR", "NONE",
1049                                   "TRANSLATION", "DESTROY", "NUMERIC", "TREAT", "DESTRUCTOR",
1050                                   "OBJECT", "TRUE", "DETERMINISTIC", "OLD", "UNDER",
1051                                   "DICTIONARY", "ONLY", "UNKNOWN", "DIAGNOSTICS", "OPERATION",
1052                                   "UNNEST", "DISCONNECT", "ORDINALITY", "USAGE", "DOMAIN",
1053                                   "OUT", "USING", "DYNAMIC", "OUTPUT", "VALUE", "EACH",
1054                                   "PAD", "VARCHAR", "END-EXEC", "PARAMETER", "VARIABLE",
1055                                   "EQUALS", "PARAMETERS", "WHENEVER", "EVERY", "PARTIAL",
1056                                   "WITHOUT", "EXCEPTION", "PATH", "WORK", "EXTERNAL",
1057                                   "POSTFIX", "WRITE", "FALSE", "PREFIX", "YEAR", "FIRST",
1058                                   "PREORDER", "ZONE", "FLOAT", "PREPARE", "ADA", "AVG",
1059                                   "BIT_LENGTH", "CHAR_LENGTH", "CHARACTER_LENGTH", "COUNT",
1060                                   "EXTRACT", "FORTRAN", "INCLUDE", "INSENSITIVE", "LOWER",
1061                                   "MAX", "MIN", "OCTET_LENGTH", "OVERLAPS", "PASCAL",
1062                                   "POSITION", "SQLCA", "SQLCODE", "SQLERROR", "SUBSTRING",
1063                                   "SUM", "TRANSLATE", "TRIM", "UPPER"
1064                         };
1065                         static DataTable instance;
1066                         static public DataTable Instance {
1067                                 get {
1068                                         if (instance == null) {
1069                                                 DataRow row = null;
1070                                                 instance = new DataTable ("ReservedWords");
1071                                                 instance.Columns.Add ("ReservedWord", typeof(string));
1072                                                 foreach (string reservedWord in reservedWords)
1073                                                 {
1074                                                         row = instance.NewRow();
1075
1076                                                         row["ReservedWord"] = reservedWord;
1077                                                         instance.Rows.Add(row);
1078                                                 }
1079                                         }
1080                                         return instance;
1081                                 }
1082                         }
1083                 }
1084
1085                 static class MetaDataCollections
1086                 {
1087                         static readonly ColumnInfo [] columns = {
1088                                 new ColumnInfo ("CollectionName", typeof (string)),
1089                                 new ColumnInfo ("NumberOfRestrictions", typeof (int)),
1090                                 new ColumnInfo ("NumberOfIdentifierParts", typeof (int))
1091                         };
1092
1093                         static readonly object [][] rows = {
1094                                 new object [] {"MetaDataCollections", 0, 0},
1095                                 new object [] {"DataSourceInformation", 0, 0},
1096                                 new object [] {"DataTypes", 0, 0},
1097                                 new object [] {"Restrictions", 0, 0},
1098                                 new object [] {"ReservedWords", 0, 0},
1099                                 new object [] {"Users", 1, 1},
1100                                 new object [] {"Databases", 1, 1},
1101                                 new object [] {"Tables", 4, 3},
1102                                 new object [] {"Columns", 4, 4},
1103                                 new object [] {"Views", 3, 3},
1104                                 new object [] {"ViewColumns", 4, 4},
1105                                 new object [] {"ProcedureParameters", 4, 1},
1106                                 new object [] {"Procedures", 4, 3},
1107                                 new object [] {"ForeignKeys", 4, 3},
1108                                 new object [] {"IndexColumns", 5, 4},
1109                                 new object [] {"Indexes", 4, 3},
1110                                 new object [] {"UserDefinedTypes", 2, 1}
1111                         };
1112
1113                         static DataTable instance;
1114                         static public DataTable Instance {
1115                                 get {
1116                                         if (instance == null) {
1117                                                 instance = new DataTable ("GetSchema");
1118                                                 foreach (ColumnInfo c in columns)
1119                                                         instance.Columns.Add (c.name, c.type);
1120                                                 foreach (object [] row in rows)
1121                                                         instance.LoadDataRow (row, true);
1122                                         }
1123                                         return instance;
1124                                 }
1125                         }
1126                 }
1127
1128                 static class DataTypes
1129                 {
1130                         static readonly ColumnInfo [] columns = {
1131                                 new ColumnInfo ("TypeName", typeof(string)),
1132                                 new ColumnInfo ("ProviderDbType", typeof(int)),
1133                                 new ColumnInfo ("ColumnSize", typeof(long)),
1134                                 new ColumnInfo ("CreateFormat", typeof(string)),
1135                                 new ColumnInfo ("CreateParameters", typeof(string)),
1136                                 new ColumnInfo ("DataType", typeof(string)),
1137                                 new ColumnInfo ("IsAutoIncrementable", typeof(bool)),
1138                                 new ColumnInfo ("IsBestMatch", typeof(bool)),
1139                                 new ColumnInfo ("IsCaseSensitive", typeof(bool)),
1140                                 new ColumnInfo ("IsFixedLength", typeof(bool)),
1141                                 new ColumnInfo ("IsFixedPrecisionScale", typeof(bool)),
1142                                 new ColumnInfo ("IsLong", typeof(bool)),
1143                                 new ColumnInfo ("IsNullable", typeof(bool)),
1144                                 new ColumnInfo ("IsSearchable", typeof(bool)),
1145                                 new ColumnInfo ("IsSearchableWithLike", typeof(bool)),
1146                                 new ColumnInfo ("IsUnsigned", typeof(bool)),
1147                                 new ColumnInfo ("MaximumScale", typeof(short)),
1148                                 new ColumnInfo ("MinimumScale", typeof(short)),
1149                                 new ColumnInfo ("IsConcurrencyType", typeof(bool)),
1150                                 new ColumnInfo ("IsLiteralSupported", typeof(bool)),
1151                                 new ColumnInfo ("LiteralPrefix", typeof(string)),
1152                                 new ColumnInfo ("LiteralSuffix", typeof(string))
1153                         };
1154
1155                         static readonly object [][] rows = {
1156                                 new object [] {"smallint", 16, 5, "smallint", null, "System.Int16", true, true,
1157                                                false, true, true, false, true, true, false, false, null,
1158                                                null, false, null, null, null},
1159                                 new object [] {"int", 8, 10, "int", null, "System.Int32",
1160                                                true, true, false, true, true, false, true, true, false,
1161                                                false, null, null, false, null, null, null},
1162                                 new object [] {"real", 13, 7, "real", null,
1163                                                "System.Single", false, true, false, true, false, false,
1164                                                true, true, false, false, null, null, false, null, null, null},
1165                                 new object [] {"float", 6, 53, "float({0})",
1166                                                "number of bits used to store the mantissa", "System.Double",
1167                                                false, true, false, true, false, false, true, true,
1168                                                false, false, null, null, false, null, null, null},
1169                                 new object [] {"money", 9, 19, "money", null,
1170                                                "System.Decimal", false, false, false, true, true,
1171                                                false, true, true, false, false, null, null, false,
1172                                                null, null, null},
1173                                 new object [] {"smallmoney", 17, 10, "smallmoney", null,
1174                                                "System.Decimal", false, false, false, true, true, false,
1175                                                true, true, false, false, null, null, false, null, null, null},
1176                                 new object [] {"bit", 2, 1, "bit", null, "System.Boolean",
1177                                                false, false, false, true, false, false, true, true,
1178                                                false, null, null, null, false, null, null, null},
1179                                 new object [] {"tinyint", 20, 3, "tinyint", null,
1180                                                "System.SByte", true, true, false, true, true, false,
1181                                                true, true, false, true, null, null, false, null, null, null},
1182                                 new object [] {"bigint", 0, 19, "bigint", null,
1183                                                "System.Int64", true, true, false, true, true, false,
1184                                                true, true, false, false, null, null, false, null, null, null},
1185                                 new object [] {"timestamp", 19, 8, "timestamp", null,
1186                                                "System.Byte[]", false, false, false, true, false, false,
1187                                                false, true, false, null, null, null, true, null, "0x", null},
1188                                 new object [] {"binary", 1, 8000, "binary({0})", "length",
1189                                                "System.Byte[]", false, true, false, true, false, false,
1190                                                true, true, false, null, null, null, false, null, "0x", null},
1191                                 new object [] {"image", 7, 2147483647, "image", null,
1192                                                "System.Byte[]", false, true, false, false, false, true,
1193                                                true, false, false, null, null, null, false, null, "0x", null},
1194                                 new object [] {"text", 18, 2147483647, "text", null,
1195                                                "System.String", false, true, false, false, false, true,
1196                                                true, false, true, null, null, null, false, null, "'", "'"},
1197                                 new object [] {"ntext", 11, 1073741823, "ntext", null,
1198                                                "System.String", false, true, false, false, false, true,
1199                                                true, false, true, null, null, null, false, null, "N'", "'"},
1200                                 new object [] {"decimal", 5, 38, "decimal({0}, {1})",
1201                                                "precision,scale", "System.Decimal", true, true, false,
1202                                                true, false, false, true, true, false, false, 38, 0,
1203                                                false, null, null, null},
1204                                 new object [] {"numeric", 5, 38, "numeric({0}, {1})",
1205                                                "precision,scale", "System.Decimal", true, true, false,
1206                                                true, false, false, true, true, false, false, 38, 0,
1207                                                false, null, null, null},
1208                                 new object [] {"datetime", 4, 23, "datetime", null,
1209                                                "System.DateTime", false, true, false, true, false, false,
1210                                                true, true, true, null, null, null, false, null, "{ts '", "'}"},
1211                                 new object [] {"smalldatetime", 15, 16, "smalldatetime", null,
1212                                                "System.DateTime", false, true, false, true, false, false,
1213                                                true, true, true, null, null, null, false, null, "{ts '", "'}"},
1214                                 new object [] {"sql_variant", 23, null, "sql_variant",
1215                                                null, "System.Object", false, true, false, false, false,
1216                                                false, true, true, false, null, null, null, false, false,
1217                                                null, null},
1218                                 new object [] {"xml", 25, 2147483647, "xml", null,
1219                                                "System.String", false, false, false, false, false, true,
1220                                                true, false, false, null, null, null, false, false, null, null},
1221                                 new object [] {"varchar", 22, 2147483647, "varchar({0})",
1222                                                "max length", "System.String", false, true, false, false,
1223                                                false, false, true, true, true, null, null, null, false,
1224                                                null, "'", "'"},
1225                                 new object [] {"char", 3, 2147483647, "char({0})", "length",
1226                                                "System.String", false, true, false, true, false, false,
1227                                                true, true, true, null, null, null, false, null, "'", "'"},
1228                                 new object [] {"nchar", 10, 1073741823, "nchar({0})", "length",
1229                                                "System.String", false, true, false, true, false, false,
1230                                                true, true, true, null, null, null, false, null, "N'", "'"},
1231                                 new object [] {"nvarchar", 12, 1073741823, "nvarchar({0})", "max length",
1232                                                "System.String", false, true, false, false, false, false, true, true,
1233                                                true, null, null, null, false, null, "N'", "'"},
1234                                 new object [] {"varbinary", 21, 1073741823, "varbinary({0})",
1235                                                "max length", "System.Byte[]", false, true, false, false,
1236                                                false, false, true, true, false, null, null, null, false,
1237                                                null, "0x", null},
1238                                 new object [] {"uniqueidentifier", 14, 16, "uniqueidentifier", null,
1239                                                "System.Guid", false, true, false, true, false, false, true,
1240                                                true, false, null, null, null, false, null, "'", "'"}
1241                         };
1242
1243                         static DataTable instance;
1244                         static public DataTable Instance {
1245                                 get {
1246                                         if (instance == null) {
1247                                                 instance = new DataTable ("DataTypes");
1248                                                 foreach (ColumnInfo c in columns)
1249                                                         instance.Columns.Add (c.name, c.type);
1250                                                 foreach (object [] row in rows)
1251                                                         instance.LoadDataRow (row, true);
1252                                         }
1253                                         return instance;
1254                                 }
1255                         }
1256                 }
1257
1258                 static class Restrictions
1259                 {
1260                         static readonly ColumnInfo [] columns = {
1261                                 new ColumnInfo ("CollectionName", typeof (string)),
1262                                 new ColumnInfo ("RestrictionName", typeof(string)),
1263                                 new ColumnInfo ("ParameterName", typeof(string)),
1264                                 new ColumnInfo ("RestrictionDefault", typeof(string)),
1265                                 new ColumnInfo ("RestrictionNumber", typeof(int))
1266                         };
1267
1268                         static readonly object [][] rows = {
1269                                 new object [] {"Users", "User_Name", "@Name", "name", 1},
1270                                 new object [] {"Databases", "Name", "@Name", "Name", 1},
1271
1272                                 new object [] {"Tables", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1273                                 new object [] {"Tables", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1274                                 new object [] {"Tables", "Table", "@Name", "TABLE_NAME", 3},
1275                                 new object [] {"Tables", "TableType", "@TableType", "TABLE_TYPE", 4},
1276
1277                                 new object [] {"Columns", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1278                                 new object [] {"Columns", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1279                                 new object [] {"Columns", "Table", "@Table", "TABLE_NAME", 3},
1280                                 new object [] {"Columns", "Column", "@Column", "COLUMN_NAME", 4},
1281
1282                                 new object [] {"Views", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1283                                 new object [] {"Views", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1284                                 new object [] {"Views", "Table", "@Table", "TABLE_NAME", 3},
1285
1286                                 new object [] {"ViewColumns", "Catalog", "@Catalog", "VIEW_CATALOG", 1},
1287                                 new object [] {"ViewColumns", "Owner", "@Owner", "VIEW_SCHEMA", 2},
1288                                 new object [] {"ViewColumns", "Table", "@Table", "VIEW_NAME", 3},
1289                                 new object [] {"ViewColumns", "Column", "@Column", "COLUMN_NAME", 4},
1290
1291                                 new object [] {"ProcedureParameters", "Catalog", "@Catalog", "SPECIFIC_CATALOG", 1},
1292                                 new object [] {"ProcedureParameters", "Owner", "@Owner", "SPECIFIC_SCHEMA", 2},
1293                                 new object [] {"ProcedureParameters", "Name", "@Name", "SPECIFIC_NAME", 3},
1294                                 new object [] {"ProcedureParameters", "Parameter", "@Parameter", "PARAMETER_NAME", 4},
1295
1296                                 new object [] {"Procedures", "Catalog", "@Catalog", "SPECIFIC_CATALOG", 1},
1297                                 new object [] {"Procedures", "Owner", "@Owner", "SPECIFIC_SCHEMA", 2},
1298                                 new object [] {"Procedures", "Name", "@Name", "SPECIFIC_NAME", 3},
1299                                 new object [] {"Procedures", "Type", "@Type", "ROUTINE_TYPE", 4},
1300
1301                                 new object [] {"IndexColumns", "Catalog", "@Catalog", "db_name(}", 1},
1302                                 new object [] {"IndexColumns", "Owner", "@Owner", "user_name(}", 2},
1303                                 new object [] {"IndexColumns", "Table", "@Table", "o.name", 3},
1304                                 new object [] {"IndexColumns", "ConstraintName", "@ConstraintName", "x.name", 4},
1305                                 new object [] {"IndexColumns", "Column", "@Column", "c.name", 5},
1306
1307                                 new object [] {"Indexes", "Catalog", "@Catalog", "db_name(}", 1},
1308                                 new object [] {"Indexes", "Owner", "@Owner", "user_name(}", 2},
1309                                 new object [] {"Indexes", "Table", "@Table", "o.name", 3},
1310                                 new object [] {"Indexes", "Name", "@Name", "x.name", 4},
1311
1312                                 new object [] {"UserDefinedTypes", "assembly_name", "@AssemblyName", "assemblies.name", 1},
1313                                 new object [] {"UserDefinedTypes", "udt_name", "@UDTName", "types.assembly_class", 2},
1314
1315                                 new object [] {"ForeignKeys", "Catalog", "@Catalog", "CONSTRAINT_CATALOG", 1},
1316                                 new object [] {"ForeignKeys", "Owner", "@Owner", "CONSTRAINT_SCHEMA", 2},
1317                                 new object [] {"ForeignKeys", "Table", "@Table", "TABLE_NAME", 3},
1318                                 new object [] {"ForeignKeys", "Name", "@Name", "CONSTRAINT_NAME", 4}
1319                         };
1320
1321                         static DataTable instance;
1322                         static public DataTable Instance {
1323                                 get {
1324                                         if (instance == null) {
1325                                                 instance = new DataTable ("Restrictions");
1326                                                 foreach (ColumnInfo c in columns)
1327                                                         instance.Columns.Add (c.name, c.type);
1328                                                 foreach (object [] row in rows)
1329                                                         instance.LoadDataRow (row, true);
1330                                         }
1331                                         return instance;
1332                                 }
1333                         }
1334                 }
1335
1336                 public override DataTable GetSchema ()
1337                 {
1338                         return MetaDataCollections.Instance;
1339                 }
1340
1341                 public override DataTable GetSchema (String collectionName)
1342                 {
1343                         return GetSchema (collectionName, null);
1344                 }
1345
1346                 public override DataTable GetSchema (String collectionName, string [] restrictionValues)
1347                 {
1348                         if (collectionName == null)
1349                                 //LAMESPEC: In MS.NET, if collectionName is null, it throws ArgumentException.
1350                                 throw new ArgumentException ();
1351
1352                         String cName          = null;
1353                         DataTable schemaTable = MetaDataCollections.Instance;
1354                         int length = restrictionValues == null ? 0 : restrictionValues.Length;
1355
1356                         foreach (DataRow row in schemaTable.Rows) {
1357                                 if (String.Compare ((string) row["CollectionName"], collectionName, true) == 0) {
1358                                         if (length > (int) row["NumberOfRestrictions"]) {
1359                                                 throw new ArgumentException ("More restrictions were provided " +
1360                                                                              "than the requested schema ('" +
1361                                                                              row["CollectionName"].ToString () + "') supports");
1362                                         }
1363                                         cName = row["CollectionName"].ToString();
1364                                 }
1365                         }
1366                         if (cName == null)
1367                                 throw new ArgumentException ("The requested collection ('" + collectionName + "') is not defined.");
1368
1369                         SqlCommand command     = null;
1370                         DataTable dataTable    = new DataTable ();
1371                         SqlDataAdapter dataAdapter = new SqlDataAdapter ();
1372
1373                         switch (cName)
1374                         {
1375                         case "Databases":
1376                                 command = new SqlCommand ("select name as database_name, dbid, crdate as create_date " +
1377                                                           "from master.sys.sysdatabases where (name = @Name or (@Name " +
1378                                                           "is null))", this);
1379                                 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1380                                 break;
1381                         case "ForeignKeys":
1382                                 command = new SqlCommand ("select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, " +
1383                                                           "TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_TYPE, " +
1384                                                           "IS_DEFERRABLE, INITIALLY_DEFERRED from " +
1385                                                           "INFORMATION_SCHEMA.TABLE_CONSTRAINTS where (CONSTRAINT_CATALOG" +
1386                                                           " = @Catalog or (@Catalog is null)) and (CONSTRAINT_SCHEMA = " +
1387                                                           "@Owner or (@Owner is null)) and (TABLE_NAME = @Table or (" +
1388                                                           "@Table is null)) and (CONSTRAINT_NAME = @Name or (@Name is null))" +
1389                                                           " and CONSTRAINT_TYPE = 'FOREIGN KEY' order by CONSTRAINT_CATALOG," +
1390                                                           " CONSTRAINT_SCHEMA, CONSTRAINT_NAME", this);
1391                                 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1392                                 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1393                                 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1394                                 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1395                                 break;
1396                         case "Indexes":
1397                                 command = new SqlCommand ("select distinct db_name() as constraint_catalog, " +
1398                                                           "constraint_schema = user_name (o.uid), " +
1399                                                           "constraint_name = x.name, table_catalog = db_name (), " +
1400                                                           "table_schema = user_name (o.uid), table_name = o.name, " +
1401                                                           "index_name  = x.name from sysobjects o, sysindexes x, " +
1402                                                           "sysindexkeys xk where o.type in ('U') and x.id = o.id and " +
1403                                                           "o.id = xk.id and x.indid = xk.indid and xk.keyno = x.keycnt " +
1404                                                           "and (db_name() = @Catalog or (@Catalog is null)) and " +
1405                                                           "(user_name() = @Owner or (@Owner is null)) and (o.name = " +
1406                                                           "@Table or (@Table is null)) and (x.name = @Name or (@Name is null))" +
1407                                                           "order by table_name, index_name", this);
1408                                 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1409                                 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1410                                 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1411                                 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1412                                 break;
1413                         case "IndexColumns":
1414                                 command = new SqlCommand ("select distinct db_name() as constraint_catalog, " +
1415                                                           "constraint_schema = user_name (o.uid), constraint_name = x.name, " +
1416                                                           "table_catalog = db_name (), table_schema = user_name (o.uid), " +
1417                                                           "table_name = o.name, column_name = c.name, " +
1418                                                           "ordinal_position = convert (int, xk.keyno), keyType = c.xtype, " +
1419                                                           "index_name = x.name from sysobjects o, sysindexes x, syscolumns c, " +
1420                                                           "sysindexkeys xk where o.type in ('U') and x.id = o.id and o.id = c.id " +
1421                                                           "and o.id = xk.id and x.indid = xk.indid and c.colid = xk.colid " +
1422                                                           "and xk.keyno <= x.keycnt and permissions (o.id, c.name) <> 0 " +
1423                                                           "and (db_name() = @Catalog or (@Catalog is null)) and (user_name() " +
1424                                                           "= @Owner or (@Owner is null)) and (o.name = @Table or (@Table is" +
1425                                                           " null)) and (x.name = @ConstraintName or (@ConstraintName is null)) " +
1426                                                           "and (c.name = @Column or (@Column is null)) order by table_name, " +
1427                                                           "index_name", this);
1428                                 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 8);
1429                                 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1430                                 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 13);
1431                                 command.Parameters.Add ("@ConstraintName", SqlDbType.NVarChar, 4000);
1432                                 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1433                                 break;
1434                         case "Procedures":
1435                                 command = new SqlCommand ("select SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, " +
1436                                                           "ROUTINE_CATALOG, ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE, " +
1437                                                           "CREATED, LAST_ALTERED from INFORMATION_SCHEMA.ROUTINES where " +
1438                                                           "(SPECIFIC_CATALOG = @Catalog or (@Catalog is null)) and " +
1439                                                           "(SPECIFIC_SCHEMA = @Owner or (@Owner is null)) and (SPECIFIC_NAME" +
1440                                                           " = @Name or (@Name is null)) and (ROUTINE_TYPE = @Type or (@Type " +
1441                                                           "is null)) order by SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME", this);
1442                                 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1443                                 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1444                                 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1445                                 command.Parameters.Add ("@Type", SqlDbType.NVarChar, 4000);
1446                                 break;
1447                         case "ProcedureParameters":
1448                                 command = new SqlCommand ("select SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, " +
1449                                                           "ORDINAL_POSITION, PARAMETER_MODE, IS_RESULT, AS_LOCATOR, " +
1450                                                           "PARAMETER_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, " +
1451                                                           "CHARACTER_OCTET_LENGTH, COLLATION_CATALOG, COLLATION_SCHEMA, " +
1452                                                           "COLLATION_NAME, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, " +
1453                                                           "CHARACTER_SET_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, " +
1454                                                           "NUMERIC_SCALE, DATETIME_PRECISION, INTERVAL_TYPE, " +
1455                                                           "INTERVAL_PRECISION from INFORMATION_SCHEMA.PARAMETERS where " +
1456                                                           "(SPECIFIC_CATALOG = @Catalog or (@Catalog is null)) and " +
1457                                                           "(SPECIFIC_SCHEMA = @Owner or (@Owner is null)) and (SPECIFIC_NAME = " +
1458                                                           "@Name or (@Name is null)) and (PARAMETER_NAME = @Parameter or (" +
1459                                                           "@Parameter is null)) order by SPECIFIC_CATALOG, SPECIFIC_SCHEMA," +
1460                                                           " SPECIFIC_NAME, PARAMETER_NAME", this);
1461                                 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1462                                 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1463                                 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1464                                 command.Parameters.Add ("@Parameter", SqlDbType.NVarChar, 4000);
1465                                 break;
1466                         case "Tables":
1467                                 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE " +
1468                                                           "from INFORMATION_SCHEMA.TABLES where" +
1469                                                           " (TABLE_CATALOG = @catalog or (@catalog is null)) and " +
1470                                                           "(TABLE_SCHEMA = @owner or (@owner is null))and " +
1471                                                           "(TABLE_NAME = @name or (@name is null)) and " +
1472                                                           "(TABLE_TYPE = @table_type or (@table_type is null))", this);
1473                                 command.Parameters.Add ("@catalog", SqlDbType.NVarChar, 8);
1474                                 command.Parameters.Add ("@owner", SqlDbType.NVarChar, 3);
1475                                 command.Parameters.Add ("@name", SqlDbType.NVarChar, 11);
1476                                 command.Parameters.Add ("@table_type", SqlDbType.NVarChar, 10);
1477                                 break;
1478                         case "Columns":
1479                                 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, " +
1480                                                           "ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, " +
1481                                                           "CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH, " +
1482                                                           "NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE, " +
1483                                                           "DATETIME_PRECISION, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, " +
1484                                                           "CHARACTER_SET_NAME, COLLATION_CATALOG from INFORMATION_SCHEMA.COLUMNS" +
1485                                                           " where (TABLE_CATALOG = @Catalog or (@Catalog is null)) and (" +
1486                                                           "TABLE_SCHEMA = @Owner or (@Owner is null)) and (TABLE_NAME = @table" +
1487                                                           " or (@Table is null)) and (COLUMN_NAME = @column or (@Column is null" +
1488                                                           ")) order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME", this);
1489                                 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1490                                 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1491                                 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1492                                 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1493                                 break;
1494                         case "Users":
1495                                 command = new SqlCommand ("select uid, name as user_name, createdate, updatedate from sysusers" +
1496                                                           " where (name = @Name or (@Name is null))", this);
1497                                 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1498                                 break;
1499                         case "Views":
1500                                 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, CHECK_OPTION, " +
1501                                                           "IS_UPDATABLE from INFORMATION_SCHEMA.VIEWS where (TABLE_CATALOG" +
1502                                                           " = @Catalog or (@Catalog is null)) TABLE_SCHEMA = @Owner or " +
1503                                                           "(@Owner is null)) and (TABLE_NAME = @table or (@Table is null))" +
1504                                                           " order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME", this);
1505                                 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1506                                 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1507                                 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1508                                 break;
1509                         case "ViewColumns":
1510                                 command = new SqlCommand ("select VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME, TABLE_CATALOG, " +
1511                                                           "TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME from " +
1512                                                           "INFORMATION_SCHEMA.VIEW_COLUMN_USAGE where (VIEW_CATALOG = " +
1513                                                           "@Catalog (@Catalog is null)) and (VIEW_SCHEMA = @Owner (@Owner" +
1514                                                           " is null)) and (VIEW_NAME = @Table or (@Table is null)) and " +
1515                                                           "(COLUMN_NAME = @Column or (@Column is null)) order by " +
1516                                                           "VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME", this);
1517                                 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1518                                 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1519                                 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1520                                 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1521                                 break;
1522                         case "UserDefinedTypes":
1523                                 command = new SqlCommand ("select assemblies.name as assembly_name, types.assembly_class " +
1524                                                           "as udt_name, ASSEMBLYPROPERTY(assemblies.name, 'VersionMajor') " +
1525                                                           "as version_major, ASSEMBLYPROPERTY(assemblies.name, 'VersionMinor') " +
1526                                                           "as version_minor, ASSEMBLYPROPERTY(assemblies.name, 'VersionBuild') " +
1527                                                           "as version_build, ASSEMBLYPROPERTY(assemblies.name, 'VersionRevision') " +
1528                                                           "as version_revision, ASSEMBLYPROPERTY(assemblies.name, 'CultureInfo') " +
1529                                                           "as culture_info, ASSEMBLYPROPERTY(assemblies.name, 'PublicKey') " +
1530                                                           "as public_key, is_fixed_length, max_length, Create_Date, " +
1531                                                           "Permission_set_desc from sys.assemblies as assemblies join " +
1532                                                           "sys.assembly_types as types on assemblies.assembly_id = types.assembly_id" +
1533                                                           " where (assportemblies.name = @AssemblyName or (@AssemblyName is null)) and " +
1534                                                           "(types.assembly_class = @UDTName or (@UDTName is null))",
1535                                                           this);
1536                                 command.Parameters.Add ("@AssemblyName", SqlDbType.NVarChar, 4000);
1537                                 command.Parameters.Add ("@UDTName", SqlDbType.NVarChar, 4000);
1538                                 break;
1539                         case "MetaDataCollections":
1540                                 return MetaDataCollections.Instance;
1541                         case "DataSourceInformation":
1542                                 throw new NotImplementedException ();
1543                         case "DataTypes":
1544                                 return DataTypes.Instance;
1545                         case "ReservedWords":
1546                                 return ReservedWords.Instance;
1547                         case "Restrictions":
1548                                 return Restrictions.Instance;
1549                         }
1550                         for (int i = 0; i < length; i++) {
1551                                 command.Parameters[i].Value = restrictionValues[i];
1552                         }
1553                         dataAdapter.SelectCommand = command;
1554                         dataAdapter.Fill (dataTable);
1555                         return dataTable;
1556                 }
1557                 
1558                 public static void ChangePassword (string connectionString, string newPassword)
1559                 {
1560                         if (connectionString == null || newPassword == null || newPassword == String.Empty)
1561                                 throw new ArgumentNullException ();
1562                         if (newPassword.Length > 128)
1563                                 throw new ArgumentException ("The value of newPassword exceeds its permittable length which is 128");
1564                         using (SqlConnection conn = new SqlConnection (connectionString)) {
1565                                 conn.Open ();
1566                                 conn.tds.Execute (String.Format ("sp_password '{0}', '{1}', '{2}'",
1567                                                                  conn.parms.Password, newPassword, conn.parms.User));
1568                         }
1569                 }
1570 #endif // NET_2_0
1571
1572                 #endregion // Methods
1573
1574 #if NET_2_0
1575                 #region Fields Net 2
1576
1577                 bool async = false;
1578
1579                 #endregion // Fields  Net 2
1580
1581                 #region Properties Net 2
1582
1583 #if !NET_2_0
1584                 [DataSysDescription ("Enable Asynchronous processing, 'Asynchrouse Processing=true/false' in the ConnectionString.")]   
1585 #endif
1586                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1587                 internal bool AsyncProcessing  {
1588                         get { return async; }
1589                 }
1590
1591                 #endregion // Properties Net 2
1592
1593 #endif // NET_2_0
1594
1595         }
1596 }