2 // System.Data.SqlClient.SqlConnection.cs
5 // Rodrigo Moya (rodrigo@ximian.com)
6 // Daniel Morgan (danmorg@sc.rr.com)
7 // Tim Coleman (tim@timcoleman.com)
8 // Phillip Jerkins (Phillip.Jerkins@morgankeegan.com)
9 // Diego Caravana (diego@toth.it)
11 // Copyright (C) Ximian, Inc 2002
12 // Copyright (C) Daniel Morgan 2002, 2003
13 // Copyright (C) Tim Coleman, 2002, 2003
14 // Copyright (C) Phillip Jerkins, 2003
18 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
20 // Permission is hereby granted, free of charge, to any person obtaining
21 // a copy of this software and associated documentation files (the
22 // "Software"), to deal in the Software without restriction, including
23 // without limitation the rights to use, copy, modify, merge, publish,
24 // distribute, sublicense, and/or sell copies of the Software, and to
25 // permit persons to whom the Software is furnished to do so, subject to
26 // the following conditions:
28 // The above copyright notice and this permission notice shall be
29 // included in all copies or substantial portions of the Software.
31 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41 using Mono.Data.Tds.Protocol;
43 using System.Collections;
44 using System.Collections.Specialized;
45 using System.ComponentModel;
47 using System.Data.Common;
48 using System.EnterpriseServices;
49 using System.Globalization;
51 using System.Net.Sockets;
55 using System.Collections.Generic;
58 namespace System.Data.SqlClient
60 [DefaultEvent ("InfoMessage")]
62 public sealed class SqlConnection : DbConnection, IDbConnection, ICloneable
64 public sealed class SqlConnection : Component, IDbConnection, ICloneable
71 // The set of SQL connection pools
72 static TdsConnectionPoolManager sqlConnectionPools = new TdsConnectionPoolManager (TdsVersion.tds70);
74 const int DEFAULT_PACKETSIZE = 8000;
76 const int DEFAULT_PACKETSIZE = 8192;
78 const int DEFAULT_CONNECTIONTIMEOUT = 15;
79 const int DEFAULT_MAXPOOLSIZE = 100;
80 const int DEFAULT_MINPOOLSIZE = 0;
81 const int DEFAULT_PORT = 1433;
83 // The current connection pool
84 TdsConnectionPool pool;
86 // The connection string that identifies this connection
87 string connectionString;
89 // The transaction object for the current transaction
90 SqlTransaction transaction;
92 // Connection parameters
94 TdsConnectionParameters parms;
98 int connectionTimeout;
103 bool fireInfoMessageEventOnUserErrors;
104 bool statisticsEnabled;
108 ConnectionState state = ConnectionState.Closed;
110 SqlDataReader dataReader;
120 public SqlConnection () : this (null)
124 public SqlConnection (string connectionString)
126 ConnectionString = connectionString;
129 #endregion // Constructors
133 #if NET_1_0 || ONLY_1_1
134 [DataSysDescription ("Information used to connect to a DataSource, such as 'Data Source=x;Initial Catalog=x;Integrated Security=SSPI'.")]
137 [EditorAttribute ("Microsoft.VSDesigner.Data.SQL.Design.SqlConnectionStringEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
138 [RecommendedAsConfigurable (true)]
139 [RefreshProperties (RefreshProperties.All)]
144 string ConnectionString {
146 if (connectionString == null)
148 return connectionString;
150 [MonoTODO("persist security info, encrypt, enlist keyword not implemented")]
152 if (state == ConnectionState.Open)
153 throw new InvalidOperationException ("Not Allowed to change ConnectionString property while Connection state is OPEN");
154 SetConnectionString (value);
159 [DataSysDescription ("Current connection timeout value, 'Connect Timeout=X' in the ConnectionString.")]
161 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
166 int ConnectionTimeout {
167 get { return connectionTimeout; }
171 [DataSysDescription ("Current SQL Server database, 'Initial Catalog=X' in the connection string.")]
173 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
180 if (State == ConnectionState.Open)
182 return parms.Database ;
186 internal SqlDataReader DataReader {
187 get { return dataReader; }
188 set { dataReader = value; }
192 [DataSysDescription ("Current SqlServer that the connection is opened to, 'Data Source=X' in the connection string. ")]
196 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
202 get { return dataSource; }
206 [DataSysDescription ("Network packet size, 'Packet Size=x' in the connection string.")]
208 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
209 public int PacketSize {
211 if (State == ConnectionState.Open)
212 return ((Tds) tds).PacketSize;
219 [DataSysDescription ("Version of the SQL Server accessed by the SqlConnection.")]
221 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
226 string ServerVersion {
228 if (state == ConnectionState.Closed)
229 throw ExceptionHelper.ConnectionClosed ();
231 return tds.ServerVersion;
237 [DataSysDescription ("The ConnectionState indicating whether the connection is open or closed.")]
239 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
244 ConnectionState State {
245 get { return state; }
252 internal SqlTransaction Transaction {
253 get { return transaction; }
254 set { transaction = value; }
258 [DataSysDescription ("Workstation Id, 'Workstation ID=x' in the connection string.")]
260 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
261 public string WorkstationId {
262 get { return parms.Hostname; }
265 internal XmlReader XmlReader {
266 get { return xmlReader; }
267 set { xmlReader = value; }
271 public bool FireInfoMessageEventOnUserErrors {
272 get { return fireInfoMessageEventOnUserErrors; }
273 set { fireInfoMessageEventOnUserErrors = value; }
276 [DefaultValue (false)]
277 public bool StatisticsEnabled {
278 get { return statisticsEnabled; }
279 set { statisticsEnabled = value; }
282 #endregion // Properties
287 [DataSysDescription ("Event triggered when messages arrive from the DataSource.")]
289 public event SqlInfoMessageEventHandler InfoMessage;
292 [DataSysDescription ("Event triggered when the connection changes state.")]
293 public new event StateChangeEventHandler StateChange;
300 private void ErrorHandler (object sender, TdsInternalErrorMessageEventArgs e)
302 throw new SqlException (e.Class, e.LineNumber, e.Message, e.Number, e.Procedure, e.Server, "Mono SqlClient Data Provider", e.State);
305 private void MessageHandler (object sender, TdsInternalInfoMessageEventArgs e)
307 OnSqlInfoMessage (CreateSqlInfoMessageEvent (e.Errors));
310 #endregion // Delegates
314 public new SqlTransaction BeginTransaction ()
316 return BeginTransaction (IsolationLevel.ReadCommitted, String.Empty);
319 public new SqlTransaction BeginTransaction (IsolationLevel iso)
321 return BeginTransaction (iso, String.Empty);
324 public SqlTransaction BeginTransaction (string transactionName)
326 return BeginTransaction (IsolationLevel.ReadCommitted, transactionName);
329 public SqlTransaction BeginTransaction (IsolationLevel iso, string transactionName)
331 if (state == ConnectionState.Closed)
332 throw ExceptionHelper.ConnectionClosed ();
333 if (transaction != null)
334 throw new InvalidOperationException ("SqlConnection does not support parallel transactions.");
336 string isolevel = String.Empty;
338 case IsolationLevel.ReadUncommitted:
339 isolevel = "READ UNCOMMITTED";
341 case IsolationLevel.RepeatableRead:
342 isolevel = "REPEATABLE READ";
344 case IsolationLevel.Serializable:
345 isolevel = "SERIALIZABLE";
347 case IsolationLevel.ReadCommitted:
348 isolevel = "READ COMMITTED";
351 case IsolationLevel.Snapshot:
352 isolevel = "SNAPSHOT";
354 case IsolationLevel.Unspecified:
355 iso = IsolationLevel.ReadCommitted;
356 isolevel = "READ COMMITTED";
358 case IsolationLevel.Chaos:
359 throw new ArgumentOutOfRangeException ("IsolationLevel",
360 string.Format (CultureInfo.CurrentCulture,
361 "The IsolationLevel enumeration " +
362 "value, {0}, is not supported by " +
363 "the .Net Framework SqlClient " +
364 "Data Provider.", (int) iso));
368 throw new ArgumentOutOfRangeException ("IsolationLevel",
369 string.Format (CultureInfo.CurrentCulture,
370 "The IsolationLevel enumeration value, {0}, is invalid.",
373 throw new ArgumentException ("Invalid IsolationLevel parameter: must be ReadCommitted, ReadUncommitted, RepeatableRead, or Serializable.");
377 tds.Execute (String.Format ("SET TRANSACTION ISOLATION LEVEL {0};BEGIN TRANSACTION {1}", isolevel, transactionName));
379 transaction = new SqlTransaction (this, iso);
387 void ChangeDatabase (string database)
389 if (!IsValidDatabaseName (database))
390 throw new ArgumentException (String.Format ("The database name {0} is not valid.", database));
391 if (state != ConnectionState.Open)
392 throw new InvalidOperationException ("The connection is not open.");
393 tds.Execute (String.Format ("use [{0}]", database));
396 private void ChangeState (ConnectionState currentState)
398 if (currentState == state)
401 ConnectionState originalState = state;
402 state = currentState;
403 OnStateChange (CreateStateChangeEvent (originalState, currentState));
412 if (transaction != null && transaction.IsOpen)
413 transaction.Rollback ();
415 if (dataReader != null || xmlReader != null) {
416 if(tds != null) tds.SkipToEnd ();
421 if (tds != null && tds.IsConnected) {
422 if (pooling && tds.Pooling) {
424 if(pool != null) pool.ReleaseConnection (ref tds);
426 if(pool != null) pool.ReleaseConnection (tds);
429 if(tds != null) tds.Disconnect ();
433 tds.TdsErrorMessage -= new TdsInternalErrorMessageEventHandler (ErrorHandler);
434 tds.TdsInfoMessage -= new TdsInternalInfoMessageEventHandler (MessageHandler);
437 ChangeState (ConnectionState.Closed);
440 public new SqlCommand CreateCommand ()
442 SqlCommand command = new SqlCommand ();
443 command.Connection = this;
447 private SqlInfoMessageEventArgs CreateSqlInfoMessageEvent (TdsInternalErrorCollection errors)
449 return new SqlInfoMessageEventArgs (errors);
452 private StateChangeEventArgs CreateStateChangeEvent (ConnectionState originalState, ConnectionState currentState)
454 return new StateChangeEventArgs (originalState, currentState);
457 protected override void Dispose (bool disposing)
460 if (disposing && !disposed) {
461 if (State == ConnectionState.Open)
463 ConnectionString = null;
467 base.Dispose (disposing);
471 [MonoTODO ("Not sure what this means at present.")]
472 public void EnlistDistributedTransaction (ITransaction transaction)
474 throw new NotImplementedException ();
477 object ICloneable.Clone ()
479 return new SqlConnection (ConnectionString);
483 protected override DbTransaction BeginDbTransaction (IsolationLevel isolationLevel)
485 return BeginTransaction (isolationLevel);
488 protected override DbCommand CreateDbCommand ()
490 return CreateCommand ();
493 IDbTransaction IDbConnection.BeginTransaction ()
495 return BeginTransaction ();
498 IDbTransaction IDbConnection.BeginTransaction (IsolationLevel iso)
500 return BeginTransaction (iso);
503 IDbCommand IDbConnection.CreateCommand ()
505 return CreateCommand ();
515 string serverName = string.Empty;
516 if (state == ConnectionState.Open)
517 throw new InvalidOperationException ("The Connection is already Open (State=Open)");
519 if (connectionString == null || connectionString.Trim().Length == 0)
520 throw new InvalidOperationException ("Connection string has not been initialized.");
524 if(!ParseDataSource (dataSource, out port, out serverName))
525 throw new SqlException(20, 0, "SQL Server does not exist or access denied.", 17, "ConnectionOpen (Connect()).", dataSource, parms.ApplicationName, 0);
526 tds = new Tds70 (serverName, port, PacketSize, ConnectionTimeout);
529 if(!ParseDataSource (dataSource, out port, out serverName))
530 throw new SqlException(20, 0, "SQL Server does not exist or access denied.", 17, "ConnectionOpen (Connect()).", dataSource, parms.ApplicationName, 0);
532 TdsConnectionInfo info = new TdsConnectionInfo (serverName, port, packetSize, ConnectionTimeout, minPoolSize, maxPoolSize);
533 pool = sqlConnectionPools.GetConnectionPool (connectionString, info);
534 tds = pool.GetConnection ();
536 } catch (TdsTimeoutException e) {
537 throw SqlException.FromTdsInternalException ((TdsInternalException) e);
538 } catch (TdsInternalException e) {
539 throw SqlException.FromTdsInternalException (e);
542 tds.TdsErrorMessage += new TdsInternalErrorMessageEventHandler (ErrorHandler);
543 tds.TdsInfoMessage += new TdsInternalInfoMessageEventHandler (MessageHandler);
545 if (!tds.IsConnected) {
550 pool.ReleaseConnection (tds);
555 disposed = false; // reset this, so using () would call Close ().
556 ChangeState (ConnectionState.Open);
559 private bool ParseDataSource (string theDataSource, out int thePort, out string theServerName)
561 theServerName = string.Empty;
562 string theInstanceName = string.Empty;
564 if (theDataSource == null)
565 throw new ArgumentException("Format of initialization string does not conform to specifications");
567 thePort = DEFAULT_PORT; // default TCP port for SQL Server
571 if ((idx = theDataSource.IndexOf (",")) > -1) {
572 theServerName = theDataSource.Substring (0, idx);
573 string p = theDataSource.Substring (idx + 1);
574 thePort = Int32.Parse (p);
575 } else if ((idx = theDataSource.IndexOf ("\\")) > -1) {
576 theServerName = theDataSource.Substring (0, idx);
577 theInstanceName = theDataSource.Substring (idx + 1);
579 // do port discovery via UDP port 1434
580 port = DiscoverTcpPortViaSqlMonitor (theServerName, theInstanceName);
584 theServerName = theDataSource;
586 if (theServerName.Length == 0 || theServerName == "(local)" || theServerName == ".")
587 theServerName = "localhost";
589 if ((idx = theServerName.IndexOf ("tcp:")) > -1)
590 theServerName = theServerName.Substring (idx + 4);
595 private bool ConvertIntegratedSecurity (string value)
597 if (value.ToUpper() == "SSPI")
600 return ConvertToBoolean("integrated security", value);
603 private bool ConvertToBoolean (string key, string value)
605 string upperValue = value.ToUpper ();
607 if (upperValue == "TRUE" || upperValue == "YES")
609 else if (upperValue == "FALSE" || upperValue == "NO")
612 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
613 "Invalid value \"{0}\" for key '{1}'.", value, key));
616 private int ConvertToInt32 (string key, string value)
619 return int.Parse (value);
620 } catch (Exception ex) {
621 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
622 "Invalid value \"{0}\" for key '{1}'.", value, key));
626 private int DiscoverTcpPortViaSqlMonitor (string ServerName, string InstanceName)
628 SqlMonitorSocket msock;
629 msock = new SqlMonitorSocket (ServerName, InstanceName);
630 int SqlServerPort = msock.DiscoverTcpPort (ConnectionTimeout);
632 return SqlServerPort;
635 void SetConnectionString (string connectionString)
637 SetDefaultConnectionParameters ();
639 if ((connectionString == null) || (connectionString.Trim().Length == 0)) {
640 this.connectionString = connectionString;
644 connectionString += ";";
646 bool inQuote = false;
647 bool inDQuote = false;
650 string name = String.Empty;
651 string value = String.Empty;
652 StringBuilder sb = new StringBuilder ();
654 for (int i = 0; i < connectionString.Length; i += 1) {
655 char c = connectionString [i];
657 if (i == connectionString.Length - 1)
660 peek = connectionString [i + 1];
666 else if (peek.Equals (c)) {
676 else if (peek.Equals (c)) {
681 inDQuote = !inDQuote;
684 if (inDQuote || inQuote)
687 if (name != String.Empty && name != null) {
688 value = sb.ToString ();
689 SetProperties (name.ToUpper ().Trim() , value);
691 else if (sb.Length != 0)
692 throw new ArgumentException ("Format of initialization string does not conform to specifications");
695 value = String.Empty;
696 sb = new StringBuilder ();
700 if (inDQuote || inQuote || !inName)
702 else if (peek.Equals (c)) {
708 name = sb.ToString ();
709 sb = new StringBuilder ();
714 if (inQuote || inDQuote)
716 else if (sb.Length > 0 && !peek.Equals (';'))
725 connectionString = connectionString.Substring (0 , connectionString.Length-1);
726 this.connectionString = connectionString;
729 void SetDefaultConnectionParameters ()
732 parms = new TdsConnectionParameters ();
735 dataSource = string.Empty;
736 connectionTimeout = DEFAULT_CONNECTIONTIMEOUT;
737 connectionReset = true;
739 maxPoolSize = DEFAULT_MAXPOOLSIZE;
740 minPoolSize = DEFAULT_MINPOOLSIZE;
741 packetSize = DEFAULT_PACKETSIZE;
748 private void SetProperties (string name , string value)
752 case "APPLICATION NAME" :
753 parms.ApplicationName = value;
755 case "ATTACHDBFILENAME" :
756 case "EXTENDED PROPERTIES" :
757 case "INITIAL FILE NAME" :
758 parms.AttachDBFileName = value;
761 case "CONNECT TIMEOUT" :
762 case "CONNECTION TIMEOUT" :
763 int tmpTimeout = ConvertToInt32 ("connection timeout", value);
765 throw new ArgumentException ("Invalid CONNECTION TIMEOUT .. Must be an integer >=0 ");
767 connectionTimeout = tmpTimeout;
769 case "CONNECTION LIFETIME" :
771 case "CONNECTION RESET" :
772 connectionReset = ConvertToBoolean ("connection reset", value);
775 case "CURRENT LANGUAGE" :
776 parms.Language = value;
782 case "NETWORK ADDRESS" :
786 if (ConvertToBoolean("encrypt", value))
787 throw new NotImplementedException("SSL encryption for"
788 + " data sent between client and server is not"
792 if (!ConvertToBoolean("enlist", value))
793 throw new NotImplementedException("Disabling the automatic"
794 + " enlistment of connections in the thread's current"
795 + " transaction context is not implemented.");
797 case "INITIAL CATALOG" :
799 parms.Database = value;
801 case "INTEGRATED SECURITY" :
802 case "TRUSTED_CONNECTION" :
803 parms.DomainLogin = ConvertIntegratedSecurity(value);
805 case "MAX POOL SIZE" :
806 int tmpMaxPoolSize = ConvertToInt32 ("max pool size" , value);
807 if (tmpMaxPoolSize < 0)
808 throw new ArgumentException ("Invalid MAX POOL SIZE. Must be a intger >= 0");
810 maxPoolSize = tmpMaxPoolSize;
812 case "MIN POOL SIZE" :
813 int tmpMinPoolSize = ConvertToInt32 ("min pool size" , value);
814 if (tmpMinPoolSize < 0)
815 throw new ArgumentException ("Invalid MIN POOL SIZE. Must be a intger >= 0");
817 minPoolSize = tmpMinPoolSize;
820 case "MULTIPLEACTIVERESULTSETS":
822 case "ASYNCHRONOUS PROCESSING" :
824 async = ConvertToBoolean (name, value);
829 case "NETWORK LIBRARY" :
830 if (!value.ToUpper ().Equals ("DBMSSOCN"))
831 throw new ArgumentException ("Unsupported network library.");
834 int tmpPacketSize = ConvertToInt32 ("packet size", value);
835 if (tmpPacketSize < 512 || tmpPacketSize > 32767)
836 throw new ArgumentException ("Invalid PACKET SIZE. The integer must be between 512 and 32767");
838 packetSize = tmpPacketSize;
842 parms.Password = value;
844 case "PERSISTSECURITYINFO" :
845 case "PERSIST SECURITY INFO" :
846 // FIXME : not implemented
847 // throw new NotImplementedException ();
850 pooling = ConvertToBoolean("pooling", value);
858 case "WORKSTATION ID" :
859 parms.Hostname = value;
862 case "USER INSTANCE":
863 userInstance = ConvertToBoolean ("user instance", value);
866 throw new ArgumentException("Keyword not supported :"+name);
870 static bool IsValidDatabaseName (string database)
872 if ( database == null || database.Trim().Length == 0 || database.Length > 128)
875 if (database[0] == '"' && database[database.Length] == '"')
876 database = database.Substring (1, database.Length - 2);
877 else if (Char.IsDigit (database[0]))
880 if (database[0] == '_')
883 foreach (char c in database.Substring (1, database.Length - 1))
884 if (!Char.IsLetterOrDigit (c) && c != '_' && c != '-')
889 private void OnSqlInfoMessage (SqlInfoMessageEventArgs value)
891 if (InfoMessage != null)
892 InfoMessage (this, value);
896 private new void OnStateChange (StateChangeEventArgs value)
898 if (StateChange != null)
899 StateChange (this, value);
903 private sealed class SqlMonitorSocket : UdpClient
905 // UDP port that the SQL Monitor listens
906 private static readonly int SqlMonitorUdpPort = 1434;
907 //private static readonly string SqlServerNotExist = "SQL Server does not exist or access denied";
909 private string server;
910 private string instance;
912 internal SqlMonitorSocket (string ServerName, string InstanceName)
913 : base (ServerName, SqlMonitorUdpPort)
916 instance = InstanceName;
919 internal int DiscoverTcpPort (int timeoutSeconds)
921 int SqlServerTcpPort;
922 Client.Blocking = false;
923 // send command to UDP 1434 (SQL Monitor) to get
924 // the TCP port to connect to the MS SQL server
925 ASCIIEncoding enc = new ASCIIEncoding ();
926 Byte[] rawrq = new Byte [instance.Length + 1];
928 enc.GetBytes (instance, 0, instance.Length, rawrq, 1);
929 int bytes = Send (rawrq, rawrq.Length);
935 long timeout = timeoutSeconds * 1000000;
936 result = Client.Poll ((int)timeout, SelectMode.SelectRead);
940 if (Client.Available <= 0)
943 IPEndPoint endpoint = new IPEndPoint (Dns.GetHostEntry ("localhost").AddressList [0], 0);
945 IPEndPoint endpoint = new IPEndPoint (Dns.GetHostByName ("localhost").AddressList [0], 0);
949 rawrs = Receive (ref endpoint);
951 string rs = Encoding.ASCII.GetString (rawrs);
953 string[] rawtokens = rs.Split (';');
954 Hashtable data = new Hashtable ();
955 for (int i = 0; i < rawtokens.Length / 2 && i < 256; i++) {
956 data [rawtokens [i * 2]] = rawtokens [ i * 2 + 1];
959 if (!data.ContainsKey ("tcp")) {
960 string msg = "Mono does not support names pipes or shared memory "
961 + "for connecting to SQL Server. Please enable the TCP/IP "
963 throw new NotImplementedException (msg);
966 SqlServerTcpPort = int.Parse ((string) data ["tcp"]);
969 return SqlServerTcpPort;
979 public ColumnInfo (string name, Type type)
981 this.name = name; this.type = type;
985 static class ReservedWords
987 static readonly string [] reservedWords =
989 "ADD", "EXCEPT", "PERCENT", "ALL", "EXEC", "PLAN", "ALTER",
990 "EXECUTE", "PRECISION", "AND", "EXISTS", "PRIMARY", "ANY",
991 "EXIT", "PRINT", "AS", "FETCH", "PROC", "ASC", "FILE",
992 "PROCEDURE", "AUTHORIZATION", "FILLFACTOR", "PUBLIC",
993 "BACKUP", "FOR", "RAISERROR", "BEGIN", "FOREIGN", "READ",
994 "BETWEEN", "FREETEXT", "READTEXT", "BREAK", "FREETEXTTABLE",
995 "RECONFIGURE", "BROWSE", "FROM", "REFERENCES", "BULK",
996 "FULL", "REPLICATION", "BY", "FUNCTION", "RESTORE",
997 "CASCADE", "GOTO", "RESTRICT", "CASE", "GRANT", "RETURN",
998 "CHECK", "GROUP", "REVOKE", "CHECKPOINT", "HAVING", "RIGHT",
999 "CLOSE", "HOLDLOCK", "ROLLBACK", "CLUSTERED", "IDENTITY",
1000 "ROWCOUNT", "COALESCE", "IDENTITY_INSERT", "ROWGUIDCOL",
1001 "COLLATE", "IDENTITYCOL", "RULE", "COLUMN", "IF", "SAVE",
1002 "COMMIT", "IN", "SCHEMA", "COMPUTE", "INDEX", "SELECT",
1003 "CONSTRAINT", "INNER", "SESSION_USER", "CONTAINS", "INSERT",
1004 "SET", "CONTAINSTABLE", "INTERSECT", "SETUSER", "CONTINUE",
1005 "INTO", "SHUTDOWN", "CONVERT", "IS", "SOME", "CREATE",
1006 "JOIN", "STATISTICS", "CROSS", "KEY", "SYSTEM_USER",
1007 "CURRENT", "KILL", "TABLE", "CURRENT_DATE", "LEFT",
1008 "TEXTSIZE", "CURRENT_TIME", "LIKE", "THEN",
1009 "CURRENT_TIMESTAMP", "LINENO", "TO", "CURRENT_USER", "LOAD",
1010 "TOP", "CURSOR", "NATIONAL", "TRAN", "DATABASE", "NOCHECK",
1011 "TRANSACTION", "DBCC", "NONCLUSTERED", "TRIGGER",
1012 "DEALLOCATE", "NOT", "TRUNCATE", "DECLARE", "NULL",
1013 "TSEQUAL", "DEFAULT", "NULLIF", "UNION", "DELETE", "OF",
1014 "UNIQUE", "DENY", "OFF", "UPDATE", "DESC", "OFFSETS",
1015 "UPDATETEXT", "DISK", "ON", "USE", "DISTINCT", "OPEN",
1016 "USER", "DISTRIBUTED", "OPENDATASOURCE", "VALUES", "DOUBLE",
1017 "OPENQUERY", "VARYING", "DROP", "OPENROWSET", "VIEW",
1018 "DUMMY", "OPENXML", "WAITFOR", "DUMP", "OPTION", "WHEN",
1019 "ELSE", "OR", "WHERE", "END", "ORDER", "WHILE", "ERRLVL",
1020 "OUTER", "WITH", "ESCAPE", "OVER", "WRITETEXT", "ABSOLUTE",
1021 "FOUND", "PRESERVE", "ACTION", "FREE", "PRIOR", "ADMIN",
1022 "GENERAL", "PRIVILEGES", "AFTER", "GET", "READS",
1023 "AGGREGATE", "GLOBAL", "REAL", "ALIAS", "GO", "RECURSIVE",
1024 "ALLOCATE", "GROUPING", "REF", "ARE", "HOST", "REFERENCING",
1025 "ARRAY", "HOUR", "RELATIVE", "ASSERTION", "IGNORE", "RESULT",
1026 "AT", "IMMEDIATE", "RETURNS", "BEFORE", "INDICATOR", "ROLE",
1027 "BINARY", "INITIALIZE", "ROLLUP", "BIT", "INITIALLY",
1028 "ROUTINE", "BLOB", "INOUT", "ROW", "BOOLEAN", "INPUT",
1029 "ROWS", "BOTH", "INT", "SAVEPOINT", "BREADTH", "INTEGER",
1030 "SCROLL", "CALL", "INTERVAL", "SCOPE", "CASCADED",
1031 "ISOLATION", "SEARCH", "CAST", "ITERATE", "SECOND",
1032 "CATALOG", "LANGUAGE", "SECTION", "CHAR", "LARGE",
1033 "SEQUENCE", "CHARACTER", "LAST", "SESSION", "CLASS",
1034 "LATERAL", "SETS", "CLOB", "LEADING", "SIZE", "COLLATION",
1035 "LESS", "SMALLINT", "COMPLETION", "LEVEL", "SPACE",
1036 "CONNECT", "LIMIT", "SPECIFIC", "CONNECTION", "LOCAL",
1037 "SPECIFICTYPE", "CONSTRAINTS", "LOCALTIME", "SQL",
1038 "CONSTRUCTOR", "LOCALTIMESTAMP", "SQLEXCEPTION",
1039 "CORRESPONDING", "LOCATOR", "SQLSTATE", "CUBE", "MAP",
1040 "SQLWARNING", "CURRENT_PATH", "MATCH", "START",
1041 "CURRENT_ROLE", "MINUTE", "STATE", "CYCLE", "MODIFIES",
1042 "STATEMENT", "DATA", "MODIFY", "STATIC", "DATE", "MODULE",
1043 "STRUCTURE", "DAY", "MONTH", "TEMPORARY", "DEC", "NAMES",
1044 "TERMINATE", "DECIMAL", "NATURAL", "THAN", "DEFERRABLE",
1045 "NCHAR", "TIME", "DEFERRED", "NCLOB", "TIMESTAMP", "DEPTH",
1046 "NEW", "TIMEZONE_HOUR", "DEREF", "NEXT", "TIMEZONE_MINUTE",
1047 "DESCRIBE", "NO", "TRAILING", "DESCRIPTOR", "NONE",
1048 "TRANSLATION", "DESTROY", "NUMERIC", "TREAT", "DESTRUCTOR",
1049 "OBJECT", "TRUE", "DETERMINISTIC", "OLD", "UNDER",
1050 "DICTIONARY", "ONLY", "UNKNOWN", "DIAGNOSTICS", "OPERATION",
1051 "UNNEST", "DISCONNECT", "ORDINALITY", "USAGE", "DOMAIN",
1052 "OUT", "USING", "DYNAMIC", "OUTPUT", "VALUE", "EACH",
1053 "PAD", "VARCHAR", "END-EXEC", "PARAMETER", "VARIABLE",
1054 "EQUALS", "PARAMETERS", "WHENEVER", "EVERY", "PARTIAL",
1055 "WITHOUT", "EXCEPTION", "PATH", "WORK", "EXTERNAL",
1056 "POSTFIX", "WRITE", "FALSE", "PREFIX", "YEAR", "FIRST",
1057 "PREORDER", "ZONE", "FLOAT", "PREPARE", "ADA", "AVG",
1058 "BIT_LENGTH", "CHAR_LENGTH", "CHARACTER_LENGTH", "COUNT",
1059 "EXTRACT", "FORTRAN", "INCLUDE", "INSENSITIVE", "LOWER",
1060 "MAX", "MIN", "OCTET_LENGTH", "OVERLAPS", "PASCAL",
1061 "POSITION", "SQLCA", "SQLCODE", "SQLERROR", "SUBSTRING",
1062 "SUM", "TRANSLATE", "TRIM", "UPPER"
1064 static DataTable instance;
1065 static public DataTable Instance {
1067 if (instance == null) {
1069 instance = new DataTable ("ReservedWords");
1070 instance.Columns.Add ("ReservedWord", typeof(string));
1071 foreach (string reservedWord in reservedWords)
1073 row = instance.NewRow();
1075 row["ReservedWord"] = reservedWord;
1076 instance.Rows.Add(row);
1084 static class MetaDataCollections
1086 static readonly ColumnInfo [] columns = {
1087 new ColumnInfo ("CollectionName", typeof (string)),
1088 new ColumnInfo ("NumberOfRestrictions", typeof (int)),
1089 new ColumnInfo ("NumberOfIdentifierParts", typeof (int))
1092 static readonly object [][] rows = {
1093 new object [] {"MetaDataCollections", 0, 0},
1094 new object [] {"DataSourceInformation", 0, 0},
1095 new object [] {"DataTypes", 0, 0},
1096 new object [] {"Restrictions", 0, 0},
1097 new object [] {"ReservedWords", 0, 0},
1098 new object [] {"Users", 1, 1},
1099 new object [] {"Databases", 1, 1},
1100 new object [] {"Tables", 4, 3},
1101 new object [] {"Columns", 4, 4},
1102 new object [] {"StructuredTypeMembers", 4, 4},
1103 new object [] {"Views", 3, 3},
1104 new object [] {"ViewColumns", 4, 4},
1105 new object [] {"ProcedureParameters", 4, 1},
1106 new object [] {"Procedures", 4, 3},
1107 new object [] {"ForeignKeys", 4, 3},
1108 new object [] {"IndexColumns", 5, 4},
1109 new object [] {"Indexes", 4, 3},
1110 new object [] {"UserDefinedTypes", 2, 1}
1113 static DataTable instance;
1114 static public DataTable Instance {
1116 if (instance == null) {
1117 instance = new DataTable ("MetaDataCollections");
1118 foreach (ColumnInfo c in columns)
1119 instance.Columns.Add (c.name, c.type);
1120 foreach (object [] row in rows)
1121 instance.LoadDataRow (row, true);
1128 static class DataSourceInformation
1130 static readonly ColumnInfo [] columns = {
1131 new ColumnInfo ("CompositeIdentifierSeparatorPattern", typeof (string)),
1132 new ColumnInfo ("DataSourceProductName", typeof(string)),
1133 new ColumnInfo ("DataSourceProductVersion", typeof(string)),
1134 new ColumnInfo ("DataSourceProductVersionNormalized", typeof(string)),
1135 new ColumnInfo ("GroupByBehavior", typeof(GroupByBehavior)),
1136 new ColumnInfo ("IdentifierPattern", typeof(string)),
1137 new ColumnInfo ("IdentifierCase", typeof(IdentifierCase)),
1138 new ColumnInfo ("OrderByColumnsInSelect", typeof(bool)),
1139 new ColumnInfo ("ParameterMarkerFormat", typeof(string)),
1140 new ColumnInfo ("ParameterMarkerPattern", typeof(string)),
1141 new ColumnInfo ("ParameterNameMaxLength", typeof(int)),
1142 new ColumnInfo ("ParameterNamePattern", typeof(string)),
1143 new ColumnInfo ("QuotedIdentifierPattern", typeof(string)),
1144 new ColumnInfo ("QuotedIdentifierCase", typeof(IdentifierCase)),
1145 new ColumnInfo ("StatementSeparatorPattern", typeof(string)),
1146 new ColumnInfo ("StringLiteralPattern", typeof(string)),
1147 new ColumnInfo ("SupportedJoinOperators", typeof(SupportedJoinOperators))
1150 static public DataTable GetInstance (SqlConnection conn)
1152 DataTable table = new DataTable ("DataSourceInformation");
1153 foreach (ColumnInfo c in columns)
1154 table.Columns.Add (c.name, c.type);
1155 DataRow row = table.NewRow ();
1157 row [1] = "Microsoft SQL Server";
1158 row [2] = conn.ServerVersion;;
1159 row [3] = conn.ServerVersion;;
1160 row [4] = GroupByBehavior.Unrelated;
1161 row [5] = @"(^\[\p{Lo}\p{Lu}\p{Ll}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Nd}@$#_]*$)|(^\[[^\]\0]|\]\]+\]$)|(^\""[^\""\0]|\""\""+\""$)";
1162 row [6] = IdentifierCase.Insensitive; // FIXME: obtain this from SQL Server
1165 row [9] = @"@[\p{Lo}\p{Lu}\p{Ll}\p{Lm}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Lm}\p{Nd}\uff3f_@#\$]*(?=\s+|$)";
1167 row [11] = @"^[\p{Lo}\p{Lu}\p{Ll}\p{Lm}_@#][\p{Lo}\p{Lu}\p{Ll}\p{Lm}\p{Nd}\uff3f_@#\$]*(?=\s+|$)";
1168 row [12] = @"(([^\[]|\]\])*)";
1169 row [13] = IdentifierCase.Insensitive; // FIXME: obtain this from SQL Server
1171 row [15] = "'(([^']|'')*)'";
1172 row [16] = (SupportedJoinOperators.FullOuter | SupportedJoinOperators.Inner |
1173 SupportedJoinOperators.LeftOuter | SupportedJoinOperators.RightOuter);
1174 table.Rows.Add (row);
1179 static class DataTypes
1181 static readonly ColumnInfo [] columns = {
1182 new ColumnInfo ("TypeName", typeof(string)),
1183 new ColumnInfo ("ProviderDbType", typeof(int)),
1184 new ColumnInfo ("ColumnSize", typeof(long)),
1185 new ColumnInfo ("CreateFormat", typeof(string)),
1186 new ColumnInfo ("CreateParameters", typeof(string)),
1187 new ColumnInfo ("DataType", typeof(string)),
1188 new ColumnInfo ("IsAutoIncrementable", typeof(bool)),
1189 new ColumnInfo ("IsBestMatch", typeof(bool)),
1190 new ColumnInfo ("IsCaseSensitive", typeof(bool)),
1191 new ColumnInfo ("IsFixedLength", typeof(bool)),
1192 new ColumnInfo ("IsFixedPrecisionScale", typeof(bool)),
1193 new ColumnInfo ("IsLong", typeof(bool)),
1194 new ColumnInfo ("IsNullable", typeof(bool)),
1195 new ColumnInfo ("IsSearchable", typeof(bool)),
1196 new ColumnInfo ("IsSearchableWithLike", typeof(bool)),
1197 new ColumnInfo ("IsUnsigned", typeof(bool)),
1198 new ColumnInfo ("MaximumScale", typeof(short)),
1199 new ColumnInfo ("MinimumScale", typeof(short)),
1200 new ColumnInfo ("IsConcurrencyType", typeof(bool)),
1201 new ColumnInfo ("IsLiteralSupported", typeof(bool)),
1202 new ColumnInfo ("LiteralPrefix", typeof(string)),
1203 new ColumnInfo ("LiteralSuffix", typeof(string))
1206 static readonly object [][] rows = {
1207 new object [] {"smallint", 16, 5, "smallint", null, "System.Int16", true, true,
1208 false, true, true, false, true, true, false, false, null,
1209 null, false, null, null, null},
1210 new object [] {"int", 8, 10, "int", null, "System.Int32",
1211 true, true, false, true, true, false, true, true, false,
1212 false, null, null, false, null, null, null},
1213 new object [] {"real", 13, 7, "real", null,
1214 "System.Single", false, true, false, true, false, false,
1215 true, true, false, false, null, null, false, null, null, null},
1216 new object [] {"float", 6, 53, "float({0})",
1217 "number of bits used to store the mantissa", "System.Double",
1218 false, true, false, true, false, false, true, true,
1219 false, false, null, null, false, null, null, null},
1220 new object [] {"money", 9, 19, "money", null,
1221 "System.Decimal", false, false, false, true, true,
1222 false, true, true, false, false, null, null, false,
1224 new object [] {"smallmoney", 17, 10, "smallmoney", null,
1225 "System.Decimal", false, false, false, true, true, false,
1226 true, true, false, false, null, null, false, null, null, null},
1227 new object [] {"bit", 2, 1, "bit", null, "System.Boolean",
1228 false, false, false, true, false, false, true, true,
1229 false, null, null, null, false, null, null, null},
1230 new object [] {"tinyint", 20, 3, "tinyint", null,
1231 "System.SByte", true, true, false, true, true, false,
1232 true, true, false, true, null, null, false, null, null, null},
1233 new object [] {"bigint", 0, 19, "bigint", null,
1234 "System.Int64", true, true, false, true, true, false,
1235 true, true, false, false, null, null, false, null, null, null},
1236 new object [] {"timestamp", 19, 8, "timestamp", null,
1237 "System.Byte[]", false, false, false, true, false, false,
1238 false, true, false, null, null, null, true, null, "0x", null},
1239 new object [] {"binary", 1, 8000, "binary({0})", "length",
1240 "System.Byte[]", false, true, false, true, false, false,
1241 true, true, false, null, null, null, false, null, "0x", null},
1242 new object [] {"image", 7, 2147483647, "image", null,
1243 "System.Byte[]", false, true, false, false, false, true,
1244 true, false, false, null, null, null, false, null, "0x", null},
1245 new object [] {"text", 18, 2147483647, "text", null,
1246 "System.String", false, true, false, false, false, true,
1247 true, false, true, null, null, null, false, null, "'", "'"},
1248 new object [] {"ntext", 11, 1073741823, "ntext", null,
1249 "System.String", false, true, false, false, false, true,
1250 true, false, true, null, null, null, false, null, "N'", "'"},
1251 new object [] {"decimal", 5, 38, "decimal({0}, {1})",
1252 "precision,scale", "System.Decimal", true, true, false,
1253 true, false, false, true, true, false, false, 38, 0,
1254 false, null, null, null},
1255 new object [] {"numeric", 5, 38, "numeric({0}, {1})",
1256 "precision,scale", "System.Decimal", true, true, false,
1257 true, false, false, true, true, false, false, 38, 0,
1258 false, null, null, null},
1259 new object [] {"datetime", 4, 23, "datetime", null,
1260 "System.DateTime", false, true, false, true, false, false,
1261 true, true, true, null, null, null, false, null, "{ts '", "'}"},
1262 new object [] {"smalldatetime", 15, 16, "smalldatetime", null,
1263 "System.DateTime", false, true, false, true, false, false,
1264 true, true, true, null, null, null, false, null, "{ts '", "'}"},
1265 new object [] {"sql_variant", 23, null, "sql_variant",
1266 null, "System.Object", false, true, false, false, false,
1267 false, true, true, false, null, null, null, false, false,
1269 new object [] {"xml", 25, 2147483647, "xml", null,
1270 "System.String", false, false, false, false, false, true,
1271 true, false, false, null, null, null, false, false, null, null},
1272 new object [] {"varchar", 22, 2147483647, "varchar({0})",
1273 "max length", "System.String", false, true, false, false,
1274 false, false, true, true, true, null, null, null, false,
1276 new object [] {"char", 3, 2147483647, "char({0})", "length",
1277 "System.String", false, true, false, true, false, false,
1278 true, true, true, null, null, null, false, null, "'", "'"},
1279 new object [] {"nchar", 10, 1073741823, "nchar({0})", "length",
1280 "System.String", false, true, false, true, false, false,
1281 true, true, true, null, null, null, false, null, "N'", "'"},
1282 new object [] {"nvarchar", 12, 1073741823, "nvarchar({0})", "max length",
1283 "System.String", false, true, false, false, false, false, true, true,
1284 true, null, null, null, false, null, "N'", "'"},
1285 new object [] {"varbinary", 21, 1073741823, "varbinary({0})",
1286 "max length", "System.Byte[]", false, true, false, false,
1287 false, false, true, true, false, null, null, null, false,
1289 new object [] {"uniqueidentifier", 14, 16, "uniqueidentifier", null,
1290 "System.Guid", false, true, false, true, false, false, true,
1291 true, false, null, null, null, false, null, "'", "'"},
1292 new object [] {"date", 31, 3L, "date", DBNull.Value,
1293 "System.DateTime", false, false, false, true, true, false,
1294 true, true, true, DBNull.Value, DBNull.Value, DBNull.Value,
1295 false, DBNull.Value, "{ts '", "'}"},
1296 new object [] {"time", 32, 5L, "time({0})", "scale",
1297 "System.TimeSpan", false, false, false, false, false, false,
1298 true, true, true, DBNull.Value, (short) 7, (short) 0,
1299 false, DBNull.Value, "{ts '", "'}"},
1300 new object [] {"datetime2", 33, 8L, "datetime2({0})", "scale",
1301 "System.DateTime", false, true, false, false, false, false,
1302 true, true, true, DBNull.Value, (short) 7, (short) 0,
1303 false, DBNull.Value, "{ts '", "'}"},
1304 new object [] {"datetimeoffset", 34, 10L, "datetimeoffset({0})",
1305 "scale", "System.DateTimeOffset", false, true, false, false,
1306 false, false, true, true, true, DBNull.Value, (short) 7, (short) 0,
1307 false, DBNull.Value, "{ts '", "'}"}
1310 static DataTable instance;
1311 static public DataTable Instance {
1313 if (instance == null) {
1314 instance = new DataTable ("DataTypes");
1315 foreach (ColumnInfo c in columns)
1316 instance.Columns.Add (c.name, c.type);
1317 foreach (object [] row in rows)
1318 instance.LoadDataRow (row, true);
1325 static class Restrictions
1327 static readonly ColumnInfo [] columns = {
1328 new ColumnInfo ("CollectionName", typeof (string)),
1329 new ColumnInfo ("RestrictionName", typeof(string)),
1330 new ColumnInfo ("ParameterName", typeof(string)),
1331 new ColumnInfo ("RestrictionDefault", typeof(string)),
1332 new ColumnInfo ("RestrictionNumber", typeof(int))
1335 static readonly object [][] rows = {
1336 new object [] {"Users", "User_Name", "@Name", "name", 1},
1337 new object [] {"Databases", "Name", "@Name", "Name", 1},
1339 new object [] {"Tables", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1340 new object [] {"Tables", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1341 new object [] {"Tables", "Table", "@Name", "TABLE_NAME", 3},
1342 new object [] {"Tables", "TableType", "@TableType", "TABLE_TYPE", 4},
1344 new object [] {"Columns", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1345 new object [] {"Columns", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1346 new object [] {"Columns", "Table", "@Table", "TABLE_NAME", 3},
1347 new object [] {"Columns", "Column", "@Column", "COLUMN_NAME", 4},
1349 new object [] {"StructuredTypeMembers", "Catalog", "@Catalog", "TYPE_CATALOG", 1},
1350 new object [] {"StructuredTypeMembers", "Owner", "@Owner", "TYPE_SCHEMA", 2},
1351 new object [] {"StructuredTypeMembers", "Type", "@Type", "TYPE_NAME", 3},
1352 new object [] {"StructuredTypeMembers", "Member", "@Member", "MEMBER_NAME", 4},
1354 new object [] {"Views", "Catalog", "@Catalog", "TABLE_CATALOG", 1},
1355 new object [] {"Views", "Owner", "@Owner", "TABLE_SCHEMA", 2},
1356 new object [] {"Views", "Table", "@Table", "TABLE_NAME", 3},
1358 new object [] {"ViewColumns", "Catalog", "@Catalog", "VIEW_CATALOG", 1},
1359 new object [] {"ViewColumns", "Owner", "@Owner", "VIEW_SCHEMA", 2},
1360 new object [] {"ViewColumns", "Table", "@Table", "VIEW_NAME", 3},
1361 new object [] {"ViewColumns", "Column", "@Column", "COLUMN_NAME", 4},
1363 new object [] {"ProcedureParameters", "Catalog", "@Catalog", "SPECIFIC_CATALOG", 1},
1364 new object [] {"ProcedureParameters", "Owner", "@Owner", "SPECIFIC_SCHEMA", 2},
1365 new object [] {"ProcedureParameters", "Name", "@Name", "SPECIFIC_NAME", 3},
1366 new object [] {"ProcedureParameters", "Parameter", "@Parameter", "PARAMETER_NAME", 4},
1368 new object [] {"Procedures", "Catalog", "@Catalog", "SPECIFIC_CATALOG", 1},
1369 new object [] {"Procedures", "Owner", "@Owner", "SPECIFIC_SCHEMA", 2},
1370 new object [] {"Procedures", "Name", "@Name", "SPECIFIC_NAME", 3},
1371 new object [] {"Procedures", "Type", "@Type", "ROUTINE_TYPE", 4},
1373 new object [] {"IndexColumns", "Catalog", "@Catalog", "db_name()", 1},
1374 new object [] {"IndexColumns", "Owner", "@Owner", "user_name()", 2},
1375 new object [] {"IndexColumns", "Table", "@Table", "o.name", 3},
1376 new object [] {"IndexColumns", "ConstraintName", "@ConstraintName", "x.name", 4},
1377 new object [] {"IndexColumns", "Column", "@Column", "c.name", 5},
1379 new object [] {"Indexes", "Catalog", "@Catalog", "db_name()", 1},
1380 new object [] {"Indexes", "Owner", "@Owner", "user_name()", 2},
1381 new object [] {"Indexes", "Table", "@Table", "o.name", 3},
1382 new object [] {"Indexes", "Name", "@Name", "x.name", 4},
1384 new object [] {"UserDefinedTypes", "assembly_name", "@AssemblyName", "assemblies.name", 1},
1385 new object [] {"UserDefinedTypes", "udt_name", "@UDTName", "types.assembly_class", 2},
1387 new object [] {"ForeignKeys", "Catalog", "@Catalog", "CONSTRAINT_CATALOG", 1},
1388 new object [] {"ForeignKeys", "Owner", "@Owner", "CONSTRAINT_SCHEMA", 2},
1389 new object [] {"ForeignKeys", "Table", "@Table", "TABLE_NAME", 3},
1390 new object [] {"ForeignKeys", "Name", "@Name", "CONSTRAINT_NAME", 4}
1393 static DataTable instance;
1394 static public DataTable Instance {
1396 if (instance == null) {
1397 instance = new DataTable ("Restrictions");
1398 foreach (ColumnInfo c in columns)
1399 instance.Columns.Add (c.name, c.type);
1400 foreach (object [] row in rows)
1401 instance.LoadDataRow (row, true);
1408 public override DataTable GetSchema ()
1410 if (state == ConnectionState.Closed)
1411 throw ExceptionHelper.ConnectionClosed ();
1413 return MetaDataCollections.Instance;
1416 public override DataTable GetSchema (String collectionName)
1418 return GetSchema (collectionName, null);
1421 public override DataTable GetSchema (String collectionName, string [] restrictionValues)
1423 // LAMESPEC: In MS.NET, if collectionName is null, it throws ArgumentException.
1425 if (state == ConnectionState.Closed)
1426 throw ExceptionHelper.ConnectionClosed ();
1428 String cName = null;
1429 DataTable schemaTable = MetaDataCollections.Instance;
1430 int length = restrictionValues == null ? 0 : restrictionValues.Length;
1432 foreach (DataRow row in schemaTable.Rows) {
1433 if (String.Compare ((string) row["CollectionName"], collectionName, true) == 0) {
1434 if (length > (int) row["NumberOfRestrictions"]) {
1435 throw new ArgumentException ("More restrictions were provided " +
1436 "than the requested schema ('" +
1437 row["CollectionName"].ToString () + "') supports");
1439 cName = row["CollectionName"].ToString();
1444 throw new ArgumentException (string.Format (CultureInfo.InvariantCulture,
1445 "The requested collection ({0}) is not defined.",
1448 SqlCommand command = null;
1449 DataTable dataTable = new DataTable ();
1450 SqlDataAdapter dataAdapter = new SqlDataAdapter ();
1455 command = new SqlCommand ("select name as database_name, dbid, crdate as create_date " +
1456 "from master.sys.sysdatabases where (name = @Name or (@Name " +
1458 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1461 command = new SqlCommand ("select CONSTRAINT_CATALOG, CONSTRAINT_SCHEMA, CONSTRAINT_NAME, " +
1462 "TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_TYPE, " +
1463 "IS_DEFERRABLE, INITIALLY_DEFERRED from " +
1464 "INFORMATION_SCHEMA.TABLE_CONSTRAINTS where (CONSTRAINT_CATALOG" +
1465 " = @Catalog or (@Catalog is null)) and (CONSTRAINT_SCHEMA = " +
1466 "@Owner or (@Owner is null)) and (TABLE_NAME = @Table or (" +
1467 "@Table is null)) and (CONSTRAINT_NAME = @Name or (@Name is null))" +
1468 " and CONSTRAINT_TYPE = 'FOREIGN KEY' order by CONSTRAINT_CATALOG," +
1469 " CONSTRAINT_SCHEMA, CONSTRAINT_NAME", this);
1470 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1471 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1472 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1473 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1476 command = new SqlCommand ("select distinct db_name() as constraint_catalog, " +
1477 "constraint_schema = user_name (o.uid), " +
1478 "constraint_name = x.name, table_catalog = db_name (), " +
1479 "table_schema = user_name (o.uid), table_name = o.name, " +
1480 "index_name = x.name from sysobjects o, sysindexes x, " +
1481 "sysindexkeys xk where o.type in ('U') and x.id = o.id and " +
1482 "o.id = xk.id and x.indid = xk.indid and xk.keyno = x.keycnt " +
1483 "and (db_name() = @Catalog or (@Catalog is null)) and " +
1484 "(user_name() = @Owner or (@Owner is null)) and (o.name = " +
1485 "@Table or (@Table is null)) and (x.name = @Name or (@Name is null))" +
1486 "order by table_name, index_name", this);
1487 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1488 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1489 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1490 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1492 case "IndexColumns":
1493 command = new SqlCommand ("select distinct db_name() as constraint_catalog, " +
1494 "constraint_schema = user_name (o.uid), constraint_name = x.name, " +
1495 "table_catalog = db_name (), table_schema = user_name (o.uid), " +
1496 "table_name = o.name, column_name = c.name, " +
1497 "ordinal_position = convert (int, xk.keyno), keyType = c.xtype, " +
1498 "index_name = x.name from sysobjects o, sysindexes x, syscolumns c, " +
1499 "sysindexkeys xk where o.type in ('U') and x.id = o.id and o.id = c.id " +
1500 "and o.id = xk.id and x.indid = xk.indid and c.colid = xk.colid " +
1501 "and xk.keyno <= x.keycnt and permissions (o.id, c.name) <> 0 " +
1502 "and (db_name() = @Catalog or (@Catalog is null)) and (user_name() " +
1503 "= @Owner or (@Owner is null)) and (o.name = @Table or (@Table is" +
1504 " null)) and (x.name = @ConstraintName or (@ConstraintName is null)) " +
1505 "and (c.name = @Column or (@Column is null)) order by table_name, " +
1506 "index_name", this);
1507 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 8);
1508 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1509 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 13);
1510 command.Parameters.Add ("@ConstraintName", SqlDbType.NVarChar, 4000);
1511 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1514 command = new SqlCommand ("select SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, " +
1515 "ROUTINE_CATALOG, ROUTINE_SCHEMA, ROUTINE_NAME, ROUTINE_TYPE, " +
1516 "CREATED, LAST_ALTERED from INFORMATION_SCHEMA.ROUTINES where " +
1517 "(SPECIFIC_CATALOG = @Catalog or (@Catalog is null)) and " +
1518 "(SPECIFIC_SCHEMA = @Owner or (@Owner is null)) and (SPECIFIC_NAME" +
1519 " = @Name or (@Name is null)) and (ROUTINE_TYPE = @Type or (@Type " +
1520 "is null)) order by SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME", this);
1521 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1522 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1523 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1524 command.Parameters.Add ("@Type", SqlDbType.NVarChar, 4000);
1526 case "ProcedureParameters":
1527 command = new SqlCommand ("select SPECIFIC_CATALOG, SPECIFIC_SCHEMA, SPECIFIC_NAME, " +
1528 "ORDINAL_POSITION, PARAMETER_MODE, IS_RESULT, AS_LOCATOR, " +
1529 "PARAMETER_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, " +
1530 "CHARACTER_OCTET_LENGTH, COLLATION_CATALOG, COLLATION_SCHEMA, " +
1531 "COLLATION_NAME, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, " +
1532 "CHARACTER_SET_NAME, NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, " +
1533 "NUMERIC_SCALE, DATETIME_PRECISION, INTERVAL_TYPE, " +
1534 "INTERVAL_PRECISION from INFORMATION_SCHEMA.PARAMETERS where " +
1535 "(SPECIFIC_CATALOG = @Catalog or (@Catalog is null)) and " +
1536 "(SPECIFIC_SCHEMA = @Owner or (@Owner is null)) and (SPECIFIC_NAME = " +
1537 "@Name or (@Name is null)) and (PARAMETER_NAME = @Parameter or (" +
1538 "@Parameter is null)) order by SPECIFIC_CATALOG, SPECIFIC_SCHEMA," +
1539 " SPECIFIC_NAME, PARAMETER_NAME", this);
1540 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1541 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1542 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1543 command.Parameters.Add ("@Parameter", SqlDbType.NVarChar, 4000);
1546 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, TABLE_TYPE " +
1547 "from INFORMATION_SCHEMA.TABLES where" +
1548 " (TABLE_CATALOG = @catalog or (@catalog is null)) and " +
1549 "(TABLE_SCHEMA = @owner or (@owner is null))and " +
1550 "(TABLE_NAME = @name or (@name is null)) and " +
1551 "(TABLE_TYPE = @table_type or (@table_type is null))", this);
1552 command.Parameters.Add ("@catalog", SqlDbType.NVarChar, 8);
1553 command.Parameters.Add ("@owner", SqlDbType.NVarChar, 3);
1554 command.Parameters.Add ("@name", SqlDbType.NVarChar, 11);
1555 command.Parameters.Add ("@table_type", SqlDbType.NVarChar, 10);
1558 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, " +
1559 "ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, " +
1560 "CHARACTER_MAXIMUM_LENGTH, CHARACTER_OCTET_LENGTH, " +
1561 "NUMERIC_PRECISION, NUMERIC_PRECISION_RADIX, NUMERIC_SCALE, " +
1562 "DATETIME_PRECISION, CHARACTER_SET_CATALOG, CHARACTER_SET_SCHEMA, " +
1563 "CHARACTER_SET_NAME, COLLATION_CATALOG from INFORMATION_SCHEMA.COLUMNS" +
1564 " where (TABLE_CATALOG = @Catalog or (@Catalog is null)) and (" +
1565 "TABLE_SCHEMA = @Owner or (@Owner is null)) and (TABLE_NAME = @table" +
1566 " or (@Table is null)) and (COLUMN_NAME = @column or (@Column is null" +
1567 ")) order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME", this);
1568 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1569 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1570 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1571 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1574 command = new SqlCommand ("select uid, name as user_name, createdate, updatedate from sysusers" +
1575 " where (name = @Name or (@Name is null))", this);
1576 command.Parameters.Add ("@Name", SqlDbType.NVarChar, 4000);
1578 case "StructuredTypeMembers":
1579 // Only available on SQL Server 2008
1580 // Running it again SQL 2005 results in the following exception:
1581 // Unable to build the 'StructuredTypeMembers' collection because
1582 // execution of the SQL query failed. See the inner exception for details.
1583 // ---> System.Data.SqlClient.SqlException: Invalid object name 'sys.table_types'.
1585 // I don't have access to SQL Server 2008 right now,
1586 // and can't find any online documentation on the 'sys.table_types'
1588 throw new NotImplementedException ();
1590 command = new SqlCommand ("select TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, CHECK_OPTION, " +
1591 "IS_UPDATABLE from INFORMATION_SCHEMA.VIEWS where (TABLE_CATALOG" +
1592 " = @Catalog or (@Catalog is null)) TABLE_SCHEMA = @Owner or " +
1593 "(@Owner is null)) and (TABLE_NAME = @table or (@Table is null))" +
1594 " order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME", this);
1595 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1596 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1597 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1600 command = new SqlCommand ("select VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME, TABLE_CATALOG, " +
1601 "TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME from " +
1602 "INFORMATION_SCHEMA.VIEW_COLUMN_USAGE where (VIEW_CATALOG = " +
1603 "@Catalog (@Catalog is null)) and (VIEW_SCHEMA = @Owner (@Owner" +
1604 " is null)) and (VIEW_NAME = @Table or (@Table is null)) and " +
1605 "(COLUMN_NAME = @Column or (@Column is null)) order by " +
1606 "VIEW_CATALOG, VIEW_SCHEMA, VIEW_NAME", this);
1607 command.Parameters.Add ("@Catalog", SqlDbType.NVarChar, 4000);
1608 command.Parameters.Add ("@Owner", SqlDbType.NVarChar, 4000);
1609 command.Parameters.Add ("@Table", SqlDbType.NVarChar, 4000);
1610 command.Parameters.Add ("@Column", SqlDbType.NVarChar, 4000);
1612 case "UserDefinedTypes":
1613 command = new SqlCommand ("select assemblies.name as assembly_name, types.assembly_class " +
1614 "as udt_name, ASSEMBLYPROPERTY(assemblies.name, 'VersionMajor') " +
1615 "as version_major, ASSEMBLYPROPERTY(assemblies.name, 'VersionMinor') " +
1616 "as version_minor, ASSEMBLYPROPERTY(assemblies.name, 'VersionBuild') " +
1617 "as version_build, ASSEMBLYPROPERTY(assemblies.name, 'VersionRevision') " +
1618 "as version_revision, ASSEMBLYPROPERTY(assemblies.name, 'CultureInfo') " +
1619 "as culture_info, ASSEMBLYPROPERTY(assemblies.name, 'PublicKey') " +
1620 "as public_key, is_fixed_length, max_length, Create_Date, " +
1621 "Permission_set_desc from sys.assemblies as assemblies join " +
1622 "sys.assembly_types as types on assemblies.assembly_id = types.assembly_id" +
1623 " where (assportemblies.name = @AssemblyName or (@AssemblyName is null)) and " +
1624 "(types.assembly_class = @UDTName or (@UDTName is null))",
1626 command.Parameters.Add ("@AssemblyName", SqlDbType.NVarChar, 4000);
1627 command.Parameters.Add ("@UDTName", SqlDbType.NVarChar, 4000);
1629 case "MetaDataCollections":
1630 return MetaDataCollections.Instance;
1631 case "DataSourceInformation":
1632 return DataSourceInformation.GetInstance (this);
1634 return DataTypes.Instance;
1635 case "ReservedWords":
1636 return ReservedWords.Instance;
1637 case "Restrictions":
1638 return Restrictions.Instance;
1640 for (int i = 0; i < length; i++) {
1641 command.Parameters[i].Value = restrictionValues[i];
1643 dataAdapter.SelectCommand = command;
1644 dataAdapter.Fill (dataTable);
1648 public static void ChangePassword (string connectionString, string newPassword)
1650 if (String.IsNullOrEmpty (connectionString))
1651 throw new ArgumentNullException ("The 'connectionString' cannot be null or empty.");
1652 if (String.IsNullOrEmpty (newPassword))
1653 throw new ArgumentNullException ("The 'newPassword' cannot be null or empty.");
1654 if (newPassword.Length > 128)
1655 throw new ArgumentException ("The length of 'newPassword' cannot exceed 128 characters.");
1656 using (SqlConnection conn = new SqlConnection (connectionString)) {
1658 conn.tds.Execute (String.Format ("sp_password '{0}', '{1}', '{2}'",
1659 conn.parms.Password, newPassword, conn.parms.User));
1663 public static void ClearAllPools ()
1666 IDictionary <string, TdsConnectionPool> pools = SqlConnection.sqlConnectionPools.GetConnectionPool ();
1668 Hashtable pools = SqlConnection.sqlConnectionPools.GetConnectionPool ();
1670 foreach (TdsConnectionPool pool in pools.Values) {
1672 pool.ResetConnectionPool ();
1673 Tds tds = pool.GetConnection ();
1674 tds.Pooling = false;
1679 public static void ClearPool (SqlConnection connection)
1681 if (connection.pooling) {
1682 connection.pooling = false;
1683 if (connection.pool != null)
1684 connection.pool.ResetConnectionPool (connection.Tds);
1690 #endregion // Methods
1693 #region Fields Net 2
1697 #endregion // Fields Net 2
1699 #region Properties Net 2
1702 [DataSysDescription ("Enable Asynchronous processing, 'Asynchrouse Processing=true/false' in the ConnectionString.")]
1704 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1705 internal bool AsyncProcessing {
1706 get { return async; }
1709 #endregion // Properties Net 2