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;
56 using System.Collections.Generic;
57 using System.Security;
59 namespace System.Data.SqlClient
61 [DefaultEvent ("InfoMessage")]
62 public sealed class SqlConnection : DbConnection, IDbConnection, ICloneable
68 // The set of SQL connection pools
69 static TdsConnectionPoolManager sqlConnectionPools = new TdsConnectionPoolManager (TdsVersion.tds80);
70 const int DEFAULT_PACKETSIZE = 8000;
71 const int MAX_PACKETSIZE = 32768;
72 const int MIN_PACKETSIZE = 512;
73 const int DEFAULT_CONNECTIONTIMEOUT = 15;
74 const int DEFAULT_CONNECTIONLIFETIME = 0;
75 const int DEFAULT_MAXPOOLSIZE = 100;
76 const int MIN_MAXPOOLSIZE = 1;
77 const int DEFAULT_MINPOOLSIZE = 0;
78 const int DEFAULT_PORT = 1433;
80 // The current connection pool
81 TdsConnectionPool pool;
83 // The connection string that identifies this connection
84 string connectionString;
86 // The connection credentials
87 SqlCredential credentials;
89 // The transaction object for the current transaction
90 SqlTransaction transaction;
92 // Connection parameters
94 TdsConnectionParameters parms;
96 int connectionLifeTime;
99 int connectionTimeout;
104 bool fireInfoMessageEventOnUserErrors;
105 bool statisticsEnabled;
108 ConnectionState state = ConnectionState.Closed;
110 SqlDataReader dataReader;
120 public SqlConnection () : this (null)
124 public SqlConnection (string connectionString)
126 ConnectionString = connectionString;
129 public SqlConnection (string connectionString, SqlCredential cred)
131 ConnectionString = connectionString;
135 #endregion // Constructors
140 [EditorAttribute ("Microsoft.VSDesigner.Data.SQL.Design.SqlConnectionStringEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
141 #pragma warning disable 618 // ignore obsolete warning about RecommendedAsConfigurable to use SettingsBindableAttribute
142 [RecommendedAsConfigurable(true)]
143 #pragma warning restore 618
144 [RefreshProperties (RefreshProperties.All)]
145 public override string ConnectionString {
147 if (connectionString == null)
149 return connectionString;
151 [MonoTODO("persist security info, encrypt, enlist keyword not implemented")]
153 if (state == ConnectionState.Open)
154 throw new InvalidOperationException ("Not Allowed to change ConnectionString property while Connection state is OPEN");
155 SetConnectionString (value);
159 public SqlCredential Credentials {
169 public Guid ClientConnectionId {
171 throw new NotImplementedException ();
175 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
178 int ConnectionTimeout {
179 get { return connectionTimeout; }
182 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
187 if (State == ConnectionState.Open)
189 return parms.Database ;
193 internal SqlDataReader DataReader {
194 get { return dataReader; }
195 set { dataReader = value; }
199 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
203 get { return dataSource; }
206 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
207 public int PacketSize {
209 if (State == ConnectionState.Open)
210 return ((Tds) tds).PacketSize;
216 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
219 string ServerVersion {
221 if (state == ConnectionState.Closed)
222 throw ExceptionHelper.ConnectionClosed ();
224 return tds.ServerVersion;
229 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
232 ConnectionState State {
233 get { return state; }
240 internal SqlTransaction Transaction {
241 get { return transaction; }
242 set { transaction = value; }
245 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
246 public string WorkstationId {
247 get { return parms.Hostname; }
250 internal XmlReader XmlReader {
251 get { return xmlReader; }
252 set { xmlReader = value; }
255 public bool FireInfoMessageEventOnUserErrors {
256 get { return fireInfoMessageEventOnUserErrors; }
257 set { fireInfoMessageEventOnUserErrors = value; }
260 [DefaultValue (false)]
261 public bool StatisticsEnabled {
262 get { return statisticsEnabled; }
263 set { statisticsEnabled = value; }
266 protected override DbProviderFactory DbProviderFactory {
268 return SqlClientFactory.Instance;
272 #endregion // Properties
276 public event SqlInfoMessageEventHandler InfoMessage;
283 private void ErrorHandler (object sender, TdsInternalErrorMessageEventArgs e)
286 if (!tds.IsConnected)
294 throw new SqlException (e.Class, e.LineNumber, e.Message, e.Number, e.Procedure, e.Server, "Mono SqlClient Data Provider", e.State);
297 private void MessageHandler (object sender, TdsInternalInfoMessageEventArgs e)
299 OnSqlInfoMessage (CreateSqlInfoMessageEvent (e.Errors));
302 #endregion // Delegates
306 public new SqlTransaction BeginTransaction ()
308 return BeginTransaction (IsolationLevel.ReadCommitted, String.Empty);
311 public new SqlTransaction BeginTransaction (IsolationLevel iso)
313 return BeginTransaction (iso, String.Empty);
316 public SqlTransaction BeginTransaction (string transactionName)
318 return BeginTransaction (IsolationLevel.ReadCommitted, transactionName);
321 public SqlTransaction BeginTransaction (IsolationLevel iso, string transactionName)
323 if (state == ConnectionState.Closed)
324 throw ExceptionHelper.ConnectionClosed ();
325 if (transaction != null)
326 throw new InvalidOperationException ("SqlConnection does not support parallel transactions.");
328 string isolevel = String.Empty;
330 case IsolationLevel.ReadUncommitted:
331 isolevel = "READ UNCOMMITTED";
333 case IsolationLevel.RepeatableRead:
334 isolevel = "REPEATABLE READ";
336 case IsolationLevel.Serializable:
337 isolevel = "SERIALIZABLE";
339 case IsolationLevel.ReadCommitted:
340 isolevel = "READ COMMITTED";
342 case IsolationLevel.Snapshot:
343 isolevel = "SNAPSHOT";
345 case IsolationLevel.Unspecified:
346 iso = IsolationLevel.ReadCommitted;
347 isolevel = "READ COMMITTED";
349 case IsolationLevel.Chaos:
350 throw new ArgumentOutOfRangeException ("IsolationLevel",
351 string.Format (CultureInfo.CurrentCulture,
352 "The IsolationLevel enumeration " +
353 "value, {0}, is not supported by " +
354 "the .Net Framework SqlClient " +
355 "Data Provider.", (int) iso));
357 throw new ArgumentOutOfRangeException ("IsolationLevel",
358 string.Format (CultureInfo.CurrentCulture,
359 "The IsolationLevel enumeration value, {0}, is invalid.",
363 tds.Execute (String.Format ("SET TRANSACTION ISOLATION LEVEL {0};BEGIN TRANSACTION {1}", isolevel, transactionName));
365 transaction = new SqlTransaction (this, iso);
371 void ChangeDatabase (string database)
373 if (!IsValidDatabaseName (database))
374 throw new ArgumentException (String.Format ("The database name {0} is not valid.", database));
375 if (state != ConnectionState.Open)
376 throw new InvalidOperationException ("The connection is not open.");
377 tds.Execute (String.Format ("use [{0}]", database));
380 private void ChangeState (ConnectionState currentState)
382 if (currentState == state)
385 ConnectionState originalState = state;
386 state = currentState;
387 OnStateChange (CreateStateChangeEvent (originalState, currentState));
394 if (transaction != null && transaction.IsOpen)
395 transaction.Rollback ();
397 if (dataReader != null || xmlReader != null) {
398 if(tds != null) tds.SkipToEnd ();
403 if (tds != null && tds.IsConnected) {
404 if (pooling && tds.Pooling) {
406 pool.ReleaseConnection (tds);
415 tds.TdsErrorMessage -= new TdsInternalErrorMessageEventHandler (ErrorHandler);
416 tds.TdsInfoMessage -= new TdsInternalInfoMessageEventHandler (MessageHandler);
419 ChangeState (ConnectionState.Closed);
422 public new SqlCommand CreateCommand ()
424 SqlCommand command = new SqlCommand ();
425 command.Connection = this;
429 private SqlInfoMessageEventArgs CreateSqlInfoMessageEvent (TdsInternalErrorCollection errors)
431 foreach (TdsInternalError e in errors)
432 return new SqlInfoMessageEventArgs (new SqlException (e.Class, e.LineNumber, e.Message, e.Number, e.Procedure, e.Server, "Mono SqlClient Data Provider", e.State));
437 private StateChangeEventArgs CreateStateChangeEvent (ConnectionState originalState, ConnectionState currentState)
439 return new StateChangeEventArgs (originalState, currentState);
442 protected override void Dispose (bool disposing)
445 if (disposing && !disposed) {
446 if (State == ConnectionState.Open)
448 ConnectionString = null;
452 base.Dispose (disposing);
457 [MonoTODO ("Not sure what this means at present.")]
458 public void EnlistDistributedTransaction (ITransaction transaction)
460 throw new NotImplementedException ();
464 object ICloneable.Clone ()
466 return new SqlConnection (ConnectionString);
469 protected override DbTransaction BeginDbTransaction (IsolationLevel isolationLevel)
471 return BeginTransaction (isolationLevel);
474 protected override DbCommand CreateDbCommand ()
476 return CreateCommand ();
483 string serverName = string.Empty;
484 if (state == ConnectionState.Open)
485 throw new InvalidOperationException ("The Connection is already Open (State=Open)");
487 if (connectionString == null || connectionString.Trim().Length == 0)
488 throw new InvalidOperationException ("Connection string has not been initialized.");
492 if(!ParseDataSource (dataSource, out port, out serverName))
493 throw new SqlException(20, 0, "SQL Server does not exist or access denied.", 17, "ConnectionOpen (Connect()).", dataSource, parms.ApplicationName, 0);
494 tds = new Tds80 (serverName, port, PacketSize, ConnectionTimeout, 0);
498 if(!ParseDataSource (dataSource, out port, out serverName))
499 throw new SqlException(20, 0, "SQL Server does not exist or access denied.", 17, "ConnectionOpen (Connect()).", dataSource, parms.ApplicationName, 0);
501 TdsConnectionInfo info = new TdsConnectionInfo (serverName, port, packetSize, ConnectionTimeout, minPoolSize, maxPoolSize, connectionLifeTime);
502 pool = sqlConnectionPools.GetConnectionPool (connectionString, info);
503 tds = pool.GetConnection ();
505 } catch (TdsTimeoutException e) {
506 throw SqlException.FromTdsInternalException ((TdsInternalException) e);
507 } catch (TdsInternalException e) {
508 throw SqlException.FromTdsInternalException (e);
511 tds.TdsErrorMessage += new TdsInternalErrorMessageEventHandler (ErrorHandler);
512 tds.TdsInfoMessage += new TdsInternalInfoMessageEventHandler (MessageHandler);
514 if (!tds.IsConnected) {
516 if (Credentials != null) {
517 if (parms.User != String.Empty)
518 throw new ArgumentException("UserID already specified");
519 if (parms.PasswordSet)
520 throw new ArgumentException("Password already specified");
521 if (parms.DomainLogin != false)
522 throw new ArgumentException("Cannot use credentials with DomainLogin");
523 parms.User = Credentials.UserId;
524 parms.Password = Credentials.Password;
529 pool.ReleaseConnection (tds);
534 disposed = false; // reset this, so using () would call Close ().
535 ChangeState (ConnectionState.Open);
538 private bool ParseDataSource (string theDataSource, out int thePort, out string theServerName)
540 theServerName = string.Empty;
541 string theInstanceName = string.Empty;
543 if (theDataSource == null)
544 throw new ArgumentException("Format of initialization string does not conform to specifications");
546 thePort = DEFAULT_PORT; // default TCP port for SQL Server
550 if ((idx = theDataSource.IndexOf (',')) > -1) {
551 theServerName = theDataSource.Substring (0, idx);
552 string p = theDataSource.Substring (idx + 1);
553 thePort = Int32.Parse (p);
554 } else if ((idx = theDataSource.IndexOf ('\\')) > -1) {
555 theServerName = theDataSource.Substring (0, idx);
556 theInstanceName = theDataSource.Substring (idx + 1);
558 // do port discovery via UDP port 1434
559 port = DiscoverTcpPortViaSqlMonitor (theServerName, theInstanceName);
563 theServerName = theDataSource;
565 if (theServerName.Length == 0 || theServerName == "(local)" || theServerName == ".")
566 theServerName = "localhost";
568 if ((idx = theServerName.IndexOf ("tcp:")) > -1)
569 theServerName = theServerName.Substring (idx + 4);
574 private bool ConvertIntegratedSecurity (string value)
576 if (value.ToUpper() == "SSPI")
579 return ConvertToBoolean ("integrated security", value, false);
582 private bool ConvertToBoolean (string key, string value, bool defaultValue)
584 if (value.Length == 0)
587 string upperValue = value.ToUpper ();
589 if (upperValue == "TRUE" || upperValue == "YES")
591 else if (upperValue == "FALSE" || upperValue == "NO")
594 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
595 "Invalid value \"{0}\" for key '{1}'.", value, key));
598 private int ConvertToInt32 (string key, string value, int defaultValue)
600 if (value.Length == 0)
604 return int.Parse (value);
605 } catch (Exception ex) {
606 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
607 "Invalid value \"{0}\" for key '{1}'.", value, key), ex);
611 private int DiscoverTcpPortViaSqlMonitor (string ServerName, string InstanceName)
613 SqlMonitorSocket msock;
614 msock = new SqlMonitorSocket (ServerName, InstanceName);
615 int SqlServerPort = msock.DiscoverTcpPort (ConnectionTimeout);
617 return SqlServerPort;
620 void SetConnectionString (string connectionString)
622 SetDefaultConnectionParameters ();
624 if ((connectionString == null) || (connectionString.Trim().Length == 0)) {
625 this.connectionString = connectionString;
629 connectionString += ";";
631 bool inQuote = false;
632 bool inDQuote = false;
635 string name = String.Empty;
636 string value = String.Empty;
637 StringBuilder sb = new StringBuilder ();
639 for (int i = 0; i < connectionString.Length; i += 1) {
640 char c = connectionString [i];
642 if (i == connectionString.Length - 1)
645 peek = connectionString [i + 1];
651 else if (peek.Equals (c)) {
661 else if (peek.Equals (c)) {
666 inDQuote = !inDQuote;
669 if (inDQuote || inQuote)
672 if (name != String.Empty && name != null) {
673 value = sb.ToString ();
674 SetProperties (name.ToLower ().Trim() , value);
676 else if (sb.Length != 0)
677 throw new ArgumentException ("Format of initialization string does not conform to specifications");
680 value = String.Empty;
681 sb = new StringBuilder ();
685 if (inDQuote || inQuote || !inName)
687 else if (peek.Equals (c)) {
693 name = sb.ToString ();
694 sb = new StringBuilder ();
699 if (inQuote || inDQuote)
701 else if (sb.Length > 0 && !peek.Equals (';'))
710 if (minPoolSize > maxPoolSize)
711 throw new ArgumentException ("Invalid value for "
712 + "'min pool size' or 'max pool size'; "
713 + "'min pool size' must not be greater "
714 + "than 'max pool size'.");
716 connectionString = connectionString.Substring (0 , connectionString.Length-1);
717 this.connectionString = connectionString;
720 void SetDefaultConnectionParameters ()
723 parms = new TdsConnectionParameters ();
726 dataSource = string.Empty;
727 connectionTimeout = DEFAULT_CONNECTIONTIMEOUT;
728 connectionLifeTime = DEFAULT_CONNECTIONLIFETIME;
729 connectionReset = true;
731 maxPoolSize = DEFAULT_MAXPOOLSIZE;
732 minPoolSize = DEFAULT_MINPOOLSIZE;
733 packetSize = DEFAULT_PACKETSIZE;
738 private void SetProperties (string name , string value)
742 case "application name" :
743 parms.ApplicationName = value;
745 case "attachdbfilename" :
746 case "extended properties" :
747 case "initial file name" :
748 parms.AttachDBFileName = value;
751 case "connect timeout" :
752 case "connection timeout" :
753 int tmpTimeout = ConvertToInt32 ("connect timeout", value,
754 DEFAULT_CONNECTIONTIMEOUT);
756 throw new ArgumentException ("Invalid 'connect timeout'. Must be an integer >=0 ");
758 connectionTimeout = tmpTimeout;
760 case "connection lifetime" :
761 connectionLifeTime = ConvertToInt32 ("connection lifetime", value, DEFAULT_CONNECTIONLIFETIME);
763 case "connection reset" :
764 connectionReset = ConvertToBoolean ("connection reset", value, true);
767 case "current language" :
768 parms.Language = value;
774 case "network address" :
778 if (ConvertToBoolean (name, value, false))
779 throw new NotImplementedException("SSL encryption for"
780 + " data sent between client and server is not"
784 if (!ConvertToBoolean (name, value, true))
785 throw new NotImplementedException("Disabling the automatic"
786 + " enlistment of connections in the thread's current"
787 + " transaction context is not implemented.");
789 case "initial catalog" :
791 parms.Database = value;
793 case "integrated security" :
794 case "trusted_connection" :
795 parms.DomainLogin = ConvertIntegratedSecurity(value);
797 case "max pool size" :
798 int tmpMaxPoolSize = ConvertToInt32 (name, value, DEFAULT_MAXPOOLSIZE);
799 if (tmpMaxPoolSize < MIN_MAXPOOLSIZE)
800 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
801 "Invalid '{0}'. The value must be greater than {1}.",
802 name, MIN_MAXPOOLSIZE));
804 maxPoolSize = tmpMaxPoolSize;
806 case "min pool size" :
807 int tmpMinPoolSize = ConvertToInt32 (name, value, DEFAULT_MINPOOLSIZE);
808 if (tmpMinPoolSize < 0)
809 throw new ArgumentException ("Invalid 'min pool size'. Must be a integer >= 0");
811 minPoolSize = tmpMinPoolSize;
813 case "multipleactiveresultsets":
814 // FIXME: not implemented
815 ConvertToBoolean (name, value, false);
817 case "asynchronous processing" :
819 async = ConvertToBoolean (name, value, false);
823 case "network library" :
824 if (!value.ToUpper ().Equals ("DBMSSOCN"))
825 throw new ArgumentException ("Unsupported network library.");
828 int tmpPacketSize = ConvertToInt32 (name, value, DEFAULT_PACKETSIZE);
829 if (tmpPacketSize < MIN_PACKETSIZE || tmpPacketSize > MAX_PACKETSIZE)
830 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
831 "Invalid 'Packet Size'. The value must be between {0} and {1}.",
832 MIN_PACKETSIZE, MAX_PACKETSIZE));
834 packetSize = tmpPacketSize;
838 parms.Password = new SecureString();
839 foreach (char c in value)
840 parms.Password.AppendChar(c);
841 parms.PasswordSet = true;
843 case "persistsecurityinfo" :
844 case "persist security info" :
845 // FIXME : not implemented
846 // throw new NotImplementedException ();
849 pooling = ConvertToBoolean (name, value, true);
857 case "workstation id" :
858 parms.Hostname = value;
860 case "user instance":
861 userInstance = ConvertToBoolean (name, value, false);
864 throw new ArgumentException("Keyword not supported : '" + name + "'.");
868 static bool IsValidDatabaseName (string database)
870 if ( database == null || database.Trim().Length == 0 || database.Length > 128)
873 if (database[0] == '"' && database[database.Length] == '"')
874 database = database.Substring (1, database.Length - 2);
875 else if (Char.IsDigit (database[0]))
878 if (database[0] == '_')
881 foreach (char c in database.Substring (1, database.Length - 1))
882 if (!Char.IsLetterOrDigit (c) && c != '_' && c != '-')
887 private void OnSqlInfoMessage (SqlInfoMessageEventArgs value)
889 if (InfoMessage != null)
890 InfoMessage (this, value);
894 private sealed class SqlMonitorSocket : UdpClient
896 // UDP port that the SQL Monitor listens
897 private static readonly int SqlMonitorUdpPort = 1434;
898 //private static readonly string SqlServerNotExist = "SQL Server does not exist or access denied";
900 private string server;
901 private string instance;
903 internal SqlMonitorSocket (string ServerName, string InstanceName)
904 : base (ServerName, SqlMonitorUdpPort)
907 instance = InstanceName;
910 internal int DiscoverTcpPort (int timeoutSeconds)
912 int SqlServerTcpPort;
913 Client.Blocking = false;
914 // send command to UDP 1434 (SQL Monitor) to get
915 // the TCP port to connect to the MS SQL server
916 ASCIIEncoding enc = new ASCIIEncoding ();
917 Byte[] rawrq = new Byte [instance.Length + 1];
919 enc.GetBytes (instance, 0, instance.Length, rawrq, 1);
920 Send (rawrq, rawrq.Length);
926 long timeout = timeoutSeconds * 1000000;
927 result = Client.Poll ((int)timeout, SelectMode.SelectRead);
931 if (Client.Available <= 0)
934 IPEndPoint remoteEndpoint;
935 switch (Client.AddressFamily) {
936 case AddressFamily.InterNetwork:
937 remoteEndpoint = new IPEndPoint(IPAddress.Any, 0);
939 case AddressFamily.InterNetworkV6:
940 remoteEndpoint = new IPEndPoint(IPAddress.IPv6Any, 0);
948 rawrs = Receive (ref remoteEndpoint);
950 string rs = Encoding.ASCII.GetString (rawrs);
952 string[] rawtokens = rs.Split (';');
953 Hashtable data = new Hashtable ();
954 for (int i = 0; i < rawtokens.Length / 2 && i < 256; i++) {
955 data [rawtokens [i * 2]] = rawtokens [ i * 2 + 1];
958 if (!data.ContainsKey ("tcp")) {
959 string msg = "Mono does not support names pipes or shared memory "
960 + "for connecting to SQL Server. Please enable the TCP/IP "
962 throw new NotImplementedException (msg);
965 SqlServerTcpPort = int.Parse ((string) data ["tcp"]);
968 return SqlServerTcpPort;
977 public ColumnInfo (string name, Type type)
979 this.name = name; this.type = type;
983 static class ReservedWords
985 static readonly string [] reservedWords =
987 "ADD", "EXCEPT", "PERCENT", "ALL", "EXEC", "PLAN", "ALTER",
988 "EXECUTE", "PRECISION", "AND", "EXISTS", "PRIMARY", "ANY",
989 "EXIT", "PRINT", "AS", "FETCH", "PROC", "ASC", "FILE",
990 "PROCEDURE", "AUTHORIZATION", "FILLFACTOR", "PUBLIC",
991 "BACKUP", "FOR", "RAISERROR", "BEGIN", "FOREIGN", "READ",
992 "BETWEEN", "FREETEXT", "READTEXT", "BREAK", "FREETEXTTABLE",
993 "RECONFIGURE", "BROWSE", "FROM", "REFERENCES", "BULK",
994 "FULL", "REPLICATION", "BY", "FUNCTION", "RESTORE",
995 "CASCADE", "GOTO", "RESTRICT", "CASE", "GRANT", "RETURN",
996 "CHECK", "GROUP", "REVOKE", "CHECKPOINT", "HAVING", "RIGHT",
997 "CLOSE", "HOLDLOCK", "ROLLBACK", "CLUSTERED", "IDENTITY",
998 "ROWCOUNT", "COALESCE", "IDENTITY_INSERT", "ROWGUIDCOL",
999 "COLLATE", "IDENTITYCOL", "RULE", "COLUMN", "IF", "SAVE",
1000 "COMMIT", "IN", "SCHEMA", "COMPUTE", "INDEX", "SELECT",
1001 "CONSTRAINT", "INNER", "SESSION_USER", "CONTAINS", "INSERT",
1002 "SET", "CONTAINSTABLE", "INTERSECT", "SETUSER", "CONTINUE",
1003 "INTO", "SHUTDOWN", "CONVERT", "IS", "SOME", "CREATE",
1004 "JOIN", "STATISTICS", "CROSS", "KEY", "SYSTEM_USER",
1005 "CURRENT", "KILL", "TABLE", "CURRENT_DATE", "LEFT",
1006 "TEXTSIZE", "CURRENT_TIME", "LIKE", "THEN",
1007 "CURRENT_TIMESTAMP", "LINENO", "TO", "CURRENT_USER", "LOAD",
1008 "TOP", "CURSOR", "NATIONAL", "TRAN", "DATABASE", "NOCHECK",
1009 "TRANSACTION", "DBCC", "NONCLUSTERED", "TRIGGER",
1010 "DEALLOCATE", "NOT", "TRUNCATE", "DECLARE", "NULL",
1011 "TSEQUAL", "DEFAULT", "NULLIF", "UNION", "DELETE", "OF",
1012 "UNIQUE", "DENY", "OFF", "UPDATE", "DESC", "OFFSETS",
1013 "UPDATETEXT", "DISK", "ON", "USE", "DISTINCT", "OPEN",
1014 "USER", "DISTRIBUTED", "OPENDATASOURCE", "VALUES", "DOUBLE",
1015 "OPENQUERY", "VARYING", "DROP", "OPENROWSET", "VIEW",
1016 "DUMMY", "OPENXML", "WAITFOR", "DUMP", "OPTION", "WHEN",
1017 "ELSE", "OR", "WHERE", "END", "ORDER", "WHILE", "ERRLVL",
1018 "OUTER", "WITH", "ESCAPE", "OVER", "WRITETEXT", "ABSOLUTE",
1019 "FOUND", "PRESERVE", "ACTION", "FREE", "PRIOR", "ADMIN",
1020 "GENERAL", "PRIVILEGES", "AFTER", "GET", "READS",
1021 "AGGREGATE", "GLOBAL", "REAL", "ALIAS", "GO", "RECURSIVE",
1022 "ALLOCATE", "GROUPING", "REF", "ARE", "HOST", "REFERENCING",
1023 "ARRAY", "HOUR", "RELATIVE", "ASSERTION", "IGNORE", "RESULT",
1024 "AT", "IMMEDIATE", "RETURNS", "BEFORE", "INDICATOR", "ROLE",
1025 "BINARY", "INITIALIZE", "ROLLUP", "BIT", "INITIALLY",
1026 "ROUTINE", "BLOB", "INOUT", "ROW", "BOOLEAN", "INPUT",
1027 "ROWS", "BOTH", "INT", "SAVEPOINT", "BREADTH", "INTEGER",
1028 "SCROLL", "CALL", "INTERVAL", "SCOPE", "CASCADED",
1029 "ISOLATION", "SEARCH", "CAST", "ITERATE", "SECOND",
1030 "CATALOG", "LANGUAGE", "SECTION", "CHAR", "LARGE",
1031 "SEQUENCE", "CHARACTER", "LAST", "SESSION", "CLASS",
1032 "LATERAL", "SETS", "CLOB", "LEADING", "SIZE", "COLLATION",
1033 "LESS", "SMALLINT", "COMPLETION", "LEVEL", "SPACE",
1034 "CONNECT", "LIMIT", "SPECIFIC", "CONNECTION", "LOCAL",
1035 "SPECIFICTYPE", "CONSTRAINTS", "LOCALTIME", "SQL",
1036 "CONSTRUCTOR", "LOCALTIMESTAMP", "SQLEXCEPTION",
1037 "CORRESPONDING", "LOCATOR", "SQLSTATE", "CUBE", "MAP",
1038 "SQLWARNING", "CURRENT_PATH", "MATCH", "START",
1039 "CURRENT_ROLE", "MINUTE", "STATE", "CYCLE", "MODIFIES",
1040 "STATEMENT", "DATA", "MODIFY", "STATIC", "DATE", "MODULE",
1041 "STRUCTURE", "DAY", "MONTH", "TEMPORARY", "DEC", "NAMES",
1042 "TERMINATE", "DECIMAL", "NATURAL", "THAN", "DEFERRABLE",
1043 "NCHAR", "TIME", "DEFERRED", "NCLOB", "TIMESTAMP", "DEPTH",
1044 "NEW", "TIMEZONE_HOUR", "DEREF", "NEXT", "TIMEZONE_MINUTE",
1045 "DESCRIBE", "NO", "TRAILING", "DESCRIPTOR", "NONE",
1046 "TRANSLATION", "DESTROY", "NUMERIC", "TREAT", "DESTRUCTOR",
1047 "OBJECT", "TRUE", "DETERMINISTIC", "OLD", "UNDER",
1048 "DICTIONARY", "ONLY", "UNKNOWN", "DIAGNOSTICS", "OPERATION",
1049 "UNNEST", "DISCONNECT", "ORDINALITY", "USAGE", "DOMAIN",
1050 "OUT", "USING", "DYNAMIC", "OUTPUT", "VALUE", "EACH",
1051 "PAD", "VARCHAR", "END-EXEC", "PARAMETER", "VARIABLE",
1052 "EQUALS", "PARAMETERS", "WHENEVER", "EVERY", "PARTIAL",
1053 "WITHOUT", "EXCEPTION", "PATH", "WORK", "EXTERNAL",
1054 "POSTFIX", "WRITE", "FALSE", "PREFIX", "YEAR", "FIRST",
1055 "PREORDER", "ZONE", "FLOAT", "PREPARE", "ADA", "AVG",
1056 "BIT_LENGTH", "CHAR_LENGTH", "CHARACTER_LENGTH", "COUNT",
1057 "EXTRACT", "FORTRAN", "INCLUDE", "INSENSITIVE", "LOWER",
1058 "MAX", "MIN", "OCTET_LENGTH", "OVERLAPS", "PASCAL",
1059 "POSITION", "SQLCA", "SQLCODE", "SQLERROR", "SUBSTRING",
1060 "SUM", "TRANSLATE", "TRIM", "UPPER"
1062 static DataTable instance;
1063 static public DataTable Instance {
1065 if (instance == null) {
1067 var newInstance = new DataTable ("ReservedWords");
1068 newInstance.Columns.Add ("ReservedWord", typeof(string));
1069 foreach (string reservedWord in reservedWords)
1071 row = newInstance.NewRow();
1073 row["ReservedWord"] = reservedWord;
1074 newInstance.Rows.Add(row);
1076 instance = newInstance;
1083 static class MetaDataCollections
1085 static readonly ColumnInfo [] columns = {
1086 new ColumnInfo ("CollectionName", typeof (string)),
1087 new ColumnInfo ("NumberOfRestrictions", typeof (int)),
1088 new ColumnInfo ("NumberOfIdentifierParts", typeof (int))
1091 static readonly object [][] rows = {
1092 new object [] {"MetaDataCollections", 0, 0},
1093 new object [] {"DataSourceInformation", 0, 0},
1094 new object [] {"DataTypes", 0, 0},
1095 new object [] {"Restrictions", 0, 0},
1096 new object [] {"ReservedWords", 0, 0},
1097 new object [] {"Users", 1, 1},
1098 new object [] {"Databases", 1, 1},
1099 new object [] {"Tables", 4, 3},
1100 new object [] {"Columns", 4, 4},
1101 new object [] {"StructuredTypeMembers", 4, 4},
1102 new object [] {"Views", 3, 3},
1103 new object [] {"ViewColumns", 4, 4},
1104 new object [] {"ProcedureParameters", 4, 1},
1105 new object [] {"Procedures", 4, 3},
1106 new object [] {"ForeignKeys", 4, 3},
1107 new object [] {"IndexColumns", 5, 4},
1108 new object [] {"Indexes", 4, 3},
1109 new object [] {"UserDefinedTypes", 2, 1}
1112 static DataTable instance;
1113 static public DataTable Instance {
1115 if (instance == null) {
1116 var newInstance = new DataTable ("MetaDataCollections");
1117 foreach (ColumnInfo c in columns)
1118 newInstance.Columns.Add (c.name, c.type);
1119 foreach (object [] row in rows)
1120 newInstance.LoadDataRow (row, true);
1121 instance = newInstance;
1128 static class DataSourceInformation
1130 static readonly ColumnInfo [] columns = {
1131 new ColumnInfo ("CompositeIdentifierSeparatorPattern", typeof (string)),
1132 new ColumnInfo ("DataSourceProductName", typeof(string)),
1133 new ColumnInfo ("DataSourceProductVersion", typeof(string)),
1134 new ColumnInfo ("DataSourceProductVersionNormalized", typeof(string)),
1135 new ColumnInfo ("GroupByBehavior", typeof(GroupByBehavior)),
1136 new ColumnInfo ("IdentifierPattern", typeof(string)),
1137 new ColumnInfo ("IdentifierCase", typeof(IdentifierCase)),
1138 new ColumnInfo ("OrderByColumnsInSelect", typeof(bool)),
1139 new ColumnInfo ("ParameterMarkerFormat", typeof(string)),
1140 new ColumnInfo ("ParameterMarkerPattern", typeof(string)),
1141 new ColumnInfo ("ParameterNameMaxLength", typeof(int)),
1142 new ColumnInfo ("ParameterNamePattern", typeof(string)),
1143 new ColumnInfo ("QuotedIdentifierPattern", typeof(string)),
1144 new ColumnInfo ("QuotedIdentifierCase", typeof(IdentifierCase)),
1145 new ColumnInfo ("StatementSeparatorPattern", typeof(string)),
1146 new ColumnInfo ("StringLiteralPattern", typeof(string)),
1147 new ColumnInfo ("SupportedJoinOperators", typeof(SupportedJoinOperators))
1150 static public DataTable GetInstance (SqlConnection conn)
1152 DataTable table = new DataTable ("DataSourceInformation");
1153 foreach (ColumnInfo c in columns)
1154 table.Columns.Add (c.name, c.type);
1155 DataRow row = table.NewRow ();
1157 row [1] = "Microsoft SQL Server";
1158 row [2] = conn.ServerVersion;;
1159 row [3] = conn.ServerVersion;;
1160 row [4] = GroupByBehavior.Unrelated;
1161 row [5] = @"(^\[\p{Lo}\p{Lu}\p{Ll}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Nd}@$#_]*$)|(^\[[^\]\0]|\]\]+\]$)|(^\""[^\""\0]|\""\""+\""$)";
1162 row [6] = IdentifierCase.Insensitive; // FIXME: obtain this from SQL Server
1165 row [9] = @"@[\p{Lo}\p{Lu}\p{Ll}\p{Lm}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Lm}\p{Nd}\uff3f_@#\$]*(?=\s+|$)";
1167 row [11] = @"^[\p{Lo}\p{Lu}\p{Ll}\p{Lm}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Lm}\p{Nd}\uff3f_@#\$]*(?=\s+|$)";
1168 row [12] = @"(([^\[]|\]\])*)";
1169 row [13] = IdentifierCase.Insensitive; // FIXME: obtain this from SQL Server
1171 row [15] = "'(([^']|'')*)'";
1172 row [16] = (SupportedJoinOperators.FullOuter | SupportedJoinOperators.Inner |
1173 SupportedJoinOperators.LeftOuter | SupportedJoinOperators.RightOuter);
1174 table.Rows.Add (row);
1179 static class DataTypes
1181 static readonly ColumnInfo [] columns = {
1182 new ColumnInfo ("TypeName", typeof(string)),
1183 new ColumnInfo ("ProviderDbType", typeof(int)),
1184 new ColumnInfo ("ColumnSize", typeof(long)),
1185 new ColumnInfo ("CreateFormat", typeof(string)),
1186 new ColumnInfo ("CreateParameters", typeof(string)),
1187 new ColumnInfo ("DataType", typeof(string)),
1188 new ColumnInfo ("IsAutoIncrementable", typeof(bool)),
1189 new ColumnInfo ("IsBestMatch", typeof(bool)),
1190 new ColumnInfo ("IsCaseSensitive", typeof(bool)),
1191 new ColumnInfo ("IsFixedLength", typeof(bool)),
1192 new ColumnInfo ("IsFixedPrecisionScale", typeof(bool)),
1193 new ColumnInfo ("IsLong", typeof(bool)),
1194 new ColumnInfo ("IsNullable", typeof(bool)),
1195 new ColumnInfo ("IsSearchable", typeof(bool)),
1196 new ColumnInfo ("IsSearchableWithLike", typeof(bool)),
1197 new ColumnInfo ("IsUnsigned", typeof(bool)),
1198 new ColumnInfo ("MaximumScale", typeof(short)),
1199 new ColumnInfo ("MinimumScale", typeof(short)),
1200 new ColumnInfo ("IsConcurrencyType", typeof(bool)),
1201 new ColumnInfo ("IsLiteralSupported", typeof(bool)),
1202 new ColumnInfo ("LiteralPrefix", typeof(string)),
1203 new ColumnInfo ("LiteralSuffix", typeof(string))
1206 static readonly object [][] rows = {
1207 new object [] {"smallint", 16, 5, "smallint", null, "System.Int16", true, true,
1208 false, true, true, false, true, true, false, false, null,
1209 null, false, null, null, null},
1210 new object [] {"int", 8, 10, "int", null, "System.Int32",
1211 true, true, false, true, true, false, true, true, false,
1212 false, null, null, false, null, null, null},
1213 new object [] {"real", 13, 7, "real", null,
1214 "System.Single", false, true, false, true, false, false,
1215 true, true, false, false, null, null, false, null, null, null},
1216 new object [] {"float", 6, 53, "float({0})",
1217 "number of bits used to store the mantissa", "System.Double",
1218 false, true, false, true, false, false, true, true,
1219 false, false, null, null, false, null, null, null},
1220 new object [] {"money", 9, 19, "money", null,
1221 "System.Decimal", false, false, false, true, true,
1222 false, true, true, false, false, null, null, false,
1224 new object [] {"smallmoney", 17, 10, "smallmoney", null,
1225 "System.Decimal", false, false, false, true, true, false,
1226 true, true, false, false, null, null, false, null, null, null},
1227 new object [] {"bit", 2, 1, "bit", null, "System.Boolean",
1228 false, false, false, true, false, false, true, true,
1229 false, null, null, null, false, null, null, null},
1230 new object [] {"tinyint", 20, 3, "tinyint", null,
1231 "System.SByte", true, true, false, true, true, false,
1232 true, true, false, true, null, null, false, null, null, null},
1233 new object [] {"bigint", 0, 19, "bigint", null,
1234 "System.Int64", true, true, false, true, true, false,
1235 true, true, false, false, null, null, false, null, null, null},
1236 new object [] {"timestamp", 19, 8, "timestamp", null,
1237 "System.Byte[]", false, false, false, true, false, false,
1238 false, true, false, null, null, null, true, null, "0x", null},
1239 new object [] {"binary", 1, 8000, "binary({0})", "length",
1240 "System.Byte[]", false, true, false, true, false, false,
1241 true, true, false, null, null, null, false, null, "0x", null},
1242 new object [] {"image", 7, 2147483647, "image", null,
1243 "System.Byte[]", false, true, false, false, false, true,
1244 true, false, false, null, null, null, false, null, "0x", null},
1245 new object [] {"text", 18, 2147483647, "text", null,
1246 "System.String", false, true, false, false, false, true,
1247 true, false, true, null, null, null, false, null, "'", "'"},
1248 new object [] {"ntext", 11, 1073741823, "ntext", null,
1249 "System.String", false, true, false, false, false, true,
1250 true, false, true, null, null, null, false, null, "N'", "'"},
1251 new object [] {"decimal", 5, 38, "decimal({0}, {1})",
1252 "precision,scale", "System.Decimal", true, true, false,
1253 true, false, false, true, true, false, false, 38, 0,
1254 false, null, null, null},
1255 new object [] {"numeric", 5, 38, "numeric({0}, {1})",
1256 "precision,scale", "System.Decimal", true, true, false,
1257 true, false, false, true, true, false, false, 38, 0,
1258 false, null, null, null},
1259 new object [] {"datetime", 4, 23, "datetime", null,
1260 "System.DateTime", false, true, false, true, false, false,
1261 true, true, true, null, null, null, false, null, "{ts '", "'}"},
1262 new object [] {"smalldatetime", 15, 16, "smalldatetime", null,
1263 "System.DateTime", false, true, false, true, false, false,
1264 true, true, true, null, null, null, false, null, "{ts '", "'}"},
1265 new object [] {"sql_variant", 23, null, "sql_variant",
1266 null, "System.Object", false, true, false, false, false,
1267 false, true, true, false, null, null, null, false, false,
1269 new object [] {"xml", 25, 2147483647, "xml", null,
1270 "System.String", false, false, false, false, false, true,
1271 true, false, false, null, null, null, false, false, null, null},
1272 new object [] {"varchar", 22, 2147483647, "varchar({0})",
1273 "max length", "System.String", false, true, false, false,
1274 false, false, true, true, true, null, null, null, false,
1276 new object [] {"char", 3, 2147483647, "char({0})", "length",
1277 "System.String", false, true, false, true, false, false,
1278 true, true, true, null, null, null, false, null, "'", "'"},
1279 new object [] {"nchar", 10, 1073741823, "nchar({0})", "length",
1280 "System.String", false, true, false, true, false, false,
1281 true, true, true, null, null, null, false, null, "N'", "'"},
1282 new object [] {"nvarchar", 12, 1073741823, "nvarchar({0})", "max length",
1283 "System.String", false, true, false, false, false, false, true, true,
1284 true, null, null, null, false, null, "N'", "'"},
1285 new object [] {"varbinary", 21, 1073741823, "varbinary({0})",
1286 "max length", "System.Byte[]", false, true, false, false,
1287 false, false, true, true, false, null, null, null, false,
1289 new object [] {"uniqueidentifier", 14, 16, "uniqueidentifier", null,
1290 "System.Guid", false, true, false, true, false, false, true,
1291 true, false, null, null, null, false, null, "'", "'"},
1292 new object [] {"date", 31, 3L, "date", DBNull.Value,
1293 "System.DateTime", false, false, false, true, true, false,
1294 true, true, true, DBNull.Value, DBNull.Value, DBNull.Value,
1295 false, DBNull.Value, "{ts '", "'}"},
1296 new object [] {"time", 32, 5L, "time({0})", "scale",
1297 "System.TimeSpan", false, false, false, false, false, false,
1298 true, true, true, DBNull.Value, (short) 7, (short) 0,
1299 false, DBNull.Value, "{ts '", "'}"},
1300 new object [] {"datetime2", 33, 8L, "datetime2({0})", "scale",
1301 "System.DateTime", false, true, false, false, false, false,
1302 true, true, true, DBNull.Value, (short) 7, (short) 0,
1303 false, DBNull.Value, "{ts '", "'}"},
1304 new object [] {"datetimeoffset", 34, 10L, "datetimeoffset({0})",
1305 "scale", "System.DateTimeOffset", false, true, false, false,
1306 false, false, true, true, true, DBNull.Value, (short) 7, (short) 0,
1307 false, DBNull.Value, "{ts '", "'}"}
1310 static DataTable instance;
1311 static public DataTable Instance {
1313 if (instance == null) {
1314 instance = new DataTable ("DataTypes");
1315 foreach (ColumnInfo c in columns)
1316 instance.Columns.Add (c.name, c.type);
1317 foreach (object [] row in rows)
1318 instance.LoadDataRow (row, true);
1325 static class Restrictions
1327 static readonly ColumnInfo [] columns = {
1328 new ColumnInfo ("CollectionName", typeof (string)),
1329 new ColumnInfo ("RestrictionName", typeof(string)),
1330 new ColumnInfo ("ParameterName", typeof(string)),
1331 new ColumnInfo ("RestrictionDefault", typeof(string)),
1332 new ColumnInfo ("RestrictionNumber", typeof(int))
1335 static readonly object [][] rows = {
1336 new object [] {"Users", "User_Name", "@Name", "name", 1},
1337 new object [] {"Databases", "Name", "@Name", "Name", 1},
1339 new object [] {"Tables", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1340 new object [] {"Tables", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1341 new object [] {"Tables", "Table", "@Name", "TABLE_NAME", 3},
1342 new object [] {"Tables", "TableType", "@TableType", "TABLE_TYPE", 4},
1344 new object [] {"Columns", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1345 new object [] {"Columns", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1346 new object [] {"Columns", "Table", "@Table", "TABLE_NAME", 3},
1347 new object [] {"Columns", "Column", "@Column", "COLUMN_NAME", 4},
1349 new object [] {"StructuredTypeMembers", "Catalog", "@Catalog", "TYPE_CATALOG", 1},
1350 new object [] {"StructuredTypeMembers", "Owner", "@Owner", "TYPE_SCHEMA", 2},
1351 new object [] {"StructuredTypeMembers", "Type", "@Type", "TYPE_NAME", 3},
1352 new object [] {"StructuredTypeMembers", "Member", "@Member", "MEMBER_NAME", 4},
1354 new object [] {"Views", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1355 new object [] {"Views", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1356 new object [] {"Views", "Table", "@Table", "TABLE_NAME", 3},
1358 new object [] {"ViewColumns", "Catalog", "@Catalog", "VIEW_CATALOG", 1},
1359 new object [] {"ViewColumns", "Owner", "@Owner", "VIEW_SCHEMA", 2},
1360 new object [] {"ViewColumns", "Table", "@Table", "VIEW_NAME", 3},
1361 new object [] {"ViewColumns", "Column", "@Column", "COLUMN_NAME", 4},
1363 new object [] {"ProcedureParameters", "Catalog", "@Catalog", "SPECIFIC_CATALOG", 1},
1364 new object [] {"ProcedureParameters", "Owner", "@Owner", "SPECIFIC_SCHEMA", 2},
1365 new object [] {"ProcedureParameters", "Name", "@Name", "SPECIFIC_NAME", 3},
1366 new object [] {"ProcedureParameters", "Parameter", "@Parameter", "PARAMETER_NAME", 4},
1368 new object [] {"Procedures", "Catalog", "@Catalog", "SPECIFIC_CATALOG", 1},
1369 new object [] {"Procedures", "Owner", "@Owner", "SPECIFIC_SCHEMA", 2},
1370 new object [] {"Procedures", "Name", "@Name", "SPECIFIC_NAME", 3},
1371 new object [] {"Procedures", "Type", "@Type", "ROUTINE_TYPE", 4},
1373 new object [] {"IndexColumns", "Catalog", "@Catalog", "db_name()", 1},
1374 new object [] {"IndexColumns", "Owner", "@Owner", "user_name()", 2},
1375 new object [] {"IndexColumns", "Table", "@Table", "o.name", 3},
1376 new object [] {"IndexColumns", "ConstraintName", "@ConstraintName", "x.name", 4},
1377 new object [] {"IndexColumns", "Column", "@Column", "c.name", 5},
1379 new object [] {"Indexes", "Catalog", "@Catalog", "db_name()", 1},
1380 new object [] {"Indexes", "Owner", "@Owner", "user_name()", 2},
1381 new object [] {"Indexes", "Table", "@Table", "o.name", 3},
1382 new object [] {"Indexes", "Name", "@Name", "x.name", 4},
1384 new object [] {"UserDefinedTypes", "assembly_name", "@AssemblyName", "assemblies.name", 1},
1385 new object [] {"UserDefinedTypes", "udt_name", "@UDTName", "types.assembly_class", 2},
1387 new object [] {"ForeignKeys", "Catalog", "@Catalog", "CONSTRAINT_CATALOG", 1},
1388 new object [] {"ForeignKeys", "Owner", "@Owner", "CONSTRAINT_SCHEMA", 2},
1389 new object [] {"ForeignKeys", "Table", "@Table", "TABLE_NAME", 3},
1390 new object [] {"ForeignKeys", "Name", "@Name", "CONSTRAINT_NAME", 4}
1393 static DataTable instance;
1394 static public DataTable Instance {
1396 if (instance == null) {
1397 instance = new DataTable ("Restrictions");
1398 foreach (ColumnInfo c in columns)
1399 instance.Columns.Add (c.name, c.type);
1400 foreach (object [] row in rows)
1401 instance.LoadDataRow (row, true);
1408 public override DataTable GetSchema ()
1410 if (state == ConnectionState.Closed)
1411 throw ExceptionHelper.ConnectionClosed ();
1413 return MetaDataCollections.Instance;
1416 public override DataTable GetSchema (String collectionName)
1418 return GetSchema (collectionName, null);
1421 public override DataTable GetSchema (String collectionName, string [] restrictionValues)
1423 // LAMESPEC: In MS.NET, if collectionName is null, it throws ArgumentException.
1425 if (state == ConnectionState.Closed)
1426 throw ExceptionHelper.ConnectionClosed ();
1428 String cName = null;
1429 DataTable schemaTable = MetaDataCollections.Instance;
1430 int length = restrictionValues == null ? 0 : restrictionValues.Length;
1432 foreach (DataRow row in schemaTable.Rows) {
1433 if (String.Compare ((string) row["CollectionName"], collectionName, true) == 0) {
1434 if (length > (int) row["NumberOfRestrictions"]) {
1435 throw new ArgumentException ("More restrictions were provided " +
1436 "than the requested schema ('" +
1437 row["CollectionName"].ToString () + "') supports");
1439 cName = row["CollectionName"].ToString();
1444 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
1445 "The requested collection ({0}) is not defined.",
1448 SqlCommand command = null;
1449 DataTable dataTable = new DataTable ();
1450 SqlDataAdapter dataAdapter = new SqlDataAdapter ();
1455 command = new SqlCommand ("select name as database_name, dbid, crdate as create_date " +
1456 "from master.sys.sysdatabases where (name = @Name or (@Name " +
1458 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1461 command = new SqlCommand ("select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, " +
1462 "TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_TYPE, " +
1463 "IS_DEFERRABLE, INITIALLY_DEFERRED from " +
1464 "INFORMATION_SCHEMA.TABLE_CONSTRAINTS where (CONSTRAINT_CATALOG" +
1465 " = @Catalog or (@Catalog is null)) and (CONSTRAINT_SCHEMA = " +
1466 "@Owner or (@Owner is null)) and (TABLE_NAME = @Table or (" +
1467 "@Table is null)) and (CONSTRAINT_NAME = @Name or (@Name is null))" +
1468 " and CONSTRAINT_TYPE = 'FOREIGN KEY' order by CONSTRAINT_CATALOG," +
1469 " CONSTRAINT_SCHEMA, CONSTRAINT_NAME", this);
1470 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1471 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1472 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1473 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1476 command = new SqlCommand ("select distinct db_name() as constraint_catalog, " +
1477 "constraint_schema = user_name (o.uid), " +
1478 "constraint_name = x.name, table_catalog = db_name (), " +
1479 "table_schema = user_name (o.uid), table_name = o.name, " +
1480 "index_name = x.name from sysobjects o, sysindexes x, " +
1481 "sysindexkeys xk where o.type in ('U') and x.id = o.id and " +
1482 "o.id = xk.id and x.indid = xk.indid and xk.keyno = x.keycnt " +
1483 "and (db_name() = @Catalog or (@Catalog is null)) and " +
1484 "(user_name() = @Owner or (@Owner is null)) and (o.name = " +
1485 "@Table or (@Table is null)) and (x.name = @Name or (@Name is null))" +
1486 "order by table_name, index_name", this);
1487 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1488 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1489 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1490 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1492 case "IndexColumns":
1493 command = new SqlCommand ("select distinct db_name() as constraint_catalog, " +
1494 "constraint_schema = user_name (o.uid), constraint_name = x.name, " +
1495 "table_catalog = db_name (), table_schema = user_name (o.uid), " +
1496 "table_name = o.name, column_name = c.name, " +
1497 "ordinal_position = convert (int, xk.keyno), keyType = c.xtype, " +
1498 "index_name = x.name from sysobjects o, sysindexes x, syscolumns c, " +
1499 "sysindexkeys xk where o.type in ('U') and x.id = o.id and o.id = c.id " +
1500 "and o.id = xk.id and x.indid = xk.indid and c.colid = xk.colid " +
1501 "and xk.keyno <= x.keycnt and permissions (o.id, c.name) <> 0 " +
1502 "and (db_name() = @Catalog or (@Catalog is null)) and (user_name() " +
1503 "= @Owner or (@Owner is null)) and (o.name = @Table or (@Table is" +
1504 " null)) and (x.name = @ConstraintName or (@ConstraintName is null)) " +
1505 "and (c.name = @Column or (@Column is null)) order by table_name, " +
1506 "index_name", this);
1507 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 8);
1508 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1509 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 13);
1510 command.Parameters.Add ("@ConstraintName", SqlDbType.NVarChar, 4000);
1511 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1514 command = new SqlCommand ("select SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, " +
1515 "ROUTINE_CATALOG, ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE, " +
1516 "CREATED, LAST_ALTERED from INFORMATION_SCHEMA.ROUTINES where " +
1517 "(SPECIFIC_CATALOG = @Catalog or (@Catalog is null)) and " +
1518 "(SPECIFIC_SCHEMA = @Owner or (@Owner is null)) and (SPECIFIC_NAME" +
1519 " = @Name or (@Name is null)) and (ROUTINE_TYPE = @Type or (@Type " +
1520 "is null)) order by SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME", this);
1521 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1522 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1523 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1524 command.Parameters.Add ("@Type", SqlDbType.NVarChar, 4000);
1526 case "ProcedureParameters":
1527 command = new SqlCommand ("select SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, " +
1528 "ORDINAL_POSITION, PARAMETER_MODE, IS_RESULT, AS_LOCATOR, " +
1529 "PARAMETER_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, " +
1530 "CHARACTER_OCTET_LENGTH, COLLATION_CATALOG, COLLATION_SCHEMA, " +
1531 "COLLATION_NAME, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, " +
1532 "CHARACTER_SET_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, " +
1533 "NUMERIC_SCALE, DATETIME_PRECISION, INTERVAL_TYPE, " +
1534 "INTERVAL_PRECISION from INFORMATION_SCHEMA.PARAMETERS where " +
1535 "(SPECIFIC_CATALOG = @Catalog or (@Catalog is null)) and " +
1536 "(SPECIFIC_SCHEMA = @Owner or (@Owner is null)) and (SPECIFIC_NAME = " +
1537 "@Name or (@Name is null)) and (PARAMETER_NAME = @Parameter or (" +
1538 "@Parameter is null)) order by SPECIFIC_CATALOG, SPECIFIC_SCHEMA," +
1539 " SPECIFIC_NAME, PARAMETER_NAME", this);
1540 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1541 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1542 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1543 command.Parameters.Add ("@Parameter", SqlDbType.NVarChar, 4000);
1546 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE " +
1547 "from INFORMATION_SCHEMA.TABLES where" +
1548 " (TABLE_CATALOG = @catalog or (@catalog is null)) and " +
1549 "(TABLE_SCHEMA = @owner or (@owner is null))and " +
1550 "(TABLE_NAME = @name or (@name is null)) and " +
1551 "(TABLE_TYPE = @table_type or (@table_type is null))", this);
1552 command.Parameters.Add ("@catalog", SqlDbType.NVarChar, 8);
1553 command.Parameters.Add ("@owner", SqlDbType.NVarChar, 3);
1554 command.Parameters.Add ("@name", SqlDbType.NVarChar, 11);
1555 command.Parameters.Add ("@table_type", SqlDbType.NVarChar, 10);
1558 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, " +
1559 "ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, " +
1560 "CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH, " +
1561 "NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE, " +
1562 "DATETIME_PRECISION, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, " +
1563 "CHARACTER_SET_NAME, COLLATION_CATALOG from INFORMATION_SCHEMA.COLUMNS" +
1564 " where (TABLE_CATALOG = @Catalog or (@Catalog is null)) and (" +
1565 "TABLE_SCHEMA = @Owner or (@Owner is null)) and (TABLE_NAME = @table" +
1566 " or (@Table is null)) and (COLUMN_NAME = @column or (@Column is null" +
1567 ")) order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME", this);
1568 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1569 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1570 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1571 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1574 command = new SqlCommand ("select uid, name as user_name, createdate, updatedate from sysusers" +
1575 " where (name = @Name or (@Name is null))", this);
1576 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1578 case "StructuredTypeMembers":
1579 // Only available on SQL Server 2008
1580 // Running it again SQL 2005 results in the following exception:
1581 // Unable to build the 'StructuredTypeMembers' collection because
1582 // execution of the SQL query failed. See the inner exception for details.
1583 // ---> System.Data.SqlClient.SqlException: Invalid object name 'sys.table_types'.
1585 // I don't have access to SQL Server 2008 right now,
1586 // and can't find any online documentation on the 'sys.table_types'
1588 throw new NotImplementedException ();
1590 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, CHECK_OPTION, " +
1591 "IS_UPDATABLE from INFORMATION_SCHEMA.VIEWS where (TABLE_CATALOG" +
1592 " = @Catalog or (@Catalog is null)) TABLE_SCHEMA = @Owner or " +
1593 "(@Owner is null)) and (TABLE_NAME = @table or (@Table is null))" +
1594 " order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME", this);
1595 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1596 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1597 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1600 command = new SqlCommand ("select VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME, TABLE_CATALOG, " +
1601 "TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME from " +
1602 "INFORMATION_SCHEMA.VIEW_COLUMN_USAGE where (VIEW_CATALOG = " +
1603 "@Catalog (@Catalog is null)) and (VIEW_SCHEMA = @Owner (@Owner" +
1604 " is null)) and (VIEW_NAME = @Table or (@Table is null)) and " +
1605 "(COLUMN_NAME = @Column or (@Column is null)) order by " +
1606 "VIEW_CATALOG, VIEW_SCHEMA, VIEW_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);
1612 case "UserDefinedTypes":
1613 command = new SqlCommand ("select assemblies.name as assembly_name, types.assembly_class " +
1614 "as udt_name, ASSEMBLYPROPERTY(assemblies.name, 'VersionMajor') " +
1615 "as version_major, ASSEMBLYPROPERTY(assemblies.name, 'VersionMinor') " +
1616 "as version_minor, ASSEMBLYPROPERTY(assemblies.name, 'VersionBuild') " +
1617 "as version_build, ASSEMBLYPROPERTY(assemblies.name, 'VersionRevision') " +
1618 "as version_revision, ASSEMBLYPROPERTY(assemblies.name, 'CultureInfo') " +
1619 "as culture_info, ASSEMBLYPROPERTY(assemblies.name, 'PublicKey') " +
1620 "as public_key, is_fixed_length, max_length, Create_Date, " +
1621 "Permission_set_desc from sys.assemblies as assemblies join " +
1622 "sys.assembly_types as types on assemblies.assembly_id = types.assembly_id" +
1623 " where (assportemblies.name = @AssemblyName or (@AssemblyName is null)) and " +
1624 "(types.assembly_class = @UDTName or (@UDTName is null))",
1626 command.Parameters.Add ("@AssemblyName", SqlDbType.NVarChar, 4000);
1627 command.Parameters.Add ("@UDTName", SqlDbType.NVarChar, 4000);
1629 case "MetaDataCollections":
1630 return MetaDataCollections.Instance;
1631 case "DataSourceInformation":
1632 return DataSourceInformation.GetInstance (this);
1634 return DataTypes.Instance;
1635 case "ReservedWords":
1636 return ReservedWords.Instance;
1637 case "Restrictions":
1638 return Restrictions.Instance;
1640 for (int i = 0; i < length; i++) {
1641 command.Parameters[i].Value = restrictionValues[i];
1643 dataAdapter.SelectCommand = command;
1644 dataAdapter.Fill (dataTable);
1648 public static void ChangePassword (string connectionString, string newPassword)
1650 if (String.IsNullOrEmpty (connectionString))
1651 throw new ArgumentNullException ("The 'connectionString' cannot be null or empty.");
1652 if (String.IsNullOrEmpty (newPassword))
1653 throw new ArgumentNullException ("The 'newPassword' cannot be null or empty.");
1654 if (newPassword.Length > 128)
1655 throw new ArgumentException ("The length of 'newPassword' cannot exceed 128 characters.");
1656 using (SqlConnection conn = new SqlConnection (connectionString)) {
1658 conn.tds.Execute (String.Format ("sp_password '{0}', '{1}', '{2}'",
1659 conn.parms.Password, newPassword, conn.parms.User));
1663 public static void ClearAllPools ()
1666 IDictionary pools = SqlConnection.sqlConnectionPools.GetConnectionPool ();
1667 foreach (TdsConnectionPool pool in pools.Values) {
1669 pool.ResetConnectionPool ();
1674 public static void ClearPool (SqlConnection connection)
1676 if (connection == null)
1677 throw new ArgumentNullException ("connection");
1680 if (connection.pooling) {
1681 TdsConnectionPool pool = sqlConnectionPools.GetConnectionPool (connection.ConnectionString);
1683 pool.ResetConnectionPool ();
1688 public void ResetStatistics ()
1690 throw new NotImplementedException ();
1694 public IDictionary RetrieveStatistics ()
1696 throw new NotImplementedException ();
1699 #endregion // Methods
1701 #region Fields Net 2
1706 #endregion // Fields Net 2
1708 #region Properties Net 2
1710 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1711 internal bool AsyncProcessing {
1712 get { return async; }
1715 #endregion // Properties Net 2