2010-06-03 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.Data / System.Data.SqlClient / SqlConnection.cs
blobc6cb08f21785ca3a21e02264393211b6d6bb5c2e
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)
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
18 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
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.
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 #if !MONOTOUCH
49 using System.EnterpriseServices;
50 #endif // !MONOTOUCH
51 using System.Globalization;
52 using System.Net;
53 using System.Net.Sockets;
54 using System.Text;
55 using System.Xml;
56 #if NET_2_0
57 using System.Collections.Generic;
58 #endif
60 namespace System.Data.SqlClient
62 [DefaultEvent ("InfoMessage")]
63 #if NET_2_0
64 public sealed class SqlConnection : DbConnection, IDbConnection, ICloneable
65 #else
66 public sealed class SqlConnection : Component, IDbConnection, ICloneable
67 #endif // NET_2_0
69 #region Fields
71 bool disposed;
73 // The set of SQL connection pools
74 static TdsConnectionPoolManager sqlConnectionPools = new TdsConnectionPoolManager (TdsVersion.tds80);
75 #if NET_2_0
76 const int DEFAULT_PACKETSIZE = 8000;
77 const int MAX_PACKETSIZE = 32768;
78 #else
79 const int DEFAULT_PACKETSIZE = 8192;
80 const int MAX_PACKETSIZE = 32767;
81 #endif
82 const int MIN_PACKETSIZE = 512;
83 const int DEFAULT_CONNECTIONTIMEOUT = 15;
84 const int DEFAULT_MAXPOOLSIZE = 100;
85 const int MIN_MAXPOOLSIZE = 1;
86 const int DEFAULT_MINPOOLSIZE = 0;
87 const int DEFAULT_PORT = 1433;
89 // The current connection pool
90 TdsConnectionPool pool;
92 // The connection string that identifies this connection
93 string connectionString;
95 // The transaction object for the current transaction
96 SqlTransaction transaction;
98 // Connection parameters
100 TdsConnectionParameters parms;
101 bool connectionReset;
102 bool pooling;
103 string dataSource;
104 int connectionTimeout;
105 int minPoolSize;
106 int maxPoolSize;
107 int packetSize;
108 int port;
109 bool fireInfoMessageEventOnUserErrors;
110 bool statisticsEnabled;
112 // The current state
113 ConnectionState state = ConnectionState.Closed;
115 SqlDataReader dataReader;
116 XmlReader xmlReader;
118 // The TDS object
119 Tds tds;
121 #endregion // Fields
123 #region Constructors
125 public SqlConnection () : this (null)
129 public SqlConnection (string connectionString)
131 ConnectionString = connectionString;
134 #endregion // Constructors
136 #region Properties
138 #if NET_1_0 || ONLY_1_1
139 [DataSysDescription ("Information used to connect to a DataSource, such as 'Data Source=x;Initial Catalog=x;Integrated Security=SSPI'.")]
140 #endif
141 [DefaultValue ("")]
142 [EditorAttribute ("Microsoft.VSDesigner.Data.SQL.Design.SqlConnectionStringEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
143 [RecommendedAsConfigurable (true)]
144 [RefreshProperties (RefreshProperties.All)]
145 public
146 #if NET_2_0
147 override
148 #endif // NET_2_0
149 string ConnectionString {
150 get {
151 if (connectionString == null)
152 return string.Empty;
153 return connectionString;
155 [MonoTODO("persist security info, encrypt, enlist keyword not implemented")]
156 set {
157 if (state == ConnectionState.Open)
158 throw new InvalidOperationException ("Not Allowed to change ConnectionString property while Connection state is OPEN");
159 SetConnectionString (value);
163 #if !NET_2_0
164 [DataSysDescription ("Current connection timeout value, 'Connect Timeout=X' in the ConnectionString.")]
165 #endif
166 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
167 public
168 #if NET_2_0
169 override
170 #endif // NET_2_0
171 int ConnectionTimeout {
172 get { return connectionTimeout; }
175 #if !NET_2_0
176 [DataSysDescription ("Current SQL Server database, 'Initial Catalog=X' in the connection string.")]
177 #endif
178 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
179 public
180 #if NET_2_0
181 override
182 #endif // NET_2_0
183 string Database {
184 get {
185 if (State == ConnectionState.Open)
186 return tds.Database;
187 return parms.Database ;
191 internal SqlDataReader DataReader {
192 get { return dataReader; }
193 set { dataReader = value; }
196 #if !NET_2_0
197 [DataSysDescription ("Current SqlServer that the connection is opened to, 'Data Source=X' in the connection string. ")]
198 #else
199 [Browsable(true)]
200 #endif
201 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
202 public
203 #if NET_2_0
204 override
205 #endif // NET_2_0
206 string DataSource {
207 get { return dataSource; }
210 #if !NET_2_0
211 [DataSysDescription ("Network packet size, 'Packet Size=x' in the connection string.")]
212 #endif
213 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
214 public int PacketSize {
215 get {
216 if (State == ConnectionState.Open)
217 return ((Tds) tds).PacketSize;
218 return packetSize;
222 [Browsable (false)]
223 #if !NET_2_0
224 [DataSysDescription ("Version of the SQL Server accessed by the SqlConnection.")]
225 #endif
226 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
227 public
228 #if NET_2_0
229 override
230 #endif // NET_2_0
231 string ServerVersion {
232 get {
233 if (state == ConnectionState.Closed)
234 throw ExceptionHelper.ConnectionClosed ();
235 else
236 return tds.ServerVersion;
240 [Browsable (false)]
241 #if !NET_2_0
242 [DataSysDescription ("The ConnectionState indicating whether the connection is open or closed.")]
243 #endif
244 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
245 public
246 #if NET_2_0
247 override
248 #endif // NET_2_0
249 ConnectionState State {
250 get { return state; }
253 internal Tds Tds {
254 get { return tds; }
257 internal SqlTransaction Transaction {
258 get { return transaction; }
259 set { transaction = value; }
262 #if !NET_2_0
263 [DataSysDescription ("Workstation Id, 'Workstation ID=x' in the connection string.")]
264 #endif
265 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
266 public string WorkstationId {
267 get { return parms.Hostname; }
270 internal XmlReader XmlReader {
271 get { return xmlReader; }
272 set { xmlReader = value; }
275 #if NET_2_0
276 public bool FireInfoMessageEventOnUserErrors {
277 get { return fireInfoMessageEventOnUserErrors; }
278 set { fireInfoMessageEventOnUserErrors = value; }
281 [DefaultValue (false)]
282 public bool StatisticsEnabled {
283 get { return statisticsEnabled; }
284 set { statisticsEnabled = value; }
286 #endif
287 #endregion // Properties
289 #region Events
291 #if !NET_2_0
292 [DataSysDescription ("Event triggered when messages arrive from the DataSource.")]
293 #endif
294 public event SqlInfoMessageEventHandler InfoMessage;
296 #if !NET_2_0
297 [DataSysDescription ("Event triggered when the connection changes state.")]
298 public new event StateChangeEventHandler StateChange;
299 #endif
301 #endregion // Events
303 #region Delegates
305 private void ErrorHandler (object sender, TdsInternalErrorMessageEventArgs e)
307 try {
308 if (!tds.IsConnected)
309 Close ();
310 } catch {
311 try {
312 Close ();
313 } catch {
316 throw new SqlException (e.Class, e.LineNumber, e.Message, e.Number, e.Procedure, e.Server, "Mono SqlClient Data Provider", e.State);
319 private void MessageHandler (object sender, TdsInternalInfoMessageEventArgs e)
321 OnSqlInfoMessage (CreateSqlInfoMessageEvent (e.Errors));
324 #endregion // Delegates
326 #region Methods
328 public new SqlTransaction BeginTransaction ()
330 return BeginTransaction (IsolationLevel.ReadCommitted, String.Empty);
333 public new SqlTransaction BeginTransaction (IsolationLevel iso)
335 return BeginTransaction (iso, String.Empty);
338 public SqlTransaction BeginTransaction (string transactionName)
340 return BeginTransaction (IsolationLevel.ReadCommitted, transactionName);
343 public SqlTransaction BeginTransaction (IsolationLevel iso, string transactionName)
345 if (state == ConnectionState.Closed)
346 throw ExceptionHelper.ConnectionClosed ();
347 if (transaction != null)
348 throw new InvalidOperationException ("SqlConnection does not support parallel transactions.");
350 string isolevel = String.Empty;
351 switch (iso) {
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 case IsolationLevel.ReadCommitted:
362 isolevel = "READ COMMITTED";
363 break;
364 #if NET_2_0
365 case IsolationLevel.Snapshot:
366 isolevel = "SNAPSHOT";
367 break;
368 case IsolationLevel.Unspecified:
369 iso = IsolationLevel.ReadCommitted;
370 isolevel = "READ COMMITTED";
371 break;
372 case IsolationLevel.Chaos:
373 throw new ArgumentOutOfRangeException ("IsolationLevel",
374 string.Format (CultureInfo.CurrentCulture,
375 "The IsolationLevel enumeration " +
376 "value, {0}, is not supported by " +
377 "the .Net Framework SqlClient " +
378 "Data Provider.", (int) iso));
379 #endif
380 default:
381 #if NET_2_0
382 throw new ArgumentOutOfRangeException ("IsolationLevel",
383 string.Format (CultureInfo.CurrentCulture,
384 "The IsolationLevel enumeration value, {0}, is invalid.",
385 (int) iso));
386 #else
387 throw new ArgumentException ("Invalid IsolationLevel parameter: must be ReadCommitted, ReadUncommitted, RepeatableRead, or Serializable.");
388 #endif
391 tds.Execute (String.Format ("SET TRANSACTION ISOLATION LEVEL {0};BEGIN TRANSACTION {1}", isolevel, transactionName));
393 transaction = new SqlTransaction (this, iso);
394 return transaction;
397 public
398 #if NET_2_0
399 override
400 #endif // NET_2_0
401 void ChangeDatabase (string database)
403 if (!IsValidDatabaseName (database))
404 throw new ArgumentException (String.Format ("The database name {0} is not valid.", database));
405 if (state != ConnectionState.Open)
406 throw new InvalidOperationException ("The connection is not open.");
407 tds.Execute (String.Format ("use [{0}]", database));
410 private void ChangeState (ConnectionState currentState)
412 if (currentState == state)
413 return;
415 ConnectionState originalState = state;
416 state = currentState;
417 OnStateChange (CreateStateChangeEvent (originalState, currentState));
420 public
421 #if NET_2_0
422 override
423 #endif // NET_2_0
424 void Close ()
426 if (transaction != null && transaction.IsOpen)
427 transaction.Rollback ();
429 if (dataReader != null || xmlReader != null) {
430 if(tds != null) tds.SkipToEnd ();
431 dataReader = null;
432 xmlReader = null;
435 if (tds != null && tds.IsConnected) {
436 if (pooling && tds.Pooling) {
437 if (pool != null) {
438 pool.ReleaseConnection (tds);
439 pool = null;
441 } else {
442 tds.Disconnect ();
446 if (tds != null) {
447 tds.TdsErrorMessage -= new TdsInternalErrorMessageEventHandler (ErrorHandler);
448 tds.TdsInfoMessage -= new TdsInternalInfoMessageEventHandler (MessageHandler);
451 ChangeState (ConnectionState.Closed);
454 public new SqlCommand CreateCommand ()
456 SqlCommand command = new SqlCommand ();
457 command.Connection = this;
458 return command;
461 private SqlInfoMessageEventArgs CreateSqlInfoMessageEvent (TdsInternalErrorCollection errors)
463 return new SqlInfoMessageEventArgs (errors);
466 private StateChangeEventArgs CreateStateChangeEvent (ConnectionState originalState, ConnectionState currentState)
468 return new StateChangeEventArgs (originalState, currentState);
471 protected override void Dispose (bool disposing)
473 try {
474 if (disposing && !disposed) {
475 if (State == ConnectionState.Open)
476 Close ();
477 ConnectionString = null;
479 } finally {
480 disposed = true;
481 base.Dispose (disposing);
485 #if !MONOTOUCH
486 [MonoTODO ("Not sure what this means at present.")]
487 public void EnlistDistributedTransaction (ITransaction transaction)
489 throw new NotImplementedException ();
491 #endif // !MONOTOUCH
493 object ICloneable.Clone ()
495 return new SqlConnection (ConnectionString);
498 #if NET_2_0
499 protected override DbTransaction BeginDbTransaction (IsolationLevel isolationLevel)
501 return BeginTransaction (isolationLevel);
504 protected override DbCommand CreateDbCommand ()
506 return CreateCommand ();
508 #else
509 IDbTransaction IDbConnection.BeginTransaction ()
511 return BeginTransaction ();
514 IDbTransaction IDbConnection.BeginTransaction (IsolationLevel iso)
516 return BeginTransaction (iso);
519 IDbCommand IDbConnection.CreateCommand ()
521 return CreateCommand ();
523 #endif
525 public
526 #if NET_2_0
527 override
528 #endif // NET_2_0
529 void Open ()
531 string serverName = string.Empty;
532 if (state == ConnectionState.Open)
533 throw new InvalidOperationException ("The Connection is already Open (State=Open)");
535 if (connectionString == null || connectionString.Trim().Length == 0)
536 throw new InvalidOperationException ("Connection string has not been initialized.");
538 try {
539 if (!pooling) {
540 if(!ParseDataSource (dataSource, out port, out serverName))
541 throw new SqlException(20, 0, "SQL Server does not exist or access denied.", 17, "ConnectionOpen (Connect()).", dataSource, parms.ApplicationName, 0);
542 tds = new Tds80 (serverName, port, PacketSize, ConnectionTimeout);
543 tds.Pooling = false;
545 else {
546 if(!ParseDataSource (dataSource, out port, out serverName))
547 throw new SqlException(20, 0, "SQL Server does not exist or access denied.", 17, "ConnectionOpen (Connect()).", dataSource, parms.ApplicationName, 0);
549 TdsConnectionInfo info = new TdsConnectionInfo (serverName, port, packetSize, ConnectionTimeout, minPoolSize, maxPoolSize);
550 pool = sqlConnectionPools.GetConnectionPool (connectionString, info);
551 tds = pool.GetConnection ();
553 } catch (TdsTimeoutException e) {
554 throw SqlException.FromTdsInternalException ((TdsInternalException) e);
555 } catch (TdsInternalException e) {
556 throw SqlException.FromTdsInternalException (e);
559 tds.TdsErrorMessage += new TdsInternalErrorMessageEventHandler (ErrorHandler);
560 tds.TdsInfoMessage += new TdsInternalInfoMessageEventHandler (MessageHandler);
562 if (!tds.IsConnected) {
563 try {
564 tds.Connect (parms);
565 } catch {
566 if (pooling)
567 pool.ReleaseConnection (tds);
568 throw;
572 disposed = false; // reset this, so using () would call Close ().
573 ChangeState (ConnectionState.Open);
576 private bool ParseDataSource (string theDataSource, out int thePort, out string theServerName)
578 theServerName = string.Empty;
579 string theInstanceName = string.Empty;
581 if (theDataSource == null)
582 throw new ArgumentException("Format of initialization string does not conform to specifications");
584 thePort = DEFAULT_PORT; // default TCP port for SQL Server
585 bool success = true;
587 int idx = 0;
588 if ((idx = theDataSource.IndexOf (',')) > -1) {
589 theServerName = theDataSource.Substring (0, idx);
590 string p = theDataSource.Substring (idx + 1);
591 thePort = Int32.Parse (p);
592 } else if ((idx = theDataSource.IndexOf ('\\')) > -1) {
593 theServerName = theDataSource.Substring (0, idx);
594 theInstanceName = theDataSource.Substring (idx + 1);
596 // do port discovery via UDP port 1434
597 port = DiscoverTcpPortViaSqlMonitor (theServerName, theInstanceName);
598 if (port == -1)
599 success = false;
600 } else
601 theServerName = theDataSource;
603 if (theServerName.Length == 0 || theServerName == "(local)" || theServerName == ".")
604 theServerName = "localhost";
606 if ((idx = theServerName.IndexOf ("tcp:")) > -1)
607 theServerName = theServerName.Substring (idx + 4);
609 return success;
612 private bool ConvertIntegratedSecurity (string value)
614 if (value.ToUpper() == "SSPI")
615 return true;
617 return ConvertToBoolean ("integrated security", value, false);
620 private bool ConvertToBoolean (string key, string value, bool defaultValue)
622 if (value.Length == 0)
623 return defaultValue;
625 string upperValue = value.ToUpper ();
627 if (upperValue == "TRUE" || upperValue == "YES")
628 return true;
629 else if (upperValue == "FALSE" || upperValue == "NO")
630 return false;
632 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
633 "Invalid value \"{0}\" for key '{1}'.", value, key));
636 private int ConvertToInt32 (string key, string value, int defaultValue)
638 if (value.Length == 0)
639 return defaultValue;
641 try {
642 return int.Parse (value);
643 } catch (Exception ex) {
644 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
645 "Invalid value \"{0}\" for key '{1}'.", value, key), ex);
649 private int DiscoverTcpPortViaSqlMonitor (string ServerName, string InstanceName)
651 SqlMonitorSocket msock;
652 msock = new SqlMonitorSocket (ServerName, InstanceName);
653 int SqlServerPort = msock.DiscoverTcpPort (ConnectionTimeout);
654 msock = null;
655 return SqlServerPort;
658 void SetConnectionString (string connectionString)
660 SetDefaultConnectionParameters ();
662 if ((connectionString == null) || (connectionString.Trim().Length == 0)) {
663 this.connectionString = connectionString;
664 return;
667 connectionString += ";";
669 bool inQuote = false;
670 bool inDQuote = false;
671 bool inName = true;
673 string name = String.Empty;
674 string value = String.Empty;
675 StringBuilder sb = new StringBuilder ();
677 for (int i = 0; i < connectionString.Length; i += 1) {
678 char c = connectionString [i];
679 char peek;
680 if (i == connectionString.Length - 1)
681 peek = '\0';
682 else
683 peek = connectionString [i + 1];
685 switch (c) {
686 case '\'':
687 if (inDQuote)
688 sb.Append (c);
689 else if (peek.Equals (c)) {
690 sb.Append (c);
691 i += 1;
693 else
694 inQuote = !inQuote;
695 break;
696 case '"':
697 if (inQuote)
698 sb.Append (c);
699 else if (peek.Equals (c)) {
700 sb.Append (c);
701 i += 1;
703 else
704 inDQuote = !inDQuote;
705 break;
706 case ';':
707 if (inDQuote || inQuote)
708 sb.Append (c);
709 else {
710 if (name != String.Empty && name != null) {
711 value = sb.ToString ();
712 SetProperties (name.ToLower ().Trim() , value);
714 else if (sb.Length != 0)
715 throw new ArgumentException ("Format of initialization string does not conform to specifications");
716 inName = true;
717 name = String.Empty;
718 value = String.Empty;
719 sb = new StringBuilder ();
721 break;
722 case '=':
723 if (inDQuote || inQuote || !inName)
724 sb.Append (c);
725 else if (peek.Equals (c)) {
726 sb.Append (c);
727 i += 1;
730 else {
731 name = sb.ToString ();
732 sb = new StringBuilder ();
733 inName = false;
735 break;
736 case ' ':
737 if (inQuote || inDQuote)
738 sb.Append (c);
739 else if (sb.Length > 0 && !peek.Equals (';'))
740 sb.Append (c);
741 break;
742 default:
743 sb.Append (c);
744 break;
748 if (minPoolSize > maxPoolSize)
749 throw new ArgumentException ("Invalid value for "
750 + "'min pool size' or 'max pool size'; "
751 + "'min pool size' must not be greater "
752 + "than 'max pool size'.");
754 connectionString = connectionString.Substring (0 , connectionString.Length-1);
755 this.connectionString = connectionString;
758 void SetDefaultConnectionParameters ()
760 if (parms == null)
761 parms = new TdsConnectionParameters ();
762 else
763 parms.Reset ();
764 dataSource = string.Empty;
765 connectionTimeout = DEFAULT_CONNECTIONTIMEOUT;
766 connectionReset = true;
767 pooling = true;
768 maxPoolSize = DEFAULT_MAXPOOLSIZE;
769 minPoolSize = DEFAULT_MINPOOLSIZE;
770 packetSize = DEFAULT_PACKETSIZE;
771 port = DEFAULT_PORT;
772 #if NET_2_0
773 async = false;
774 #endif
777 private void SetProperties (string name , string value)
779 switch (name) {
780 case "app" :
781 case "application name" :
782 parms.ApplicationName = value;
783 break;
784 case "attachdbfilename" :
785 case "extended properties" :
786 case "initial file name" :
787 parms.AttachDBFileName = value;
788 break;
789 case "timeout" :
790 case "connect timeout" :
791 case "connection timeout" :
792 int tmpTimeout = ConvertToInt32 ("connect timeout", value,
793 DEFAULT_CONNECTIONTIMEOUT);
794 if (tmpTimeout < 0)
795 throw new ArgumentException ("Invalid 'connect timeout'. Must be an integer >=0 ");
796 else
797 connectionTimeout = tmpTimeout;
798 break;
799 case "connection lifetime" :
800 break;
801 case "connection reset" :
802 connectionReset = ConvertToBoolean ("connection reset", value, true);
803 break;
804 case "language" :
805 case "current language" :
806 parms.Language = value;
807 break;
808 case "data source" :
809 case "server" :
810 case "address" :
811 case "addr" :
812 case "network address" :
813 dataSource = value;
814 break;
815 case "encrypt":
816 if (ConvertToBoolean (name, value, false))
817 throw new NotImplementedException("SSL encryption for"
818 + " data sent between client and server is not"
819 + " implemented.");
820 break;
821 case "enlist" :
822 if (!ConvertToBoolean (name, value, true))
823 throw new NotImplementedException("Disabling the automatic"
824 + " enlistment of connections in the thread's current"
825 + " transaction context is not implemented.");
826 break;
827 case "initial catalog" :
828 case "database" :
829 parms.Database = value;
830 break;
831 case "integrated security" :
832 case "trusted_connection" :
833 parms.DomainLogin = ConvertIntegratedSecurity(value);
834 break;
835 case "max pool size" :
836 int tmpMaxPoolSize = ConvertToInt32 (name, value, DEFAULT_MAXPOOLSIZE);
837 if (tmpMaxPoolSize < MIN_MAXPOOLSIZE)
838 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
839 "Invalid '{0}'. The value must be greater than {1}.",
840 name, MIN_MAXPOOLSIZE));
841 else
842 maxPoolSize = tmpMaxPoolSize;
843 break;
844 case "min pool size" :
845 int tmpMinPoolSize = ConvertToInt32 (name, value, DEFAULT_MINPOOLSIZE);
846 if (tmpMinPoolSize < 0)
847 throw new ArgumentException ("Invalid 'min pool size'. Must be a integer >= 0");
848 else
849 minPoolSize = tmpMinPoolSize;
850 break;
851 #if NET_2_0
852 case "multipleactiveresultsets":
853 // FIXME: not implemented
854 ConvertToBoolean (name, value, false);
855 break;
856 case "asynchronous processing" :
857 case "async" :
858 async = ConvertToBoolean (name, value, false);
859 break;
860 #endif
861 case "net" :
862 case "network" :
863 case "network library" :
864 if (!value.ToUpper ().Equals ("DBMSSOCN"))
865 throw new ArgumentException ("Unsupported network library.");
866 break;
867 case "packet size" :
868 int tmpPacketSize = ConvertToInt32 (name, value, DEFAULT_PACKETSIZE);
869 if (tmpPacketSize < MIN_PACKETSIZE || tmpPacketSize > MAX_PACKETSIZE)
870 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
871 "Invalid 'Packet Size'. The value must be between {0} and {1}.",
872 MIN_PACKETSIZE, MAX_PACKETSIZE));
873 else
874 packetSize = tmpPacketSize;
875 break;
876 case "password" :
877 case "pwd" :
878 parms.Password = value;
879 break;
880 case "persistsecurityinfo" :
881 case "persist security info" :
882 // FIXME : not implemented
883 // throw new NotImplementedException ();
884 break;
885 case "pooling" :
886 pooling = ConvertToBoolean (name, value, true);
887 break;
888 case "uid" :
889 case "user" :
890 case "user id" :
891 parms.User = value;
892 break;
893 case "wsid" :
894 case "workstation id" :
895 parms.Hostname = value;
896 break;
897 #if NET_2_0
898 case "user instance":
899 userInstance = ConvertToBoolean (name, value, false);
900 break;
901 #endif
902 default :
903 throw new ArgumentException("Keyword not supported : '" + name + "'.");
907 static bool IsValidDatabaseName (string database)
909 if ( database == null || database.Trim().Length == 0 || database.Length > 128)
910 return false ;
912 if (database[0] == '"' && database[database.Length] == '"')
913 database = database.Substring (1, database.Length - 2);
914 else if (Char.IsDigit (database[0]))
915 return false;
917 if (database[0] == '_')
918 return false;
920 foreach (char c in database.Substring (1, database.Length - 1))
921 if (!Char.IsLetterOrDigit (c) && c != '_' && c != '-')
922 return false;
923 return true;
926 private void OnSqlInfoMessage (SqlInfoMessageEventArgs value)
928 if (InfoMessage != null)
929 InfoMessage (this, value);
932 #if !NET_2_0
933 private new void OnStateChange (StateChangeEventArgs value)
935 if (StateChange != null)
936 StateChange (this, value);
938 #endif
940 private sealed class SqlMonitorSocket : UdpClient
942 // UDP port that the SQL Monitor listens
943 private static readonly int SqlMonitorUdpPort = 1434;
944 //private static readonly string SqlServerNotExist = "SQL Server does not exist or access denied";
946 private string server;
947 private string instance;
949 internal SqlMonitorSocket (string ServerName, string InstanceName)
950 : base (ServerName, SqlMonitorUdpPort)
952 server = ServerName;
953 instance = InstanceName;
956 internal int DiscoverTcpPort (int timeoutSeconds)
958 int SqlServerTcpPort;
959 Client.Blocking = false;
960 // send command to UDP 1434 (SQL Monitor) to get
961 // the TCP port to connect to the MS SQL server
962 ASCIIEncoding enc = new ASCIIEncoding ();
963 Byte[] rawrq = new Byte [instance.Length + 1];
964 rawrq[0] = 4;
965 enc.GetBytes (instance, 0, instance.Length, rawrq, 1);
966 Send (rawrq, rawrq.Length);
968 if (!Active)
969 return -1; // Error
971 bool result;
972 long timeout = timeoutSeconds * 1000000;
973 result = Client.Poll ((int)timeout, SelectMode.SelectRead);
974 if (result == false)
975 return -1; // Error
977 if (Client.Available <= 0)
978 return -1; // Error
979 #if NET_2_0
980 IPEndPoint endpoint = new IPEndPoint (Dns.GetHostEntry ("localhost").AddressList [0], 0);
981 #else
982 IPEndPoint endpoint = new IPEndPoint (Dns.GetHostByName ("localhost").AddressList [0], 0);
983 #endif
984 Byte [] rawrs;
986 rawrs = Receive (ref endpoint);
988 string rs = Encoding.ASCII.GetString (rawrs);
990 string[] rawtokens = rs.Split (';');
991 Hashtable data = new Hashtable ();
992 for (int i = 0; i < rawtokens.Length / 2 && i < 256; i++) {
993 data [rawtokens [i * 2]] = rawtokens [ i * 2 + 1];
996 if (!data.ContainsKey ("tcp")) {
997 string msg = "Mono does not support names pipes or shared memory "
998 + "for connecting to SQL Server. Please enable the TCP/IP "
999 + "protocol.";
1000 throw new NotImplementedException (msg);
1003 SqlServerTcpPort = int.Parse ((string) data ["tcp"]);
1004 Close ();
1006 return SqlServerTcpPort;
1010 #if NET_2_0
1011 struct ColumnInfo
1013 public string name;
1014 public Type type;
1016 public ColumnInfo (string name, Type type)
1018 this.name = name; this.type = type;
1022 static class ReservedWords
1024 static readonly string [] reservedWords =
1026 "ADD", "EXCEPT", "PERCENT", "ALL", "EXEC", "PLAN", "ALTER",
1027 "EXECUTE", "PRECISION", "AND", "EXISTS", "PRIMARY", "ANY",
1028 "EXIT", "PRINT", "AS", "FETCH", "PROC", "ASC", "FILE",
1029 "PROCEDURE", "AUTHORIZATION", "FILLFACTOR", "PUBLIC",
1030 "BACKUP", "FOR", "RAISERROR", "BEGIN", "FOREIGN", "READ",
1031 "BETWEEN", "FREETEXT", "READTEXT", "BREAK", "FREETEXTTABLE",
1032 "RECONFIGURE", "BROWSE", "FROM", "REFERENCES", "BULK",
1033 "FULL", "REPLICATION", "BY", "FUNCTION", "RESTORE",
1034 "CASCADE", "GOTO", "RESTRICT", "CASE", "GRANT", "RETURN",
1035 "CHECK", "GROUP", "REVOKE", "CHECKPOINT", "HAVING", "RIGHT",
1036 "CLOSE", "HOLDLOCK", "ROLLBACK", "CLUSTERED", "IDENTITY",
1037 "ROWCOUNT", "COALESCE", "IDENTITY_INSERT", "ROWGUIDCOL",
1038 "COLLATE", "IDENTITYCOL", "RULE", "COLUMN", "IF", "SAVE",
1039 "COMMIT", "IN", "SCHEMA", "COMPUTE", "INDEX", "SELECT",
1040 "CONSTRAINT", "INNER", "SESSION_USER", "CONTAINS", "INSERT",
1041 "SET", "CONTAINSTABLE", "INTERSECT", "SETUSER", "CONTINUE",
1042 "INTO", "SHUTDOWN", "CONVERT", "IS", "SOME", "CREATE",
1043 "JOIN", "STATISTICS", "CROSS", "KEY", "SYSTEM_USER",
1044 "CURRENT", "KILL", "TABLE", "CURRENT_DATE", "LEFT",
1045 "TEXTSIZE", "CURRENT_TIME", "LIKE", "THEN",
1046 "CURRENT_TIMESTAMP", "LINENO", "TO", "CURRENT_USER", "LOAD",
1047 "TOP", "CURSOR", "NATIONAL", "TRAN", "DATABASE", "NOCHECK",
1048 "TRANSACTION", "DBCC", "NONCLUSTERED", "TRIGGER",
1049 "DEALLOCATE", "NOT", "TRUNCATE", "DECLARE", "NULL",
1050 "TSEQUAL", "DEFAULT", "NULLIF", "UNION", "DELETE", "OF",
1051 "UNIQUE", "DENY", "OFF", "UPDATE", "DESC", "OFFSETS",
1052 "UPDATETEXT", "DISK", "ON", "USE", "DISTINCT", "OPEN",
1053 "USER", "DISTRIBUTED", "OPENDATASOURCE", "VALUES", "DOUBLE",
1054 "OPENQUERY", "VARYING", "DROP", "OPENROWSET", "VIEW",
1055 "DUMMY", "OPENXML", "WAITFOR", "DUMP", "OPTION", "WHEN",
1056 "ELSE", "OR", "WHERE", "END", "ORDER", "WHILE", "ERRLVL",
1057 "OUTER", "WITH", "ESCAPE", "OVER", "WRITETEXT", "ABSOLUTE",
1058 "FOUND", "PRESERVE", "ACTION", "FREE", "PRIOR", "ADMIN",
1059 "GENERAL", "PRIVILEGES", "AFTER", "GET", "READS",
1060 "AGGREGATE", "GLOBAL", "REAL", "ALIAS", "GO", "RECURSIVE",
1061 "ALLOCATE", "GROUPING", "REF", "ARE", "HOST", "REFERENCING",
1062 "ARRAY", "HOUR", "RELATIVE", "ASSERTION", "IGNORE", "RESULT",
1063 "AT", "IMMEDIATE", "RETURNS", "BEFORE", "INDICATOR", "ROLE",
1064 "BINARY", "INITIALIZE", "ROLLUP", "BIT", "INITIALLY",
1065 "ROUTINE", "BLOB", "INOUT", "ROW", "BOOLEAN", "INPUT",
1066 "ROWS", "BOTH", "INT", "SAVEPOINT", "BREADTH", "INTEGER",
1067 "SCROLL", "CALL", "INTERVAL", "SCOPE", "CASCADED",
1068 "ISOLATION", "SEARCH", "CAST", "ITERATE", "SECOND",
1069 "CATALOG", "LANGUAGE", "SECTION", "CHAR", "LARGE",
1070 "SEQUENCE", "CHARACTER", "LAST", "SESSION", "CLASS",
1071 "LATERAL", "SETS", "CLOB", "LEADING", "SIZE", "COLLATION",
1072 "LESS", "SMALLINT", "COMPLETION", "LEVEL", "SPACE",
1073 "CONNECT", "LIMIT", "SPECIFIC", "CONNECTION", "LOCAL",
1074 "SPECIFICTYPE", "CONSTRAINTS", "LOCALTIME", "SQL",
1075 "CONSTRUCTOR", "LOCALTIMESTAMP", "SQLEXCEPTION",
1076 "CORRESPONDING", "LOCATOR", "SQLSTATE", "CUBE", "MAP",
1077 "SQLWARNING", "CURRENT_PATH", "MATCH", "START",
1078 "CURRENT_ROLE", "MINUTE", "STATE", "CYCLE", "MODIFIES",
1079 "STATEMENT", "DATA", "MODIFY", "STATIC", "DATE", "MODULE",
1080 "STRUCTURE", "DAY", "MONTH", "TEMPORARY", "DEC", "NAMES",
1081 "TERMINATE", "DECIMAL", "NATURAL", "THAN", "DEFERRABLE",
1082 "NCHAR", "TIME", "DEFERRED", "NCLOB", "TIMESTAMP", "DEPTH",
1083 "NEW", "TIMEZONE_HOUR", "DEREF", "NEXT", "TIMEZONE_MINUTE",
1084 "DESCRIBE", "NO", "TRAILING", "DESCRIPTOR", "NONE",
1085 "TRANSLATION", "DESTROY", "NUMERIC", "TREAT", "DESTRUCTOR",
1086 "OBJECT", "TRUE", "DETERMINISTIC", "OLD", "UNDER",
1087 "DICTIONARY", "ONLY", "UNKNOWN", "DIAGNOSTICS", "OPERATION",
1088 "UNNEST", "DISCONNECT", "ORDINALITY", "USAGE", "DOMAIN",
1089 "OUT", "USING", "DYNAMIC", "OUTPUT", "VALUE", "EACH",
1090 "PAD", "VARCHAR", "END-EXEC", "PARAMETER", "VARIABLE",
1091 "EQUALS", "PARAMETERS", "WHENEVER", "EVERY", "PARTIAL",
1092 "WITHOUT", "EXCEPTION", "PATH", "WORK", "EXTERNAL",
1093 "POSTFIX", "WRITE", "FALSE", "PREFIX", "YEAR", "FIRST",
1094 "PREORDER", "ZONE", "FLOAT", "PREPARE", "ADA", "AVG",
1095 "BIT_LENGTH", "CHAR_LENGTH", "CHARACTER_LENGTH", "COUNT",
1096 "EXTRACT", "FORTRAN", "INCLUDE", "INSENSITIVE", "LOWER",
1097 "MAX", "MIN", "OCTET_LENGTH", "OVERLAPS", "PASCAL",
1098 "POSITION", "SQLCA", "SQLCODE", "SQLERROR", "SUBSTRING",
1099 "SUM", "TRANSLATE", "TRIM", "UPPER"
1101 static DataTable instance;
1102 static public DataTable Instance {
1103 get {
1104 if (instance == null) {
1105 DataRow row = null;
1106 instance = new DataTable ("ReservedWords");
1107 instance.Columns.Add ("ReservedWord", typeof(string));
1108 foreach (string reservedWord in reservedWords)
1110 row = instance.NewRow();
1112 row["ReservedWord"] = reservedWord;
1113 instance.Rows.Add(row);
1116 return instance;
1121 static class MetaDataCollections
1123 static readonly ColumnInfo [] columns = {
1124 new ColumnInfo ("CollectionName", typeof (string)),
1125 new ColumnInfo ("NumberOfRestrictions", typeof (int)),
1126 new ColumnInfo ("NumberOfIdentifierParts", typeof (int))
1129 static readonly object [][] rows = {
1130 new object [] {"MetaDataCollections", 0, 0},
1131 new object [] {"DataSourceInformation", 0, 0},
1132 new object [] {"DataTypes", 0, 0},
1133 new object [] {"Restrictions", 0, 0},
1134 new object [] {"ReservedWords", 0, 0},
1135 new object [] {"Users", 1, 1},
1136 new object [] {"Databases", 1, 1},
1137 new object [] {"Tables", 4, 3},
1138 new object [] {"Columns", 4, 4},
1139 new object [] {"StructuredTypeMembers", 4, 4},
1140 new object [] {"Views", 3, 3},
1141 new object [] {"ViewColumns", 4, 4},
1142 new object [] {"ProcedureParameters", 4, 1},
1143 new object [] {"Procedures", 4, 3},
1144 new object [] {"ForeignKeys", 4, 3},
1145 new object [] {"IndexColumns", 5, 4},
1146 new object [] {"Indexes", 4, 3},
1147 new object [] {"UserDefinedTypes", 2, 1}
1150 static DataTable instance;
1151 static public DataTable Instance {
1152 get {
1153 if (instance == null) {
1154 instance = new DataTable ("MetaDataCollections");
1155 foreach (ColumnInfo c in columns)
1156 instance.Columns.Add (c.name, c.type);
1157 foreach (object [] row in rows)
1158 instance.LoadDataRow (row, true);
1160 return instance;
1165 static class DataSourceInformation
1167 static readonly ColumnInfo [] columns = {
1168 new ColumnInfo ("CompositeIdentifierSeparatorPattern", typeof (string)),
1169 new ColumnInfo ("DataSourceProductName", typeof(string)),
1170 new ColumnInfo ("DataSourceProductVersion", typeof(string)),
1171 new ColumnInfo ("DataSourceProductVersionNormalized", typeof(string)),
1172 new ColumnInfo ("GroupByBehavior", typeof(GroupByBehavior)),
1173 new ColumnInfo ("IdentifierPattern", typeof(string)),
1174 new ColumnInfo ("IdentifierCase", typeof(IdentifierCase)),
1175 new ColumnInfo ("OrderByColumnsInSelect", typeof(bool)),
1176 new ColumnInfo ("ParameterMarkerFormat", typeof(string)),
1177 new ColumnInfo ("ParameterMarkerPattern", typeof(string)),
1178 new ColumnInfo ("ParameterNameMaxLength", typeof(int)),
1179 new ColumnInfo ("ParameterNamePattern", typeof(string)),
1180 new ColumnInfo ("QuotedIdentifierPattern", typeof(string)),
1181 new ColumnInfo ("QuotedIdentifierCase", typeof(IdentifierCase)),
1182 new ColumnInfo ("StatementSeparatorPattern", typeof(string)),
1183 new ColumnInfo ("StringLiteralPattern", typeof(string)),
1184 new ColumnInfo ("SupportedJoinOperators", typeof(SupportedJoinOperators))
1187 static public DataTable GetInstance (SqlConnection conn)
1189 DataTable table = new DataTable ("DataSourceInformation");
1190 foreach (ColumnInfo c in columns)
1191 table.Columns.Add (c.name, c.type);
1192 DataRow row = table.NewRow ();
1193 row [0] = "\\.";
1194 row [1] = "Microsoft SQL Server";
1195 row [2] = conn.ServerVersion;;
1196 row [3] = conn.ServerVersion;;
1197 row [4] = GroupByBehavior.Unrelated;
1198 row [5] = @"(^\[\p{Lo}\p{Lu}\p{Ll}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Nd}@$#_]*$)|(^\[[^\]\0]|\]\]+\]$)|(^\""[^\""\0]|\""\""+\""$)";
1199 row [6] = IdentifierCase.Insensitive; // FIXME: obtain this from SQL Server
1200 row [7] = false;
1201 row [8] = "{0}";
1202 row [9] = @"@[\p{Lo}\p{Lu}\p{Ll}\p{Lm}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Lm}\p{Nd}\uff3f_@#\$]*(?=\s+|$)";
1203 row [10] = 128;
1204 row [11] = @"^[\p{Lo}\p{Lu}\p{Ll}\p{Lm}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Lm}\p{Nd}\uff3f_@#\$]*(?=\s+|$)";
1205 row [12] = @"(([^\[]|\]\])*)";
1206 row [13] = IdentifierCase.Insensitive; // FIXME: obtain this from SQL Server
1207 row [14] =";";
1208 row [15] = "'(([^']|'')*)'";
1209 row [16] = (SupportedJoinOperators.FullOuter | SupportedJoinOperators.Inner |
1210 SupportedJoinOperators.LeftOuter | SupportedJoinOperators.RightOuter);
1211 table.Rows.Add (row);
1212 return table;
1216 static class DataTypes
1218 static readonly ColumnInfo [] columns = {
1219 new ColumnInfo ("TypeName", typeof(string)),
1220 new ColumnInfo ("ProviderDbType", typeof(int)),
1221 new ColumnInfo ("ColumnSize", typeof(long)),
1222 new ColumnInfo ("CreateFormat", typeof(string)),
1223 new ColumnInfo ("CreateParameters", typeof(string)),
1224 new ColumnInfo ("DataType", typeof(string)),
1225 new ColumnInfo ("IsAutoIncrementable", typeof(bool)),
1226 new ColumnInfo ("IsBestMatch", typeof(bool)),
1227 new ColumnInfo ("IsCaseSensitive", typeof(bool)),
1228 new ColumnInfo ("IsFixedLength", typeof(bool)),
1229 new ColumnInfo ("IsFixedPrecisionScale", typeof(bool)),
1230 new ColumnInfo ("IsLong", typeof(bool)),
1231 new ColumnInfo ("IsNullable", typeof(bool)),
1232 new ColumnInfo ("IsSearchable", typeof(bool)),
1233 new ColumnInfo ("IsSearchableWithLike", typeof(bool)),
1234 new ColumnInfo ("IsUnsigned", typeof(bool)),
1235 new ColumnInfo ("MaximumScale", typeof(short)),
1236 new ColumnInfo ("MinimumScale", typeof(short)),
1237 new ColumnInfo ("IsConcurrencyType", typeof(bool)),
1238 new ColumnInfo ("IsLiteralSupported", typeof(bool)),
1239 new ColumnInfo ("LiteralPrefix", typeof(string)),
1240 new ColumnInfo ("LiteralSuffix", typeof(string))
1243 static readonly object [][] rows = {
1244 new object [] {"smallint", 16, 5, "smallint", null, "System.Int16", true, true,
1245 false, true, true, false, true, true, false, false, null,
1246 null, false, null, null, null},
1247 new object [] {"int", 8, 10, "int", null, "System.Int32",
1248 true, true, false, true, true, false, true, true, false,
1249 false, null, null, false, null, null, null},
1250 new object [] {"real", 13, 7, "real", null,
1251 "System.Single", false, true, false, true, false, false,
1252 true, true, false, false, null, null, false, null, null, null},
1253 new object [] {"float", 6, 53, "float({0})",
1254 "number of bits used to store the mantissa", "System.Double",
1255 false, true, false, true, false, false, true, true,
1256 false, false, null, null, false, null, null, null},
1257 new object [] {"money", 9, 19, "money", null,
1258 "System.Decimal", false, false, false, true, true,
1259 false, true, true, false, false, null, null, false,
1260 null, null, null},
1261 new object [] {"smallmoney", 17, 10, "smallmoney", null,
1262 "System.Decimal", false, false, false, true, true, false,
1263 true, true, false, false, null, null, false, null, null, null},
1264 new object [] {"bit", 2, 1, "bit", null, "System.Boolean",
1265 false, false, false, true, false, false, true, true,
1266 false, null, null, null, false, null, null, null},
1267 new object [] {"tinyint", 20, 3, "tinyint", null,
1268 "System.SByte", true, true, false, true, true, false,
1269 true, true, false, true, null, null, false, null, null, null},
1270 new object [] {"bigint", 0, 19, "bigint", null,
1271 "System.Int64", true, true, false, true, true, false,
1272 true, true, false, false, null, null, false, null, null, null},
1273 new object [] {"timestamp", 19, 8, "timestamp", null,
1274 "System.Byte[]", false, false, false, true, false, false,
1275 false, true, false, null, null, null, true, null, "0x", null},
1276 new object [] {"binary", 1, 8000, "binary({0})", "length",
1277 "System.Byte[]", false, true, false, true, false, false,
1278 true, true, false, null, null, null, false, null, "0x", null},
1279 new object [] {"image", 7, 2147483647, "image", null,
1280 "System.Byte[]", false, true, false, false, false, true,
1281 true, false, false, null, null, null, false, null, "0x", null},
1282 new object [] {"text", 18, 2147483647, "text", null,
1283 "System.String", false, true, false, false, false, true,
1284 true, false, true, null, null, null, false, null, "'", "'"},
1285 new object [] {"ntext", 11, 1073741823, "ntext", null,
1286 "System.String", false, true, false, false, false, true,
1287 true, false, true, null, null, null, false, null, "N'", "'"},
1288 new object [] {"decimal", 5, 38, "decimal({0}, {1})",
1289 "precision,scale", "System.Decimal", true, true, false,
1290 true, false, false, true, true, false, false, 38, 0,
1291 false, null, null, null},
1292 new object [] {"numeric", 5, 38, "numeric({0}, {1})",
1293 "precision,scale", "System.Decimal", true, true, false,
1294 true, false, false, true, true, false, false, 38, 0,
1295 false, null, null, null},
1296 new object [] {"datetime", 4, 23, "datetime", null,
1297 "System.DateTime", false, true, false, true, false, false,
1298 true, true, true, null, null, null, false, null, "{ts '", "'}"},
1299 new object [] {"smalldatetime", 15, 16, "smalldatetime", null,
1300 "System.DateTime", false, true, false, true, false, false,
1301 true, true, true, null, null, null, false, null, "{ts '", "'}"},
1302 new object [] {"sql_variant", 23, null, "sql_variant",
1303 null, "System.Object", false, true, false, false, false,
1304 false, true, true, false, null, null, null, false, false,
1305 null, null},
1306 new object [] {"xml", 25, 2147483647, "xml", null,
1307 "System.String", false, false, false, false, false, true,
1308 true, false, false, null, null, null, false, false, null, null},
1309 new object [] {"varchar", 22, 2147483647, "varchar({0})",
1310 "max length", "System.String", false, true, false, false,
1311 false, false, true, true, true, null, null, null, false,
1312 null, "'", "'"},
1313 new object [] {"char", 3, 2147483647, "char({0})", "length",
1314 "System.String", false, true, false, true, false, false,
1315 true, true, true, null, null, null, false, null, "'", "'"},
1316 new object [] {"nchar", 10, 1073741823, "nchar({0})", "length",
1317 "System.String", false, true, false, true, false, false,
1318 true, true, true, null, null, null, false, null, "N'", "'"},
1319 new object [] {"nvarchar", 12, 1073741823, "nvarchar({0})", "max length",
1320 "System.String", false, true, false, false, false, false, true, true,
1321 true, null, null, null, false, null, "N'", "'"},
1322 new object [] {"varbinary", 21, 1073741823, "varbinary({0})",
1323 "max length", "System.Byte[]", false, true, false, false,
1324 false, false, true, true, false, null, null, null, false,
1325 null, "0x", null},
1326 new object [] {"uniqueidentifier", 14, 16, "uniqueidentifier", null,
1327 "System.Guid", false, true, false, true, false, false, true,
1328 true, false, null, null, null, false, null, "'", "'"},
1329 new object [] {"date", 31, 3L, "date", DBNull.Value,
1330 "System.DateTime", false, false, false, true, true, false,
1331 true, true, true, DBNull.Value, DBNull.Value, DBNull.Value,
1332 false, DBNull.Value, "{ts '", "'}"},
1333 new object [] {"time", 32, 5L, "time({0})", "scale",
1334 "System.TimeSpan", false, false, false, false, false, false,
1335 true, true, true, DBNull.Value, (short) 7, (short) 0,
1336 false, DBNull.Value, "{ts '", "'}"},
1337 new object [] {"datetime2", 33, 8L, "datetime2({0})", "scale",
1338 "System.DateTime", false, true, false, false, false, false,
1339 true, true, true, DBNull.Value, (short) 7, (short) 0,
1340 false, DBNull.Value, "{ts '", "'}"},
1341 new object [] {"datetimeoffset", 34, 10L, "datetimeoffset({0})",
1342 "scale", "System.DateTimeOffset", false, true, false, false,
1343 false, false, true, true, true, DBNull.Value, (short) 7, (short) 0,
1344 false, DBNull.Value, "{ts '", "'}"}
1347 static DataTable instance;
1348 static public DataTable Instance {
1349 get {
1350 if (instance == null) {
1351 instance = new DataTable ("DataTypes");
1352 foreach (ColumnInfo c in columns)
1353 instance.Columns.Add (c.name, c.type);
1354 foreach (object [] row in rows)
1355 instance.LoadDataRow (row, true);
1357 return instance;
1362 static class Restrictions
1364 static readonly ColumnInfo [] columns = {
1365 new ColumnInfo ("CollectionName", typeof (string)),
1366 new ColumnInfo ("RestrictionName", typeof(string)),
1367 new ColumnInfo ("ParameterName", typeof(string)),
1368 new ColumnInfo ("RestrictionDefault", typeof(string)),
1369 new ColumnInfo ("RestrictionNumber", typeof(int))
1372 static readonly object [][] rows = {
1373 new object [] {"Users", "User_Name", "@Name", "name", 1},
1374 new object [] {"Databases", "Name", "@Name", "Name", 1},
1376 new object [] {"Tables", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1377 new object [] {"Tables", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1378 new object [] {"Tables", "Table", "@Name", "TABLE_NAME", 3},
1379 new object [] {"Tables", "TableType", "@TableType", "TABLE_TYPE", 4},
1381 new object [] {"Columns", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1382 new object [] {"Columns", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1383 new object [] {"Columns", "Table", "@Table", "TABLE_NAME", 3},
1384 new object [] {"Columns", "Column", "@Column", "COLUMN_NAME", 4},
1386 new object [] {"StructuredTypeMembers", "Catalog", "@Catalog", "TYPE_CATALOG", 1},
1387 new object [] {"StructuredTypeMembers", "Owner", "@Owner", "TYPE_SCHEMA", 2},
1388 new object [] {"StructuredTypeMembers", "Type", "@Type", "TYPE_NAME", 3},
1389 new object [] {"StructuredTypeMembers", "Member", "@Member", "MEMBER_NAME", 4},
1391 new object [] {"Views", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1392 new object [] {"Views", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1393 new object [] {"Views", "Table", "@Table", "TABLE_NAME", 3},
1395 new object [] {"ViewColumns", "Catalog", "@Catalog", "VIEW_CATALOG", 1},
1396 new object [] {"ViewColumns", "Owner", "@Owner", "VIEW_SCHEMA", 2},
1397 new object [] {"ViewColumns", "Table", "@Table", "VIEW_NAME", 3},
1398 new object [] {"ViewColumns", "Column", "@Column", "COLUMN_NAME", 4},
1400 new object [] {"ProcedureParameters", "Catalog", "@Catalog", "SPECIFIC_CATALOG", 1},
1401 new object [] {"ProcedureParameters", "Owner", "@Owner", "SPECIFIC_SCHEMA", 2},
1402 new object [] {"ProcedureParameters", "Name", "@Name", "SPECIFIC_NAME", 3},
1403 new object [] {"ProcedureParameters", "Parameter", "@Parameter", "PARAMETER_NAME", 4},
1405 new object [] {"Procedures", "Catalog", "@Catalog", "SPECIFIC_CATALOG", 1},
1406 new object [] {"Procedures", "Owner", "@Owner", "SPECIFIC_SCHEMA", 2},
1407 new object [] {"Procedures", "Name", "@Name", "SPECIFIC_NAME", 3},
1408 new object [] {"Procedures", "Type", "@Type", "ROUTINE_TYPE", 4},
1410 new object [] {"IndexColumns", "Catalog", "@Catalog", "db_name()", 1},
1411 new object [] {"IndexColumns", "Owner", "@Owner", "user_name()", 2},
1412 new object [] {"IndexColumns", "Table", "@Table", "o.name", 3},
1413 new object [] {"IndexColumns", "ConstraintName", "@ConstraintName", "x.name", 4},
1414 new object [] {"IndexColumns", "Column", "@Column", "c.name", 5},
1416 new object [] {"Indexes", "Catalog", "@Catalog", "db_name()", 1},
1417 new object [] {"Indexes", "Owner", "@Owner", "user_name()", 2},
1418 new object [] {"Indexes", "Table", "@Table", "o.name", 3},
1419 new object [] {"Indexes", "Name", "@Name", "x.name", 4},
1421 new object [] {"UserDefinedTypes", "assembly_name", "@AssemblyName", "assemblies.name", 1},
1422 new object [] {"UserDefinedTypes", "udt_name", "@UDTName", "types.assembly_class", 2},
1424 new object [] {"ForeignKeys", "Catalog", "@Catalog", "CONSTRAINT_CATALOG", 1},
1425 new object [] {"ForeignKeys", "Owner", "@Owner", "CONSTRAINT_SCHEMA", 2},
1426 new object [] {"ForeignKeys", "Table", "@Table", "TABLE_NAME", 3},
1427 new object [] {"ForeignKeys", "Name", "@Name", "CONSTRAINT_NAME", 4}
1430 static DataTable instance;
1431 static public DataTable Instance {
1432 get {
1433 if (instance == null) {
1434 instance = new DataTable ("Restrictions");
1435 foreach (ColumnInfo c in columns)
1436 instance.Columns.Add (c.name, c.type);
1437 foreach (object [] row in rows)
1438 instance.LoadDataRow (row, true);
1440 return instance;
1445 public override DataTable GetSchema ()
1447 if (state == ConnectionState.Closed)
1448 throw ExceptionHelper.ConnectionClosed ();
1450 return MetaDataCollections.Instance;
1453 public override DataTable GetSchema (String collectionName)
1455 return GetSchema (collectionName, null);
1458 public override DataTable GetSchema (String collectionName, string [] restrictionValues)
1460 // LAMESPEC: In MS.NET, if collectionName is null, it throws ArgumentException.
1462 if (state == ConnectionState.Closed)
1463 throw ExceptionHelper.ConnectionClosed ();
1465 String cName = null;
1466 DataTable schemaTable = MetaDataCollections.Instance;
1467 int length = restrictionValues == null ? 0 : restrictionValues.Length;
1469 foreach (DataRow row in schemaTable.Rows) {
1470 if (String.Compare ((string) row["CollectionName"], collectionName, true) == 0) {
1471 if (length > (int) row["NumberOfRestrictions"]) {
1472 throw new ArgumentException ("More restrictions were provided " +
1473 "than the requested schema ('" +
1474 row["CollectionName"].ToString () + "') supports");
1476 cName = row["CollectionName"].ToString();
1480 if (cName == null)
1481 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
1482 "The requested collection ({0}) is not defined.",
1483 collectionName));
1485 SqlCommand command = null;
1486 DataTable dataTable = new DataTable ();
1487 SqlDataAdapter dataAdapter = new SqlDataAdapter ();
1489 switch (cName)
1491 case "Databases":
1492 command = new SqlCommand ("select name as database_name, dbid, crdate as create_date " +
1493 "from master.sys.sysdatabases where (name = @Name or (@Name " +
1494 "is null))", this);
1495 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1496 break;
1497 case "ForeignKeys":
1498 command = new SqlCommand ("select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, " +
1499 "TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_TYPE, " +
1500 "IS_DEFERRABLE, INITIALLY_DEFERRED from " +
1501 "INFORMATION_SCHEMA.TABLE_CONSTRAINTS where (CONSTRAINT_CATALOG" +
1502 " = @Catalog or (@Catalog is null)) and (CONSTRAINT_SCHEMA = " +
1503 "@Owner or (@Owner is null)) and (TABLE_NAME = @Table or (" +
1504 "@Table is null)) and (CONSTRAINT_NAME = @Name or (@Name is null))" +
1505 " and CONSTRAINT_TYPE = 'FOREIGN KEY' order by CONSTRAINT_CATALOG," +
1506 " CONSTRAINT_SCHEMA, CONSTRAINT_NAME", this);
1507 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1508 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1509 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1510 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1511 break;
1512 case "Indexes":
1513 command = new SqlCommand ("select distinct db_name() as constraint_catalog, " +
1514 "constraint_schema = user_name (o.uid), " +
1515 "constraint_name = x.name, table_catalog = db_name (), " +
1516 "table_schema = user_name (o.uid), table_name = o.name, " +
1517 "index_name = x.name from sysobjects o, sysindexes x, " +
1518 "sysindexkeys xk where o.type in ('U') and x.id = o.id and " +
1519 "o.id = xk.id and x.indid = xk.indid and xk.keyno = x.keycnt " +
1520 "and (db_name() = @Catalog or (@Catalog is null)) and " +
1521 "(user_name() = @Owner or (@Owner is null)) and (o.name = " +
1522 "@Table or (@Table is null)) and (x.name = @Name or (@Name is null))" +
1523 "order by table_name, index_name", this);
1524 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1525 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1526 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1527 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1528 break;
1529 case "IndexColumns":
1530 command = new SqlCommand ("select distinct db_name() as constraint_catalog, " +
1531 "constraint_schema = user_name (o.uid), constraint_name = x.name, " +
1532 "table_catalog = db_name (), table_schema = user_name (o.uid), " +
1533 "table_name = o.name, column_name = c.name, " +
1534 "ordinal_position = convert (int, xk.keyno), keyType = c.xtype, " +
1535 "index_name = x.name from sysobjects o, sysindexes x, syscolumns c, " +
1536 "sysindexkeys xk where o.type in ('U') and x.id = o.id and o.id = c.id " +
1537 "and o.id = xk.id and x.indid = xk.indid and c.colid = xk.colid " +
1538 "and xk.keyno <= x.keycnt and permissions (o.id, c.name) <> 0 " +
1539 "and (db_name() = @Catalog or (@Catalog is null)) and (user_name() " +
1540 "= @Owner or (@Owner is null)) and (o.name = @Table or (@Table is" +
1541 " null)) and (x.name = @ConstraintName or (@ConstraintName is null)) " +
1542 "and (c.name = @Column or (@Column is null)) order by table_name, " +
1543 "index_name", this);
1544 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 8);
1545 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1546 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 13);
1547 command.Parameters.Add ("@ConstraintName", SqlDbType.NVarChar, 4000);
1548 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1549 break;
1550 case "Procedures":
1551 command = new SqlCommand ("select SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, " +
1552 "ROUTINE_CATALOG, ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE, " +
1553 "CREATED, LAST_ALTERED from INFORMATION_SCHEMA.ROUTINES where " +
1554 "(SPECIFIC_CATALOG = @Catalog or (@Catalog is null)) and " +
1555 "(SPECIFIC_SCHEMA = @Owner or (@Owner is null)) and (SPECIFIC_NAME" +
1556 " = @Name or (@Name is null)) and (ROUTINE_TYPE = @Type or (@Type " +
1557 "is null)) order by SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME", this);
1558 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1559 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1560 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1561 command.Parameters.Add ("@Type", SqlDbType.NVarChar, 4000);
1562 break;
1563 case "ProcedureParameters":
1564 command = new SqlCommand ("select SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, " +
1565 "ORDINAL_POSITION, PARAMETER_MODE, IS_RESULT, AS_LOCATOR, " +
1566 "PARAMETER_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, " +
1567 "CHARACTER_OCTET_LENGTH, COLLATION_CATALOG, COLLATION_SCHEMA, " +
1568 "COLLATION_NAME, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, " +
1569 "CHARACTER_SET_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, " +
1570 "NUMERIC_SCALE, DATETIME_PRECISION, INTERVAL_TYPE, " +
1571 "INTERVAL_PRECISION from INFORMATION_SCHEMA.PARAMETERS where " +
1572 "(SPECIFIC_CATALOG = @Catalog or (@Catalog is null)) and " +
1573 "(SPECIFIC_SCHEMA = @Owner or (@Owner is null)) and (SPECIFIC_NAME = " +
1574 "@Name or (@Name is null)) and (PARAMETER_NAME = @Parameter or (" +
1575 "@Parameter is null)) order by SPECIFIC_CATALOG, SPECIFIC_SCHEMA," +
1576 " SPECIFIC_NAME, PARAMETER_NAME", this);
1577 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1578 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1579 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1580 command.Parameters.Add ("@Parameter", SqlDbType.NVarChar, 4000);
1581 break;
1582 case "Tables":
1583 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE " +
1584 "from INFORMATION_SCHEMA.TABLES where" +
1585 " (TABLE_CATALOG = @catalog or (@catalog is null)) and " +
1586 "(TABLE_SCHEMA = @owner or (@owner is null))and " +
1587 "(TABLE_NAME = @name or (@name is null)) and " +
1588 "(TABLE_TYPE = @table_type or (@table_type is null))", this);
1589 command.Parameters.Add ("@catalog", SqlDbType.NVarChar, 8);
1590 command.Parameters.Add ("@owner", SqlDbType.NVarChar, 3);
1591 command.Parameters.Add ("@name", SqlDbType.NVarChar, 11);
1592 command.Parameters.Add ("@table_type", SqlDbType.NVarChar, 10);
1593 break;
1594 case "Columns":
1595 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, " +
1596 "ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, " +
1597 "CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH, " +
1598 "NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE, " +
1599 "DATETIME_PRECISION, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, " +
1600 "CHARACTER_SET_NAME, COLLATION_CATALOG from INFORMATION_SCHEMA.COLUMNS" +
1601 " where (TABLE_CATALOG = @Catalog or (@Catalog is null)) and (" +
1602 "TABLE_SCHEMA = @Owner or (@Owner is null)) and (TABLE_NAME = @table" +
1603 " or (@Table is null)) and (COLUMN_NAME = @column or (@Column is null" +
1604 ")) order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME", this);
1605 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1606 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1607 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1608 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1609 break;
1610 case "Users":
1611 command = new SqlCommand ("select uid, name as user_name, createdate, updatedate from sysusers" +
1612 " where (name = @Name or (@Name is null))", this);
1613 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1614 break;
1615 case "StructuredTypeMembers":
1616 // Only available on SQL Server 2008
1617 // Running it again SQL 2005 results in the following exception:
1618 // Unable to build the 'StructuredTypeMembers' collection because
1619 // execution of the SQL query failed. See the inner exception for details.
1620 // ---> System.Data.SqlClient.SqlException: Invalid object name 'sys.table_types'.
1622 // I don't have access to SQL Server 2008 right now,
1623 // and can't find any online documentation on the 'sys.table_types'
1624 // view
1625 throw new NotImplementedException ();
1626 case "Views":
1627 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, CHECK_OPTION, " +
1628 "IS_UPDATABLE from INFORMATION_SCHEMA.VIEWS where (TABLE_CATALOG" +
1629 " = @Catalog or (@Catalog is null)) TABLE_SCHEMA = @Owner or " +
1630 "(@Owner is null)) and (TABLE_NAME = @table or (@Table is null))" +
1631 " order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME", this);
1632 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1633 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1634 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1635 break;
1636 case "ViewColumns":
1637 command = new SqlCommand ("select VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME, TABLE_CATALOG, " +
1638 "TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME from " +
1639 "INFORMATION_SCHEMA.VIEW_COLUMN_USAGE where (VIEW_CATALOG = " +
1640 "@Catalog (@Catalog is null)) and (VIEW_SCHEMA = @Owner (@Owner" +
1641 " is null)) and (VIEW_NAME = @Table or (@Table is null)) and " +
1642 "(COLUMN_NAME = @Column or (@Column is null)) order by " +
1643 "VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME", this);
1644 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1645 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1646 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1647 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1648 break;
1649 case "UserDefinedTypes":
1650 command = new SqlCommand ("select assemblies.name as assembly_name, types.assembly_class " +
1651 "as udt_name, ASSEMBLYPROPERTY(assemblies.name, 'VersionMajor') " +
1652 "as version_major, ASSEMBLYPROPERTY(assemblies.name, 'VersionMinor') " +
1653 "as version_minor, ASSEMBLYPROPERTY(assemblies.name, 'VersionBuild') " +
1654 "as version_build, ASSEMBLYPROPERTY(assemblies.name, 'VersionRevision') " +
1655 "as version_revision, ASSEMBLYPROPERTY(assemblies.name, 'CultureInfo') " +
1656 "as culture_info, ASSEMBLYPROPERTY(assemblies.name, 'PublicKey') " +
1657 "as public_key, is_fixed_length, max_length, Create_Date, " +
1658 "Permission_set_desc from sys.assemblies as assemblies join " +
1659 "sys.assembly_types as types on assemblies.assembly_id = types.assembly_id" +
1660 " where (assportemblies.name = @AssemblyName or (@AssemblyName is null)) and " +
1661 "(types.assembly_class = @UDTName or (@UDTName is null))",
1662 this);
1663 command.Parameters.Add ("@AssemblyName", SqlDbType.NVarChar, 4000);
1664 command.Parameters.Add ("@UDTName", SqlDbType.NVarChar, 4000);
1665 break;
1666 case "MetaDataCollections":
1667 return MetaDataCollections.Instance;
1668 case "DataSourceInformation":
1669 return DataSourceInformation.GetInstance (this);
1670 case "DataTypes":
1671 return DataTypes.Instance;
1672 case "ReservedWords":
1673 return ReservedWords.Instance;
1674 case "Restrictions":
1675 return Restrictions.Instance;
1677 for (int i = 0; i < length; i++) {
1678 command.Parameters[i].Value = restrictionValues[i];
1680 dataAdapter.SelectCommand = command;
1681 dataAdapter.Fill (dataTable);
1682 return dataTable;
1685 public static void ChangePassword (string connectionString, string newPassword)
1687 if (String.IsNullOrEmpty (connectionString))
1688 throw new ArgumentNullException ("The 'connectionString' cannot be null or empty.");
1689 if (String.IsNullOrEmpty (newPassword))
1690 throw new ArgumentNullException ("The 'newPassword' cannot be null or empty.");
1691 if (newPassword.Length > 128)
1692 throw new ArgumentException ("The length of 'newPassword' cannot exceed 128 characters.");
1693 using (SqlConnection conn = new SqlConnection (connectionString)) {
1694 conn.Open ();
1695 conn.tds.Execute (String.Format ("sp_password '{0}', '{1}', '{2}'",
1696 conn.parms.Password, newPassword, conn.parms.User));
1700 public static void ClearAllPools ()
1702 // FIXME: locking
1703 IDictionary pools = SqlConnection.sqlConnectionPools.GetConnectionPool ();
1704 foreach (TdsConnectionPool pool in pools.Values) {
1705 if (pool != null)
1706 pool.ResetConnectionPool ();
1708 pools.Clear ();
1711 public static void ClearPool (SqlConnection connection)
1713 if (connection == null)
1714 throw new ArgumentNullException ("connection");
1716 // FIXME: locking
1717 if (connection.pooling) {
1718 TdsConnectionPool pool = sqlConnectionPools.GetConnectionPool (connection.ConnectionString);
1719 if (pool != null)
1720 pool.ResetConnectionPool ();
1724 #endif // NET_2_0
1726 #endregion // Methods
1728 #if NET_2_0
1729 #region Fields Net 2
1731 bool async;
1732 bool userInstance;
1734 #endregion // Fields Net 2
1736 #region Properties Net 2
1738 #if NET_1_0
1739 [DataSysDescription ("Enable Asynchronous processing, 'Asynchrouse Processing=true/false' in the ConnectionString.")]
1740 #endif
1741 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1742 internal bool AsyncProcessing {
1743 get { return async; }
1746 #endregion // Properties Net 2
1748 #endif // NET_2_0