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 [RecommendedAsConfigurable (true)]
142 [RefreshProperties (RefreshProperties.All)]
143 public override string ConnectionString {
145 if (connectionString == null)
147 return connectionString;
149 [MonoTODO("persist security info, encrypt, enlist keyword not implemented")]
151 if (state == ConnectionState.Open)
152 throw new InvalidOperationException ("Not Allowed to change ConnectionString property while Connection state is OPEN");
153 SetConnectionString (value);
157 public SqlCredential Credentials {
166 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
169 int ConnectionTimeout {
170 get { return connectionTimeout; }
173 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
178 if (State == ConnectionState.Open)
180 return parms.Database ;
184 internal SqlDataReader DataReader {
185 get { return dataReader; }
186 set { dataReader = value; }
190 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
194 get { return dataSource; }
197 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
198 public int PacketSize {
200 if (State == ConnectionState.Open)
201 return ((Tds) tds).PacketSize;
207 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
210 string ServerVersion {
212 if (state == ConnectionState.Closed)
213 throw ExceptionHelper.ConnectionClosed ();
215 return tds.ServerVersion;
220 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
223 ConnectionState State {
224 get { return state; }
231 internal SqlTransaction Transaction {
232 get { return transaction; }
233 set { transaction = value; }
236 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
237 public string WorkstationId {
238 get { return parms.Hostname; }
241 internal XmlReader XmlReader {
242 get { return xmlReader; }
243 set { xmlReader = value; }
246 public bool FireInfoMessageEventOnUserErrors {
247 get { return fireInfoMessageEventOnUserErrors; }
248 set { fireInfoMessageEventOnUserErrors = value; }
251 [DefaultValue (false)]
252 public bool StatisticsEnabled {
253 get { return statisticsEnabled; }
254 set { statisticsEnabled = value; }
257 protected override DbProviderFactory DbProviderFactory {
259 return SqlClientFactory.Instance;
263 #endregion // Properties
267 public event SqlInfoMessageEventHandler InfoMessage;
274 private void ErrorHandler (object sender, TdsInternalErrorMessageEventArgs e)
277 if (!tds.IsConnected)
285 throw new SqlException (e.Class, e.LineNumber, e.Message, e.Number, e.Procedure, e.Server, "Mono SqlClient Data Provider", e.State);
288 private void MessageHandler (object sender, TdsInternalInfoMessageEventArgs e)
290 OnSqlInfoMessage (CreateSqlInfoMessageEvent (e.Errors));
293 #endregion // Delegates
297 public new SqlTransaction BeginTransaction ()
299 return BeginTransaction (IsolationLevel.ReadCommitted, String.Empty);
302 public new SqlTransaction BeginTransaction (IsolationLevel iso)
304 return BeginTransaction (iso, String.Empty);
307 public SqlTransaction BeginTransaction (string transactionName)
309 return BeginTransaction (IsolationLevel.ReadCommitted, transactionName);
312 public SqlTransaction BeginTransaction (IsolationLevel iso, string transactionName)
314 if (state == ConnectionState.Closed)
315 throw ExceptionHelper.ConnectionClosed ();
316 if (transaction != null)
317 throw new InvalidOperationException ("SqlConnection does not support parallel transactions.");
319 string isolevel = String.Empty;
321 case IsolationLevel.ReadUncommitted:
322 isolevel = "READ UNCOMMITTED";
324 case IsolationLevel.RepeatableRead:
325 isolevel = "REPEATABLE READ";
327 case IsolationLevel.Serializable:
328 isolevel = "SERIALIZABLE";
330 case IsolationLevel.ReadCommitted:
331 isolevel = "READ COMMITTED";
333 case IsolationLevel.Snapshot:
334 isolevel = "SNAPSHOT";
336 case IsolationLevel.Unspecified:
337 iso = IsolationLevel.ReadCommitted;
338 isolevel = "READ COMMITTED";
340 case IsolationLevel.Chaos:
341 throw new ArgumentOutOfRangeException ("IsolationLevel",
342 string.Format (CultureInfo.CurrentCulture,
343 "The IsolationLevel enumeration " +
344 "value, {0}, is not supported by " +
345 "the .Net Framework SqlClient " +
346 "Data Provider.", (int) iso));
348 throw new ArgumentOutOfRangeException ("IsolationLevel",
349 string.Format (CultureInfo.CurrentCulture,
350 "The IsolationLevel enumeration value, {0}, is invalid.",
354 tds.Execute (String.Format ("SET TRANSACTION ISOLATION LEVEL {0};BEGIN TRANSACTION {1}", isolevel, transactionName));
356 transaction = new SqlTransaction (this, iso);
362 void ChangeDatabase (string database)
364 if (!IsValidDatabaseName (database))
365 throw new ArgumentException (String.Format ("The database name {0} is not valid.", database));
366 if (state != ConnectionState.Open)
367 throw new InvalidOperationException ("The connection is not open.");
368 tds.Execute (String.Format ("use [{0}]", database));
371 private void ChangeState (ConnectionState currentState)
373 if (currentState == state)
376 ConnectionState originalState = state;
377 state = currentState;
378 OnStateChange (CreateStateChangeEvent (originalState, currentState));
385 if (transaction != null && transaction.IsOpen)
386 transaction.Rollback ();
388 if (dataReader != null || xmlReader != null) {
389 if(tds != null) tds.SkipToEnd ();
394 if (tds != null && tds.IsConnected) {
395 if (pooling && tds.Pooling) {
397 pool.ReleaseConnection (tds);
406 tds.TdsErrorMessage -= new TdsInternalErrorMessageEventHandler (ErrorHandler);
407 tds.TdsInfoMessage -= new TdsInternalInfoMessageEventHandler (MessageHandler);
410 ChangeState (ConnectionState.Closed);
413 public new SqlCommand CreateCommand ()
415 SqlCommand command = new SqlCommand ();
416 command.Connection = this;
420 private SqlInfoMessageEventArgs CreateSqlInfoMessageEvent (TdsInternalErrorCollection errors)
422 foreach (TdsInternalError e in errors)
423 return new SqlInfoMessageEventArgs (new SqlException (e.Class, e.LineNumber, e.Message, e.Number, e.Procedure, e.Server, "Mono SqlClient Data Provider", e.State));
428 private StateChangeEventArgs CreateStateChangeEvent (ConnectionState originalState, ConnectionState currentState)
430 return new StateChangeEventArgs (originalState, currentState);
433 protected override void Dispose (bool disposing)
436 if (disposing && !disposed) {
437 if (State == ConnectionState.Open)
439 ConnectionString = null;
443 base.Dispose (disposing);
448 [MonoTODO ("Not sure what this means at present.")]
449 public void EnlistDistributedTransaction (ITransaction transaction)
451 throw new NotImplementedException ();
455 object ICloneable.Clone ()
457 return new SqlConnection (ConnectionString);
460 protected override DbTransaction BeginDbTransaction (IsolationLevel isolationLevel)
462 return BeginTransaction (isolationLevel);
465 protected override DbCommand CreateDbCommand ()
467 return CreateCommand ();
474 string serverName = string.Empty;
475 if (state == ConnectionState.Open)
476 throw new InvalidOperationException ("The Connection is already Open (State=Open)");
478 if (connectionString == null || connectionString.Trim().Length == 0)
479 throw new InvalidOperationException ("Connection string has not been initialized.");
483 if(!ParseDataSource (dataSource, out port, out serverName))
484 throw new SqlException(20, 0, "SQL Server does not exist or access denied.", 17, "ConnectionOpen (Connect()).", dataSource, parms.ApplicationName, 0);
485 tds = new Tds80 (serverName, port, PacketSize, ConnectionTimeout, 0);
489 if(!ParseDataSource (dataSource, out port, out serverName))
490 throw new SqlException(20, 0, "SQL Server does not exist or access denied.", 17, "ConnectionOpen (Connect()).", dataSource, parms.ApplicationName, 0);
492 TdsConnectionInfo info = new TdsConnectionInfo (serverName, port, packetSize, ConnectionTimeout, minPoolSize, maxPoolSize, connectionLifeTime);
493 pool = sqlConnectionPools.GetConnectionPool (connectionString, info);
494 tds = pool.GetConnection ();
496 } catch (TdsTimeoutException e) {
497 throw SqlException.FromTdsInternalException ((TdsInternalException) e);
498 } catch (TdsInternalException e) {
499 throw SqlException.FromTdsInternalException (e);
502 tds.TdsErrorMessage += new TdsInternalErrorMessageEventHandler (ErrorHandler);
503 tds.TdsInfoMessage += new TdsInternalInfoMessageEventHandler (MessageHandler);
505 if (!tds.IsConnected) {
507 if (Credentials != null) {
508 if (parms.User != String.Empty)
509 throw new ArgumentException("UserID already specified");
510 if (parms.PasswordSet)
511 throw new ArgumentException("Password already specified");
512 if (parms.DomainLogin != false)
513 throw new ArgumentException("Cannot use credentials with DomainLogin");
514 parms.User = Credentials.UserId;
515 parms.Password = Credentials.Password;
520 pool.ReleaseConnection (tds);
525 disposed = false; // reset this, so using () would call Close ().
526 ChangeState (ConnectionState.Open);
529 private bool ParseDataSource (string theDataSource, out int thePort, out string theServerName)
531 theServerName = string.Empty;
532 string theInstanceName = string.Empty;
534 if (theDataSource == null)
535 throw new ArgumentException("Format of initialization string does not conform to specifications");
537 thePort = DEFAULT_PORT; // default TCP port for SQL Server
541 if ((idx = theDataSource.IndexOf (',')) > -1) {
542 theServerName = theDataSource.Substring (0, idx);
543 string p = theDataSource.Substring (idx + 1);
544 thePort = Int32.Parse (p);
545 } else if ((idx = theDataSource.IndexOf ('\\')) > -1) {
546 theServerName = theDataSource.Substring (0, idx);
547 theInstanceName = theDataSource.Substring (idx + 1);
549 // do port discovery via UDP port 1434
550 port = DiscoverTcpPortViaSqlMonitor (theServerName, theInstanceName);
554 theServerName = theDataSource;
556 if (theServerName.Length == 0 || theServerName == "(local)" || theServerName == ".")
557 theServerName = "localhost";
559 if ((idx = theServerName.IndexOf ("tcp:")) > -1)
560 theServerName = theServerName.Substring (idx + 4);
565 private bool ConvertIntegratedSecurity (string value)
567 if (value.ToUpper() == "SSPI")
570 return ConvertToBoolean ("integrated security", value, false);
573 private bool ConvertToBoolean (string key, string value, bool defaultValue)
575 if (value.Length == 0)
578 string upperValue = value.ToUpper ();
580 if (upperValue == "TRUE" || upperValue == "YES")
582 else if (upperValue == "FALSE" || upperValue == "NO")
585 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
586 "Invalid value \"{0}\" for key '{1}'.", value, key));
589 private int ConvertToInt32 (string key, string value, int defaultValue)
591 if (value.Length == 0)
595 return int.Parse (value);
596 } catch (Exception ex) {
597 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
598 "Invalid value \"{0}\" for key '{1}'.", value, key), ex);
602 private int DiscoverTcpPortViaSqlMonitor (string ServerName, string InstanceName)
604 SqlMonitorSocket msock;
605 msock = new SqlMonitorSocket (ServerName, InstanceName);
606 int SqlServerPort = msock.DiscoverTcpPort (ConnectionTimeout);
608 return SqlServerPort;
611 void SetConnectionString (string connectionString)
613 SetDefaultConnectionParameters ();
615 if ((connectionString == null) || (connectionString.Trim().Length == 0)) {
616 this.connectionString = connectionString;
620 connectionString += ";";
622 bool inQuote = false;
623 bool inDQuote = false;
626 string name = String.Empty;
627 string value = String.Empty;
628 StringBuilder sb = new StringBuilder ();
630 for (int i = 0; i < connectionString.Length; i += 1) {
631 char c = connectionString [i];
633 if (i == connectionString.Length - 1)
636 peek = connectionString [i + 1];
642 else if (peek.Equals (c)) {
652 else if (peek.Equals (c)) {
657 inDQuote = !inDQuote;
660 if (inDQuote || inQuote)
663 if (name != String.Empty && name != null) {
664 value = sb.ToString ();
665 SetProperties (name.ToLower ().Trim() , value);
667 else if (sb.Length != 0)
668 throw new ArgumentException ("Format of initialization string does not conform to specifications");
671 value = String.Empty;
672 sb = new StringBuilder ();
676 if (inDQuote || inQuote || !inName)
678 else if (peek.Equals (c)) {
684 name = sb.ToString ();
685 sb = new StringBuilder ();
690 if (inQuote || inDQuote)
692 else if (sb.Length > 0 && !peek.Equals (';'))
701 if (minPoolSize > maxPoolSize)
702 throw new ArgumentException ("Invalid value for "
703 + "'min pool size' or 'max pool size'; "
704 + "'min pool size' must not be greater "
705 + "than 'max pool size'.");
707 connectionString = connectionString.Substring (0 , connectionString.Length-1);
708 this.connectionString = connectionString;
711 void SetDefaultConnectionParameters ()
714 parms = new TdsConnectionParameters ();
717 dataSource = string.Empty;
718 connectionTimeout = DEFAULT_CONNECTIONTIMEOUT;
719 connectionLifeTime = DEFAULT_CONNECTIONLIFETIME;
720 connectionReset = true;
722 maxPoolSize = DEFAULT_MAXPOOLSIZE;
723 minPoolSize = DEFAULT_MINPOOLSIZE;
724 packetSize = DEFAULT_PACKETSIZE;
729 private void SetProperties (string name , string value)
733 case "application name" :
734 parms.ApplicationName = value;
736 case "attachdbfilename" :
737 case "extended properties" :
738 case "initial file name" :
739 parms.AttachDBFileName = value;
742 case "connect timeout" :
743 case "connection timeout" :
744 int tmpTimeout = ConvertToInt32 ("connect timeout", value,
745 DEFAULT_CONNECTIONTIMEOUT);
747 throw new ArgumentException ("Invalid 'connect timeout'. Must be an integer >=0 ");
749 connectionTimeout = tmpTimeout;
751 case "connection lifetime" :
752 connectionLifeTime = ConvertToInt32 ("connection lifetime", value, DEFAULT_CONNECTIONLIFETIME);
754 case "connection reset" :
755 connectionReset = ConvertToBoolean ("connection reset", value, true);
758 case "current language" :
759 parms.Language = value;
765 case "network address" :
769 if (ConvertToBoolean (name, value, false))
770 throw new NotImplementedException("SSL encryption for"
771 + " data sent between client and server is not"
775 if (!ConvertToBoolean (name, value, true))
776 throw new NotImplementedException("Disabling the automatic"
777 + " enlistment of connections in the thread's current"
778 + " transaction context is not implemented.");
780 case "initial catalog" :
782 parms.Database = value;
784 case "integrated security" :
785 case "trusted_connection" :
786 parms.DomainLogin = ConvertIntegratedSecurity(value);
788 case "max pool size" :
789 int tmpMaxPoolSize = ConvertToInt32 (name, value, DEFAULT_MAXPOOLSIZE);
790 if (tmpMaxPoolSize < MIN_MAXPOOLSIZE)
791 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
792 "Invalid '{0}'. The value must be greater than {1}.",
793 name, MIN_MAXPOOLSIZE));
795 maxPoolSize = tmpMaxPoolSize;
797 case "min pool size" :
798 int tmpMinPoolSize = ConvertToInt32 (name, value, DEFAULT_MINPOOLSIZE);
799 if (tmpMinPoolSize < 0)
800 throw new ArgumentException ("Invalid 'min pool size'. Must be a integer >= 0");
802 minPoolSize = tmpMinPoolSize;
804 case "multipleactiveresultsets":
805 // FIXME: not implemented
806 ConvertToBoolean (name, value, false);
808 case "asynchronous processing" :
810 async = ConvertToBoolean (name, value, false);
814 case "network library" :
815 if (!value.ToUpper ().Equals ("DBMSSOCN"))
816 throw new ArgumentException ("Unsupported network library.");
819 int tmpPacketSize = ConvertToInt32 (name, value, DEFAULT_PACKETSIZE);
820 if (tmpPacketSize < MIN_PACKETSIZE || tmpPacketSize > MAX_PACKETSIZE)
821 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
822 "Invalid 'Packet Size'. The value must be between {0} and {1}.",
823 MIN_PACKETSIZE, MAX_PACKETSIZE));
825 packetSize = tmpPacketSize;
829 parms.Password = new SecureString();
830 foreach (char c in value)
831 parms.Password.AppendChar(c);
832 parms.PasswordSet = true;
834 case "persistsecurityinfo" :
835 case "persist security info" :
836 // FIXME : not implemented
837 // throw new NotImplementedException ();
840 pooling = ConvertToBoolean (name, value, true);
848 case "workstation id" :
849 parms.Hostname = value;
851 case "user instance":
852 userInstance = ConvertToBoolean (name, value, false);
855 throw new ArgumentException("Keyword not supported : '" + name + "'.");
859 static bool IsValidDatabaseName (string database)
861 if ( database == null || database.Trim().Length == 0 || database.Length > 128)
864 if (database[0] == '"' && database[database.Length] == '"')
865 database = database.Substring (1, database.Length - 2);
866 else if (Char.IsDigit (database[0]))
869 if (database[0] == '_')
872 foreach (char c in database.Substring (1, database.Length - 1))
873 if (!Char.IsLetterOrDigit (c) && c != '_' && c != '-')
878 private void OnSqlInfoMessage (SqlInfoMessageEventArgs value)
880 if (InfoMessage != null)
881 InfoMessage (this, value);
885 private sealed class SqlMonitorSocket : UdpClient
887 // UDP port that the SQL Monitor listens
888 private static readonly int SqlMonitorUdpPort = 1434;
889 //private static readonly string SqlServerNotExist = "SQL Server does not exist or access denied";
891 private string server;
892 private string instance;
894 internal SqlMonitorSocket (string ServerName, string InstanceName)
895 : base (ServerName, SqlMonitorUdpPort)
898 instance = InstanceName;
901 internal int DiscoverTcpPort (int timeoutSeconds)
903 int SqlServerTcpPort;
904 Client.Blocking = false;
905 // send command to UDP 1434 (SQL Monitor) to get
906 // the TCP port to connect to the MS SQL server
907 ASCIIEncoding enc = new ASCIIEncoding ();
908 Byte[] rawrq = new Byte [instance.Length + 1];
910 enc.GetBytes (instance, 0, instance.Length, rawrq, 1);
911 Send (rawrq, rawrq.Length);
917 long timeout = timeoutSeconds * 1000000;
918 result = Client.Poll ((int)timeout, SelectMode.SelectRead);
922 if (Client.Available <= 0)
924 IPEndPoint endpoint = new IPEndPoint (Dns.GetHostEntry ("localhost").AddressList [0], 0);
927 rawrs = Receive (ref endpoint);
929 string rs = Encoding.ASCII.GetString (rawrs);
931 string[] rawtokens = rs.Split (';');
932 Hashtable data = new Hashtable ();
933 for (int i = 0; i < rawtokens.Length / 2 && i < 256; i++) {
934 data [rawtokens [i * 2]] = rawtokens [ i * 2 + 1];
937 if (!data.ContainsKey ("tcp")) {
938 string msg = "Mono does not support names pipes or shared memory "
939 + "for connecting to SQL Server. Please enable the TCP/IP "
941 throw new NotImplementedException (msg);
944 SqlServerTcpPort = int.Parse ((string) data ["tcp"]);
947 return SqlServerTcpPort;
956 public ColumnInfo (string name, Type type)
958 this.name = name; this.type = type;
962 static class ReservedWords
964 static readonly string [] reservedWords =
966 "ADD", "EXCEPT", "PERCENT", "ALL", "EXEC", "PLAN", "ALTER",
967 "EXECUTE", "PRECISION", "AND", "EXISTS", "PRIMARY", "ANY",
968 "EXIT", "PRINT", "AS", "FETCH", "PROC", "ASC", "FILE",
969 "PROCEDURE", "AUTHORIZATION", "FILLFACTOR", "PUBLIC",
970 "BACKUP", "FOR", "RAISERROR", "BEGIN", "FOREIGN", "READ",
971 "BETWEEN", "FREETEXT", "READTEXT", "BREAK", "FREETEXTTABLE",
972 "RECONFIGURE", "BROWSE", "FROM", "REFERENCES", "BULK",
973 "FULL", "REPLICATION", "BY", "FUNCTION", "RESTORE",
974 "CASCADE", "GOTO", "RESTRICT", "CASE", "GRANT", "RETURN",
975 "CHECK", "GROUP", "REVOKE", "CHECKPOINT", "HAVING", "RIGHT",
976 "CLOSE", "HOLDLOCK", "ROLLBACK", "CLUSTERED", "IDENTITY",
977 "ROWCOUNT", "COALESCE", "IDENTITY_INSERT", "ROWGUIDCOL",
978 "COLLATE", "IDENTITYCOL", "RULE", "COLUMN", "IF", "SAVE",
979 "COMMIT", "IN", "SCHEMA", "COMPUTE", "INDEX", "SELECT",
980 "CONSTRAINT", "INNER", "SESSION_USER", "CONTAINS", "INSERT",
981 "SET", "CONTAINSTABLE", "INTERSECT", "SETUSER", "CONTINUE",
982 "INTO", "SHUTDOWN", "CONVERT", "IS", "SOME", "CREATE",
983 "JOIN", "STATISTICS", "CROSS", "KEY", "SYSTEM_USER",
984 "CURRENT", "KILL", "TABLE", "CURRENT_DATE", "LEFT",
985 "TEXTSIZE", "CURRENT_TIME", "LIKE", "THEN",
986 "CURRENT_TIMESTAMP", "LINENO", "TO", "CURRENT_USER", "LOAD",
987 "TOP", "CURSOR", "NATIONAL", "TRAN", "DATABASE", "NOCHECK",
988 "TRANSACTION", "DBCC", "NONCLUSTERED", "TRIGGER",
989 "DEALLOCATE", "NOT", "TRUNCATE", "DECLARE", "NULL",
990 "TSEQUAL", "DEFAULT", "NULLIF", "UNION", "DELETE", "OF",
991 "UNIQUE", "DENY", "OFF", "UPDATE", "DESC", "OFFSETS",
992 "UPDATETEXT", "DISK", "ON", "USE", "DISTINCT", "OPEN",
993 "USER", "DISTRIBUTED", "OPENDATASOURCE", "VALUES", "DOUBLE",
994 "OPENQUERY", "VARYING", "DROP", "OPENROWSET", "VIEW",
995 "DUMMY", "OPENXML", "WAITFOR", "DUMP", "OPTION", "WHEN",
996 "ELSE", "OR", "WHERE", "END", "ORDER", "WHILE", "ERRLVL",
997 "OUTER", "WITH", "ESCAPE", "OVER", "WRITETEXT", "ABSOLUTE",
998 "FOUND", "PRESERVE", "ACTION", "FREE", "PRIOR", "ADMIN",
999 "GENERAL", "PRIVILEGES", "AFTER", "GET", "READS",
1000 "AGGREGATE", "GLOBAL", "REAL", "ALIAS", "GO", "RECURSIVE",
1001 "ALLOCATE", "GROUPING", "REF", "ARE", "HOST", "REFERENCING",
1002 "ARRAY", "HOUR", "RELATIVE", "ASSERTION", "IGNORE", "RESULT",
1003 "AT", "IMMEDIATE", "RETURNS", "BEFORE", "INDICATOR", "ROLE",
1004 "BINARY", "INITIALIZE", "ROLLUP", "BIT", "INITIALLY",
1005 "ROUTINE", "BLOB", "INOUT", "ROW", "BOOLEAN", "INPUT",
1006 "ROWS", "BOTH", "INT", "SAVEPOINT", "BREADTH", "INTEGER",
1007 "SCROLL", "CALL", "INTERVAL", "SCOPE", "CASCADED",
1008 "ISOLATION", "SEARCH", "CAST", "ITERATE", "SECOND",
1009 "CATALOG", "LANGUAGE", "SECTION", "CHAR", "LARGE",
1010 "SEQUENCE", "CHARACTER", "LAST", "SESSION", "CLASS",
1011 "LATERAL", "SETS", "CLOB", "LEADING", "SIZE", "COLLATION",
1012 "LESS", "SMALLINT", "COMPLETION", "LEVEL", "SPACE",
1013 "CONNECT", "LIMIT", "SPECIFIC", "CONNECTION", "LOCAL",
1014 "SPECIFICTYPE", "CONSTRAINTS", "LOCALTIME", "SQL",
1015 "CONSTRUCTOR", "LOCALTIMESTAMP", "SQLEXCEPTION",
1016 "CORRESPONDING", "LOCATOR", "SQLSTATE", "CUBE", "MAP",
1017 "SQLWARNING", "CURRENT_PATH", "MATCH", "START",
1018 "CURRENT_ROLE", "MINUTE", "STATE", "CYCLE", "MODIFIES",
1019 "STATEMENT", "DATA", "MODIFY", "STATIC", "DATE", "MODULE",
1020 "STRUCTURE", "DAY", "MONTH", "TEMPORARY", "DEC", "NAMES",
1021 "TERMINATE", "DECIMAL", "NATURAL", "THAN", "DEFERRABLE",
1022 "NCHAR", "TIME", "DEFERRED", "NCLOB", "TIMESTAMP", "DEPTH",
1023 "NEW", "TIMEZONE_HOUR", "DEREF", "NEXT", "TIMEZONE_MINUTE",
1024 "DESCRIBE", "NO", "TRAILING", "DESCRIPTOR", "NONE",
1025 "TRANSLATION", "DESTROY", "NUMERIC", "TREAT", "DESTRUCTOR",
1026 "OBJECT", "TRUE", "DETERMINISTIC", "OLD", "UNDER",
1027 "DICTIONARY", "ONLY", "UNKNOWN", "DIAGNOSTICS", "OPERATION",
1028 "UNNEST", "DISCONNECT", "ORDINALITY", "USAGE", "DOMAIN",
1029 "OUT", "USING", "DYNAMIC", "OUTPUT", "VALUE", "EACH",
1030 "PAD", "VARCHAR", "END-EXEC", "PARAMETER", "VARIABLE",
1031 "EQUALS", "PARAMETERS", "WHENEVER", "EVERY", "PARTIAL",
1032 "WITHOUT", "EXCEPTION", "PATH", "WORK", "EXTERNAL",
1033 "POSTFIX", "WRITE", "FALSE", "PREFIX", "YEAR", "FIRST",
1034 "PREORDER", "ZONE", "FLOAT", "PREPARE", "ADA", "AVG",
1035 "BIT_LENGTH", "CHAR_LENGTH", "CHARACTER_LENGTH", "COUNT",
1036 "EXTRACT", "FORTRAN", "INCLUDE", "INSENSITIVE", "LOWER",
1037 "MAX", "MIN", "OCTET_LENGTH", "OVERLAPS", "PASCAL",
1038 "POSITION", "SQLCA", "SQLCODE", "SQLERROR", "SUBSTRING",
1039 "SUM", "TRANSLATE", "TRIM", "UPPER"
1041 static DataTable instance;
1042 static public DataTable Instance {
1044 if (instance == null) {
1046 var newInstance = new DataTable ("ReservedWords");
1047 newInstance.Columns.Add ("ReservedWord", typeof(string));
1048 foreach (string reservedWord in reservedWords)
1050 row = newInstance.NewRow();
1052 row["ReservedWord"] = reservedWord;
1053 newInstance.Rows.Add(row);
1055 instance = newInstance;
1062 static class MetaDataCollections
1064 static readonly ColumnInfo [] columns = {
1065 new ColumnInfo ("CollectionName", typeof (string)),
1066 new ColumnInfo ("NumberOfRestrictions", typeof (int)),
1067 new ColumnInfo ("NumberOfIdentifierParts", typeof (int))
1070 static readonly object [][] rows = {
1071 new object [] {"MetaDataCollections", 0, 0},
1072 new object [] {"DataSourceInformation", 0, 0},
1073 new object [] {"DataTypes", 0, 0},
1074 new object [] {"Restrictions", 0, 0},
1075 new object [] {"ReservedWords", 0, 0},
1076 new object [] {"Users", 1, 1},
1077 new object [] {"Databases", 1, 1},
1078 new object [] {"Tables", 4, 3},
1079 new object [] {"Columns", 4, 4},
1080 new object [] {"StructuredTypeMembers", 4, 4},
1081 new object [] {"Views", 3, 3},
1082 new object [] {"ViewColumns", 4, 4},
1083 new object [] {"ProcedureParameters", 4, 1},
1084 new object [] {"Procedures", 4, 3},
1085 new object [] {"ForeignKeys", 4, 3},
1086 new object [] {"IndexColumns", 5, 4},
1087 new object [] {"Indexes", 4, 3},
1088 new object [] {"UserDefinedTypes", 2, 1}
1091 static DataTable instance;
1092 static public DataTable Instance {
1094 if (instance == null) {
1095 var newInstance = new DataTable ("MetaDataCollections");
1096 foreach (ColumnInfo c in columns)
1097 newInstance.Columns.Add (c.name, c.type);
1098 foreach (object [] row in rows)
1099 newInstance.LoadDataRow (row, true);
1100 instance = newInstance;
1107 static class DataSourceInformation
1109 static readonly ColumnInfo [] columns = {
1110 new ColumnInfo ("CompositeIdentifierSeparatorPattern", typeof (string)),
1111 new ColumnInfo ("DataSourceProductName", typeof(string)),
1112 new ColumnInfo ("DataSourceProductVersion", typeof(string)),
1113 new ColumnInfo ("DataSourceProductVersionNormalized", typeof(string)),
1114 new ColumnInfo ("GroupByBehavior", typeof(GroupByBehavior)),
1115 new ColumnInfo ("IdentifierPattern", typeof(string)),
1116 new ColumnInfo ("IdentifierCase", typeof(IdentifierCase)),
1117 new ColumnInfo ("OrderByColumnsInSelect", typeof(bool)),
1118 new ColumnInfo ("ParameterMarkerFormat", typeof(string)),
1119 new ColumnInfo ("ParameterMarkerPattern", typeof(string)),
1120 new ColumnInfo ("ParameterNameMaxLength", typeof(int)),
1121 new ColumnInfo ("ParameterNamePattern", typeof(string)),
1122 new ColumnInfo ("QuotedIdentifierPattern", typeof(string)),
1123 new ColumnInfo ("QuotedIdentifierCase", typeof(IdentifierCase)),
1124 new ColumnInfo ("StatementSeparatorPattern", typeof(string)),
1125 new ColumnInfo ("StringLiteralPattern", typeof(string)),
1126 new ColumnInfo ("SupportedJoinOperators", typeof(SupportedJoinOperators))
1129 static public DataTable GetInstance (SqlConnection conn)
1131 DataTable table = new DataTable ("DataSourceInformation");
1132 foreach (ColumnInfo c in columns)
1133 table.Columns.Add (c.name, c.type);
1134 DataRow row = table.NewRow ();
1136 row [1] = "Microsoft SQL Server";
1137 row [2] = conn.ServerVersion;;
1138 row [3] = conn.ServerVersion;;
1139 row [4] = GroupByBehavior.Unrelated;
1140 row [5] = @"(^\[\p{Lo}\p{Lu}\p{Ll}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Nd}@$#_]*$)|(^\[[^\]\0]|\]\]+\]$)|(^\""[^\""\0]|\""\""+\""$)";
1141 row [6] = IdentifierCase.Insensitive; // FIXME: obtain this from SQL Server
1144 row [9] = @"@[\p{Lo}\p{Lu}\p{Ll}\p{Lm}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Lm}\p{Nd}\uff3f_@#\$]*(?=\s+|$)";
1146 row [11] = @"^[\p{Lo}\p{Lu}\p{Ll}\p{Lm}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Lm}\p{Nd}\uff3f_@#\$]*(?=\s+|$)";
1147 row [12] = @"(([^\[]|\]\])*)";
1148 row [13] = IdentifierCase.Insensitive; // FIXME: obtain this from SQL Server
1150 row [15] = "'(([^']|'')*)'";
1151 row [16] = (SupportedJoinOperators.FullOuter | SupportedJoinOperators.Inner |
1152 SupportedJoinOperators.LeftOuter | SupportedJoinOperators.RightOuter);
1153 table.Rows.Add (row);
1158 static class DataTypes
1160 static readonly ColumnInfo [] columns = {
1161 new ColumnInfo ("TypeName", typeof(string)),
1162 new ColumnInfo ("ProviderDbType", typeof(int)),
1163 new ColumnInfo ("ColumnSize", typeof(long)),
1164 new ColumnInfo ("CreateFormat", typeof(string)),
1165 new ColumnInfo ("CreateParameters", typeof(string)),
1166 new ColumnInfo ("DataType", typeof(string)),
1167 new ColumnInfo ("IsAutoIncrementable", typeof(bool)),
1168 new ColumnInfo ("IsBestMatch", typeof(bool)),
1169 new ColumnInfo ("IsCaseSensitive", typeof(bool)),
1170 new ColumnInfo ("IsFixedLength", typeof(bool)),
1171 new ColumnInfo ("IsFixedPrecisionScale", typeof(bool)),
1172 new ColumnInfo ("IsLong", typeof(bool)),
1173 new ColumnInfo ("IsNullable", typeof(bool)),
1174 new ColumnInfo ("IsSearchable", typeof(bool)),
1175 new ColumnInfo ("IsSearchableWithLike", typeof(bool)),
1176 new ColumnInfo ("IsUnsigned", typeof(bool)),
1177 new ColumnInfo ("MaximumScale", typeof(short)),
1178 new ColumnInfo ("MinimumScale", typeof(short)),
1179 new ColumnInfo ("IsConcurrencyType", typeof(bool)),
1180 new ColumnInfo ("IsLiteralSupported", typeof(bool)),
1181 new ColumnInfo ("LiteralPrefix", typeof(string)),
1182 new ColumnInfo ("LiteralSuffix", typeof(string))
1185 static readonly object [][] rows = {
1186 new object [] {"smallint", 16, 5, "smallint", null, "System.Int16", true, true,
1187 false, true, true, false, true, true, false, false, null,
1188 null, false, null, null, null},
1189 new object [] {"int", 8, 10, "int", null, "System.Int32",
1190 true, true, false, true, true, false, true, true, false,
1191 false, null, null, false, null, null, null},
1192 new object [] {"real", 13, 7, "real", null,
1193 "System.Single", false, true, false, true, false, false,
1194 true, true, false, false, null, null, false, null, null, null},
1195 new object [] {"float", 6, 53, "float({0})",
1196 "number of bits used to store the mantissa", "System.Double",
1197 false, true, false, true, false, false, true, true,
1198 false, false, null, null, false, null, null, null},
1199 new object [] {"money", 9, 19, "money", null,
1200 "System.Decimal", false, false, false, true, true,
1201 false, true, true, false, false, null, null, false,
1203 new object [] {"smallmoney", 17, 10, "smallmoney", null,
1204 "System.Decimal", false, false, false, true, true, false,
1205 true, true, false, false, null, null, false, null, null, null},
1206 new object [] {"bit", 2, 1, "bit", null, "System.Boolean",
1207 false, false, false, true, false, false, true, true,
1208 false, null, null, null, false, null, null, null},
1209 new object [] {"tinyint", 20, 3, "tinyint", null,
1210 "System.SByte", true, true, false, true, true, false,
1211 true, true, false, true, null, null, false, null, null, null},
1212 new object [] {"bigint", 0, 19, "bigint", null,
1213 "System.Int64", true, true, false, true, true, false,
1214 true, true, false, false, null, null, false, null, null, null},
1215 new object [] {"timestamp", 19, 8, "timestamp", null,
1216 "System.Byte[]", false, false, false, true, false, false,
1217 false, true, false, null, null, null, true, null, "0x", null},
1218 new object [] {"binary", 1, 8000, "binary({0})", "length",
1219 "System.Byte[]", false, true, false, true, false, false,
1220 true, true, false, null, null, null, false, null, "0x", null},
1221 new object [] {"image", 7, 2147483647, "image", null,
1222 "System.Byte[]", false, true, false, false, false, true,
1223 true, false, false, null, null, null, false, null, "0x", null},
1224 new object [] {"text", 18, 2147483647, "text", null,
1225 "System.String", false, true, false, false, false, true,
1226 true, false, true, null, null, null, false, null, "'", "'"},
1227 new object [] {"ntext", 11, 1073741823, "ntext", null,
1228 "System.String", false, true, false, false, false, true,
1229 true, false, true, null, null, null, false, null, "N'", "'"},
1230 new object [] {"decimal", 5, 38, "decimal({0}, {1})",
1231 "precision,scale", "System.Decimal", true, true, false,
1232 true, false, false, true, true, false, false, 38, 0,
1233 false, null, null, null},
1234 new object [] {"numeric", 5, 38, "numeric({0}, {1})",
1235 "precision,scale", "System.Decimal", true, true, false,
1236 true, false, false, true, true, false, false, 38, 0,
1237 false, null, null, null},
1238 new object [] {"datetime", 4, 23, "datetime", null,
1239 "System.DateTime", false, true, false, true, false, false,
1240 true, true, true, null, null, null, false, null, "{ts '", "'}"},
1241 new object [] {"smalldatetime", 15, 16, "smalldatetime", null,
1242 "System.DateTime", false, true, false, true, false, false,
1243 true, true, true, null, null, null, false, null, "{ts '", "'}"},
1244 new object [] {"sql_variant", 23, null, "sql_variant",
1245 null, "System.Object", false, true, false, false, false,
1246 false, true, true, false, null, null, null, false, false,
1248 new object [] {"xml", 25, 2147483647, "xml", null,
1249 "System.String", false, false, false, false, false, true,
1250 true, false, false, null, null, null, false, false, null, null},
1251 new object [] {"varchar", 22, 2147483647, "varchar({0})",
1252 "max length", "System.String", false, true, false, false,
1253 false, false, true, true, true, null, null, null, false,
1255 new object [] {"char", 3, 2147483647, "char({0})", "length",
1256 "System.String", false, true, false, true, false, false,
1257 true, true, true, null, null, null, false, null, "'", "'"},
1258 new object [] {"nchar", 10, 1073741823, "nchar({0})", "length",
1259 "System.String", false, true, false, true, false, false,
1260 true, true, true, null, null, null, false, null, "N'", "'"},
1261 new object [] {"nvarchar", 12, 1073741823, "nvarchar({0})", "max length",
1262 "System.String", false, true, false, false, false, false, true, true,
1263 true, null, null, null, false, null, "N'", "'"},
1264 new object [] {"varbinary", 21, 1073741823, "varbinary({0})",
1265 "max length", "System.Byte[]", false, true, false, false,
1266 false, false, true, true, false, null, null, null, false,
1268 new object [] {"uniqueidentifier", 14, 16, "uniqueidentifier", null,
1269 "System.Guid", false, true, false, true, false, false, true,
1270 true, false, null, null, null, false, null, "'", "'"},
1271 new object [] {"date", 31, 3L, "date", DBNull.Value,
1272 "System.DateTime", false, false, false, true, true, false,
1273 true, true, true, DBNull.Value, DBNull.Value, DBNull.Value,
1274 false, DBNull.Value, "{ts '", "'}"},
1275 new object [] {"time", 32, 5L, "time({0})", "scale",
1276 "System.TimeSpan", false, false, false, false, false, false,
1277 true, true, true, DBNull.Value, (short) 7, (short) 0,
1278 false, DBNull.Value, "{ts '", "'}"},
1279 new object [] {"datetime2", 33, 8L, "datetime2({0})", "scale",
1280 "System.DateTime", false, true, false, false, false, false,
1281 true, true, true, DBNull.Value, (short) 7, (short) 0,
1282 false, DBNull.Value, "{ts '", "'}"},
1283 new object [] {"datetimeoffset", 34, 10L, "datetimeoffset({0})",
1284 "scale", "System.DateTimeOffset", false, true, false, false,
1285 false, false, true, true, true, DBNull.Value, (short) 7, (short) 0,
1286 false, DBNull.Value, "{ts '", "'}"}
1289 static DataTable instance;
1290 static public DataTable Instance {
1292 if (instance == null) {
1293 instance = new DataTable ("DataTypes");
1294 foreach (ColumnInfo c in columns)
1295 instance.Columns.Add (c.name, c.type);
1296 foreach (object [] row in rows)
1297 instance.LoadDataRow (row, true);
1304 static class Restrictions
1306 static readonly ColumnInfo [] columns = {
1307 new ColumnInfo ("CollectionName", typeof (string)),
1308 new ColumnInfo ("RestrictionName", typeof(string)),
1309 new ColumnInfo ("ParameterName", typeof(string)),
1310 new ColumnInfo ("RestrictionDefault", typeof(string)),
1311 new ColumnInfo ("RestrictionNumber", typeof(int))
1314 static readonly object [][] rows = {
1315 new object [] {"Users", "User_Name", "@Name", "name", 1},
1316 new object [] {"Databases", "Name", "@Name", "Name", 1},
1318 new object [] {"Tables", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1319 new object [] {"Tables", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1320 new object [] {"Tables", "Table", "@Name", "TABLE_NAME", 3},
1321 new object [] {"Tables", "TableType", "@TableType", "TABLE_TYPE", 4},
1323 new object [] {"Columns", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1324 new object [] {"Columns", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1325 new object [] {"Columns", "Table", "@Table", "TABLE_NAME", 3},
1326 new object [] {"Columns", "Column", "@Column", "COLUMN_NAME", 4},
1328 new object [] {"StructuredTypeMembers", "Catalog", "@Catalog", "TYPE_CATALOG", 1},
1329 new object [] {"StructuredTypeMembers", "Owner", "@Owner", "TYPE_SCHEMA", 2},
1330 new object [] {"StructuredTypeMembers", "Type", "@Type", "TYPE_NAME", 3},
1331 new object [] {"StructuredTypeMembers", "Member", "@Member", "MEMBER_NAME", 4},
1333 new object [] {"Views", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1334 new object [] {"Views", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1335 new object [] {"Views", "Table", "@Table", "TABLE_NAME", 3},
1337 new object [] {"ViewColumns", "Catalog", "@Catalog", "VIEW_CATALOG", 1},
1338 new object [] {"ViewColumns", "Owner", "@Owner", "VIEW_SCHEMA", 2},
1339 new object [] {"ViewColumns", "Table", "@Table", "VIEW_NAME", 3},
1340 new object [] {"ViewColumns", "Column", "@Column", "COLUMN_NAME", 4},
1342 new object [] {"ProcedureParameters", "Catalog", "@Catalog", "SPECIFIC_CATALOG", 1},
1343 new object [] {"ProcedureParameters", "Owner", "@Owner", "SPECIFIC_SCHEMA", 2},
1344 new object [] {"ProcedureParameters", "Name", "@Name", "SPECIFIC_NAME", 3},
1345 new object [] {"ProcedureParameters", "Parameter", "@Parameter", "PARAMETER_NAME", 4},
1347 new object [] {"Procedures", "Catalog", "@Catalog", "SPECIFIC_CATALOG", 1},
1348 new object [] {"Procedures", "Owner", "@Owner", "SPECIFIC_SCHEMA", 2},
1349 new object [] {"Procedures", "Name", "@Name", "SPECIFIC_NAME", 3},
1350 new object [] {"Procedures", "Type", "@Type", "ROUTINE_TYPE", 4},
1352 new object [] {"IndexColumns", "Catalog", "@Catalog", "db_name()", 1},
1353 new object [] {"IndexColumns", "Owner", "@Owner", "user_name()", 2},
1354 new object [] {"IndexColumns", "Table", "@Table", "o.name", 3},
1355 new object [] {"IndexColumns", "ConstraintName", "@ConstraintName", "x.name", 4},
1356 new object [] {"IndexColumns", "Column", "@Column", "c.name", 5},
1358 new object [] {"Indexes", "Catalog", "@Catalog", "db_name()", 1},
1359 new object [] {"Indexes", "Owner", "@Owner", "user_name()", 2},
1360 new object [] {"Indexes", "Table", "@Table", "o.name", 3},
1361 new object [] {"Indexes", "Name", "@Name", "x.name", 4},
1363 new object [] {"UserDefinedTypes", "assembly_name", "@AssemblyName", "assemblies.name", 1},
1364 new object [] {"UserDefinedTypes", "udt_name", "@UDTName", "types.assembly_class", 2},
1366 new object [] {"ForeignKeys", "Catalog", "@Catalog", "CONSTRAINT_CATALOG", 1},
1367 new object [] {"ForeignKeys", "Owner", "@Owner", "CONSTRAINT_SCHEMA", 2},
1368 new object [] {"ForeignKeys", "Table", "@Table", "TABLE_NAME", 3},
1369 new object [] {"ForeignKeys", "Name", "@Name", "CONSTRAINT_NAME", 4}
1372 static DataTable instance;
1373 static public DataTable Instance {
1375 if (instance == null) {
1376 instance = new DataTable ("Restrictions");
1377 foreach (ColumnInfo c in columns)
1378 instance.Columns.Add (c.name, c.type);
1379 foreach (object [] row in rows)
1380 instance.LoadDataRow (row, true);
1387 public override DataTable GetSchema ()
1389 if (state == ConnectionState.Closed)
1390 throw ExceptionHelper.ConnectionClosed ();
1392 return MetaDataCollections.Instance;
1395 public override DataTable GetSchema (String collectionName)
1397 return GetSchema (collectionName, null);
1400 public override DataTable GetSchema (String collectionName, string [] restrictionValues)
1402 // LAMESPEC: In MS.NET, if collectionName is null, it throws ArgumentException.
1404 if (state == ConnectionState.Closed)
1405 throw ExceptionHelper.ConnectionClosed ();
1407 String cName = null;
1408 DataTable schemaTable = MetaDataCollections.Instance;
1409 int length = restrictionValues == null ? 0 : restrictionValues.Length;
1411 foreach (DataRow row in schemaTable.Rows) {
1412 if (String.Compare ((string) row["CollectionName"], collectionName, true) == 0) {
1413 if (length > (int) row["NumberOfRestrictions"]) {
1414 throw new ArgumentException ("More restrictions were provided " +
1415 "than the requested schema ('" +
1416 row["CollectionName"].ToString () + "') supports");
1418 cName = row["CollectionName"].ToString();
1423 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
1424 "The requested collection ({0}) is not defined.",
1427 SqlCommand command = null;
1428 DataTable dataTable = new DataTable ();
1429 SqlDataAdapter dataAdapter = new SqlDataAdapter ();
1434 command = new SqlCommand ("select name as database_name, dbid, crdate as create_date " +
1435 "from master.sys.sysdatabases where (name = @Name or (@Name " +
1437 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1440 command = new SqlCommand ("select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, " +
1441 "TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_TYPE, " +
1442 "IS_DEFERRABLE, INITIALLY_DEFERRED from " +
1443 "INFORMATION_SCHEMA.TABLE_CONSTRAINTS where (CONSTRAINT_CATALOG" +
1444 " = @Catalog or (@Catalog is null)) and (CONSTRAINT_SCHEMA = " +
1445 "@Owner or (@Owner is null)) and (TABLE_NAME = @Table or (" +
1446 "@Table is null)) and (CONSTRAINT_NAME = @Name or (@Name is null))" +
1447 " and CONSTRAINT_TYPE = 'FOREIGN KEY' order by CONSTRAINT_CATALOG," +
1448 " CONSTRAINT_SCHEMA, CONSTRAINT_NAME", this);
1449 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1450 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1451 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1452 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1455 command = new SqlCommand ("select distinct db_name() as constraint_catalog, " +
1456 "constraint_schema = user_name (o.uid), " +
1457 "constraint_name = x.name, table_catalog = db_name (), " +
1458 "table_schema = user_name (o.uid), table_name = o.name, " +
1459 "index_name = x.name from sysobjects o, sysindexes x, " +
1460 "sysindexkeys xk where o.type in ('U') and x.id = o.id and " +
1461 "o.id = xk.id and x.indid = xk.indid and xk.keyno = x.keycnt " +
1462 "and (db_name() = @Catalog or (@Catalog is null)) and " +
1463 "(user_name() = @Owner or (@Owner is null)) and (o.name = " +
1464 "@Table or (@Table is null)) and (x.name = @Name or (@Name is null))" +
1465 "order by table_name, index_name", this);
1466 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1467 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1468 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1469 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1471 case "IndexColumns":
1472 command = new SqlCommand ("select distinct db_name() as constraint_catalog, " +
1473 "constraint_schema = user_name (o.uid), constraint_name = x.name, " +
1474 "table_catalog = db_name (), table_schema = user_name (o.uid), " +
1475 "table_name = o.name, column_name = c.name, " +
1476 "ordinal_position = convert (int, xk.keyno), keyType = c.xtype, " +
1477 "index_name = x.name from sysobjects o, sysindexes x, syscolumns c, " +
1478 "sysindexkeys xk where o.type in ('U') and x.id = o.id and o.id = c.id " +
1479 "and o.id = xk.id and x.indid = xk.indid and c.colid = xk.colid " +
1480 "and xk.keyno <= x.keycnt and permissions (o.id, c.name) <> 0 " +
1481 "and (db_name() = @Catalog or (@Catalog is null)) and (user_name() " +
1482 "= @Owner or (@Owner is null)) and (o.name = @Table or (@Table is" +
1483 " null)) and (x.name = @ConstraintName or (@ConstraintName is null)) " +
1484 "and (c.name = @Column or (@Column is null)) order by table_name, " +
1485 "index_name", this);
1486 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 8);
1487 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1488 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 13);
1489 command.Parameters.Add ("@ConstraintName", SqlDbType.NVarChar, 4000);
1490 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1493 command = new SqlCommand ("select SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, " +
1494 "ROUTINE_CATALOG, ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE, " +
1495 "CREATED, LAST_ALTERED from INFORMATION_SCHEMA.ROUTINES where " +
1496 "(SPECIFIC_CATALOG = @Catalog or (@Catalog is null)) and " +
1497 "(SPECIFIC_SCHEMA = @Owner or (@Owner is null)) and (SPECIFIC_NAME" +
1498 " = @Name or (@Name is null)) and (ROUTINE_TYPE = @Type or (@Type " +
1499 "is null)) order by SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME", this);
1500 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1501 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1502 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1503 command.Parameters.Add ("@Type", SqlDbType.NVarChar, 4000);
1505 case "ProcedureParameters":
1506 command = new SqlCommand ("select SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, " +
1507 "ORDINAL_POSITION, PARAMETER_MODE, IS_RESULT, AS_LOCATOR, " +
1508 "PARAMETER_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, " +
1509 "CHARACTER_OCTET_LENGTH, COLLATION_CATALOG, COLLATION_SCHEMA, " +
1510 "COLLATION_NAME, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, " +
1511 "CHARACTER_SET_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, " +
1512 "NUMERIC_SCALE, DATETIME_PRECISION, INTERVAL_TYPE, " +
1513 "INTERVAL_PRECISION from INFORMATION_SCHEMA.PARAMETERS where " +
1514 "(SPECIFIC_CATALOG = @Catalog or (@Catalog is null)) and " +
1515 "(SPECIFIC_SCHEMA = @Owner or (@Owner is null)) and (SPECIFIC_NAME = " +
1516 "@Name or (@Name is null)) and (PARAMETER_NAME = @Parameter or (" +
1517 "@Parameter is null)) order by SPECIFIC_CATALOG, SPECIFIC_SCHEMA," +
1518 " SPECIFIC_NAME, PARAMETER_NAME", this);
1519 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1520 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1521 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1522 command.Parameters.Add ("@Parameter", SqlDbType.NVarChar, 4000);
1525 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE " +
1526 "from INFORMATION_SCHEMA.TABLES where" +
1527 " (TABLE_CATALOG = @catalog or (@catalog is null)) and " +
1528 "(TABLE_SCHEMA = @owner or (@owner is null))and " +
1529 "(TABLE_NAME = @name or (@name is null)) and " +
1530 "(TABLE_TYPE = @table_type or (@table_type is null))", this);
1531 command.Parameters.Add ("@catalog", SqlDbType.NVarChar, 8);
1532 command.Parameters.Add ("@owner", SqlDbType.NVarChar, 3);
1533 command.Parameters.Add ("@name", SqlDbType.NVarChar, 11);
1534 command.Parameters.Add ("@table_type", SqlDbType.NVarChar, 10);
1537 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, " +
1538 "ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, " +
1539 "CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH, " +
1540 "NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE, " +
1541 "DATETIME_PRECISION, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, " +
1542 "CHARACTER_SET_NAME, COLLATION_CATALOG from INFORMATION_SCHEMA.COLUMNS" +
1543 " where (TABLE_CATALOG = @Catalog or (@Catalog is null)) and (" +
1544 "TABLE_SCHEMA = @Owner or (@Owner is null)) and (TABLE_NAME = @table" +
1545 " or (@Table is null)) and (COLUMN_NAME = @column or (@Column is null" +
1546 ")) order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME", this);
1547 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1548 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1549 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1550 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1553 command = new SqlCommand ("select uid, name as user_name, createdate, updatedate from sysusers" +
1554 " where (name = @Name or (@Name is null))", this);
1555 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1557 case "StructuredTypeMembers":
1558 // Only available on SQL Server 2008
1559 // Running it again SQL 2005 results in the following exception:
1560 // Unable to build the 'StructuredTypeMembers' collection because
1561 // execution of the SQL query failed. See the inner exception for details.
1562 // ---> System.Data.SqlClient.SqlException: Invalid object name 'sys.table_types'.
1564 // I don't have access to SQL Server 2008 right now,
1565 // and can't find any online documentation on the 'sys.table_types'
1567 throw new NotImplementedException ();
1569 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, CHECK_OPTION, " +
1570 "IS_UPDATABLE from INFORMATION_SCHEMA.VIEWS where (TABLE_CATALOG" +
1571 " = @Catalog or (@Catalog is null)) TABLE_SCHEMA = @Owner or " +
1572 "(@Owner is null)) and (TABLE_NAME = @table or (@Table is null))" +
1573 " order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME", this);
1574 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1575 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1576 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1579 command = new SqlCommand ("select VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME, TABLE_CATALOG, " +
1580 "TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME from " +
1581 "INFORMATION_SCHEMA.VIEW_COLUMN_USAGE where (VIEW_CATALOG = " +
1582 "@Catalog (@Catalog is null)) and (VIEW_SCHEMA = @Owner (@Owner" +
1583 " is null)) and (VIEW_NAME = @Table or (@Table is null)) and " +
1584 "(COLUMN_NAME = @Column or (@Column is null)) order by " +
1585 "VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME", this);
1586 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1587 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1588 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1589 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1591 case "UserDefinedTypes":
1592 command = new SqlCommand ("select assemblies.name as assembly_name, types.assembly_class " +
1593 "as udt_name, ASSEMBLYPROPERTY(assemblies.name, 'VersionMajor') " +
1594 "as version_major, ASSEMBLYPROPERTY(assemblies.name, 'VersionMinor') " +
1595 "as version_minor, ASSEMBLYPROPERTY(assemblies.name, 'VersionBuild') " +
1596 "as version_build, ASSEMBLYPROPERTY(assemblies.name, 'VersionRevision') " +
1597 "as version_revision, ASSEMBLYPROPERTY(assemblies.name, 'CultureInfo') " +
1598 "as culture_info, ASSEMBLYPROPERTY(assemblies.name, 'PublicKey') " +
1599 "as public_key, is_fixed_length, max_length, Create_Date, " +
1600 "Permission_set_desc from sys.assemblies as assemblies join " +
1601 "sys.assembly_types as types on assemblies.assembly_id = types.assembly_id" +
1602 " where (assportemblies.name = @AssemblyName or (@AssemblyName is null)) and " +
1603 "(types.assembly_class = @UDTName or (@UDTName is null))",
1605 command.Parameters.Add ("@AssemblyName", SqlDbType.NVarChar, 4000);
1606 command.Parameters.Add ("@UDTName", SqlDbType.NVarChar, 4000);
1608 case "MetaDataCollections":
1609 return MetaDataCollections.Instance;
1610 case "DataSourceInformation":
1611 return DataSourceInformation.GetInstance (this);
1613 return DataTypes.Instance;
1614 case "ReservedWords":
1615 return ReservedWords.Instance;
1616 case "Restrictions":
1617 return Restrictions.Instance;
1619 for (int i = 0; i < length; i++) {
1620 command.Parameters[i].Value = restrictionValues[i];
1622 dataAdapter.SelectCommand = command;
1623 dataAdapter.Fill (dataTable);
1627 public static void ChangePassword (string connectionString, string newPassword)
1629 if (String.IsNullOrEmpty (connectionString))
1630 throw new ArgumentNullException ("The 'connectionString' cannot be null or empty.");
1631 if (String.IsNullOrEmpty (newPassword))
1632 throw new ArgumentNullException ("The 'newPassword' cannot be null or empty.");
1633 if (newPassword.Length > 128)
1634 throw new ArgumentException ("The length of 'newPassword' cannot exceed 128 characters.");
1635 using (SqlConnection conn = new SqlConnection (connectionString)) {
1637 conn.tds.Execute (String.Format ("sp_password '{0}', '{1}', '{2}'",
1638 conn.parms.Password, newPassword, conn.parms.User));
1642 public static void ClearAllPools ()
1645 IDictionary pools = SqlConnection.sqlConnectionPools.GetConnectionPool ();
1646 foreach (TdsConnectionPool pool in pools.Values) {
1648 pool.ResetConnectionPool ();
1653 public static void ClearPool (SqlConnection connection)
1655 if (connection == null)
1656 throw new ArgumentNullException ("connection");
1659 if (connection.pooling) {
1660 TdsConnectionPool pool = sqlConnectionPools.GetConnectionPool (connection.ConnectionString);
1662 pool.ResetConnectionPool ();
1667 #endregion // Methods
1669 #region Fields Net 2
1674 #endregion // Fields Net 2
1676 #region Properties Net 2
1678 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1679 internal bool AsyncProcessing {
1680 get { return async; }
1683 #endregion // Properties Net 2