2 // System.Data.SqlClient.SqlConnection.cs
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:
28 // The above copyright notice and this permission notice shall be
29 // included in all copies or substantial portions of the Software.
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.
41 using Mono.Data.Tds.Protocol;
43 using System.Collections;
44 using System.Collections.Specialized;
45 using System.ComponentModel;
47 using System.Data.Common;
49 using System.EnterpriseServices;
51 using System.Globalization;
53 using System.Net.Sockets;
57 using System.Collections.Generic;
60 namespace System.Data.SqlClient
62 [DefaultEvent ("InfoMessage")]
64 public sealed class SqlConnection : DbConnection, IDbConnection, ICloneable
66 public sealed class SqlConnection : Component, IDbConnection, ICloneable
73 // The set of SQL connection pools
74 static TdsConnectionPoolManager sqlConnectionPools = new TdsConnectionPoolManager (TdsVersion.tds80);
76 const int DEFAULT_PACKETSIZE = 8000;
77 const int MAX_PACKETSIZE = 32768;
79 const int DEFAULT_PACKETSIZE = 8192;
80 const int MAX_PACKETSIZE = 32767;
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;
104 int connectionTimeout;
109 bool fireInfoMessageEventOnUserErrors;
110 bool statisticsEnabled;
113 ConnectionState state = ConnectionState.Closed;
115 SqlDataReader dataReader;
125 public SqlConnection () : this (null)
129 public SqlConnection (string connectionString)
131 ConnectionString = connectionString;
134 #endregion // Constructors
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'.")]
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)]
149 string ConnectionString {
151 if (connectionString == null)
153 return connectionString;
155 [MonoTODO("persist security info, encrypt, enlist keyword not implemented")]
157 if (state == ConnectionState.Open)
158 throw new InvalidOperationException ("Not Allowed to change ConnectionString property while Connection state is OPEN");
159 SetConnectionString (value);
164 [DataSysDescription ("Current connection timeout value, 'Connect Timeout=X' in the ConnectionString.")]
166 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
171 int ConnectionTimeout {
172 get { return connectionTimeout; }
176 [DataSysDescription ("Current SQL Server database, 'Initial Catalog=X' in the connection string.")]
178 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
185 if (State == ConnectionState.Open)
187 return parms.Database ;
191 internal SqlDataReader DataReader {
192 get { return dataReader; }
193 set { dataReader = value; }
197 [DataSysDescription ("Current SqlServer that the connection is opened to, 'Data Source=X' in the connection string. ")]
201 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
207 get { return dataSource; }
211 [DataSysDescription ("Network packet size, 'Packet Size=x' in the connection string.")]
213 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
214 public int PacketSize {
216 if (State == ConnectionState.Open)
217 return ((Tds) tds).PacketSize;
224 [DataSysDescription ("Version of the SQL Server accessed by the SqlConnection.")]
226 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
231 string ServerVersion {
233 if (state == ConnectionState.Closed)
234 throw ExceptionHelper.ConnectionClosed ();
236 return tds.ServerVersion;
242 [DataSysDescription ("The ConnectionState indicating whether the connection is open or closed.")]
244 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
249 ConnectionState State {
250 get { return state; }
257 internal SqlTransaction Transaction {
258 get { return transaction; }
259 set { transaction = value; }
263 [DataSysDescription ("Workstation Id, 'Workstation ID=x' in the connection string.")]
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; }
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; }
287 #endregion // Properties
292 [DataSysDescription ("Event triggered when messages arrive from the DataSource.")]
294 public event SqlInfoMessageEventHandler InfoMessage;
297 [DataSysDescription ("Event triggered when the connection changes state.")]
298 public new event StateChangeEventHandler StateChange;
305 private void ErrorHandler (object sender, TdsInternalErrorMessageEventArgs e)
308 if (!tds.IsConnected)
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
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;
352 case IsolationLevel.ReadUncommitted:
353 isolevel = "READ UNCOMMITTED";
355 case IsolationLevel.RepeatableRead:
356 isolevel = "REPEATABLE READ";
358 case IsolationLevel.Serializable:
359 isolevel = "SERIALIZABLE";
361 case IsolationLevel.ReadCommitted:
362 isolevel = "READ COMMITTED";
365 case IsolationLevel.Snapshot:
366 isolevel = "SNAPSHOT";
368 case IsolationLevel.Unspecified:
369 iso = IsolationLevel.ReadCommitted;
370 isolevel = "READ COMMITTED";
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));
382 throw new ArgumentOutOfRangeException ("IsolationLevel",
383 string.Format (CultureInfo.CurrentCulture,
384 "The IsolationLevel enumeration value, {0}, is invalid.",
387 throw new ArgumentException ("Invalid IsolationLevel parameter: must be ReadCommitted, ReadUncommitted, RepeatableRead, or Serializable.");
391 tds.Execute (String.Format ("SET TRANSACTION ISOLATION LEVEL {0};BEGIN TRANSACTION {1}", isolevel, transactionName));
393 transaction = new SqlTransaction (this, iso);
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)
415 ConnectionState originalState = state;
416 state = currentState;
417 OnStateChange (CreateStateChangeEvent (originalState, currentState));
426 if (transaction != null && transaction.IsOpen)
427 transaction.Rollback ();
429 if (dataReader != null || xmlReader != null) {
430 if(tds != null) tds.SkipToEnd ();
435 if (tds != null && tds.IsConnected) {
436 if (pooling && tds.Pooling) {
438 pool.ReleaseConnection (tds);
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;
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)
474 if (disposing && !disposed) {
475 if (State == ConnectionState.Open)
477 ConnectionString = null;
481 base.Dispose (disposing);
486 [MonoTODO ("Not sure what this means at present.")]
487 public void EnlistDistributedTransaction (ITransaction transaction)
489 throw new NotImplementedException ();
493 object ICloneable.Clone ()
495 return new SqlConnection (ConnectionString);
499 protected override DbTransaction BeginDbTransaction (IsolationLevel isolationLevel)
501 return BeginTransaction (isolationLevel);
504 protected override DbCommand CreateDbCommand ()
506 return CreateCommand ();
509 IDbTransaction IDbConnection.BeginTransaction ()
511 return BeginTransaction ();
514 IDbTransaction IDbConnection.BeginTransaction (IsolationLevel iso)
516 return BeginTransaction (iso);
519 IDbCommand IDbConnection.CreateCommand ()
521 return CreateCommand ();
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.");
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);
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) {
567 pool.ReleaseConnection (tds);
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
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);
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);
612 private bool ConvertIntegratedSecurity (string value)
614 if (value.ToUpper() == "SSPI")
617 return ConvertToBoolean ("integrated security", value, false);
620 private bool ConvertToBoolean (string key, string value, bool defaultValue)
622 if (value.Length == 0)
625 string upperValue = value.ToUpper ();
627 if (upperValue == "TRUE" || upperValue == "YES")
629 else if (upperValue == "FALSE" || upperValue == "NO")
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)
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);
655 return SqlServerPort;
658 void SetConnectionString (string connectionString)
660 SetDefaultConnectionParameters ();
662 if ((connectionString == null) || (connectionString.Trim().Length == 0)) {
663 this.connectionString = connectionString;
667 connectionString += ";";
669 bool inQuote = false;
670 bool inDQuote = false;
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];
680 if (i == connectionString.Length - 1)
683 peek = connectionString [i + 1];
689 else if (peek.Equals (c)) {
699 else if (peek.Equals (c)) {
704 inDQuote = !inDQuote;
707 if (inDQuote || inQuote)
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");
718 value = String.Empty;
719 sb = new StringBuilder ();
723 if (inDQuote || inQuote || !inName)
725 else if (peek.Equals (c)) {
731 name = sb.ToString ();
732 sb = new StringBuilder ();
737 if (inQuote || inDQuote)
739 else if (sb.Length > 0 && !peek.Equals (';'))
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 ()
761 parms = new TdsConnectionParameters ();
764 dataSource = string.Empty;
765 connectionTimeout = DEFAULT_CONNECTIONTIMEOUT;
766 connectionReset = true;
768 maxPoolSize = DEFAULT_MAXPOOLSIZE;
769 minPoolSize = DEFAULT_MINPOOLSIZE;
770 packetSize = DEFAULT_PACKETSIZE;
777 private void SetProperties (string name , string value)
781 case "application name" :
782 parms.ApplicationName = value;
784 case "attachdbfilename" :
785 case "extended properties" :
786 case "initial file name" :
787 parms.AttachDBFileName = value;
790 case "connect timeout" :
791 case "connection timeout" :
792 int tmpTimeout = ConvertToInt32 ("connect timeout", value,
793 DEFAULT_CONNECTIONTIMEOUT);
795 throw new ArgumentException ("Invalid 'connect timeout'. Must be an integer >=0 ");
797 connectionTimeout = tmpTimeout;
799 case "connection lifetime" :
801 case "connection reset" :
802 connectionReset = ConvertToBoolean ("connection reset", value, true);
805 case "current language" :
806 parms.Language = value;
812 case "network address" :
816 if (ConvertToBoolean (name, value, false))
817 throw new NotImplementedException("SSL encryption for"
818 + " data sent between client and server is not"
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.");
827 case "initial catalog" :
829 parms.Database = value;
831 case "integrated security" :
832 case "trusted_connection" :
833 parms.DomainLogin = ConvertIntegratedSecurity(value);
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));
842 maxPoolSize = tmpMaxPoolSize;
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");
849 minPoolSize = tmpMinPoolSize;
852 case "multipleactiveresultsets":
853 // FIXME: not implemented
854 ConvertToBoolean (name, value, false);
856 case "asynchronous processing" :
858 async = ConvertToBoolean (name, value, false);
863 case "network library" :
864 if (!value.ToUpper ().Equals ("DBMSSOCN"))
865 throw new ArgumentException ("Unsupported network library.");
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));
874 packetSize = tmpPacketSize;
878 parms.Password = value;
880 case "persistsecurityinfo" :
881 case "persist security info" :
882 // FIXME : not implemented
883 // throw new NotImplementedException ();
886 pooling = ConvertToBoolean (name, value, true);
894 case "workstation id" :
895 parms.Hostname = value;
898 case "user instance":
899 userInstance = ConvertToBoolean (name, value, false);
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)
912 if (database[0] == '"' && database[database.Length] == '"')
913 database = database.Substring (1, database.Length - 2);
914 else if (Char.IsDigit (database[0]))
917 if (database[0] == '_')
920 foreach (char c in database.Substring (1, database.Length - 1))
921 if (!Char.IsLetterOrDigit (c) && c != '_' && c != '-')
926 private void OnSqlInfoMessage (SqlInfoMessageEventArgs value)
928 if (InfoMessage != null)
929 InfoMessage (this, value);
933 private new void OnStateChange (StateChangeEventArgs value)
935 if (StateChange != null)
936 StateChange (this, value);
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)
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];
965 enc.GetBytes (instance, 0, instance.Length, rawrq, 1);
966 Send (rawrq, rawrq.Length);
972 long timeout = timeoutSeconds * 1000000;
973 result = Client.Poll ((int)timeout, SelectMode.SelectRead);
977 if (Client.Available <= 0)
980 IPEndPoint endpoint = new IPEndPoint (Dns.GetHostEntry ("localhost").AddressList [0], 0);
982 IPEndPoint endpoint = new IPEndPoint (Dns.GetHostByName ("localhost").AddressList [0], 0);
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 "
1000 throw new NotImplementedException (msg);
1003 SqlServerTcpPort = int.Parse ((string) data ["tcp"]);
1006 return SqlServerTcpPort;
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 {
1104 if (instance == null) {
1106 var newInstance = new DataTable ("ReservedWords");
1107 newInstance.Columns.Add ("ReservedWord", typeof(string));
1108 foreach (string reservedWord in reservedWords)
1110 row = newInstance.NewRow();
1112 row["ReservedWord"] = reservedWord;
1113 newInstance.Rows.Add(row);
1115 instance = newInstance;
1122 static class MetaDataCollections
1124 static readonly ColumnInfo [] columns = {
1125 new ColumnInfo ("CollectionName", typeof (string)),
1126 new ColumnInfo ("NumberOfRestrictions", typeof (int)),
1127 new ColumnInfo ("NumberOfIdentifierParts", typeof (int))
1130 static readonly object [][] rows = {
1131 new object [] {"MetaDataCollections", 0, 0},
1132 new object [] {"DataSourceInformation", 0, 0},
1133 new object [] {"DataTypes", 0, 0},
1134 new object [] {"Restrictions", 0, 0},
1135 new object [] {"ReservedWords", 0, 0},
1136 new object [] {"Users", 1, 1},
1137 new object [] {"Databases", 1, 1},
1138 new object [] {"Tables", 4, 3},
1139 new object [] {"Columns", 4, 4},
1140 new object [] {"StructuredTypeMembers", 4, 4},
1141 new object [] {"Views", 3, 3},
1142 new object [] {"ViewColumns", 4, 4},
1143 new object [] {"ProcedureParameters", 4, 1},
1144 new object [] {"Procedures", 4, 3},
1145 new object [] {"ForeignKeys", 4, 3},
1146 new object [] {"IndexColumns", 5, 4},
1147 new object [] {"Indexes", 4, 3},
1148 new object [] {"UserDefinedTypes", 2, 1}
1151 static DataTable instance;
1152 static public DataTable Instance {
1154 if (instance == null) {
1155 var newInstance = new DataTable ("MetaDataCollections");
1156 foreach (ColumnInfo c in columns)
1157 newInstance.Columns.Add (c.name, c.type);
1158 foreach (object [] row in rows)
1159 newInstance.LoadDataRow (row, true);
1160 instance = newInstance;
1167 static class DataSourceInformation
1169 static readonly ColumnInfo [] columns = {
1170 new ColumnInfo ("CompositeIdentifierSeparatorPattern", typeof (string)),
1171 new ColumnInfo ("DataSourceProductName", typeof(string)),
1172 new ColumnInfo ("DataSourceProductVersion", typeof(string)),
1173 new ColumnInfo ("DataSourceProductVersionNormalized", typeof(string)),
1174 new ColumnInfo ("GroupByBehavior", typeof(GroupByBehavior)),
1175 new ColumnInfo ("IdentifierPattern", typeof(string)),
1176 new ColumnInfo ("IdentifierCase", typeof(IdentifierCase)),
1177 new ColumnInfo ("OrderByColumnsInSelect", typeof(bool)),
1178 new ColumnInfo ("ParameterMarkerFormat", typeof(string)),
1179 new ColumnInfo ("ParameterMarkerPattern", typeof(string)),
1180 new ColumnInfo ("ParameterNameMaxLength", typeof(int)),
1181 new ColumnInfo ("ParameterNamePattern", typeof(string)),
1182 new ColumnInfo ("QuotedIdentifierPattern", typeof(string)),
1183 new ColumnInfo ("QuotedIdentifierCase", typeof(IdentifierCase)),
1184 new ColumnInfo ("StatementSeparatorPattern", typeof(string)),
1185 new ColumnInfo ("StringLiteralPattern", typeof(string)),
1186 new ColumnInfo ("SupportedJoinOperators", typeof(SupportedJoinOperators))
1189 static public DataTable GetInstance (SqlConnection conn)
1191 DataTable table = new DataTable ("DataSourceInformation");
1192 foreach (ColumnInfo c in columns)
1193 table.Columns.Add (c.name, c.type);
1194 DataRow row = table.NewRow ();
1196 row [1] = "Microsoft SQL Server";
1197 row [2] = conn.ServerVersion;;
1198 row [3] = conn.ServerVersion;;
1199 row [4] = GroupByBehavior.Unrelated;
1200 row [5] = @"(^\[\p{Lo}\p{Lu}\p{Ll}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Nd}@$#_]*$)|(^\[[^\]\0]|\]\]+\]$)|(^\""[^\""\0]|\""\""+\""$)";
1201 row [6] = IdentifierCase.Insensitive; // FIXME: obtain this from SQL Server
1204 row [9] = @"@[\p{Lo}\p{Lu}\p{Ll}\p{Lm}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Lm}\p{Nd}\uff3f_@#\$]*(?=\s+|$)";
1206 row [11] = @"^[\p{Lo}\p{Lu}\p{Ll}\p{Lm}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Lm}\p{Nd}\uff3f_@#\$]*(?=\s+|$)";
1207 row [12] = @"(([^\[]|\]\])*)";
1208 row [13] = IdentifierCase.Insensitive; // FIXME: obtain this from SQL Server
1210 row [15] = "'(([^']|'')*)'";
1211 row [16] = (SupportedJoinOperators.FullOuter | SupportedJoinOperators.Inner |
1212 SupportedJoinOperators.LeftOuter | SupportedJoinOperators.RightOuter);
1213 table.Rows.Add (row);
1218 static class DataTypes
1220 static readonly ColumnInfo [] columns = {
1221 new ColumnInfo ("TypeName", typeof(string)),
1222 new ColumnInfo ("ProviderDbType", typeof(int)),
1223 new ColumnInfo ("ColumnSize", typeof(long)),
1224 new ColumnInfo ("CreateFormat", typeof(string)),
1225 new ColumnInfo ("CreateParameters", typeof(string)),
1226 new ColumnInfo ("DataType", typeof(string)),
1227 new ColumnInfo ("IsAutoIncrementable", typeof(bool)),
1228 new ColumnInfo ("IsBestMatch", typeof(bool)),
1229 new ColumnInfo ("IsCaseSensitive", typeof(bool)),
1230 new ColumnInfo ("IsFixedLength", typeof(bool)),
1231 new ColumnInfo ("IsFixedPrecisionScale", typeof(bool)),
1232 new ColumnInfo ("IsLong", typeof(bool)),
1233 new ColumnInfo ("IsNullable", typeof(bool)),
1234 new ColumnInfo ("IsSearchable", typeof(bool)),
1235 new ColumnInfo ("IsSearchableWithLike", typeof(bool)),
1236 new ColumnInfo ("IsUnsigned", typeof(bool)),
1237 new ColumnInfo ("MaximumScale", typeof(short)),
1238 new ColumnInfo ("MinimumScale", typeof(short)),
1239 new ColumnInfo ("IsConcurrencyType", typeof(bool)),
1240 new ColumnInfo ("IsLiteralSupported", typeof(bool)),
1241 new ColumnInfo ("LiteralPrefix", typeof(string)),
1242 new ColumnInfo ("LiteralSuffix", typeof(string))
1245 static readonly object [][] rows = {
1246 new object [] {"smallint", 16, 5, "smallint", null, "System.Int16", true, true,
1247 false, true, true, false, true, true, false, false, null,
1248 null, false, null, null, null},
1249 new object [] {"int", 8, 10, "int", null, "System.Int32",
1250 true, true, false, true, true, false, true, true, false,
1251 false, null, null, false, null, null, null},
1252 new object [] {"real", 13, 7, "real", null,
1253 "System.Single", false, true, false, true, false, false,
1254 true, true, false, false, null, null, false, null, null, null},
1255 new object [] {"float", 6, 53, "float({0})",
1256 "number of bits used to store the mantissa", "System.Double",
1257 false, true, false, true, false, false, true, true,
1258 false, false, null, null, false, null, null, null},
1259 new object [] {"money", 9, 19, "money", null,
1260 "System.Decimal", false, false, false, true, true,
1261 false, true, true, false, false, null, null, false,
1263 new object [] {"smallmoney", 17, 10, "smallmoney", null,
1264 "System.Decimal", false, false, false, true, true, false,
1265 true, true, false, false, null, null, false, null, null, null},
1266 new object [] {"bit", 2, 1, "bit", null, "System.Boolean",
1267 false, false, false, true, false, false, true, true,
1268 false, null, null, null, false, null, null, null},
1269 new object [] {"tinyint", 20, 3, "tinyint", null,
1270 "System.SByte", true, true, false, true, true, false,
1271 true, true, false, true, null, null, false, null, null, null},
1272 new object [] {"bigint", 0, 19, "bigint", null,
1273 "System.Int64", true, true, false, true, true, false,
1274 true, true, false, false, null, null, false, null, null, null},
1275 new object [] {"timestamp", 19, 8, "timestamp", null,
1276 "System.Byte[]", false, false, false, true, false, false,
1277 false, true, false, null, null, null, true, null, "0x", null},
1278 new object [] {"binary", 1, 8000, "binary({0})", "length",
1279 "System.Byte[]", false, true, false, true, false, false,
1280 true, true, false, null, null, null, false, null, "0x", null},
1281 new object [] {"image", 7, 2147483647, "image", null,
1282 "System.Byte[]", false, true, false, false, false, true,
1283 true, false, false, null, null, null, false, null, "0x", null},
1284 new object [] {"text", 18, 2147483647, "text", null,
1285 "System.String", false, true, false, false, false, true,
1286 true, false, true, null, null, null, false, null, "'", "'"},
1287 new object [] {"ntext", 11, 1073741823, "ntext", null,
1288 "System.String", false, true, false, false, false, true,
1289 true, false, true, null, null, null, false, null, "N'", "'"},
1290 new object [] {"decimal", 5, 38, "decimal({0}, {1})",
1291 "precision,scale", "System.Decimal", true, true, false,
1292 true, false, false, true, true, false, false, 38, 0,
1293 false, null, null, null},
1294 new object [] {"numeric", 5, 38, "numeric({0}, {1})",
1295 "precision,scale", "System.Decimal", true, true, false,
1296 true, false, false, true, true, false, false, 38, 0,
1297 false, null, null, null},
1298 new object [] {"datetime", 4, 23, "datetime", null,
1299 "System.DateTime", false, true, false, true, false, false,
1300 true, true, true, null, null, null, false, null, "{ts '", "'}"},
1301 new object [] {"smalldatetime", 15, 16, "smalldatetime", null,
1302 "System.DateTime", false, true, false, true, false, false,
1303 true, true, true, null, null, null, false, null, "{ts '", "'}"},
1304 new object [] {"sql_variant", 23, null, "sql_variant",
1305 null, "System.Object", false, true, false, false, false,
1306 false, true, true, false, null, null, null, false, false,
1308 new object [] {"xml", 25, 2147483647, "xml", null,
1309 "System.String", false, false, false, false, false, true,
1310 true, false, false, null, null, null, false, false, null, null},
1311 new object [] {"varchar", 22, 2147483647, "varchar({0})",
1312 "max length", "System.String", false, true, false, false,
1313 false, false, true, true, true, null, null, null, false,
1315 new object [] {"char", 3, 2147483647, "char({0})", "length",
1316 "System.String", false, true, false, true, false, false,
1317 true, true, true, null, null, null, false, null, "'", "'"},
1318 new object [] {"nchar", 10, 1073741823, "nchar({0})", "length",
1319 "System.String", false, true, false, true, false, false,
1320 true, true, true, null, null, null, false, null, "N'", "'"},
1321 new object [] {"nvarchar", 12, 1073741823, "nvarchar({0})", "max length",
1322 "System.String", false, true, false, false, false, false, true, true,
1323 true, null, null, null, false, null, "N'", "'"},
1324 new object [] {"varbinary", 21, 1073741823, "varbinary({0})",
1325 "max length", "System.Byte[]", false, true, false, false,
1326 false, false, true, true, false, null, null, null, false,
1328 new object [] {"uniqueidentifier", 14, 16, "uniqueidentifier", null,
1329 "System.Guid", false, true, false, true, false, false, true,
1330 true, false, null, null, null, false, null, "'", "'"},
1331 new object [] {"date", 31, 3L, "date", DBNull.Value,
1332 "System.DateTime", false, false, false, true, true, false,
1333 true, true, true, DBNull.Value, DBNull.Value, DBNull.Value,
1334 false, DBNull.Value, "{ts '", "'}"},
1335 new object [] {"time", 32, 5L, "time({0})", "scale",
1336 "System.TimeSpan", false, false, false, false, false, false,
1337 true, true, true, DBNull.Value, (short) 7, (short) 0,
1338 false, DBNull.Value, "{ts '", "'}"},
1339 new object [] {"datetime2", 33, 8L, "datetime2({0})", "scale",
1340 "System.DateTime", false, true, false, false, false, false,
1341 true, true, true, DBNull.Value, (short) 7, (short) 0,
1342 false, DBNull.Value, "{ts '", "'}"},
1343 new object [] {"datetimeoffset", 34, 10L, "datetimeoffset({0})",
1344 "scale", "System.DateTimeOffset", false, true, false, false,
1345 false, false, true, true, true, DBNull.Value, (short) 7, (short) 0,
1346 false, DBNull.Value, "{ts '", "'}"}
1349 static DataTable instance;
1350 static public DataTable Instance {
1352 if (instance == null) {
1353 instance = new DataTable ("DataTypes");
1354 foreach (ColumnInfo c in columns)
1355 instance.Columns.Add (c.name, c.type);
1356 foreach (object [] row in rows)
1357 instance.LoadDataRow (row, true);
1364 static class Restrictions
1366 static readonly ColumnInfo [] columns = {
1367 new ColumnInfo ("CollectionName", typeof (string)),
1368 new ColumnInfo ("RestrictionName", typeof(string)),
1369 new ColumnInfo ("ParameterName", typeof(string)),
1370 new ColumnInfo ("RestrictionDefault", typeof(string)),
1371 new ColumnInfo ("RestrictionNumber", typeof(int))
1374 static readonly object [][] rows = {
1375 new object [] {"Users", "User_Name", "@Name", "name", 1},
1376 new object [] {"Databases", "Name", "@Name", "Name", 1},
1378 new object [] {"Tables", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1379 new object [] {"Tables", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1380 new object [] {"Tables", "Table", "@Name", "TABLE_NAME", 3},
1381 new object [] {"Tables", "TableType", "@TableType", "TABLE_TYPE", 4},
1383 new object [] {"Columns", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1384 new object [] {"Columns", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1385 new object [] {"Columns", "Table", "@Table", "TABLE_NAME", 3},
1386 new object [] {"Columns", "Column", "@Column", "COLUMN_NAME", 4},
1388 new object [] {"StructuredTypeMembers", "Catalog", "@Catalog", "TYPE_CATALOG", 1},
1389 new object [] {"StructuredTypeMembers", "Owner", "@Owner", "TYPE_SCHEMA", 2},
1390 new object [] {"StructuredTypeMembers", "Type", "@Type", "TYPE_NAME", 3},
1391 new object [] {"StructuredTypeMembers", "Member", "@Member", "MEMBER_NAME", 4},
1393 new object [] {"Views", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1394 new object [] {"Views", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1395 new object [] {"Views", "Table", "@Table", "TABLE_NAME", 3},
1397 new object [] {"ViewColumns", "Catalog", "@Catalog", "VIEW_CATALOG", 1},
1398 new object [] {"ViewColumns", "Owner", "@Owner", "VIEW_SCHEMA", 2},
1399 new object [] {"ViewColumns", "Table", "@Table", "VIEW_NAME", 3},
1400 new object [] {"ViewColumns", "Column", "@Column", "COLUMN_NAME", 4},
1402 new object [] {"ProcedureParameters", "Catalog", "@Catalog", "SPECIFIC_CATALOG", 1},
1403 new object [] {"ProcedureParameters", "Owner", "@Owner", "SPECIFIC_SCHEMA", 2},
1404 new object [] {"ProcedureParameters", "Name", "@Name", "SPECIFIC_NAME", 3},
1405 new object [] {"ProcedureParameters", "Parameter", "@Parameter", "PARAMETER_NAME", 4},
1407 new object [] {"Procedures", "Catalog", "@Catalog", "SPECIFIC_CATALOG", 1},
1408 new object [] {"Procedures", "Owner", "@Owner", "SPECIFIC_SCHEMA", 2},
1409 new object [] {"Procedures", "Name", "@Name", "SPECIFIC_NAME", 3},
1410 new object [] {"Procedures", "Type", "@Type", "ROUTINE_TYPE", 4},
1412 new object [] {"IndexColumns", "Catalog", "@Catalog", "db_name()", 1},
1413 new object [] {"IndexColumns", "Owner", "@Owner", "user_name()", 2},
1414 new object [] {"IndexColumns", "Table", "@Table", "o.name", 3},
1415 new object [] {"IndexColumns", "ConstraintName", "@ConstraintName", "x.name", 4},
1416 new object [] {"IndexColumns", "Column", "@Column", "c.name", 5},
1418 new object [] {"Indexes", "Catalog", "@Catalog", "db_name()", 1},
1419 new object [] {"Indexes", "Owner", "@Owner", "user_name()", 2},
1420 new object [] {"Indexes", "Table", "@Table", "o.name", 3},
1421 new object [] {"Indexes", "Name", "@Name", "x.name", 4},
1423 new object [] {"UserDefinedTypes", "assembly_name", "@AssemblyName", "assemblies.name", 1},
1424 new object [] {"UserDefinedTypes", "udt_name", "@UDTName", "types.assembly_class", 2},
1426 new object [] {"ForeignKeys", "Catalog", "@Catalog", "CONSTRAINT_CATALOG", 1},
1427 new object [] {"ForeignKeys", "Owner", "@Owner", "CONSTRAINT_SCHEMA", 2},
1428 new object [] {"ForeignKeys", "Table", "@Table", "TABLE_NAME", 3},
1429 new object [] {"ForeignKeys", "Name", "@Name", "CONSTRAINT_NAME", 4}
1432 static DataTable instance;
1433 static public DataTable Instance {
1435 if (instance == null) {
1436 instance = new DataTable ("Restrictions");
1437 foreach (ColumnInfo c in columns)
1438 instance.Columns.Add (c.name, c.type);
1439 foreach (object [] row in rows)
1440 instance.LoadDataRow (row, true);
1447 public override DataTable GetSchema ()
1449 if (state == ConnectionState.Closed)
1450 throw ExceptionHelper.ConnectionClosed ();
1452 return MetaDataCollections.Instance;
1455 public override DataTable GetSchema (String collectionName)
1457 return GetSchema (collectionName, null);
1460 public override DataTable GetSchema (String collectionName, string [] restrictionValues)
1462 // LAMESPEC: In MS.NET, if collectionName is null, it throws ArgumentException.
1464 if (state == ConnectionState.Closed)
1465 throw ExceptionHelper.ConnectionClosed ();
1467 String cName = null;
1468 DataTable schemaTable = MetaDataCollections.Instance;
1469 int length = restrictionValues == null ? 0 : restrictionValues.Length;
1471 foreach (DataRow row in schemaTable.Rows) {
1472 if (String.Compare ((string) row["CollectionName"], collectionName, true) == 0) {
1473 if (length > (int) row["NumberOfRestrictions"]) {
1474 throw new ArgumentException ("More restrictions were provided " +
1475 "than the requested schema ('" +
1476 row["CollectionName"].ToString () + "') supports");
1478 cName = row["CollectionName"].ToString();
1483 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
1484 "The requested collection ({0}) is not defined.",
1487 SqlCommand command = null;
1488 DataTable dataTable = new DataTable ();
1489 SqlDataAdapter dataAdapter = new SqlDataAdapter ();
1494 command = new SqlCommand ("select name as database_name, dbid, crdate as create_date " +
1495 "from master.sys.sysdatabases where (name = @Name or (@Name " +
1497 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1500 command = new SqlCommand ("select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, " +
1501 "TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_TYPE, " +
1502 "IS_DEFERRABLE, INITIALLY_DEFERRED from " +
1503 "INFORMATION_SCHEMA.TABLE_CONSTRAINTS where (CONSTRAINT_CATALOG" +
1504 " = @Catalog or (@Catalog is null)) and (CONSTRAINT_SCHEMA = " +
1505 "@Owner or (@Owner is null)) and (TABLE_NAME = @Table or (" +
1506 "@Table is null)) and (CONSTRAINT_NAME = @Name or (@Name is null))" +
1507 " and CONSTRAINT_TYPE = 'FOREIGN KEY' order by CONSTRAINT_CATALOG," +
1508 " CONSTRAINT_SCHEMA, CONSTRAINT_NAME", this);
1509 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1510 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1511 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1512 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1515 command = new SqlCommand ("select distinct db_name() as constraint_catalog, " +
1516 "constraint_schema = user_name (o.uid), " +
1517 "constraint_name = x.name, table_catalog = db_name (), " +
1518 "table_schema = user_name (o.uid), table_name = o.name, " +
1519 "index_name = x.name from sysobjects o, sysindexes x, " +
1520 "sysindexkeys xk where o.type in ('U') and x.id = o.id and " +
1521 "o.id = xk.id and x.indid = xk.indid and xk.keyno = x.keycnt " +
1522 "and (db_name() = @Catalog or (@Catalog is null)) and " +
1523 "(user_name() = @Owner or (@Owner is null)) and (o.name = " +
1524 "@Table or (@Table is null)) and (x.name = @Name or (@Name is null))" +
1525 "order by table_name, index_name", this);
1526 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1527 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1528 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1529 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1531 case "IndexColumns":
1532 command = new SqlCommand ("select distinct db_name() as constraint_catalog, " +
1533 "constraint_schema = user_name (o.uid), constraint_name = x.name, " +
1534 "table_catalog = db_name (), table_schema = user_name (o.uid), " +
1535 "table_name = o.name, column_name = c.name, " +
1536 "ordinal_position = convert (int, xk.keyno), keyType = c.xtype, " +
1537 "index_name = x.name from sysobjects o, sysindexes x, syscolumns c, " +
1538 "sysindexkeys xk where o.type in ('U') and x.id = o.id and o.id = c.id " +
1539 "and o.id = xk.id and x.indid = xk.indid and c.colid = xk.colid " +
1540 "and xk.keyno <= x.keycnt and permissions (o.id, c.name) <> 0 " +
1541 "and (db_name() = @Catalog or (@Catalog is null)) and (user_name() " +
1542 "= @Owner or (@Owner is null)) and (o.name = @Table or (@Table is" +
1543 " null)) and (x.name = @ConstraintName or (@ConstraintName is null)) " +
1544 "and (c.name = @Column or (@Column is null)) order by table_name, " +
1545 "index_name", this);
1546 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 8);
1547 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1548 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 13);
1549 command.Parameters.Add ("@ConstraintName", SqlDbType.NVarChar, 4000);
1550 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1553 command = new SqlCommand ("select SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, " +
1554 "ROUTINE_CATALOG, ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE, " +
1555 "CREATED, LAST_ALTERED from INFORMATION_SCHEMA.ROUTINES where " +
1556 "(SPECIFIC_CATALOG = @Catalog or (@Catalog is null)) and " +
1557 "(SPECIFIC_SCHEMA = @Owner or (@Owner is null)) and (SPECIFIC_NAME" +
1558 " = @Name or (@Name is null)) and (ROUTINE_TYPE = @Type or (@Type " +
1559 "is null)) order by SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME", this);
1560 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1561 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1562 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1563 command.Parameters.Add ("@Type", SqlDbType.NVarChar, 4000);
1565 case "ProcedureParameters":
1566 command = new SqlCommand ("select SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, " +
1567 "ORDINAL_POSITION, PARAMETER_MODE, IS_RESULT, AS_LOCATOR, " +
1568 "PARAMETER_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, " +
1569 "CHARACTER_OCTET_LENGTH, COLLATION_CATALOG, COLLATION_SCHEMA, " +
1570 "COLLATION_NAME, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, " +
1571 "CHARACTER_SET_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, " +
1572 "NUMERIC_SCALE, DATETIME_PRECISION, INTERVAL_TYPE, " +
1573 "INTERVAL_PRECISION from INFORMATION_SCHEMA.PARAMETERS where " +
1574 "(SPECIFIC_CATALOG = @Catalog or (@Catalog is null)) and " +
1575 "(SPECIFIC_SCHEMA = @Owner or (@Owner is null)) and (SPECIFIC_NAME = " +
1576 "@Name or (@Name is null)) and (PARAMETER_NAME = @Parameter or (" +
1577 "@Parameter is null)) order by SPECIFIC_CATALOG, SPECIFIC_SCHEMA," +
1578 " SPECIFIC_NAME, PARAMETER_NAME", this);
1579 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1580 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1581 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1582 command.Parameters.Add ("@Parameter", SqlDbType.NVarChar, 4000);
1585 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE " +
1586 "from INFORMATION_SCHEMA.TABLES where" +
1587 " (TABLE_CATALOG = @catalog or (@catalog is null)) and " +
1588 "(TABLE_SCHEMA = @owner or (@owner is null))and " +
1589 "(TABLE_NAME = @name or (@name is null)) and " +
1590 "(TABLE_TYPE = @table_type or (@table_type is null))", this);
1591 command.Parameters.Add ("@catalog", SqlDbType.NVarChar, 8);
1592 command.Parameters.Add ("@owner", SqlDbType.NVarChar, 3);
1593 command.Parameters.Add ("@name", SqlDbType.NVarChar, 11);
1594 command.Parameters.Add ("@table_type", SqlDbType.NVarChar, 10);
1597 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, " +
1598 "ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, " +
1599 "CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH, " +
1600 "NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE, " +
1601 "DATETIME_PRECISION, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, " +
1602 "CHARACTER_SET_NAME, COLLATION_CATALOG from INFORMATION_SCHEMA.COLUMNS" +
1603 " where (TABLE_CATALOG = @Catalog or (@Catalog is null)) and (" +
1604 "TABLE_SCHEMA = @Owner or (@Owner is null)) and (TABLE_NAME = @table" +
1605 " or (@Table is null)) and (COLUMN_NAME = @column or (@Column is null" +
1606 ")) order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME", this);
1607 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1608 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1609 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1610 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1613 command = new SqlCommand ("select uid, name as user_name, createdate, updatedate from sysusers" +
1614 " where (name = @Name or (@Name is null))", this);
1615 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1617 case "StructuredTypeMembers":
1618 // Only available on SQL Server 2008
1619 // Running it again SQL 2005 results in the following exception:
1620 // Unable to build the 'StructuredTypeMembers' collection because
1621 // execution of the SQL query failed. See the inner exception for details.
1622 // ---> System.Data.SqlClient.SqlException: Invalid object name 'sys.table_types'.
1624 // I don't have access to SQL Server 2008 right now,
1625 // and can't find any online documentation on the 'sys.table_types'
1627 throw new NotImplementedException ();
1629 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, CHECK_OPTION, " +
1630 "IS_UPDATABLE from INFORMATION_SCHEMA.VIEWS where (TABLE_CATALOG" +
1631 " = @Catalog or (@Catalog is null)) TABLE_SCHEMA = @Owner or " +
1632 "(@Owner is null)) and (TABLE_NAME = @table or (@Table is null))" +
1633 " order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME", this);
1634 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1635 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1636 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1639 command = new SqlCommand ("select VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME, TABLE_CATALOG, " +
1640 "TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME from " +
1641 "INFORMATION_SCHEMA.VIEW_COLUMN_USAGE where (VIEW_CATALOG = " +
1642 "@Catalog (@Catalog is null)) and (VIEW_SCHEMA = @Owner (@Owner" +
1643 " is null)) and (VIEW_NAME = @Table or (@Table is null)) and " +
1644 "(COLUMN_NAME = @Column or (@Column is null)) order by " +
1645 "VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME", this);
1646 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1647 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1648 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1649 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1651 case "UserDefinedTypes":
1652 command = new SqlCommand ("select assemblies.name as assembly_name, types.assembly_class " +
1653 "as udt_name, ASSEMBLYPROPERTY(assemblies.name, 'VersionMajor') " +
1654 "as version_major, ASSEMBLYPROPERTY(assemblies.name, 'VersionMinor') " +
1655 "as version_minor, ASSEMBLYPROPERTY(assemblies.name, 'VersionBuild') " +
1656 "as version_build, ASSEMBLYPROPERTY(assemblies.name, 'VersionRevision') " +
1657 "as version_revision, ASSEMBLYPROPERTY(assemblies.name, 'CultureInfo') " +
1658 "as culture_info, ASSEMBLYPROPERTY(assemblies.name, 'PublicKey') " +
1659 "as public_key, is_fixed_length, max_length, Create_Date, " +
1660 "Permission_set_desc from sys.assemblies as assemblies join " +
1661 "sys.assembly_types as types on assemblies.assembly_id = types.assembly_id" +
1662 " where (assportemblies.name = @AssemblyName or (@AssemblyName is null)) and " +
1663 "(types.assembly_class = @UDTName or (@UDTName is null))",
1665 command.Parameters.Add ("@AssemblyName", SqlDbType.NVarChar, 4000);
1666 command.Parameters.Add ("@UDTName", SqlDbType.NVarChar, 4000);
1668 case "MetaDataCollections":
1669 return MetaDataCollections.Instance;
1670 case "DataSourceInformation":
1671 return DataSourceInformation.GetInstance (this);
1673 return DataTypes.Instance;
1674 case "ReservedWords":
1675 return ReservedWords.Instance;
1676 case "Restrictions":
1677 return Restrictions.Instance;
1679 for (int i = 0; i < length; i++) {
1680 command.Parameters[i].Value = restrictionValues[i];
1682 dataAdapter.SelectCommand = command;
1683 dataAdapter.Fill (dataTable);
1687 public static void ChangePassword (string connectionString, string newPassword)
1689 if (String.IsNullOrEmpty (connectionString))
1690 throw new ArgumentNullException ("The 'connectionString' cannot be null or empty.");
1691 if (String.IsNullOrEmpty (newPassword))
1692 throw new ArgumentNullException ("The 'newPassword' cannot be null or empty.");
1693 if (newPassword.Length > 128)
1694 throw new ArgumentException ("The length of 'newPassword' cannot exceed 128 characters.");
1695 using (SqlConnection conn = new SqlConnection (connectionString)) {
1697 conn.tds.Execute (String.Format ("sp_password '{0}', '{1}', '{2}'",
1698 conn.parms.Password, newPassword, conn.parms.User));
1702 public static void ClearAllPools ()
1705 IDictionary pools = SqlConnection.sqlConnectionPools.GetConnectionPool ();
1706 foreach (TdsConnectionPool pool in pools.Values) {
1708 pool.ResetConnectionPool ();
1713 public static void ClearPool (SqlConnection connection)
1715 if (connection == null)
1716 throw new ArgumentNullException ("connection");
1719 if (connection.pooling) {
1720 TdsConnectionPool pool = sqlConnectionPools.GetConnectionPool (connection.ConnectionString);
1722 pool.ResetConnectionPool ();
1728 #endregion // Methods
1731 #region Fields Net 2
1736 #endregion // Fields Net 2
1738 #region Properties Net 2
1741 [DataSysDescription ("Enable Asynchronous processing, 'Asynchrouse Processing=true/false' in the ConnectionString.")]
1743 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1744 internal bool AsyncProcessing {
1745 get { return async; }
1748 #endregion // Properties Net 2