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