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;
48 using System.EnterpriseServices;
49 using System.Globalization;
51 using System.Net.Sockets;
55 using System.Collections.Generic;
58 namespace System.Data.SqlClient
60 [DefaultEvent ("InfoMessage")]
62 public sealed class SqlConnection : DbConnection, IDbConnection, ICloneable
64 public sealed class SqlConnection : Component, IDbConnection, ICloneable
71 // The set of SQL connection pools
72 static TdsConnectionPoolManager sqlConnectionPools = new TdsConnectionPoolManager (TdsVersion.tds70);
74 const int DEFAULT_PACKETSIZE = 8000;
76 const int DEFAULT_PACKETSIZE = 8192;
78 const int DEFAULT_CONNECTIONTIMEOUT = 15;
79 const int DEFAULT_MAXPOOLSIZE = 100;
80 const int DEFAULT_MINPOOLSIZE = 0;
81 const int DEFAULT_PORT = 1433;
83 // The current connection pool
84 TdsConnectionPool pool;
86 // The connection string that identifies this connection
87 string connectionString;
89 // The transaction object for the current transaction
90 SqlTransaction transaction;
92 // Connection parameters
94 TdsConnectionParameters parms = new TdsConnectionParameters ();
98 int connectionTimeout;
103 bool fireInfoMessageEventOnUserErrors;
104 bool statisticsEnabled;
108 ConnectionState state = ConnectionState.Closed;
110 SqlDataReader dataReader;
120 public SqlConnection () : this (String.Empty)
124 public SqlConnection (string connectionString)
126 Init (connectionString);
129 private void Init (string connectionString)
131 connectionTimeout = DEFAULT_CONNECTIONTIMEOUT;
132 dataSource = string.Empty;
133 packetSize = DEFAULT_PACKETSIZE;
135 ConnectionString = connectionString;
138 #endregion // Constructors
142 #if NET_1_0 || ONLY_1_1
143 [DataSysDescription ("Information used to connect to a DataSource, such as 'Data Source=x;Initial Catalog=x;Integrated Security=SSPI'.")]
146 [EditorAttribute ("Microsoft.VSDesigner.Data.SQL.Design.SqlConnectionStringEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
147 [RecommendedAsConfigurable (true)]
148 [RefreshProperties (RefreshProperties.All)]
153 string ConnectionString {
155 if (connectionString == null)
157 return connectionString;
159 [MonoTODO("persist security info, encrypt, enlist keyword not implemented")]
161 if (state == ConnectionState.Open)
162 throw new InvalidOperationException ("Not Allowed to change ConnectionString property while Connection state is OPEN");
163 SetConnectionString (value);
168 [DataSysDescription ("Current connection timeout value, 'Connect Timeout=X' in the ConnectionString.")]
170 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
175 int ConnectionTimeout {
176 get { return connectionTimeout; }
180 [DataSysDescription ("Current SQL Server database, 'Initial Catalog=X' in the connection string.")]
182 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
189 if (State == ConnectionState.Open)
191 return parms.Database ;
195 internal SqlDataReader DataReader {
196 get { return dataReader; }
197 set { dataReader = value; }
201 [DataSysDescription ("Current SqlServer that the connection is opened to, 'Data Source=X' in the connection string. ")]
205 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
211 get { return dataSource; }
215 [DataSysDescription ("Network packet size, 'Packet Size=x' in the connection string.")]
217 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
218 public int PacketSize {
220 if (State == ConnectionState.Open)
221 return ((Tds) tds).PacketSize;
228 [DataSysDescription ("Version of the SQL Server accessed by the SqlConnection.")]
230 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
235 string ServerVersion {
237 if (state == ConnectionState.Closed)
238 throw ExceptionHelper.ConnectionClosed ();
240 return tds.ServerVersion;
246 [DataSysDescription ("The ConnectionState indicating whether the connection is open or closed.")]
248 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
253 ConnectionState State {
254 get { return state; }
261 internal SqlTransaction Transaction {
262 get { return transaction; }
263 set { transaction = value; }
267 [DataSysDescription ("Workstation Id, 'Workstation ID=x' in the connection string.")]
269 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
270 public string WorkstationId {
271 get { return parms.Hostname; }
274 internal XmlReader XmlReader {
275 get { return xmlReader; }
276 set { xmlReader = value; }
280 public bool FireInfoMessageEventOnUserErrors {
281 get { return fireInfoMessageEventOnUserErrors; }
282 set { fireInfoMessageEventOnUserErrors = value; }
285 [DefaultValue (false)]
286 public bool StatisticsEnabled {
287 get { return statisticsEnabled; }
288 set { statisticsEnabled = value; }
291 #endregion // Properties
296 [DataSysDescription ("Event triggered when messages arrive from the DataSource.")]
298 public event SqlInfoMessageEventHandler InfoMessage;
301 [DataSysDescription ("Event triggered when the connection changes state.")]
302 public new event StateChangeEventHandler StateChange;
309 private void ErrorHandler (object sender, TdsInternalErrorMessageEventArgs e)
311 throw new SqlException (e.Class, e.LineNumber, e.Message, e.Number, e.Procedure, e.Server, "Mono SqlClient Data Provider", e.State);
314 private void MessageHandler (object sender, TdsInternalInfoMessageEventArgs e)
316 OnSqlInfoMessage (CreateSqlInfoMessageEvent (e.Errors));
319 #endregion // Delegates
323 public new SqlTransaction BeginTransaction ()
325 return BeginTransaction (IsolationLevel.ReadCommitted, String.Empty);
328 public new SqlTransaction BeginTransaction (IsolationLevel iso)
330 return BeginTransaction (iso, String.Empty);
333 public SqlTransaction BeginTransaction (string transactionName)
335 return BeginTransaction (IsolationLevel.ReadCommitted, transactionName);
338 public SqlTransaction BeginTransaction (IsolationLevel iso, string transactionName)
340 if (state == ConnectionState.Closed)
341 throw ExceptionHelper.ConnectionClosed ();
342 if (transaction != null)
343 throw new InvalidOperationException ("SqlConnection does not support parallel transactions.");
345 string isolevel = String.Empty;
347 case IsolationLevel.ReadUncommitted:
348 isolevel = "READ UNCOMMITTED";
350 case IsolationLevel.RepeatableRead:
351 isolevel = "REPEATABLE READ";
353 case IsolationLevel.Serializable:
354 isolevel = "SERIALIZABLE";
356 case IsolationLevel.ReadCommitted:
357 isolevel = "READ COMMITTED";
360 case IsolationLevel.Snapshot:
361 isolevel = "SNAPSHOT";
363 case IsolationLevel.Unspecified:
364 iso = IsolationLevel.ReadCommitted;
365 isolevel = "READ COMMITTED";
367 case IsolationLevel.Chaos:
368 throw new ArgumentOutOfRangeException ("IsolationLevel",
369 string.Format (CultureInfo.CurrentCulture,
370 "The IsolationLevel enumeration " +
371 "value, {0}, is not supported by " +
372 "the .Net Framework SqlClient " +
373 "Data Provider.", (int) iso));
377 throw new ArgumentOutOfRangeException ("IsolationLevel",
378 string.Format (CultureInfo.CurrentCulture,
379 "The IsolationLevel enumeration value, {0}, is invalid.",
382 throw new ArgumentException ("Invalid IsolationLevel parameter: must be ReadCommitted, ReadUncommitted, RepeatableRead, or Serializable.");
386 tds.Execute (String.Format ("SET TRANSACTION ISOLATION LEVEL {0};BEGIN TRANSACTION {1}", isolevel, transactionName));
388 transaction = new SqlTransaction (this, iso);
396 void ChangeDatabase (string database)
398 if (!IsValidDatabaseName (database))
399 throw new ArgumentException (String.Format ("The database name {0} is not valid.", database));
400 if (state != ConnectionState.Open)
401 throw new InvalidOperationException ("The connection is not open.");
402 tds.Execute (String.Format ("use [{0}]", database));
405 private void ChangeState (ConnectionState currentState)
407 if (currentState == state)
410 ConnectionState originalState = state;
411 state = currentState;
412 OnStateChange (CreateStateChangeEvent (originalState, currentState));
421 if (transaction != null && transaction.IsOpen)
422 transaction.Rollback ();
424 if (dataReader != null || xmlReader != null) {
425 if(tds != null) tds.SkipToEnd ();
430 if (tds != null && tds.IsConnected) {
431 if (pooling && tds.Pooling) {
433 if(pool != null) pool.ReleaseConnection (ref tds);
435 if(pool != null) pool.ReleaseConnection (tds);
438 if(tds != null) tds.Disconnect ();
442 tds.TdsErrorMessage -= new TdsInternalErrorMessageEventHandler (ErrorHandler);
443 tds.TdsInfoMessage -= new TdsInternalInfoMessageEventHandler (MessageHandler);
446 ChangeState (ConnectionState.Closed);
449 public new SqlCommand CreateCommand ()
451 SqlCommand command = new SqlCommand ();
452 command.Connection = this;
456 private SqlInfoMessageEventArgs CreateSqlInfoMessageEvent (TdsInternalErrorCollection errors)
458 return new SqlInfoMessageEventArgs (errors);
461 private StateChangeEventArgs CreateStateChangeEvent (ConnectionState originalState, ConnectionState currentState)
463 return new StateChangeEventArgs (originalState, currentState);
466 protected override void Dispose (bool disposing)
473 if (State == ConnectionState.Open)
475 ConnectionString = string.Empty;
479 base.Dispose (disposing);
483 [MonoTODO ("Not sure what this means at present.")]
484 public void EnlistDistributedTransaction (ITransaction transaction)
486 throw new NotImplementedException ();
489 object ICloneable.Clone ()
491 return new SqlConnection (ConnectionString);
495 protected override DbTransaction BeginDbTransaction (IsolationLevel isolationLevel)
497 return BeginTransaction (isolationLevel);
500 protected override DbCommand CreateDbCommand ()
502 return CreateCommand ();
505 IDbTransaction IDbConnection.BeginTransaction ()
507 return BeginTransaction ();
510 IDbTransaction IDbConnection.BeginTransaction (IsolationLevel iso)
512 return BeginTransaction (iso);
515 IDbCommand IDbConnection.CreateCommand ()
517 return CreateCommand ();
527 string serverName = string.Empty;
528 if (state == ConnectionState.Open)
529 throw new InvalidOperationException ("The Connection is already Open (State=Open)");
531 if (connectionString == null || connectionString.Trim().Length == 0)
532 throw new InvalidOperationException ("Connection string has not been initialized.");
536 if(!ParseDataSource (dataSource, out port, out serverName))
537 throw new SqlException(20, 0, "SQL Server does not exist or access denied.", 17, "ConnectionOpen (Connect()).", dataSource, parms.ApplicationName, 0);
538 tds = new Tds70 (serverName, port, PacketSize, ConnectionTimeout);
541 if(!ParseDataSource (dataSource, out port, out serverName))
542 throw new SqlException(20, 0, "SQL Server does not exist or access denied.", 17, "ConnectionOpen (Connect()).", dataSource, parms.ApplicationName, 0);
544 TdsConnectionInfo info = new TdsConnectionInfo (serverName, port, packetSize, ConnectionTimeout, minPoolSize, maxPoolSize);
545 pool = sqlConnectionPools.GetConnectionPool (connectionString, info);
546 tds = pool.GetConnection ();
548 } catch (TdsTimeoutException e) {
549 throw SqlException.FromTdsInternalException ((TdsInternalException) e);
550 } catch (TdsInternalException e) {
551 throw SqlException.FromTdsInternalException (e);
554 tds.TdsErrorMessage += new TdsInternalErrorMessageEventHandler (ErrorHandler);
555 tds.TdsInfoMessage += new TdsInternalInfoMessageEventHandler (MessageHandler);
557 if (!tds.IsConnected) {
562 pool.ReleaseConnection (tds);
567 disposed = false; // reset this, so using () would call Close ().
568 ChangeState (ConnectionState.Open);
571 private bool ParseDataSource (string theDataSource, out int thePort, out string theServerName)
573 theServerName = string.Empty;
574 string theInstanceName = string.Empty;
576 if (theDataSource == null)
577 throw new ArgumentException("Format of initialization string does not conform to specifications");
579 thePort = DEFAULT_PORT; // default TCP port for SQL Server
583 if ((idx = theDataSource.IndexOf (",")) > -1) {
584 theServerName = theDataSource.Substring (0, idx);
585 string p = theDataSource.Substring (idx + 1);
586 thePort = Int32.Parse (p);
587 } else if ((idx = theDataSource.IndexOf ("\\")) > -1) {
588 theServerName = theDataSource.Substring (0, idx);
589 theInstanceName = theDataSource.Substring (idx + 1);
591 // do port discovery via UDP port 1434
592 port = DiscoverTcpPortViaSqlMonitor (theServerName, theInstanceName);
596 theServerName = theDataSource;
598 if (theServerName.Length == 0 || theServerName == "(local)" || theServerName == ".")
599 theServerName = "localhost";
601 if ((idx = theServerName.IndexOf ("tcp:")) > -1)
602 theServerName = theServerName.Substring (idx + 4);
607 private bool ConvertIntegratedSecurity (string value)
609 if (value.ToUpper() == "SSPI")
612 return ConvertToBoolean("integrated security", value);
615 private bool ConvertToBoolean (string key, string value)
617 string upperValue = value.ToUpper ();
619 if (upperValue == "TRUE" || upperValue == "YES")
621 else if (upperValue == "FALSE" || upperValue == "NO")
624 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
625 "Invalid value \"{0}\" for key '{1}'.", value, key));
628 private int ConvertToInt32 (string key, string value)
631 return int.Parse (value);
632 } catch (Exception ex) {
633 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
634 "Invalid value \"{0}\" for key '{1}'.", value, key));
638 private int DiscoverTcpPortViaSqlMonitor (string ServerName, string InstanceName)
640 SqlMonitorSocket msock;
641 msock = new SqlMonitorSocket (ServerName, InstanceName);
642 int SqlServerPort = msock.DiscoverTcpPort (ConnectionTimeout);
644 return SqlServerPort;
647 void SetConnectionString (string connectionString)
649 SetDefaultConnectionParameters ();
651 if ((connectionString == null) || (connectionString.Trim().Length == 0)) {
652 this.connectionString = connectionString;
656 connectionString += ";";
658 bool inQuote = false;
659 bool inDQuote = false;
662 string name = String.Empty;
663 string value = String.Empty;
664 StringBuilder sb = new StringBuilder ();
666 for (int i = 0; i < connectionString.Length; i += 1) {
667 char c = connectionString [i];
669 if (i == connectionString.Length - 1)
672 peek = connectionString [i + 1];
678 else if (peek.Equals (c)) {
688 else if (peek.Equals (c)) {
693 inDQuote = !inDQuote;
696 if (inDQuote || inQuote)
699 if (name != String.Empty && name != null) {
700 value = sb.ToString ();
701 SetProperties (name.ToUpper ().Trim() , value);
703 else if (sb.Length != 0)
704 throw new ArgumentException ("Format of initialization string does not conform to specifications");
707 value = String.Empty;
708 sb = new StringBuilder ();
712 if (inDQuote || inQuote || !inName)
714 else if (peek.Equals (c)) {
720 name = sb.ToString ();
721 sb = new StringBuilder ();
726 if (inQuote || inDQuote)
728 else if (sb.Length > 0 && !peek.Equals (';'))
737 connectionString = connectionString.Substring (0 , connectionString.Length-1);
738 this.connectionString = connectionString;
741 void SetDefaultConnectionParameters ()
744 dataSource = string.Empty;
745 connectionTimeout = DEFAULT_CONNECTIONTIMEOUT;
746 connectionReset = true;
748 maxPoolSize = DEFAULT_MAXPOOLSIZE;
749 minPoolSize = DEFAULT_MINPOOLSIZE;
750 packetSize = DEFAULT_PACKETSIZE;
756 private void SetProperties (string name , string value)
760 case "APPLICATION NAME" :
761 parms.ApplicationName = value;
763 case "ATTACHDBFILENAME" :
764 case "EXTENDED PROPERTIES" :
765 case "INITIAL FILE NAME" :
766 parms.AttachDBFileName = value;
769 case "CONNECT TIMEOUT" :
770 case "CONNECTION TIMEOUT" :
771 int tmpTimeout = ConvertToInt32 ("connection timeout", value);
773 throw new ArgumentException ("Invalid CONNECTION TIMEOUT .. Must be an integer >=0 ");
775 connectionTimeout = tmpTimeout;
777 case "CONNECTION LIFETIME" :
779 case "CONNECTION RESET" :
780 connectionReset = ConvertToBoolean ("connection reset", value);
783 case "CURRENT LANGUAGE" :
784 parms.Language = value;
790 case "NETWORK ADDRESS" :
794 if (ConvertToBoolean("encrypt", value))
795 throw new NotImplementedException("SSL encryption for"
796 + " data sent between client and server is not"
800 if (!ConvertToBoolean("enlist", value))
801 throw new NotImplementedException("Disabling the automatic"
802 + " enlistment of connections in the thread's current"
803 + " transaction context is not implemented.");
805 case "INITIAL CATALOG" :
807 parms.Database = value;
809 case "INTEGRATED SECURITY" :
810 case "TRUSTED_CONNECTION" :
811 parms.DomainLogin = ConvertIntegratedSecurity(value);
813 case "MAX POOL SIZE" :
814 int tmpMaxPoolSize = ConvertToInt32 ("max pool size" , value);
815 if (tmpMaxPoolSize < 0)
816 throw new ArgumentException ("Invalid MAX POOL SIZE. Must be a intger >= 0");
818 maxPoolSize = tmpMaxPoolSize;
820 case "MIN POOL SIZE" :
821 int tmpMinPoolSize = ConvertToInt32 ("min pool size" , value);
822 if (tmpMinPoolSize < 0)
823 throw new ArgumentException ("Invalid MIN POOL SIZE. Must be a intger >= 0");
825 minPoolSize = tmpMinPoolSize;
828 case "MULTIPLEACTIVERESULTSETS":
830 case "ASYNCHRONOUS PROCESSING" :
832 async = ConvertToBoolean (name, value);
837 case "NETWORK LIBRARY" :
838 if (!value.ToUpper ().Equals ("DBMSSOCN"))
839 throw new ArgumentException ("Unsupported network library.");
842 int tmpPacketSize = ConvertToInt32 ("packet size", value);
843 if (tmpPacketSize < 512 || tmpPacketSize > 32767)
844 throw new ArgumentException ("Invalid PACKET SIZE. The integer must be between 512 and 32767");
846 packetSize = tmpPacketSize;
850 parms.Password = value;
852 case "PERSISTSECURITYINFO" :
853 case "PERSIST SECURITY INFO" :
854 // FIXME : not implemented
855 // throw new NotImplementedException ();
858 pooling = ConvertToBoolean("pooling", value);
866 case "WORKSTATION ID" :
867 parms.Hostname = value;
870 case "USER INSTANCE":
871 userInstance = ConvertToBoolean ("user instance", value);
874 throw new ArgumentException("Keyword not supported :"+name);
878 static bool IsValidDatabaseName (string database)
880 if ( database == null || database.Trim().Length == 0 || database.Length > 128)
883 if (database[0] == '"' && database[database.Length] == '"')
884 database = database.Substring (1, database.Length - 2);
885 else if (Char.IsDigit (database[0]))
888 if (database[0] == '_')
891 foreach (char c in database.Substring (1, database.Length - 1))
892 if (!Char.IsLetterOrDigit (c) && c != '_' && c != '-')
897 private void OnSqlInfoMessage (SqlInfoMessageEventArgs value)
899 if (InfoMessage != null)
900 InfoMessage (this, value);
904 private new void OnStateChange (StateChangeEventArgs value)
906 if (StateChange != null)
907 StateChange (this, value);
911 private sealed class SqlMonitorSocket : UdpClient
913 // UDP port that the SQL Monitor listens
914 private static readonly int SqlMonitorUdpPort = 1434;
915 //private static readonly string SqlServerNotExist = "SQL Server does not exist or access denied";
917 private string server;
918 private string instance;
920 internal SqlMonitorSocket (string ServerName, string InstanceName)
921 : base (ServerName, SqlMonitorUdpPort)
924 instance = InstanceName;
927 internal int DiscoverTcpPort (int timeoutSeconds)
929 int SqlServerTcpPort;
930 Client.Blocking = false;
931 // send command to UDP 1434 (SQL Monitor) to get
932 // the TCP port to connect to the MS SQL server
933 ASCIIEncoding enc = new ASCIIEncoding ();
934 Byte[] rawrq = new Byte [instance.Length + 1];
936 enc.GetBytes (instance, 0, instance.Length, rawrq, 1);
937 int bytes = Send (rawrq, rawrq.Length);
943 long timeout = timeoutSeconds * 1000000;
944 result = Client.Poll ((int)timeout, SelectMode.SelectRead);
948 if (Client.Available <= 0)
951 IPEndPoint endpoint = new IPEndPoint (Dns.GetHostEntry ("localhost").AddressList [0], 0);
953 IPEndPoint endpoint = new IPEndPoint (Dns.GetHostByName ("localhost").AddressList [0], 0);
957 rawrs = Receive (ref endpoint);
959 string rs = Encoding.ASCII.GetString (rawrs);
961 string[] rawtokens = rs.Split (';');
962 Hashtable data = new Hashtable ();
963 for (int i = 0; i < rawtokens.Length / 2 && i < 256; i++) {
964 data [rawtokens [i * 2]] = rawtokens [ i * 2 + 1];
967 if (!data.ContainsKey ("tcp")) {
968 string msg = "Mono does not support names pipes or shared memory "
969 + "for connecting to SQL Server. Please enable the TCP/IP "
971 throw new NotImplementedException (msg);
974 SqlServerTcpPort = int.Parse ((string) data ["tcp"]);
977 return SqlServerTcpPort;
987 public ColumnInfo (string name, Type type)
989 this.name = name; this.type = type;
993 static class ReservedWords
995 static readonly string [] reservedWords =
997 "ADD", "EXCEPT", "PERCENT", "ALL", "EXEC", "PLAN", "ALTER",
998 "EXECUTE", "PRECISION", "AND", "EXISTS", "PRIMARY", "ANY",
999 "EXIT", "PRINT", "AS", "FETCH", "PROC", "ASC", "FILE",
1000 "PROCEDURE", "AUTHORIZATION", "FILLFACTOR", "PUBLIC",
1001 "BACKUP", "FOR", "RAISERROR", "BEGIN", "FOREIGN", "READ",
1002 "BETWEEN", "FREETEXT", "READTEXT", "BREAK", "FREETEXTTABLE",
1003 "RECONFIGURE", "BROWSE", "FROM", "REFERENCES", "BULK",
1004 "FULL", "REPLICATION", "BY", "FUNCTION", "RESTORE",
1005 "CASCADE", "GOTO", "RESTRICT", "CASE", "GRANT", "RETURN",
1006 "CHECK", "GROUP", "REVOKE", "CHECKPOINT", "HAVING", "RIGHT",
1007 "CLOSE", "HOLDLOCK", "ROLLBACK", "CLUSTERED", "IDENTITY",
1008 "ROWCOUNT", "COALESCE", "IDENTITY_INSERT", "ROWGUIDCOL",
1009 "COLLATE", "IDENTITYCOL", "RULE", "COLUMN", "IF", "SAVE",
1010 "COMMIT", "IN", "SCHEMA", "COMPUTE", "INDEX", "SELECT",
1011 "CONSTRAINT", "INNER", "SESSION_USER", "CONTAINS", "INSERT",
1012 "SET", "CONTAINSTABLE", "INTERSECT", "SETUSER", "CONTINUE",
1013 "INTO", "SHUTDOWN", "CONVERT", "IS", "SOME", "CREATE",
1014 "JOIN", "STATISTICS", "CROSS", "KEY", "SYSTEM_USER",
1015 "CURRENT", "KILL", "TABLE", "CURRENT_DATE", "LEFT",
1016 "TEXTSIZE", "CURRENT_TIME", "LIKE", "THEN",
1017 "CURRENT_TIMESTAMP", "LINENO", "TO", "CURRENT_USER", "LOAD",
1018 "TOP", "CURSOR", "NATIONAL", "TRAN", "DATABASE", "NOCHECK",
1019 "TRANSACTION", "DBCC", "NONCLUSTERED", "TRIGGER",
1020 "DEALLOCATE", "NOT", "TRUNCATE", "DECLARE", "NULL",
1021 "TSEQUAL", "DEFAULT", "NULLIF", "UNION", "DELETE", "OF",
1022 "UNIQUE", "DENY", "OFF", "UPDATE", "DESC", "OFFSETS",
1023 "UPDATETEXT", "DISK", "ON", "USE", "DISTINCT", "OPEN",
1024 "USER", "DISTRIBUTED", "OPENDATASOURCE", "VALUES", "DOUBLE",
1025 "OPENQUERY", "VARYING", "DROP", "OPENROWSET", "VIEW",
1026 "DUMMY", "OPENXML", "WAITFOR", "DUMP", "OPTION", "WHEN",
1027 "ELSE", "OR", "WHERE", "END", "ORDER", "WHILE", "ERRLVL",
1028 "OUTER", "WITH", "ESCAPE", "OVER", "WRITETEXT", "ABSOLUTE",
1029 "FOUND", "PRESERVE", "ACTION", "FREE", "PRIOR", "ADMIN",
1030 "GENERAL", "PRIVILEGES", "AFTER", "GET", "READS",
1031 "AGGREGATE", "GLOBAL", "REAL", "ALIAS", "GO", "RECURSIVE",
1032 "ALLOCATE", "GROUPING", "REF", "ARE", "HOST", "REFERENCING",
1033 "ARRAY", "HOUR", "RELATIVE", "ASSERTION", "IGNORE", "RESULT",
1034 "AT", "IMMEDIATE", "RETURNS", "BEFORE", "INDICATOR", "ROLE",
1035 "BINARY", "INITIALIZE", "ROLLUP", "BIT", "INITIALLY",
1036 "ROUTINE", "BLOB", "INOUT", "ROW", "BOOLEAN", "INPUT",
1037 "ROWS", "BOTH", "INT", "SAVEPOINT", "BREADTH", "INTEGER",
1038 "SCROLL", "CALL", "INTERVAL", "SCOPE", "CASCADED",
1039 "ISOLATION", "SEARCH", "CAST", "ITERATE", "SECOND",
1040 "CATALOG", "LANGUAGE", "SECTION", "CHAR", "LARGE",
1041 "SEQUENCE", "CHARACTER", "LAST", "SESSION", "CLASS",
1042 "LATERAL", "SETS", "CLOB", "LEADING", "SIZE", "COLLATION",
1043 "LESS", "SMALLINT", "COMPLETION", "LEVEL", "SPACE",
1044 "CONNECT", "LIMIT", "SPECIFIC", "CONNECTION", "LOCAL",
1045 "SPECIFICTYPE", "CONSTRAINTS", "LOCALTIME", "SQL",
1046 "CONSTRUCTOR", "LOCALTIMESTAMP", "SQLEXCEPTION",
1047 "CORRESPONDING", "LOCATOR", "SQLSTATE", "CUBE", "MAP",
1048 "SQLWARNING", "CURRENT_PATH", "MATCH", "START",
1049 "CURRENT_ROLE", "MINUTE", "STATE", "CYCLE", "MODIFIES",
1050 "STATEMENT", "DATA", "MODIFY", "STATIC", "DATE", "MODULE",
1051 "STRUCTURE", "DAY", "MONTH", "TEMPORARY", "DEC", "NAMES",
1052 "TERMINATE", "DECIMAL", "NATURAL", "THAN", "DEFERRABLE",
1053 "NCHAR", "TIME", "DEFERRED", "NCLOB", "TIMESTAMP", "DEPTH",
1054 "NEW", "TIMEZONE_HOUR", "DEREF", "NEXT", "TIMEZONE_MINUTE",
1055 "DESCRIBE", "NO", "TRAILING", "DESCRIPTOR", "NONE",
1056 "TRANSLATION", "DESTROY", "NUMERIC", "TREAT", "DESTRUCTOR",
1057 "OBJECT", "TRUE", "DETERMINISTIC", "OLD", "UNDER",
1058 "DICTIONARY", "ONLY", "UNKNOWN", "DIAGNOSTICS", "OPERATION",
1059 "UNNEST", "DISCONNECT", "ORDINALITY", "USAGE", "DOMAIN",
1060 "OUT", "USING", "DYNAMIC", "OUTPUT", "VALUE", "EACH",
1061 "PAD", "VARCHAR", "END-EXEC", "PARAMETER", "VARIABLE",
1062 "EQUALS", "PARAMETERS", "WHENEVER", "EVERY", "PARTIAL",
1063 "WITHOUT", "EXCEPTION", "PATH", "WORK", "EXTERNAL",
1064 "POSTFIX", "WRITE", "FALSE", "PREFIX", "YEAR", "FIRST",
1065 "PREORDER", "ZONE", "FLOAT", "PREPARE", "ADA", "AVG",
1066 "BIT_LENGTH", "CHAR_LENGTH", "CHARACTER_LENGTH", "COUNT",
1067 "EXTRACT", "FORTRAN", "INCLUDE", "INSENSITIVE", "LOWER",
1068 "MAX", "MIN", "OCTET_LENGTH", "OVERLAPS", "PASCAL",
1069 "POSITION", "SQLCA", "SQLCODE", "SQLERROR", "SUBSTRING",
1070 "SUM", "TRANSLATE", "TRIM", "UPPER"
1072 static DataTable instance;
1073 static public DataTable Instance {
1075 if (instance == null) {
1077 instance = new DataTable ("ReservedWords");
1078 instance.Columns.Add ("ReservedWord", typeof(string));
1079 foreach (string reservedWord in reservedWords)
1081 row = instance.NewRow();
1083 row["ReservedWord"] = reservedWord;
1084 instance.Rows.Add(row);
1092 static class MetaDataCollections
1094 static readonly ColumnInfo [] columns = {
1095 new ColumnInfo ("CollectionName", typeof (string)),
1096 new ColumnInfo ("NumberOfRestrictions", typeof (int)),
1097 new ColumnInfo ("NumberOfIdentifierParts", typeof (int))
1100 static readonly object [][] rows = {
1101 new object [] {"MetaDataCollections", 0, 0},
1102 new object [] {"DataSourceInformation", 0, 0},
1103 new object [] {"DataTypes", 0, 0},
1104 new object [] {"Restrictions", 0, 0},
1105 new object [] {"ReservedWords", 0, 0},
1106 new object [] {"Users", 1, 1},
1107 new object [] {"Databases", 1, 1},
1108 new object [] {"Tables", 4, 3},
1109 new object [] {"Columns", 4, 4},
1110 new object [] {"StructuredTypeMembers", 4, 4},
1111 new object [] {"Views", 3, 3},
1112 new object [] {"ViewColumns", 4, 4},
1113 new object [] {"ProcedureParameters", 4, 1},
1114 new object [] {"Procedures", 4, 3},
1115 new object [] {"ForeignKeys", 4, 3},
1116 new object [] {"IndexColumns", 5, 4},
1117 new object [] {"Indexes", 4, 3},
1118 new object [] {"UserDefinedTypes", 2, 1}
1121 static DataTable instance;
1122 static public DataTable Instance {
1124 if (instance == null) {
1125 instance = new DataTable ("MetaDataCollections");
1126 foreach (ColumnInfo c in columns)
1127 instance.Columns.Add (c.name, c.type);
1128 foreach (object [] row in rows)
1129 instance.LoadDataRow (row, true);
1136 static class DataSourceInformation
1138 static readonly ColumnInfo [] columns = {
1139 new ColumnInfo ("CompositeIdentifierSeparatorPattern", typeof (string)),
1140 new ColumnInfo ("DataSourceProductName", typeof(string)),
1141 new ColumnInfo ("DataSourceProductVersion", typeof(string)),
1142 new ColumnInfo ("DataSourceProductVersionNormalized", typeof(string)),
1143 new ColumnInfo ("GroupByBehavior", typeof(GroupByBehavior)),
1144 new ColumnInfo ("IdentifierPattern", typeof(string)),
1145 new ColumnInfo ("IdentifierCase", typeof(IdentifierCase)),
1146 new ColumnInfo ("OrderByColumnsInSelect", typeof(bool)),
1147 new ColumnInfo ("ParameterMarkerFormat", typeof(string)),
1148 new ColumnInfo ("ParameterMarkerPattern", typeof(string)),
1149 new ColumnInfo ("ParameterNameMaxLength", typeof(int)),
1150 new ColumnInfo ("ParameterNamePattern", typeof(string)),
1151 new ColumnInfo ("QuotedIdentifierPattern", typeof(string)),
1152 new ColumnInfo ("QuotedIdentifierCase", typeof(IdentifierCase)),
1153 new ColumnInfo ("StatementSeparatorPattern", typeof(string)),
1154 new ColumnInfo ("StringLiteralPattern", typeof(string)),
1155 new ColumnInfo ("SupportedJoinOperators", typeof(SupportedJoinOperators))
1158 static public DataTable GetInstance (SqlConnection conn)
1160 DataTable table = new DataTable ("DataSourceInformation");
1161 foreach (ColumnInfo c in columns)
1162 table.Columns.Add (c.name, c.type);
1163 DataRow row = table.NewRow ();
1165 row [1] = "Microsoft SQL Server";
1166 row [2] = conn.ServerVersion;;
1167 row [3] = conn.ServerVersion;;
1168 row [4] = GroupByBehavior.Unrelated;
1169 row [5] = @"(^\[\p{Lo}\p{Lu}\p{Ll}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Nd}@$#_]*$)|(^\[[^\]\0]|\]\]+\]$)|(^\""[^\""\0]|\""\""+\""$)";
1170 row [6] = IdentifierCase.Insensitive; // FIXME: obtain this from SQL Server
1173 row [9] = @"@[\p{Lo}\p{Lu}\p{Ll}\p{Lm}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Lm}\p{Nd}\uff3f_@#\$]*(?=\s+|$)";
1175 row [11] = @"^[\p{Lo}\p{Lu}\p{Ll}\p{Lm}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Lm}\p{Nd}\uff3f_@#\$]*(?=\s+|$)";
1176 row [12] = @"(([^\[]|\]\])*)";
1177 row [13] = IdentifierCase.Insensitive; // FIXME: obtain this from SQL Server
1179 row [15] = "'(([^']|'')*)'";
1180 row [16] = (SupportedJoinOperators.FullOuter | SupportedJoinOperators.Inner |
1181 SupportedJoinOperators.LeftOuter | SupportedJoinOperators.RightOuter);
1182 table.Rows.Add (row);
1187 static class DataTypes
1189 static readonly ColumnInfo [] columns = {
1190 new ColumnInfo ("TypeName", typeof(string)),
1191 new ColumnInfo ("ProviderDbType", typeof(int)),
1192 new ColumnInfo ("ColumnSize", typeof(long)),
1193 new ColumnInfo ("CreateFormat", typeof(string)),
1194 new ColumnInfo ("CreateParameters", typeof(string)),
1195 new ColumnInfo ("DataType", typeof(string)),
1196 new ColumnInfo ("IsAutoIncrementable", typeof(bool)),
1197 new ColumnInfo ("IsBestMatch", typeof(bool)),
1198 new ColumnInfo ("IsCaseSensitive", typeof(bool)),
1199 new ColumnInfo ("IsFixedLength", typeof(bool)),
1200 new ColumnInfo ("IsFixedPrecisionScale", typeof(bool)),
1201 new ColumnInfo ("IsLong", typeof(bool)),
1202 new ColumnInfo ("IsNullable", typeof(bool)),
1203 new ColumnInfo ("IsSearchable", typeof(bool)),
1204 new ColumnInfo ("IsSearchableWithLike", typeof(bool)),
1205 new ColumnInfo ("IsUnsigned", typeof(bool)),
1206 new ColumnInfo ("MaximumScale", typeof(short)),
1207 new ColumnInfo ("MinimumScale", typeof(short)),
1208 new ColumnInfo ("IsConcurrencyType", typeof(bool)),
1209 new ColumnInfo ("IsLiteralSupported", typeof(bool)),
1210 new ColumnInfo ("LiteralPrefix", typeof(string)),
1211 new ColumnInfo ("LiteralSuffix", typeof(string))
1214 static readonly object [][] rows = {
1215 new object [] {"smallint", 16, 5, "smallint", null, "System.Int16", true, true,
1216 false, true, true, false, true, true, false, false, null,
1217 null, false, null, null, null},
1218 new object [] {"int", 8, 10, "int", null, "System.Int32",
1219 true, true, false, true, true, false, true, true, false,
1220 false, null, null, false, null, null, null},
1221 new object [] {"real", 13, 7, "real", null,
1222 "System.Single", false, true, false, true, false, false,
1223 true, true, false, false, null, null, false, null, null, null},
1224 new object [] {"float", 6, 53, "float({0})",
1225 "number of bits used to store the mantissa", "System.Double",
1226 false, true, false, true, false, false, true, true,
1227 false, false, null, null, false, null, null, null},
1228 new object [] {"money", 9, 19, "money", null,
1229 "System.Decimal", false, false, false, true, true,
1230 false, true, true, false, false, null, null, false,
1232 new object [] {"smallmoney", 17, 10, "smallmoney", null,
1233 "System.Decimal", false, false, false, true, true, false,
1234 true, true, false, false, null, null, false, null, null, null},
1235 new object [] {"bit", 2, 1, "bit", null, "System.Boolean",
1236 false, false, false, true, false, false, true, true,
1237 false, null, null, null, false, null, null, null},
1238 new object [] {"tinyint", 20, 3, "tinyint", null,
1239 "System.SByte", true, true, false, true, true, false,
1240 true, true, false, true, null, null, false, null, null, null},
1241 new object [] {"bigint", 0, 19, "bigint", null,
1242 "System.Int64", true, true, false, true, true, false,
1243 true, true, false, false, null, null, false, null, null, null},
1244 new object [] {"timestamp", 19, 8, "timestamp", null,
1245 "System.Byte[]", false, false, false, true, false, false,
1246 false, true, false, null, null, null, true, null, "0x", null},
1247 new object [] {"binary", 1, 8000, "binary({0})", "length",
1248 "System.Byte[]", false, true, false, true, false, false,
1249 true, true, false, null, null, null, false, null, "0x", null},
1250 new object [] {"image", 7, 2147483647, "image", null,
1251 "System.Byte[]", false, true, false, false, false, true,
1252 true, false, false, null, null, null, false, null, "0x", null},
1253 new object [] {"text", 18, 2147483647, "text", null,
1254 "System.String", false, true, false, false, false, true,
1255 true, false, true, null, null, null, false, null, "'", "'"},
1256 new object [] {"ntext", 11, 1073741823, "ntext", null,
1257 "System.String", false, true, false, false, false, true,
1258 true, false, true, null, null, null, false, null, "N'", "'"},
1259 new object [] {"decimal", 5, 38, "decimal({0}, {1})",
1260 "precision,scale", "System.Decimal", true, true, false,
1261 true, false, false, true, true, false, false, 38, 0,
1262 false, null, null, null},
1263 new object [] {"numeric", 5, 38, "numeric({0}, {1})",
1264 "precision,scale", "System.Decimal", true, true, false,
1265 true, false, false, true, true, false, false, 38, 0,
1266 false, null, null, null},
1267 new object [] {"datetime", 4, 23, "datetime", null,
1268 "System.DateTime", false, true, false, true, false, false,
1269 true, true, true, null, null, null, false, null, "{ts '", "'}"},
1270 new object [] {"smalldatetime", 15, 16, "smalldatetime", null,
1271 "System.DateTime", false, true, false, true, false, false,
1272 true, true, true, null, null, null, false, null, "{ts '", "'}"},
1273 new object [] {"sql_variant", 23, null, "sql_variant",
1274 null, "System.Object", false, true, false, false, false,
1275 false, true, true, false, null, null, null, false, false,
1277 new object [] {"xml", 25, 2147483647, "xml", null,
1278 "System.String", false, false, false, false, false, true,
1279 true, false, false, null, null, null, false, false, null, null},
1280 new object [] {"varchar", 22, 2147483647, "varchar({0})",
1281 "max length", "System.String", false, true, false, false,
1282 false, false, true, true, true, null, null, null, false,
1284 new object [] {"char", 3, 2147483647, "char({0})", "length",
1285 "System.String", false, true, false, true, false, false,
1286 true, true, true, null, null, null, false, null, "'", "'"},
1287 new object [] {"nchar", 10, 1073741823, "nchar({0})", "length",
1288 "System.String", false, true, false, true, false, false,
1289 true, true, true, null, null, null, false, null, "N'", "'"},
1290 new object [] {"nvarchar", 12, 1073741823, "nvarchar({0})", "max length",
1291 "System.String", false, true, false, false, false, false, true, true,
1292 true, null, null, null, false, null, "N'", "'"},
1293 new object [] {"varbinary", 21, 1073741823, "varbinary({0})",
1294 "max length", "System.Byte[]", false, true, false, false,
1295 false, false, true, true, false, null, null, null, false,
1297 new object [] {"uniqueidentifier", 14, 16, "uniqueidentifier", null,
1298 "System.Guid", false, true, false, true, false, false, true,
1299 true, false, null, null, null, false, null, "'", "'"},
1300 new object [] {"date", 31, 3L, "date", DBNull.Value,
1301 "System.DateTime", false, false, false, true, true, false,
1302 true, true, true, DBNull.Value, DBNull.Value, DBNull.Value,
1303 false, DBNull.Value, "{ts '", "'}"},
1304 new object [] {"time", 32, 5L, "time({0})", "scale",
1305 "System.TimeSpan", false, false, false, false, false, false,
1306 true, true, true, DBNull.Value, (short) 7, (short) 0,
1307 false, DBNull.Value, "{ts '", "'}"},
1308 new object [] {"datetime2", 33, 8L, "datetime2({0})", "scale",
1309 "System.DateTime", false, true, false, false, false, false,
1310 true, true, true, DBNull.Value, (short) 7, (short) 0,
1311 false, DBNull.Value, "{ts '", "'}"},
1312 new object [] {"datetimeoffset", 34, 10L, "datetimeoffset({0})",
1313 "scale", "System.DateTimeOffset", false, true, false, false,
1314 false, false, true, true, true, DBNull.Value, (short) 7, (short) 0,
1315 false, DBNull.Value, "{ts '", "'}"}
1318 static DataTable instance;
1319 static public DataTable Instance {
1321 if (instance == null) {
1322 instance = new DataTable ("DataTypes");
1323 foreach (ColumnInfo c in columns)
1324 instance.Columns.Add (c.name, c.type);
1325 foreach (object [] row in rows)
1326 instance.LoadDataRow (row, true);
1333 static class Restrictions
1335 static readonly ColumnInfo [] columns = {
1336 new ColumnInfo ("CollectionName", typeof (string)),
1337 new ColumnInfo ("RestrictionName", typeof(string)),
1338 new ColumnInfo ("ParameterName", typeof(string)),
1339 new ColumnInfo ("RestrictionDefault", typeof(string)),
1340 new ColumnInfo ("RestrictionNumber", typeof(int))
1343 static readonly object [][] rows = {
1344 new object [] {"Users", "User_Name", "@Name", "name", 1},
1345 new object [] {"Databases", "Name", "@Name", "Name", 1},
1347 new object [] {"Tables", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1348 new object [] {"Tables", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1349 new object [] {"Tables", "Table", "@Name", "TABLE_NAME", 3},
1350 new object [] {"Tables", "TableType", "@TableType", "TABLE_TYPE", 4},
1352 new object [] {"Columns", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1353 new object [] {"Columns", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1354 new object [] {"Columns", "Table", "@Table", "TABLE_NAME", 3},
1355 new object [] {"Columns", "Column", "@Column", "COLUMN_NAME", 4},
1357 new object [] {"StructuredTypeMembers", "Catalog", "@Catalog", "TYPE_CATALOG", 1},
1358 new object [] {"StructuredTypeMembers", "Owner", "@Owner", "TYPE_SCHEMA", 2},
1359 new object [] {"StructuredTypeMembers", "Type", "@Type", "TYPE_NAME", 3},
1360 new object [] {"StructuredTypeMembers", "Member", "@Member", "MEMBER_NAME", 4},
1362 new object [] {"Views", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1363 new object [] {"Views", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1364 new object [] {"Views", "Table", "@Table", "TABLE_NAME", 3},
1366 new object [] {"ViewColumns", "Catalog", "@Catalog", "VIEW_CATALOG", 1},
1367 new object [] {"ViewColumns", "Owner", "@Owner", "VIEW_SCHEMA", 2},
1368 new object [] {"ViewColumns", "Table", "@Table", "VIEW_NAME", 3},
1369 new object [] {"ViewColumns", "Column", "@Column", "COLUMN_NAME", 4},
1371 new object [] {"ProcedureParameters", "Catalog", "@Catalog", "SPECIFIC_CATALOG", 1},
1372 new object [] {"ProcedureParameters", "Owner", "@Owner", "SPECIFIC_SCHEMA", 2},
1373 new object [] {"ProcedureParameters", "Name", "@Name", "SPECIFIC_NAME", 3},
1374 new object [] {"ProcedureParameters", "Parameter", "@Parameter", "PARAMETER_NAME", 4},
1376 new object [] {"Procedures", "Catalog", "@Catalog", "SPECIFIC_CATALOG", 1},
1377 new object [] {"Procedures", "Owner", "@Owner", "SPECIFIC_SCHEMA", 2},
1378 new object [] {"Procedures", "Name", "@Name", "SPECIFIC_NAME", 3},
1379 new object [] {"Procedures", "Type", "@Type", "ROUTINE_TYPE", 4},
1381 new object [] {"IndexColumns", "Catalog", "@Catalog", "db_name()", 1},
1382 new object [] {"IndexColumns", "Owner", "@Owner", "user_name()", 2},
1383 new object [] {"IndexColumns", "Table", "@Table", "o.name", 3},
1384 new object [] {"IndexColumns", "ConstraintName", "@ConstraintName", "x.name", 4},
1385 new object [] {"IndexColumns", "Column", "@Column", "c.name", 5},
1387 new object [] {"Indexes", "Catalog", "@Catalog", "db_name()", 1},
1388 new object [] {"Indexes", "Owner", "@Owner", "user_name()", 2},
1389 new object [] {"Indexes", "Table", "@Table", "o.name", 3},
1390 new object [] {"Indexes", "Name", "@Name", "x.name", 4},
1392 new object [] {"UserDefinedTypes", "assembly_name", "@AssemblyName", "assemblies.name", 1},
1393 new object [] {"UserDefinedTypes", "udt_name", "@UDTName", "types.assembly_class", 2},
1395 new object [] {"ForeignKeys", "Catalog", "@Catalog", "CONSTRAINT_CATALOG", 1},
1396 new object [] {"ForeignKeys", "Owner", "@Owner", "CONSTRAINT_SCHEMA", 2},
1397 new object [] {"ForeignKeys", "Table", "@Table", "TABLE_NAME", 3},
1398 new object [] {"ForeignKeys", "Name", "@Name", "CONSTRAINT_NAME", 4}
1401 static DataTable instance;
1402 static public DataTable Instance {
1404 if (instance == null) {
1405 instance = new DataTable ("Restrictions");
1406 foreach (ColumnInfo c in columns)
1407 instance.Columns.Add (c.name, c.type);
1408 foreach (object [] row in rows)
1409 instance.LoadDataRow (row, true);
1416 public override DataTable GetSchema ()
1418 if (state == ConnectionState.Closed)
1419 throw ExceptionHelper.ConnectionClosed ();
1421 return MetaDataCollections.Instance;
1424 public override DataTable GetSchema (String collectionName)
1426 return GetSchema (collectionName, null);
1429 public override DataTable GetSchema (String collectionName, string [] restrictionValues)
1431 // LAMESPEC: In MS.NET, if collectionName is null, it throws ArgumentException.
1433 if (state == ConnectionState.Closed)
1434 throw ExceptionHelper.ConnectionClosed ();
1436 String cName = null;
1437 DataTable schemaTable = MetaDataCollections.Instance;
1438 int length = restrictionValues == null ? 0 : restrictionValues.Length;
1440 foreach (DataRow row in schemaTable.Rows) {
1441 if (String.Compare ((string) row["CollectionName"], collectionName, true) == 0) {
1442 if (length > (int) row["NumberOfRestrictions"]) {
1443 throw new ArgumentException ("More restrictions were provided " +
1444 "than the requested schema ('" +
1445 row["CollectionName"].ToString () + "') supports");
1447 cName = row["CollectionName"].ToString();
1452 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
1453 "The requested collection ({0}) is not defined.",
1456 SqlCommand command = null;
1457 DataTable dataTable = new DataTable ();
1458 SqlDataAdapter dataAdapter = new SqlDataAdapter ();
1463 command = new SqlCommand ("select name as database_name, dbid, crdate as create_date " +
1464 "from master.sys.sysdatabases where (name = @Name or (@Name " +
1466 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1469 command = new SqlCommand ("select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, " +
1470 "TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_TYPE, " +
1471 "IS_DEFERRABLE, INITIALLY_DEFERRED from " +
1472 "INFORMATION_SCHEMA.TABLE_CONSTRAINTS where (CONSTRAINT_CATALOG" +
1473 " = @Catalog or (@Catalog is null)) and (CONSTRAINT_SCHEMA = " +
1474 "@Owner or (@Owner is null)) and (TABLE_NAME = @Table or (" +
1475 "@Table is null)) and (CONSTRAINT_NAME = @Name or (@Name is null))" +
1476 " and CONSTRAINT_TYPE = 'FOREIGN KEY' order by CONSTRAINT_CATALOG," +
1477 " CONSTRAINT_SCHEMA, CONSTRAINT_NAME", this);
1478 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1479 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1480 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1481 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1484 command = new SqlCommand ("select distinct db_name() as constraint_catalog, " +
1485 "constraint_schema = user_name (o.uid), " +
1486 "constraint_name = x.name, table_catalog = db_name (), " +
1487 "table_schema = user_name (o.uid), table_name = o.name, " +
1488 "index_name = x.name from sysobjects o, sysindexes x, " +
1489 "sysindexkeys xk where o.type in ('U') and x.id = o.id and " +
1490 "o.id = xk.id and x.indid = xk.indid and xk.keyno = x.keycnt " +
1491 "and (db_name() = @Catalog or (@Catalog is null)) and " +
1492 "(user_name() = @Owner or (@Owner is null)) and (o.name = " +
1493 "@Table or (@Table is null)) and (x.name = @Name or (@Name is null))" +
1494 "order by table_name, index_name", this);
1495 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1496 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1497 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1498 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1500 case "IndexColumns":
1501 command = new SqlCommand ("select distinct db_name() as constraint_catalog, " +
1502 "constraint_schema = user_name (o.uid), constraint_name = x.name, " +
1503 "table_catalog = db_name (), table_schema = user_name (o.uid), " +
1504 "table_name = o.name, column_name = c.name, " +
1505 "ordinal_position = convert (int, xk.keyno), keyType = c.xtype, " +
1506 "index_name = x.name from sysobjects o, sysindexes x, syscolumns c, " +
1507 "sysindexkeys xk where o.type in ('U') and x.id = o.id and o.id = c.id " +
1508 "and o.id = xk.id and x.indid = xk.indid and c.colid = xk.colid " +
1509 "and xk.keyno <= x.keycnt and permissions (o.id, c.name) <> 0 " +
1510 "and (db_name() = @Catalog or (@Catalog is null)) and (user_name() " +
1511 "= @Owner or (@Owner is null)) and (o.name = @Table or (@Table is" +
1512 " null)) and (x.name = @ConstraintName or (@ConstraintName is null)) " +
1513 "and (c.name = @Column or (@Column is null)) order by table_name, " +
1514 "index_name", this);
1515 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 8);
1516 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1517 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 13);
1518 command.Parameters.Add ("@ConstraintName", SqlDbType.NVarChar, 4000);
1519 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1522 command = new SqlCommand ("select SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, " +
1523 "ROUTINE_CATALOG, ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE, " +
1524 "CREATED, LAST_ALTERED from INFORMATION_SCHEMA.ROUTINES where " +
1525 "(SPECIFIC_CATALOG = @Catalog or (@Catalog is null)) and " +
1526 "(SPECIFIC_SCHEMA = @Owner or (@Owner is null)) and (SPECIFIC_NAME" +
1527 " = @Name or (@Name is null)) and (ROUTINE_TYPE = @Type or (@Type " +
1528 "is null)) order by SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME", this);
1529 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1530 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1531 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1532 command.Parameters.Add ("@Type", SqlDbType.NVarChar, 4000);
1534 case "ProcedureParameters":
1535 command = new SqlCommand ("select SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, " +
1536 "ORDINAL_POSITION, PARAMETER_MODE, IS_RESULT, AS_LOCATOR, " +
1537 "PARAMETER_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, " +
1538 "CHARACTER_OCTET_LENGTH, COLLATION_CATALOG, COLLATION_SCHEMA, " +
1539 "COLLATION_NAME, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, " +
1540 "CHARACTER_SET_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, " +
1541 "NUMERIC_SCALE, DATETIME_PRECISION, INTERVAL_TYPE, " +
1542 "INTERVAL_PRECISION from INFORMATION_SCHEMA.PARAMETERS where " +
1543 "(SPECIFIC_CATALOG = @Catalog or (@Catalog is null)) and " +
1544 "(SPECIFIC_SCHEMA = @Owner or (@Owner is null)) and (SPECIFIC_NAME = " +
1545 "@Name or (@Name is null)) and (PARAMETER_NAME = @Parameter or (" +
1546 "@Parameter is null)) order by SPECIFIC_CATALOG, SPECIFIC_SCHEMA," +
1547 " SPECIFIC_NAME, PARAMETER_NAME", this);
1548 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1549 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1550 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1551 command.Parameters.Add ("@Parameter", SqlDbType.NVarChar, 4000);
1554 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE " +
1555 "from INFORMATION_SCHEMA.TABLES where" +
1556 " (TABLE_CATALOG = @catalog or (@catalog is null)) and " +
1557 "(TABLE_SCHEMA = @owner or (@owner is null))and " +
1558 "(TABLE_NAME = @name or (@name is null)) and " +
1559 "(TABLE_TYPE = @table_type or (@table_type is null))", this);
1560 command.Parameters.Add ("@catalog", SqlDbType.NVarChar, 8);
1561 command.Parameters.Add ("@owner", SqlDbType.NVarChar, 3);
1562 command.Parameters.Add ("@name", SqlDbType.NVarChar, 11);
1563 command.Parameters.Add ("@table_type", SqlDbType.NVarChar, 10);
1566 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, " +
1567 "ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, " +
1568 "CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH, " +
1569 "NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE, " +
1570 "DATETIME_PRECISION, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, " +
1571 "CHARACTER_SET_NAME, COLLATION_CATALOG from INFORMATION_SCHEMA.COLUMNS" +
1572 " where (TABLE_CATALOG = @Catalog or (@Catalog is null)) and (" +
1573 "TABLE_SCHEMA = @Owner or (@Owner is null)) and (TABLE_NAME = @table" +
1574 " or (@Table is null)) and (COLUMN_NAME = @column or (@Column is null" +
1575 ")) order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME", this);
1576 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1577 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1578 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1579 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1582 command = new SqlCommand ("select uid, name as user_name, createdate, updatedate from sysusers" +
1583 " where (name = @Name or (@Name is null))", this);
1584 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1586 case "StructuredTypeMembers":
1587 // Only available on SQL Server 2008
1588 // Running it again SQL 2005 results in the following exception:
1589 // Unable to build the 'StructuredTypeMembers' collection because
1590 // execution of the SQL query failed. See the inner exception for details.
1591 // ---> System.Data.SqlClient.SqlException: Invalid object name 'sys.table_types'.
1593 // I don't have access to SQL Server 2008 right now,
1594 // and can't find any online documentation on the 'sys.table_types'
1596 throw new NotImplementedException ();
1598 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, CHECK_OPTION, " +
1599 "IS_UPDATABLE from INFORMATION_SCHEMA.VIEWS where (TABLE_CATALOG" +
1600 " = @Catalog or (@Catalog is null)) TABLE_SCHEMA = @Owner or " +
1601 "(@Owner is null)) and (TABLE_NAME = @table or (@Table is null))" +
1602 " order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME", this);
1603 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1604 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1605 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1608 command = new SqlCommand ("select VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME, TABLE_CATALOG, " +
1609 "TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME from " +
1610 "INFORMATION_SCHEMA.VIEW_COLUMN_USAGE where (VIEW_CATALOG = " +
1611 "@Catalog (@Catalog is null)) and (VIEW_SCHEMA = @Owner (@Owner" +
1612 " is null)) and (VIEW_NAME = @Table or (@Table is null)) and " +
1613 "(COLUMN_NAME = @Column or (@Column is null)) order by " +
1614 "VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME", this);
1615 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1616 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1617 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1618 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1620 case "UserDefinedTypes":
1621 command = new SqlCommand ("select assemblies.name as assembly_name, types.assembly_class " +
1622 "as udt_name, ASSEMBLYPROPERTY(assemblies.name, 'VersionMajor') " +
1623 "as version_major, ASSEMBLYPROPERTY(assemblies.name, 'VersionMinor') " +
1624 "as version_minor, ASSEMBLYPROPERTY(assemblies.name, 'VersionBuild') " +
1625 "as version_build, ASSEMBLYPROPERTY(assemblies.name, 'VersionRevision') " +
1626 "as version_revision, ASSEMBLYPROPERTY(assemblies.name, 'CultureInfo') " +
1627 "as culture_info, ASSEMBLYPROPERTY(assemblies.name, 'PublicKey') " +
1628 "as public_key, is_fixed_length, max_length, Create_Date, " +
1629 "Permission_set_desc from sys.assemblies as assemblies join " +
1630 "sys.assembly_types as types on assemblies.assembly_id = types.assembly_id" +
1631 " where (assportemblies.name = @AssemblyName or (@AssemblyName is null)) and " +
1632 "(types.assembly_class = @UDTName or (@UDTName is null))",
1634 command.Parameters.Add ("@AssemblyName", SqlDbType.NVarChar, 4000);
1635 command.Parameters.Add ("@UDTName", SqlDbType.NVarChar, 4000);
1637 case "MetaDataCollections":
1638 return MetaDataCollections.Instance;
1639 case "DataSourceInformation":
1640 return DataSourceInformation.GetInstance (this);
1642 return DataTypes.Instance;
1643 case "ReservedWords":
1644 return ReservedWords.Instance;
1645 case "Restrictions":
1646 return Restrictions.Instance;
1648 for (int i = 0; i < length; i++) {
1649 command.Parameters[i].Value = restrictionValues[i];
1651 dataAdapter.SelectCommand = command;
1652 dataAdapter.Fill (dataTable);
1656 public static void ChangePassword (string connectionString, string newPassword)
1658 if (connectionString == null || newPassword == null || newPassword == String.Empty)
1659 throw new ArgumentNullException ();
1660 if (newPassword.Length > 128)
1661 throw new ArgumentException ("The value of newPassword exceeds its permittable length which is 128");
1662 using (SqlConnection conn = new SqlConnection (connectionString)) {
1664 conn.tds.Execute (String.Format ("sp_password '{0}', '{1}', '{2}'",
1665 conn.parms.Password, newPassword, conn.parms.User));
1669 public static void ClearAllPools ()
1672 IDictionary <string, TdsConnectionPool> pools = SqlConnection.sqlConnectionPools.GetConnectionPool ();
1674 Hashtable pools = SqlConnection.sqlConnectionPools.GetConnectionPool ();
1676 foreach (TdsConnectionPool pool in pools.Values) {
1678 pool.ResetConnectionPool ();
1679 Tds tds = pool.GetConnection ();
1680 tds.Pooling = false;
1685 public static void ClearPool (SqlConnection connection)
1687 if (connection.pooling) {
1688 connection.pooling = false;
1689 if (connection.pool != null)
1690 connection.pool.ResetConnectionPool (connection.Tds);
1696 #endregion // Methods
1699 #region Fields Net 2
1703 #endregion // Fields Net 2
1705 #region Properties Net 2
1708 [DataSysDescription ("Enable Asynchronous processing, 'Asynchrouse Processing=true/false' in the ConnectionString.")]
1710 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1711 internal bool AsyncProcessing {
1712 get { return async; }
1715 #endregion // Properties Net 2