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
139 [EditorAttribute ("Microsoft.VSDesigner.Data.SQL.Design.SqlConnectionStringEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
140 [RecommendedAsConfigurable (true)]
141 [RefreshProperties (RefreshProperties.All)]
142 public override string ConnectionString {
144 if (connectionString == null)
146 return connectionString;
148 [MonoTODO("persist security info, encrypt, enlist keyword not implemented")]
150 if (state == ConnectionState.Open)
151 throw new InvalidOperationException ("Not Allowed to change ConnectionString property while Connection state is OPEN");
152 SetConnectionString (value);
157 [DataSysDescription ("Current connection timeout value, 'Connect Timeout=X' in the ConnectionString.")]
159 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
164 int ConnectionTimeout {
165 get { return connectionTimeout; }
169 [DataSysDescription ("Current SQL Server database, 'Initial Catalog=X' in the connection string.")]
171 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
178 if (State == ConnectionState.Open)
180 return parms.Database ;
184 internal SqlDataReader DataReader {
185 get { return dataReader; }
186 set { dataReader = value; }
190 [DataSysDescription ("Current SqlServer that the connection is opened to, 'Data Source=X' in the connection string. ")]
194 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
200 get { return dataSource; }
204 [DataSysDescription ("Network packet size, 'Packet Size=x' in the connection string.")]
206 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
207 public int PacketSize {
209 if (State == ConnectionState.Open)
210 return ((Tds) tds).PacketSize;
217 [DataSysDescription ("Version of the SQL Server accessed by the SqlConnection.")]
219 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
224 string ServerVersion {
226 if (state == ConnectionState.Closed)
227 throw ExceptionHelper.ConnectionClosed ();
229 return tds.ServerVersion;
235 [DataSysDescription ("The ConnectionState indicating whether the connection is open or closed.")]
237 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
242 ConnectionState State {
243 get { return state; }
250 internal SqlTransaction Transaction {
251 get { return transaction; }
252 set { transaction = value; }
256 [DataSysDescription ("Workstation Id, 'Workstation ID=x' in the connection string.")]
258 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
259 public string WorkstationId {
260 get { return parms.Hostname; }
263 internal XmlReader XmlReader {
264 get { return xmlReader; }
265 set { xmlReader = value; }
269 public bool FireInfoMessageEventOnUserErrors {
270 get { return fireInfoMessageEventOnUserErrors; }
271 set { fireInfoMessageEventOnUserErrors = value; }
274 [DefaultValue (false)]
275 public bool StatisticsEnabled {
276 get { return statisticsEnabled; }
277 set { statisticsEnabled = value; }
280 #endregion // Properties
285 [DataSysDescription ("Event triggered when messages arrive from the DataSource.")]
287 public event SqlInfoMessageEventHandler InfoMessage;
290 [DataSysDescription ("Event triggered when the connection changes state.")]
291 public new event StateChangeEventHandler StateChange;
298 private void ErrorHandler (object sender, TdsInternalErrorMessageEventArgs e)
301 if (!tds.IsConnected)
309 throw new SqlException (e.Class, e.LineNumber, e.Message, e.Number, e.Procedure, e.Server, "Mono SqlClient Data Provider", e.State);
312 private void MessageHandler (object sender, TdsInternalInfoMessageEventArgs e)
314 OnSqlInfoMessage (CreateSqlInfoMessageEvent (e.Errors));
317 #endregion // Delegates
321 public new SqlTransaction BeginTransaction ()
323 return BeginTransaction (IsolationLevel.ReadCommitted, String.Empty);
326 public new SqlTransaction BeginTransaction (IsolationLevel iso)
328 return BeginTransaction (iso, String.Empty);
331 public SqlTransaction BeginTransaction (string transactionName)
333 return BeginTransaction (IsolationLevel.ReadCommitted, transactionName);
336 public SqlTransaction BeginTransaction (IsolationLevel iso, string transactionName)
338 if (state == ConnectionState.Closed)
339 throw ExceptionHelper.ConnectionClosed ();
340 if (transaction != null)
341 throw new InvalidOperationException ("SqlConnection does not support parallel transactions.");
343 string isolevel = String.Empty;
345 case IsolationLevel.ReadUncommitted:
346 isolevel = "READ UNCOMMITTED";
348 case IsolationLevel.RepeatableRead:
349 isolevel = "REPEATABLE READ";
351 case IsolationLevel.Serializable:
352 isolevel = "SERIALIZABLE";
354 case IsolationLevel.ReadCommitted:
355 isolevel = "READ COMMITTED";
358 case IsolationLevel.Snapshot:
359 isolevel = "SNAPSHOT";
361 case IsolationLevel.Unspecified:
362 iso = IsolationLevel.ReadCommitted;
363 isolevel = "READ COMMITTED";
365 case IsolationLevel.Chaos:
366 throw new ArgumentOutOfRangeException ("IsolationLevel",
367 string.Format (CultureInfo.CurrentCulture,
368 "The IsolationLevel enumeration " +
369 "value, {0}, is not supported by " +
370 "the .Net Framework SqlClient " +
371 "Data Provider.", (int) iso));
375 throw new ArgumentOutOfRangeException ("IsolationLevel",
376 string.Format (CultureInfo.CurrentCulture,
377 "The IsolationLevel enumeration value, {0}, is invalid.",
380 throw new ArgumentException ("Invalid IsolationLevel parameter: must be ReadCommitted, ReadUncommitted, RepeatableRead, or Serializable.");
384 tds.Execute (String.Format ("SET TRANSACTION ISOLATION LEVEL {0};BEGIN TRANSACTION {1}", isolevel, transactionName));
386 transaction = new SqlTransaction (this, iso);
394 void ChangeDatabase (string database)
396 if (!IsValidDatabaseName (database))
397 throw new ArgumentException (String.Format ("The database name {0} is not valid.", database));
398 if (state != ConnectionState.Open)
399 throw new InvalidOperationException ("The connection is not open.");
400 tds.Execute (String.Format ("use [{0}]", database));
403 private void ChangeState (ConnectionState currentState)
405 if (currentState == state)
408 ConnectionState originalState = state;
409 state = currentState;
410 OnStateChange (CreateStateChangeEvent (originalState, currentState));
419 if (transaction != null && transaction.IsOpen)
420 transaction.Rollback ();
422 if (dataReader != null || xmlReader != null) {
423 if(tds != null) tds.SkipToEnd ();
428 if (tds != null && tds.IsConnected) {
429 if (pooling && tds.Pooling) {
431 pool.ReleaseConnection (tds);
440 tds.TdsErrorMessage -= new TdsInternalErrorMessageEventHandler (ErrorHandler);
441 tds.TdsInfoMessage -= new TdsInternalInfoMessageEventHandler (MessageHandler);
444 ChangeState (ConnectionState.Closed);
447 public new SqlCommand CreateCommand ()
449 SqlCommand command = new SqlCommand ();
450 command.Connection = this;
454 private SqlInfoMessageEventArgs CreateSqlInfoMessageEvent (TdsInternalErrorCollection errors)
456 return new SqlInfoMessageEventArgs (errors);
459 private StateChangeEventArgs CreateStateChangeEvent (ConnectionState originalState, ConnectionState currentState)
461 return new StateChangeEventArgs (originalState, currentState);
464 protected override void Dispose (bool disposing)
467 if (disposing && !disposed) {
468 if (State == ConnectionState.Open)
470 ConnectionString = null;
474 base.Dispose (disposing);
479 [MonoTODO ("Not sure what this means at present.")]
480 public void EnlistDistributedTransaction (ITransaction transaction)
482 throw new NotImplementedException ();
486 object ICloneable.Clone ()
488 return new SqlConnection (ConnectionString);
492 protected override DbTransaction BeginDbTransaction (IsolationLevel isolationLevel)
494 return BeginTransaction (isolationLevel);
497 protected override DbCommand CreateDbCommand ()
499 return CreateCommand ();
502 IDbTransaction IDbConnection.BeginTransaction ()
504 return BeginTransaction ();
507 IDbTransaction IDbConnection.BeginTransaction (IsolationLevel iso)
509 return BeginTransaction (iso);
512 IDbCommand IDbConnection.CreateCommand ()
514 return CreateCommand ();
524 string serverName = string.Empty;
525 if (state == ConnectionState.Open)
526 throw new InvalidOperationException ("The Connection is already Open (State=Open)");
528 if (connectionString == null || connectionString.Trim().Length == 0)
529 throw new InvalidOperationException ("Connection string has not been initialized.");
533 if(!ParseDataSource (dataSource, out port, out serverName))
534 throw new SqlException(20, 0, "SQL Server does not exist or access denied.", 17, "ConnectionOpen (Connect()).", dataSource, parms.ApplicationName, 0);
535 tds = new Tds80 (serverName, port, PacketSize, ConnectionTimeout);
539 if(!ParseDataSource (dataSource, out port, out serverName))
540 throw new SqlException(20, 0, "SQL Server does not exist or access denied.", 17, "ConnectionOpen (Connect()).", dataSource, parms.ApplicationName, 0);
542 TdsConnectionInfo info = new TdsConnectionInfo (serverName, port, packetSize, ConnectionTimeout, minPoolSize, maxPoolSize);
543 pool = sqlConnectionPools.GetConnectionPool (connectionString, info);
544 tds = pool.GetConnection ();
546 } catch (TdsTimeoutException e) {
547 throw SqlException.FromTdsInternalException ((TdsInternalException) e);
548 } catch (TdsInternalException e) {
549 throw SqlException.FromTdsInternalException (e);
552 tds.TdsErrorMessage += new TdsInternalErrorMessageEventHandler (ErrorHandler);
553 tds.TdsInfoMessage += new TdsInternalInfoMessageEventHandler (MessageHandler);
555 if (!tds.IsConnected) {
560 pool.ReleaseConnection (tds);
565 disposed = false; // reset this, so using () would call Close ().
566 ChangeState (ConnectionState.Open);
569 private bool ParseDataSource (string theDataSource, out int thePort, out string theServerName)
571 theServerName = string.Empty;
572 string theInstanceName = string.Empty;
574 if (theDataSource == null)
575 throw new ArgumentException("Format of initialization string does not conform to specifications");
577 thePort = DEFAULT_PORT; // default TCP port for SQL Server
581 if ((idx = theDataSource.IndexOf (',')) > -1) {
582 theServerName = theDataSource.Substring (0, idx);
583 string p = theDataSource.Substring (idx + 1);
584 thePort = Int32.Parse (p);
585 } else if ((idx = theDataSource.IndexOf ('\\')) > -1) {
586 theServerName = theDataSource.Substring (0, idx);
587 theInstanceName = theDataSource.Substring (idx + 1);
589 // do port discovery via UDP port 1434
590 port = DiscoverTcpPortViaSqlMonitor (theServerName, theInstanceName);
594 theServerName = theDataSource;
596 if (theServerName.Length == 0 || theServerName == "(local)" || theServerName == ".")
597 theServerName = "localhost";
599 if ((idx = theServerName.IndexOf ("tcp:")) > -1)
600 theServerName = theServerName.Substring (idx + 4);
605 private bool ConvertIntegratedSecurity (string value)
607 if (value.ToUpper() == "SSPI")
610 return ConvertToBoolean ("integrated security", value, false);
613 private bool ConvertToBoolean (string key, string value, bool defaultValue)
615 if (value.Length == 0)
618 string upperValue = value.ToUpper ();
620 if (upperValue == "TRUE" || upperValue == "YES")
622 else if (upperValue == "FALSE" || upperValue == "NO")
625 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
626 "Invalid value \"{0}\" for key '{1}'.", value, key));
629 private int ConvertToInt32 (string key, string value, int defaultValue)
631 if (value.Length == 0)
635 return int.Parse (value);
636 } catch (Exception ex) {
637 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
638 "Invalid value \"{0}\" for key '{1}'.", value, key), ex);
642 private int DiscoverTcpPortViaSqlMonitor (string ServerName, string InstanceName)
644 SqlMonitorSocket msock;
645 msock = new SqlMonitorSocket (ServerName, InstanceName);
646 int SqlServerPort = msock.DiscoverTcpPort (ConnectionTimeout);
648 return SqlServerPort;
651 void SetConnectionString (string connectionString)
653 SetDefaultConnectionParameters ();
655 if ((connectionString == null) || (connectionString.Trim().Length == 0)) {
656 this.connectionString = connectionString;
660 connectionString += ";";
662 bool inQuote = false;
663 bool inDQuote = false;
666 string name = String.Empty;
667 string value = String.Empty;
668 StringBuilder sb = new StringBuilder ();
670 for (int i = 0; i < connectionString.Length; i += 1) {
671 char c = connectionString [i];
673 if (i == connectionString.Length - 1)
676 peek = connectionString [i + 1];
682 else if (peek.Equals (c)) {
692 else if (peek.Equals (c)) {
697 inDQuote = !inDQuote;
700 if (inDQuote || inQuote)
703 if (name != String.Empty && name != null) {
704 value = sb.ToString ();
705 SetProperties (name.ToLower ().Trim() , value);
707 else if (sb.Length != 0)
708 throw new ArgumentException ("Format of initialization string does not conform to specifications");
711 value = String.Empty;
712 sb = new StringBuilder ();
716 if (inDQuote || inQuote || !inName)
718 else if (peek.Equals (c)) {
724 name = sb.ToString ();
725 sb = new StringBuilder ();
730 if (inQuote || inDQuote)
732 else if (sb.Length > 0 && !peek.Equals (';'))
741 if (minPoolSize > maxPoolSize)
742 throw new ArgumentException ("Invalid value for "
743 + "'min pool size' or 'max pool size'; "
744 + "'min pool size' must not be greater "
745 + "than 'max pool size'.");
747 connectionString = connectionString.Substring (0 , connectionString.Length-1);
748 this.connectionString = connectionString;
751 void SetDefaultConnectionParameters ()
754 parms = new TdsConnectionParameters ();
757 dataSource = string.Empty;
758 connectionTimeout = DEFAULT_CONNECTIONTIMEOUT;
759 connectionReset = true;
761 maxPoolSize = DEFAULT_MAXPOOLSIZE;
762 minPoolSize = DEFAULT_MINPOOLSIZE;
763 packetSize = DEFAULT_PACKETSIZE;
770 private void SetProperties (string name , string value)
774 case "application name" :
775 parms.ApplicationName = value;
777 case "attachdbfilename" :
778 case "extended properties" :
779 case "initial file name" :
780 parms.AttachDBFileName = value;
783 case "connect timeout" :
784 case "connection timeout" :
785 int tmpTimeout = ConvertToInt32 ("connect timeout", value,
786 DEFAULT_CONNECTIONTIMEOUT);
788 throw new ArgumentException ("Invalid 'connect timeout'. Must be an integer >=0 ");
790 connectionTimeout = tmpTimeout;
792 case "connection lifetime" :
794 case "connection reset" :
795 connectionReset = ConvertToBoolean ("connection reset", value, true);
798 case "current language" :
799 parms.Language = value;
805 case "network address" :
809 if (ConvertToBoolean (name, value, false))
810 throw new NotImplementedException("SSL encryption for"
811 + " data sent between client and server is not"
815 if (!ConvertToBoolean (name, value, true))
816 throw new NotImplementedException("Disabling the automatic"
817 + " enlistment of connections in the thread's current"
818 + " transaction context is not implemented.");
820 case "initial catalog" :
822 parms.Database = value;
824 case "integrated security" :
825 case "trusted_connection" :
826 parms.DomainLogin = ConvertIntegratedSecurity(value);
828 case "max pool size" :
829 int tmpMaxPoolSize = ConvertToInt32 (name, value, DEFAULT_MAXPOOLSIZE);
830 if (tmpMaxPoolSize < MIN_MAXPOOLSIZE)
831 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
832 "Invalid '{0}'. The value must be greater than {1}.",
833 name, MIN_MAXPOOLSIZE));
835 maxPoolSize = tmpMaxPoolSize;
837 case "min pool size" :
838 int tmpMinPoolSize = ConvertToInt32 (name, value, DEFAULT_MINPOOLSIZE);
839 if (tmpMinPoolSize < 0)
840 throw new ArgumentException ("Invalid 'min pool size'. Must be a integer >= 0");
842 minPoolSize = tmpMinPoolSize;
845 case "multipleactiveresultsets":
846 // FIXME: not implemented
847 ConvertToBoolean (name, value, false);
849 case "asynchronous processing" :
851 async = ConvertToBoolean (name, value, false);
856 case "network library" :
857 if (!value.ToUpper ().Equals ("DBMSSOCN"))
858 throw new ArgumentException ("Unsupported network library.");
861 int tmpPacketSize = ConvertToInt32 (name, value, DEFAULT_PACKETSIZE);
862 if (tmpPacketSize < MIN_PACKETSIZE || tmpPacketSize > MAX_PACKETSIZE)
863 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
864 "Invalid 'Packet Size'. The value must be between {0} and {1}.",
865 MIN_PACKETSIZE, MAX_PACKETSIZE));
867 packetSize = tmpPacketSize;
871 parms.Password = value;
873 case "persistsecurityinfo" :
874 case "persist security info" :
875 // FIXME : not implemented
876 // throw new NotImplementedException ();
879 pooling = ConvertToBoolean (name, value, true);
887 case "workstation id" :
888 parms.Hostname = value;
891 case "user instance":
892 userInstance = ConvertToBoolean (name, value, false);
896 throw new ArgumentException("Keyword not supported : '" + name + "'.");
900 static bool IsValidDatabaseName (string database)
902 if ( database == null || database.Trim().Length == 0 || database.Length > 128)
905 if (database[0] == '"' && database[database.Length] == '"')
906 database = database.Substring (1, database.Length - 2);
907 else if (Char.IsDigit (database[0]))
910 if (database[0] == '_')
913 foreach (char c in database.Substring (1, database.Length - 1))
914 if (!Char.IsLetterOrDigit (c) && c != '_' && c != '-')
919 private void OnSqlInfoMessage (SqlInfoMessageEventArgs value)
921 if (InfoMessage != null)
922 InfoMessage (this, value);
926 private new void OnStateChange (StateChangeEventArgs value)
928 if (StateChange != null)
929 StateChange (this, value);
933 private sealed class SqlMonitorSocket : UdpClient
935 // UDP port that the SQL Monitor listens
936 private static readonly int SqlMonitorUdpPort = 1434;
937 //private static readonly string SqlServerNotExist = "SQL Server does not exist or access denied";
939 private string server;
940 private string instance;
942 internal SqlMonitorSocket (string ServerName, string InstanceName)
943 : base (ServerName, SqlMonitorUdpPort)
946 instance = InstanceName;
949 internal int DiscoverTcpPort (int timeoutSeconds)
951 int SqlServerTcpPort;
952 Client.Blocking = false;
953 // send command to UDP 1434 (SQL Monitor) to get
954 // the TCP port to connect to the MS SQL server
955 ASCIIEncoding enc = new ASCIIEncoding ();
956 Byte[] rawrq = new Byte [instance.Length + 1];
958 enc.GetBytes (instance, 0, instance.Length, rawrq, 1);
959 Send (rawrq, rawrq.Length);
965 long timeout = timeoutSeconds * 1000000;
966 result = Client.Poll ((int)timeout, SelectMode.SelectRead);
970 if (Client.Available <= 0)
973 IPEndPoint endpoint = new IPEndPoint (Dns.GetHostEntry ("localhost").AddressList [0], 0);
975 IPEndPoint endpoint = new IPEndPoint (Dns.GetHostByName ("localhost").AddressList [0], 0);
979 rawrs = Receive (ref endpoint);
981 string rs = Encoding.ASCII.GetString (rawrs);
983 string[] rawtokens = rs.Split (';');
984 Hashtable data = new Hashtable ();
985 for (int i = 0; i < rawtokens.Length / 2 && i < 256; i++) {
986 data [rawtokens [i * 2]] = rawtokens [ i * 2 + 1];
989 if (!data.ContainsKey ("tcp")) {
990 string msg = "Mono does not support names pipes or shared memory "
991 + "for connecting to SQL Server. Please enable the TCP/IP "
993 throw new NotImplementedException (msg);
996 SqlServerTcpPort = int.Parse ((string) data ["tcp"]);
999 return SqlServerTcpPort;
1009 public ColumnInfo (string name, Type type)
1011 this.name = name; this.type = type;
1015 static class ReservedWords
1017 static readonly string [] reservedWords =
1019 "ADD", "EXCEPT", "PERCENT", "ALL", "EXEC", "PLAN", "ALTER",
1020 "EXECUTE", "PRECISION", "AND", "EXISTS", "PRIMARY", "ANY",
1021 "EXIT", "PRINT", "AS", "FETCH", "PROC", "ASC", "FILE",
1022 "PROCEDURE", "AUTHORIZATION", "FILLFACTOR", "PUBLIC",
1023 "BACKUP", "FOR", "RAISERROR", "BEGIN", "FOREIGN", "READ",
1024 "BETWEEN", "FREETEXT", "READTEXT", "BREAK", "FREETEXTTABLE",
1025 "RECONFIGURE", "BROWSE", "FROM", "REFERENCES", "BULK",
1026 "FULL", "REPLICATION", "BY", "FUNCTION", "RESTORE",
1027 "CASCADE", "GOTO", "RESTRICT", "CASE", "GRANT", "RETURN",
1028 "CHECK", "GROUP", "REVOKE", "CHECKPOINT", "HAVING", "RIGHT",
1029 "CLOSE", "HOLDLOCK", "ROLLBACK", "CLUSTERED", "IDENTITY",
1030 "ROWCOUNT", "COALESCE", "IDENTITY_INSERT", "ROWGUIDCOL",
1031 "COLLATE", "IDENTITYCOL", "RULE", "COLUMN", "IF", "SAVE",
1032 "COMMIT", "IN", "SCHEMA", "COMPUTE", "INDEX", "SELECT",
1033 "CONSTRAINT", "INNER", "SESSION_USER", "CONTAINS", "INSERT",
1034 "SET", "CONTAINSTABLE", "INTERSECT", "SETUSER", "CONTINUE",
1035 "INTO", "SHUTDOWN", "CONVERT", "IS", "SOME", "CREATE",
1036 "JOIN", "STATISTICS", "CROSS", "KEY", "SYSTEM_USER",
1037 "CURRENT", "KILL", "TABLE", "CURRENT_DATE", "LEFT",
1038 "TEXTSIZE", "CURRENT_TIME", "LIKE", "THEN",
1039 "CURRENT_TIMESTAMP", "LINENO", "TO", "CURRENT_USER", "LOAD",
1040 "TOP", "CURSOR", "NATIONAL", "TRAN", "DATABASE", "NOCHECK",
1041 "TRANSACTION", "DBCC", "NONCLUSTERED", "TRIGGER",
1042 "DEALLOCATE", "NOT", "TRUNCATE", "DECLARE", "NULL",
1043 "TSEQUAL", "DEFAULT", "NULLIF", "UNION", "DELETE", "OF",
1044 "UNIQUE", "DENY", "OFF", "UPDATE", "DESC", "OFFSETS",
1045 "UPDATETEXT", "DISK", "ON", "USE", "DISTINCT", "OPEN",
1046 "USER", "DISTRIBUTED", "OPENDATASOURCE", "VALUES", "DOUBLE",
1047 "OPENQUERY", "VARYING", "DROP", "OPENROWSET", "VIEW",
1048 "DUMMY", "OPENXML", "WAITFOR", "DUMP", "OPTION", "WHEN",
1049 "ELSE", "OR", "WHERE", "END", "ORDER", "WHILE", "ERRLVL",
1050 "OUTER", "WITH", "ESCAPE", "OVER", "WRITETEXT", "ABSOLUTE",
1051 "FOUND", "PRESERVE", "ACTION", "FREE", "PRIOR", "ADMIN",
1052 "GENERAL", "PRIVILEGES", "AFTER", "GET", "READS",
1053 "AGGREGATE", "GLOBAL", "REAL", "ALIAS", "GO", "RECURSIVE",
1054 "ALLOCATE", "GROUPING", "REF", "ARE", "HOST", "REFERENCING",
1055 "ARRAY", "HOUR", "RELATIVE", "ASSERTION", "IGNORE", "RESULT",
1056 "AT", "IMMEDIATE", "RETURNS", "BEFORE", "INDICATOR", "ROLE",
1057 "BINARY", "INITIALIZE", "ROLLUP", "BIT", "INITIALLY",
1058 "ROUTINE", "BLOB", "INOUT", "ROW", "BOOLEAN", "INPUT",
1059 "ROWS", "BOTH", "INT", "SAVEPOINT", "BREADTH", "INTEGER",
1060 "SCROLL", "CALL", "INTERVAL", "SCOPE", "CASCADED",
1061 "ISOLATION", "SEARCH", "CAST", "ITERATE", "SECOND",
1062 "CATALOG", "LANGUAGE", "SECTION", "CHAR", "LARGE",
1063 "SEQUENCE", "CHARACTER", "LAST", "SESSION", "CLASS",
1064 "LATERAL", "SETS", "CLOB", "LEADING", "SIZE", "COLLATION",
1065 "LESS", "SMALLINT", "COMPLETION", "LEVEL", "SPACE",
1066 "CONNECT", "LIMIT", "SPECIFIC", "CONNECTION", "LOCAL",
1067 "SPECIFICTYPE", "CONSTRAINTS", "LOCALTIME", "SQL",
1068 "CONSTRUCTOR", "LOCALTIMESTAMP", "SQLEXCEPTION",
1069 "CORRESPONDING", "LOCATOR", "SQLSTATE", "CUBE", "MAP",
1070 "SQLWARNING", "CURRENT_PATH", "MATCH", "START",
1071 "CURRENT_ROLE", "MINUTE", "STATE", "CYCLE", "MODIFIES",
1072 "STATEMENT", "DATA", "MODIFY", "STATIC", "DATE", "MODULE",
1073 "STRUCTURE", "DAY", "MONTH", "TEMPORARY", "DEC", "NAMES",
1074 "TERMINATE", "DECIMAL", "NATURAL", "THAN", "DEFERRABLE",
1075 "NCHAR", "TIME", "DEFERRED", "NCLOB", "TIMESTAMP", "DEPTH",
1076 "NEW", "TIMEZONE_HOUR", "DEREF", "NEXT", "TIMEZONE_MINUTE",
1077 "DESCRIBE", "NO", "TRAILING", "DESCRIPTOR", "NONE",
1078 "TRANSLATION", "DESTROY", "NUMERIC", "TREAT", "DESTRUCTOR",
1079 "OBJECT", "TRUE", "DETERMINISTIC", "OLD", "UNDER",
1080 "DICTIONARY", "ONLY", "UNKNOWN", "DIAGNOSTICS", "OPERATION",
1081 "UNNEST", "DISCONNECT", "ORDINALITY", "USAGE", "DOMAIN",
1082 "OUT", "USING", "DYNAMIC", "OUTPUT", "VALUE", "EACH",
1083 "PAD", "VARCHAR", "END-EXEC", "PARAMETER", "VARIABLE",
1084 "EQUALS", "PARAMETERS", "WHENEVER", "EVERY", "PARTIAL",
1085 "WITHOUT", "EXCEPTION", "PATH", "WORK", "EXTERNAL",
1086 "POSTFIX", "WRITE", "FALSE", "PREFIX", "YEAR", "FIRST",
1087 "PREORDER", "ZONE", "FLOAT", "PREPARE", "ADA", "AVG",
1088 "BIT_LENGTH", "CHAR_LENGTH", "CHARACTER_LENGTH", "COUNT",
1089 "EXTRACT", "FORTRAN", "INCLUDE", "INSENSITIVE", "LOWER",
1090 "MAX", "MIN", "OCTET_LENGTH", "OVERLAPS", "PASCAL",
1091 "POSITION", "SQLCA", "SQLCODE", "SQLERROR", "SUBSTRING",
1092 "SUM", "TRANSLATE", "TRIM", "UPPER"
1094 static DataTable instance;
1095 static public DataTable Instance {
1097 if (instance == null) {
1099 var newInstance = new DataTable ("ReservedWords");
1100 newInstance.Columns.Add ("ReservedWord", typeof(string));
1101 foreach (string reservedWord in reservedWords)
1103 row = newInstance.NewRow();
1105 row["ReservedWord"] = reservedWord;
1106 newInstance.Rows.Add(row);
1108 instance = newInstance;
1115 static class MetaDataCollections
1117 static readonly ColumnInfo [] columns = {
1118 new ColumnInfo ("CollectionName", typeof (string)),
1119 new ColumnInfo ("NumberOfRestrictions", typeof (int)),
1120 new ColumnInfo ("NumberOfIdentifierParts", typeof (int))
1123 static readonly object [][] rows = {
1124 new object [] {"MetaDataCollections", 0, 0},
1125 new object [] {"DataSourceInformation", 0, 0},
1126 new object [] {"DataTypes", 0, 0},
1127 new object [] {"Restrictions", 0, 0},
1128 new object [] {"ReservedWords", 0, 0},
1129 new object [] {"Users", 1, 1},
1130 new object [] {"Databases", 1, 1},
1131 new object [] {"Tables", 4, 3},
1132 new object [] {"Columns", 4, 4},
1133 new object [] {"StructuredTypeMembers", 4, 4},
1134 new object [] {"Views", 3, 3},
1135 new object [] {"ViewColumns", 4, 4},
1136 new object [] {"ProcedureParameters", 4, 1},
1137 new object [] {"Procedures", 4, 3},
1138 new object [] {"ForeignKeys", 4, 3},
1139 new object [] {"IndexColumns", 5, 4},
1140 new object [] {"Indexes", 4, 3},
1141 new object [] {"UserDefinedTypes", 2, 1}
1144 static DataTable instance;
1145 static public DataTable Instance {
1147 if (instance == null) {
1148 var newInstance = new DataTable ("MetaDataCollections");
1149 foreach (ColumnInfo c in columns)
1150 newInstance.Columns.Add (c.name, c.type);
1151 foreach (object [] row in rows)
1152 newInstance.LoadDataRow (row, true);
1153 instance = newInstance;
1160 static class DataSourceInformation
1162 static readonly ColumnInfo [] columns = {
1163 new ColumnInfo ("CompositeIdentifierSeparatorPattern", typeof (string)),
1164 new ColumnInfo ("DataSourceProductName", typeof(string)),
1165 new ColumnInfo ("DataSourceProductVersion", typeof(string)),
1166 new ColumnInfo ("DataSourceProductVersionNormalized", typeof(string)),
1167 new ColumnInfo ("GroupByBehavior", typeof(GroupByBehavior)),
1168 new ColumnInfo ("IdentifierPattern", typeof(string)),
1169 new ColumnInfo ("IdentifierCase", typeof(IdentifierCase)),
1170 new ColumnInfo ("OrderByColumnsInSelect", typeof(bool)),
1171 new ColumnInfo ("ParameterMarkerFormat", typeof(string)),
1172 new ColumnInfo ("ParameterMarkerPattern", typeof(string)),
1173 new ColumnInfo ("ParameterNameMaxLength", typeof(int)),
1174 new ColumnInfo ("ParameterNamePattern", typeof(string)),
1175 new ColumnInfo ("QuotedIdentifierPattern", typeof(string)),
1176 new ColumnInfo ("QuotedIdentifierCase", typeof(IdentifierCase)),
1177 new ColumnInfo ("StatementSeparatorPattern", typeof(string)),
1178 new ColumnInfo ("StringLiteralPattern", typeof(string)),
1179 new ColumnInfo ("SupportedJoinOperators", typeof(SupportedJoinOperators))
1182 static public DataTable GetInstance (SqlConnection conn)
1184 DataTable table = new DataTable ("DataSourceInformation");
1185 foreach (ColumnInfo c in columns)
1186 table.Columns.Add (c.name, c.type);
1187 DataRow row = table.NewRow ();
1189 row [1] = "Microsoft SQL Server";
1190 row [2] = conn.ServerVersion;;
1191 row [3] = conn.ServerVersion;;
1192 row [4] = GroupByBehavior.Unrelated;
1193 row [5] = @"(^\[\p{Lo}\p{Lu}\p{Ll}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Nd}@$#_]*$)|(^\[[^\]\0]|\]\]+\]$)|(^\""[^\""\0]|\""\""+\""$)";
1194 row [6] = IdentifierCase.Insensitive; // FIXME: obtain this from SQL Server
1197 row [9] = @"@[\p{Lo}\p{Lu}\p{Ll}\p{Lm}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Lm}\p{Nd}\uff3f_@#\$]*(?=\s+|$)";
1199 row [11] = @"^[\p{Lo}\p{Lu}\p{Ll}\p{Lm}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Lm}\p{Nd}\uff3f_@#\$]*(?=\s+|$)";
1200 row [12] = @"(([^\[]|\]\])*)";
1201 row [13] = IdentifierCase.Insensitive; // FIXME: obtain this from SQL Server
1203 row [15] = "'(([^']|'')*)'";
1204 row [16] = (SupportedJoinOperators.FullOuter | SupportedJoinOperators.Inner |
1205 SupportedJoinOperators.LeftOuter | SupportedJoinOperators.RightOuter);
1206 table.Rows.Add (row);
1211 static class DataTypes
1213 static readonly ColumnInfo [] columns = {
1214 new ColumnInfo ("TypeName", typeof(string)),
1215 new ColumnInfo ("ProviderDbType", typeof(int)),
1216 new ColumnInfo ("ColumnSize", typeof(long)),
1217 new ColumnInfo ("CreateFormat", typeof(string)),
1218 new ColumnInfo ("CreateParameters", typeof(string)),
1219 new ColumnInfo ("DataType", typeof(string)),
1220 new ColumnInfo ("IsAutoIncrementable", typeof(bool)),
1221 new ColumnInfo ("IsBestMatch", typeof(bool)),
1222 new ColumnInfo ("IsCaseSensitive", typeof(bool)),
1223 new ColumnInfo ("IsFixedLength", typeof(bool)),
1224 new ColumnInfo ("IsFixedPrecisionScale", typeof(bool)),
1225 new ColumnInfo ("IsLong", typeof(bool)),
1226 new ColumnInfo ("IsNullable", typeof(bool)),
1227 new ColumnInfo ("IsSearchable", typeof(bool)),
1228 new ColumnInfo ("IsSearchableWithLike", typeof(bool)),
1229 new ColumnInfo ("IsUnsigned", typeof(bool)),
1230 new ColumnInfo ("MaximumScale", typeof(short)),
1231 new ColumnInfo ("MinimumScale", typeof(short)),
1232 new ColumnInfo ("IsConcurrencyType", typeof(bool)),
1233 new ColumnInfo ("IsLiteralSupported", typeof(bool)),
1234 new ColumnInfo ("LiteralPrefix", typeof(string)),
1235 new ColumnInfo ("LiteralSuffix", typeof(string))
1238 static readonly object [][] rows = {
1239 new object [] {"smallint", 16, 5, "smallint", null, "System.Int16", true, true,
1240 false, true, true, false, true, true, false, false, null,
1241 null, false, null, null, null},
1242 new object [] {"int", 8, 10, "int", null, "System.Int32",
1243 true, true, false, true, true, false, true, true, false,
1244 false, null, null, false, null, null, null},
1245 new object [] {"real", 13, 7, "real", null,
1246 "System.Single", false, true, false, true, false, false,
1247 true, true, false, false, null, null, false, null, null, null},
1248 new object [] {"float", 6, 53, "float({0})",
1249 "number of bits used to store the mantissa", "System.Double",
1250 false, true, false, true, false, false, true, true,
1251 false, false, null, null, false, null, null, null},
1252 new object [] {"money", 9, 19, "money", null,
1253 "System.Decimal", false, false, false, true, true,
1254 false, true, true, false, false, null, null, false,
1256 new object [] {"smallmoney", 17, 10, "smallmoney", null,
1257 "System.Decimal", false, false, false, true, true, false,
1258 true, true, false, false, null, null, false, null, null, null},
1259 new object [] {"bit", 2, 1, "bit", null, "System.Boolean",
1260 false, false, false, true, false, false, true, true,
1261 false, null, null, null, false, null, null, null},
1262 new object [] {"tinyint", 20, 3, "tinyint", null,
1263 "System.SByte", true, true, false, true, true, false,
1264 true, true, false, true, null, null, false, null, null, null},
1265 new object [] {"bigint", 0, 19, "bigint", null,
1266 "System.Int64", true, true, false, true, true, false,
1267 true, true, false, false, null, null, false, null, null, null},
1268 new object [] {"timestamp", 19, 8, "timestamp", null,
1269 "System.Byte[]", false, false, false, true, false, false,
1270 false, true, false, null, null, null, true, null, "0x", null},
1271 new object [] {"binary", 1, 8000, "binary({0})", "length",
1272 "System.Byte[]", false, true, false, true, false, false,
1273 true, true, false, null, null, null, false, null, "0x", null},
1274 new object [] {"image", 7, 2147483647, "image", null,
1275 "System.Byte[]", false, true, false, false, false, true,
1276 true, false, false, null, null, null, false, null, "0x", null},
1277 new object [] {"text", 18, 2147483647, "text", null,
1278 "System.String", false, true, false, false, false, true,
1279 true, false, true, null, null, null, false, null, "'", "'"},
1280 new object [] {"ntext", 11, 1073741823, "ntext", null,
1281 "System.String", false, true, false, false, false, true,
1282 true, false, true, null, null, null, false, null, "N'", "'"},
1283 new object [] {"decimal", 5, 38, "decimal({0}, {1})",
1284 "precision,scale", "System.Decimal", true, true, false,
1285 true, false, false, true, true, false, false, 38, 0,
1286 false, null, null, null},
1287 new object [] {"numeric", 5, 38, "numeric({0}, {1})",
1288 "precision,scale", "System.Decimal", true, true, false,
1289 true, false, false, true, true, false, false, 38, 0,
1290 false, null, null, null},
1291 new object [] {"datetime", 4, 23, "datetime", null,
1292 "System.DateTime", false, true, false, true, false, false,
1293 true, true, true, null, null, null, false, null, "{ts '", "'}"},
1294 new object [] {"smalldatetime", 15, 16, "smalldatetime", null,
1295 "System.DateTime", false, true, false, true, false, false,
1296 true, true, true, null, null, null, false, null, "{ts '", "'}"},
1297 new object [] {"sql_variant", 23, null, "sql_variant",
1298 null, "System.Object", false, true, false, false, false,
1299 false, true, true, false, null, null, null, false, false,
1301 new object [] {"xml", 25, 2147483647, "xml", null,
1302 "System.String", false, false, false, false, false, true,
1303 true, false, false, null, null, null, false, false, null, null},
1304 new object [] {"varchar", 22, 2147483647, "varchar({0})",
1305 "max length", "System.String", false, true, false, false,
1306 false, false, true, true, true, null, null, null, false,
1308 new object [] {"char", 3, 2147483647, "char({0})", "length",
1309 "System.String", false, true, false, true, false, false,
1310 true, true, true, null, null, null, false, null, "'", "'"},
1311 new object [] {"nchar", 10, 1073741823, "nchar({0})", "length",
1312 "System.String", false, true, false, true, false, false,
1313 true, true, true, null, null, null, false, null, "N'", "'"},
1314 new object [] {"nvarchar", 12, 1073741823, "nvarchar({0})", "max length",
1315 "System.String", false, true, false, false, false, false, true, true,
1316 true, null, null, null, false, null, "N'", "'"},
1317 new object [] {"varbinary", 21, 1073741823, "varbinary({0})",
1318 "max length", "System.Byte[]", false, true, false, false,
1319 false, false, true, true, false, null, null, null, false,
1321 new object [] {"uniqueidentifier", 14, 16, "uniqueidentifier", null,
1322 "System.Guid", false, true, false, true, false, false, true,
1323 true, false, null, null, null, false, null, "'", "'"},
1324 new object [] {"date", 31, 3L, "date", DBNull.Value,
1325 "System.DateTime", false, false, false, true, true, false,
1326 true, true, true, DBNull.Value, DBNull.Value, DBNull.Value,
1327 false, DBNull.Value, "{ts '", "'}"},
1328 new object [] {"time", 32, 5L, "time({0})", "scale",
1329 "System.TimeSpan", false, false, false, false, false, false,
1330 true, true, true, DBNull.Value, (short) 7, (short) 0,
1331 false, DBNull.Value, "{ts '", "'}"},
1332 new object [] {"datetime2", 33, 8L, "datetime2({0})", "scale",
1333 "System.DateTime", false, true, false, false, false, false,
1334 true, true, true, DBNull.Value, (short) 7, (short) 0,
1335 false, DBNull.Value, "{ts '", "'}"},
1336 new object [] {"datetimeoffset", 34, 10L, "datetimeoffset({0})",
1337 "scale", "System.DateTimeOffset", false, true, false, false,
1338 false, false, true, true, true, DBNull.Value, (short) 7, (short) 0,
1339 false, DBNull.Value, "{ts '", "'}"}
1342 static DataTable instance;
1343 static public DataTable Instance {
1345 if (instance == null) {
1346 instance = new DataTable ("DataTypes");
1347 foreach (ColumnInfo c in columns)
1348 instance.Columns.Add (c.name, c.type);
1349 foreach (object [] row in rows)
1350 instance.LoadDataRow (row, true);
1357 static class Restrictions
1359 static readonly ColumnInfo [] columns = {
1360 new ColumnInfo ("CollectionName", typeof (string)),
1361 new ColumnInfo ("RestrictionName", typeof(string)),
1362 new ColumnInfo ("ParameterName", typeof(string)),
1363 new ColumnInfo ("RestrictionDefault", typeof(string)),
1364 new ColumnInfo ("RestrictionNumber", typeof(int))
1367 static readonly object [][] rows = {
1368 new object [] {"Users", "User_Name", "@Name", "name", 1},
1369 new object [] {"Databases", "Name", "@Name", "Name", 1},
1371 new object [] {"Tables", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1372 new object [] {"Tables", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1373 new object [] {"Tables", "Table", "@Name", "TABLE_NAME", 3},
1374 new object [] {"Tables", "TableType", "@TableType", "TABLE_TYPE", 4},
1376 new object [] {"Columns", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1377 new object [] {"Columns", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1378 new object [] {"Columns", "Table", "@Table", "TABLE_NAME", 3},
1379 new object [] {"Columns", "Column", "@Column", "COLUMN_NAME", 4},
1381 new object [] {"StructuredTypeMembers", "Catalog", "@Catalog", "TYPE_CATALOG", 1},
1382 new object [] {"StructuredTypeMembers", "Owner", "@Owner", "TYPE_SCHEMA", 2},
1383 new object [] {"StructuredTypeMembers", "Type", "@Type", "TYPE_NAME", 3},
1384 new object [] {"StructuredTypeMembers", "Member", "@Member", "MEMBER_NAME", 4},
1386 new object [] {"Views", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1387 new object [] {"Views", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1388 new object [] {"Views", "Table", "@Table", "TABLE_NAME", 3},
1390 new object [] {"ViewColumns", "Catalog", "@Catalog", "VIEW_CATALOG", 1},
1391 new object [] {"ViewColumns", "Owner", "@Owner", "VIEW_SCHEMA", 2},
1392 new object [] {"ViewColumns", "Table", "@Table", "VIEW_NAME", 3},
1393 new object [] {"ViewColumns", "Column", "@Column", "COLUMN_NAME", 4},
1395 new object [] {"ProcedureParameters", "Catalog", "@Catalog", "SPECIFIC_CATALOG", 1},
1396 new object [] {"ProcedureParameters", "Owner", "@Owner", "SPECIFIC_SCHEMA", 2},
1397 new object [] {"ProcedureParameters", "Name", "@Name", "SPECIFIC_NAME", 3},
1398 new object [] {"ProcedureParameters", "Parameter", "@Parameter", "PARAMETER_NAME", 4},
1400 new object [] {"Procedures", "Catalog", "@Catalog", "SPECIFIC_CATALOG", 1},
1401 new object [] {"Procedures", "Owner", "@Owner", "SPECIFIC_SCHEMA", 2},
1402 new object [] {"Procedures", "Name", "@Name", "SPECIFIC_NAME", 3},
1403 new object [] {"Procedures", "Type", "@Type", "ROUTINE_TYPE", 4},
1405 new object [] {"IndexColumns", "Catalog", "@Catalog", "db_name()", 1},
1406 new object [] {"IndexColumns", "Owner", "@Owner", "user_name()", 2},
1407 new object [] {"IndexColumns", "Table", "@Table", "o.name", 3},
1408 new object [] {"IndexColumns", "ConstraintName", "@ConstraintName", "x.name", 4},
1409 new object [] {"IndexColumns", "Column", "@Column", "c.name", 5},
1411 new object [] {"Indexes", "Catalog", "@Catalog", "db_name()", 1},
1412 new object [] {"Indexes", "Owner", "@Owner", "user_name()", 2},
1413 new object [] {"Indexes", "Table", "@Table", "o.name", 3},
1414 new object [] {"Indexes", "Name", "@Name", "x.name", 4},
1416 new object [] {"UserDefinedTypes", "assembly_name", "@AssemblyName", "assemblies.name", 1},
1417 new object [] {"UserDefinedTypes", "udt_name", "@UDTName", "types.assembly_class", 2},
1419 new object [] {"ForeignKeys", "Catalog", "@Catalog", "CONSTRAINT_CATALOG", 1},
1420 new object [] {"ForeignKeys", "Owner", "@Owner", "CONSTRAINT_SCHEMA", 2},
1421 new object [] {"ForeignKeys", "Table", "@Table", "TABLE_NAME", 3},
1422 new object [] {"ForeignKeys", "Name", "@Name", "CONSTRAINT_NAME", 4}
1425 static DataTable instance;
1426 static public DataTable Instance {
1428 if (instance == null) {
1429 instance = new DataTable ("Restrictions");
1430 foreach (ColumnInfo c in columns)
1431 instance.Columns.Add (c.name, c.type);
1432 foreach (object [] row in rows)
1433 instance.LoadDataRow (row, true);
1440 public override DataTable GetSchema ()
1442 if (state == ConnectionState.Closed)
1443 throw ExceptionHelper.ConnectionClosed ();
1445 return MetaDataCollections.Instance;
1448 public override DataTable GetSchema (String collectionName)
1450 return GetSchema (collectionName, null);
1453 public override DataTable GetSchema (String collectionName, string [] restrictionValues)
1455 // LAMESPEC: In MS.NET, if collectionName is null, it throws ArgumentException.
1457 if (state == ConnectionState.Closed)
1458 throw ExceptionHelper.ConnectionClosed ();
1460 String cName = null;
1461 DataTable schemaTable = MetaDataCollections.Instance;
1462 int length = restrictionValues == null ? 0 : restrictionValues.Length;
1464 foreach (DataRow row in schemaTable.Rows) {
1465 if (String.Compare ((string) row["CollectionName"], collectionName, true) == 0) {
1466 if (length > (int) row["NumberOfRestrictions"]) {
1467 throw new ArgumentException ("More restrictions were provided " +
1468 "than the requested schema ('" +
1469 row["CollectionName"].ToString () + "') supports");
1471 cName = row["CollectionName"].ToString();
1476 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
1477 "The requested collection ({0}) is not defined.",
1480 SqlCommand command = null;
1481 DataTable dataTable = new DataTable ();
1482 SqlDataAdapter dataAdapter = new SqlDataAdapter ();
1487 command = new SqlCommand ("select name as database_name, dbid, crdate as create_date " +
1488 "from master.sys.sysdatabases where (name = @Name or (@Name " +
1490 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1493 command = new SqlCommand ("select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, " +
1494 "TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_TYPE, " +
1495 "IS_DEFERRABLE, INITIALLY_DEFERRED from " +
1496 "INFORMATION_SCHEMA.TABLE_CONSTRAINTS where (CONSTRAINT_CATALOG" +
1497 " = @Catalog or (@Catalog is null)) and (CONSTRAINT_SCHEMA = " +
1498 "@Owner or (@Owner is null)) and (TABLE_NAME = @Table or (" +
1499 "@Table is null)) and (CONSTRAINT_NAME = @Name or (@Name is null))" +
1500 " and CONSTRAINT_TYPE = 'FOREIGN KEY' order by CONSTRAINT_CATALOG," +
1501 " CONSTRAINT_SCHEMA, CONSTRAINT_NAME", this);
1502 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1503 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1504 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1505 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1508 command = new SqlCommand ("select distinct db_name() as constraint_catalog, " +
1509 "constraint_schema = user_name (o.uid), " +
1510 "constraint_name = x.name, table_catalog = db_name (), " +
1511 "table_schema = user_name (o.uid), table_name = o.name, " +
1512 "index_name = x.name from sysobjects o, sysindexes x, " +
1513 "sysindexkeys xk where o.type in ('U') and x.id = o.id and " +
1514 "o.id = xk.id and x.indid = xk.indid and xk.keyno = x.keycnt " +
1515 "and (db_name() = @Catalog or (@Catalog is null)) and " +
1516 "(user_name() = @Owner or (@Owner is null)) and (o.name = " +
1517 "@Table or (@Table is null)) and (x.name = @Name or (@Name is null))" +
1518 "order by table_name, index_name", this);
1519 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1520 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1521 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1522 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1524 case "IndexColumns":
1525 command = new SqlCommand ("select distinct db_name() as constraint_catalog, " +
1526 "constraint_schema = user_name (o.uid), constraint_name = x.name, " +
1527 "table_catalog = db_name (), table_schema = user_name (o.uid), " +
1528 "table_name = o.name, column_name = c.name, " +
1529 "ordinal_position = convert (int, xk.keyno), keyType = c.xtype, " +
1530 "index_name = x.name from sysobjects o, sysindexes x, syscolumns c, " +
1531 "sysindexkeys xk where o.type in ('U') and x.id = o.id and o.id = c.id " +
1532 "and o.id = xk.id and x.indid = xk.indid and c.colid = xk.colid " +
1533 "and xk.keyno <= x.keycnt and permissions (o.id, c.name) <> 0 " +
1534 "and (db_name() = @Catalog or (@Catalog is null)) and (user_name() " +
1535 "= @Owner or (@Owner is null)) and (o.name = @Table or (@Table is" +
1536 " null)) and (x.name = @ConstraintName or (@ConstraintName is null)) " +
1537 "and (c.name = @Column or (@Column is null)) order by table_name, " +
1538 "index_name", this);
1539 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 8);
1540 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1541 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 13);
1542 command.Parameters.Add ("@ConstraintName", SqlDbType.NVarChar, 4000);
1543 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1546 command = new SqlCommand ("select SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, " +
1547 "ROUTINE_CATALOG, ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE, " +
1548 "CREATED, LAST_ALTERED from INFORMATION_SCHEMA.ROUTINES where " +
1549 "(SPECIFIC_CATALOG = @Catalog or (@Catalog is null)) and " +
1550 "(SPECIFIC_SCHEMA = @Owner or (@Owner is null)) and (SPECIFIC_NAME" +
1551 " = @Name or (@Name is null)) and (ROUTINE_TYPE = @Type or (@Type " +
1552 "is null)) order by SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME", this);
1553 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1554 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1555 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1556 command.Parameters.Add ("@Type", SqlDbType.NVarChar, 4000);
1558 case "ProcedureParameters":
1559 command = new SqlCommand ("select SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, " +
1560 "ORDINAL_POSITION, PARAMETER_MODE, IS_RESULT, AS_LOCATOR, " +
1561 "PARAMETER_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, " +
1562 "CHARACTER_OCTET_LENGTH, COLLATION_CATALOG, COLLATION_SCHEMA, " +
1563 "COLLATION_NAME, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, " +
1564 "CHARACTER_SET_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, " +
1565 "NUMERIC_SCALE, DATETIME_PRECISION, INTERVAL_TYPE, " +
1566 "INTERVAL_PRECISION from INFORMATION_SCHEMA.PARAMETERS where " +
1567 "(SPECIFIC_CATALOG = @Catalog or (@Catalog is null)) and " +
1568 "(SPECIFIC_SCHEMA = @Owner or (@Owner is null)) and (SPECIFIC_NAME = " +
1569 "@Name or (@Name is null)) and (PARAMETER_NAME = @Parameter or (" +
1570 "@Parameter is null)) order by SPECIFIC_CATALOG, SPECIFIC_SCHEMA," +
1571 " SPECIFIC_NAME, PARAMETER_NAME", this);
1572 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1573 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1574 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1575 command.Parameters.Add ("@Parameter", SqlDbType.NVarChar, 4000);
1578 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE " +
1579 "from INFORMATION_SCHEMA.TABLES where" +
1580 " (TABLE_CATALOG = @catalog or (@catalog is null)) and " +
1581 "(TABLE_SCHEMA = @owner or (@owner is null))and " +
1582 "(TABLE_NAME = @name or (@name is null)) and " +
1583 "(TABLE_TYPE = @table_type or (@table_type is null))", this);
1584 command.Parameters.Add ("@catalog", SqlDbType.NVarChar, 8);
1585 command.Parameters.Add ("@owner", SqlDbType.NVarChar, 3);
1586 command.Parameters.Add ("@name", SqlDbType.NVarChar, 11);
1587 command.Parameters.Add ("@table_type", SqlDbType.NVarChar, 10);
1590 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, " +
1591 "ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, " +
1592 "CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH, " +
1593 "NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE, " +
1594 "DATETIME_PRECISION, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, " +
1595 "CHARACTER_SET_NAME, COLLATION_CATALOG from INFORMATION_SCHEMA.COLUMNS" +
1596 " where (TABLE_CATALOG = @Catalog or (@Catalog is null)) and (" +
1597 "TABLE_SCHEMA = @Owner or (@Owner is null)) and (TABLE_NAME = @table" +
1598 " or (@Table is null)) and (COLUMN_NAME = @column or (@Column is null" +
1599 ")) order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME", this);
1600 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1601 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1602 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1603 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1606 command = new SqlCommand ("select uid, name as user_name, createdate, updatedate from sysusers" +
1607 " where (name = @Name or (@Name is null))", this);
1608 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1610 case "StructuredTypeMembers":
1611 // Only available on SQL Server 2008
1612 // Running it again SQL 2005 results in the following exception:
1613 // Unable to build the 'StructuredTypeMembers' collection because
1614 // execution of the SQL query failed. See the inner exception for details.
1615 // ---> System.Data.SqlClient.SqlException: Invalid object name 'sys.table_types'.
1617 // I don't have access to SQL Server 2008 right now,
1618 // and can't find any online documentation on the 'sys.table_types'
1620 throw new NotImplementedException ();
1622 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, CHECK_OPTION, " +
1623 "IS_UPDATABLE from INFORMATION_SCHEMA.VIEWS where (TABLE_CATALOG" +
1624 " = @Catalog or (@Catalog is null)) TABLE_SCHEMA = @Owner or " +
1625 "(@Owner is null)) and (TABLE_NAME = @table or (@Table is null))" +
1626 " order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME", this);
1627 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1628 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1629 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1632 command = new SqlCommand ("select VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME, TABLE_CATALOG, " +
1633 "TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME from " +
1634 "INFORMATION_SCHEMA.VIEW_COLUMN_USAGE where (VIEW_CATALOG = " +
1635 "@Catalog (@Catalog is null)) and (VIEW_SCHEMA = @Owner (@Owner" +
1636 " is null)) and (VIEW_NAME = @Table or (@Table is null)) and " +
1637 "(COLUMN_NAME = @Column or (@Column is null)) order by " +
1638 "VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME", this);
1639 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1640 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1641 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1642 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1644 case "UserDefinedTypes":
1645 command = new SqlCommand ("select assemblies.name as assembly_name, types.assembly_class " +
1646 "as udt_name, ASSEMBLYPROPERTY(assemblies.name, 'VersionMajor') " +
1647 "as version_major, ASSEMBLYPROPERTY(assemblies.name, 'VersionMinor') " +
1648 "as version_minor, ASSEMBLYPROPERTY(assemblies.name, 'VersionBuild') " +
1649 "as version_build, ASSEMBLYPROPERTY(assemblies.name, 'VersionRevision') " +
1650 "as version_revision, ASSEMBLYPROPERTY(assemblies.name, 'CultureInfo') " +
1651 "as culture_info, ASSEMBLYPROPERTY(assemblies.name, 'PublicKey') " +
1652 "as public_key, is_fixed_length, max_length, Create_Date, " +
1653 "Permission_set_desc from sys.assemblies as assemblies join " +
1654 "sys.assembly_types as types on assemblies.assembly_id = types.assembly_id" +
1655 " where (assportemblies.name = @AssemblyName or (@AssemblyName is null)) and " +
1656 "(types.assembly_class = @UDTName or (@UDTName is null))",
1658 command.Parameters.Add ("@AssemblyName", SqlDbType.NVarChar, 4000);
1659 command.Parameters.Add ("@UDTName", SqlDbType.NVarChar, 4000);
1661 case "MetaDataCollections":
1662 return MetaDataCollections.Instance;
1663 case "DataSourceInformation":
1664 return DataSourceInformation.GetInstance (this);
1666 return DataTypes.Instance;
1667 case "ReservedWords":
1668 return ReservedWords.Instance;
1669 case "Restrictions":
1670 return Restrictions.Instance;
1672 for (int i = 0; i < length; i++) {
1673 command.Parameters[i].Value = restrictionValues[i];
1675 dataAdapter.SelectCommand = command;
1676 dataAdapter.Fill (dataTable);
1680 public static void ChangePassword (string connectionString, string newPassword)
1682 if (String.IsNullOrEmpty (connectionString))
1683 throw new ArgumentNullException ("The 'connectionString' cannot be null or empty.");
1684 if (String.IsNullOrEmpty (newPassword))
1685 throw new ArgumentNullException ("The 'newPassword' cannot be null or empty.");
1686 if (newPassword.Length > 128)
1687 throw new ArgumentException ("The length of 'newPassword' cannot exceed 128 characters.");
1688 using (SqlConnection conn = new SqlConnection (connectionString)) {
1690 conn.tds.Execute (String.Format ("sp_password '{0}', '{1}', '{2}'",
1691 conn.parms.Password, newPassword, conn.parms.User));
1695 public static void ClearAllPools ()
1698 IDictionary pools = SqlConnection.sqlConnectionPools.GetConnectionPool ();
1699 foreach (TdsConnectionPool pool in pools.Values) {
1701 pool.ResetConnectionPool ();
1706 public static void ClearPool (SqlConnection connection)
1708 if (connection == null)
1709 throw new ArgumentNullException ("connection");
1712 if (connection.pooling) {
1713 TdsConnectionPool pool = sqlConnectionPools.GetConnectionPool (connection.ConnectionString);
1715 pool.ResetConnectionPool ();
1721 #endregion // Methods
1724 #region Fields Net 2
1729 #endregion // Fields Net 2
1731 #region Properties Net 2
1733 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1734 internal bool AsyncProcessing {
1735 get { return async; }
1738 #endregion // Properties Net 2