//
// Author:
// Tim Coleman (tim@timcoleman.com)
+// Daniel Morgan (danmorg@sc.rr.com)
//
-// Copyright (C) Tim Coleman, 2002
+// Copyright (C) Tim Coleman, 2002-2003
+// Copyright (C) Daniel Morgan, 2003
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using Mono.Data.Tds.Protocol;
using System.Data.Common;
using System.EnterpriseServices;
using System.Net;
+using System.Net.Sockets;
using System.Text;
namespace Mono.Data.SybaseClient {
bool disposed = false;
// The set of SQL connection pools
- static Hashtable SybaseConnectionPools = new Hashtable ();
+ static TdsConnectionPoolManager sybaseConnectionPools = new TdsConnectionPoolManager (TdsVersion.tds50);
// The current connection pool
- SybaseConnectionPool pool;
+ TdsConnectionPool pool;
// The connection string that identifies this connection
string connectionString = null;
int minPoolSize;
int maxPoolSize;
int packetSize;
- int port = 1533;
+ int port = 2048;
// The current state
ConnectionState state = ConnectionState.Closed;
break;
}
- tds.ExecuteNonQuery (String.Format ("SET TRANSACTION ISOLATION LEVEL {0};BEGIN TRANSACTION {1}", isolevel, transactionName));
+ tds.Execute (String.Format ("SET TRANSACTION ISOLATION LEVEL {0}\nBEGIN TRANSACTION {1}", isolevel, transactionName));
transaction = new SybaseTransaction (this, iso);
return transaction;
}
throw new ArgumentException (String.Format ("The database name {0} is not valid."));
if (State != ConnectionState.Open)
throw new InvalidOperationException ("The connection is not open");
- tds.ExecuteNonQuery (String.Format ("use {0}", database));
+ tds.Execute (String.Format ("use {0}", database));
}
private void ChangeState (ConnectionState currentState)
[MonoTODO ("Figure out the Sybase way to reset the connection.")]
public void Open ()
{
- if (connectionString == null)
+ string serverName = "";
+ if (connectionString == null || connectionString.Equals (""))
throw new InvalidOperationException ("Connection string has not been initialized.");
try {
- if (!pooling)
- tds = new Tds50 (DataSource, port, PacketSize, ConnectionTimeout);
+ if (!pooling) {
+ ParseDataSource (dataSource, out port, out serverName);
+ tds = new Tds50 (serverName, port, PacketSize, ConnectionTimeout);
+ }
else {
- pool = (SybaseConnectionPool) SybaseConnectionPools [connectionString];
- if (pool == null) {
- pool = new SybaseConnectionPool (dataSource, port, packetSize, ConnectionTimeout, minPoolSize, maxPoolSize);
- SybaseConnectionPools [connectionString] = pool;
- }
- tds = pool.AllocateConnection ();
+ ParseDataSource (dataSource, out port, out serverName);
+ TdsConnectionInfo info = new TdsConnectionInfo (serverName, port, packetSize, ConnectionTimeout, minPoolSize, maxPoolSize);
+ pool = sybaseConnectionPools.GetConnectionPool (connectionString, info);
+ tds = pool.GetConnection ();
}
}
catch (TdsTimeoutException e) {
tds.TdsInfoMessage += new TdsInternalInfoMessageEventHandler (MessageHandler);
if (!tds.IsConnected) {
- tds.Connect (parms);
- ChangeState (ConnectionState.Open);
- ChangeDatabase (parms.Database);
+ try {
+ tds.Connect (parms);
+ ChangeState (ConnectionState.Open);
+ ChangeDatabase (parms.Database);
+ }
+ catch {
+ if (pooling)
+ pool.ReleaseConnection (tds);
+ throw;
+ }
}
else if (connectionReset) {
// tds.ExecuteNonQuery ("EXEC sp_reset_connection"); FIXME
}
}
- void SetConnectionString (string connectionString)
- {
- connectionString += ";";
- NameValueCollection parameters = new NameValueCollection ();
-
- if (connectionString == String.Empty)
- return;
-
- bool inQuote = false;
- bool inDQuote = false;
-
- string name = String.Empty;
- string value = String.Empty;
- StringBuilder sb = new StringBuilder ();
-
- foreach (char c in connectionString)
- {
- switch (c) {
- case '\'':
- inQuote = !inQuote;
- break;
- case '"' :
- inDQuote = !inDQuote;
- break;
- case ';' :
- if (!inDQuote && !inQuote) {
- if (name != String.Empty && name != null) {
- value = sb.ToString ();
- parameters [name.ToUpper ().Trim ()] = value.Trim ();
- }
- name = String.Empty;
- value = String.Empty;
- sb = new StringBuilder ();
- }
- else
- sb.Append (c);
- break;
- case '=' :
- if (!inDQuote && !inQuote) {
- name = sb.ToString ();
- sb = new StringBuilder ();
- }
- else
- sb.Append (c);
- break;
- default:
- sb.Append (c);
- break;
- }
- }
-
- if (this.ConnectionString == null)
- {
- SetDefaultConnectionParameters (parameters);
- }
-
- SetProperties (parameters);
-
- this.connectionString = connectionString;
- }
-
- void SetDefaultConnectionParameters (NameValueCollection parameters)
- {
- if (null == parameters.Get ("APPLICATION NAME"))
- parameters["APPLICATION NAME"] = ".Net SybaseClient Data Provider";
- if (null == parameters.Get ("CONNECT TIMEOUT") && null == parameters.Get ("CONNECTION TIMEOUT"))
- parameters["CONNECT TIMEOUT"] = "15";
- if (null == parameters.Get ("CONNECTION LIFETIME"))
- parameters["CONNECTION LIFETIME"] = "0";
- if (null == parameters.Get ("CONNECTION RESET"))
- parameters["CONNECTION RESET"] = "true";
- if (null == parameters.Get ("ENLIST"))
- parameters["ENLIST"] = "true";
- if (null == parameters.Get ("INTEGRATED SECURITY") && null == parameters.Get ("TRUSTED_CONNECTION"))
- parameters["INTEGRATED SECURITY"] = "false";
- if (null == parameters.Get ("MAX POOL SIZE"))
- parameters["MAX POOL SIZE"] = "100";
- if (null == parameters.Get ("MIN POOL SIZE"))
- parameters["MIN POOL SIZE"] = "0";
- if (null == parameters.Get ("NETWORK LIBRARY") && null == parameters.Get ("NET"))
- parameters["NETWORK LIBRARY"] = "dbmssocn";
- if (null == parameters.Get ("PACKET SIZE"))
- parameters["PACKET SIZE"] = "512";
- if (null == parameters.Get ("PERSIST SECURITY INFO"))
- parameters["PERSIST SECURITY INFO"] = "false";
- if (null == parameters.Get ("POOLING"))
- parameters["POOLING"] = "true";
- if (null == parameters.Get ("WORKSTATION ID"))
- parameters["WORKSTATION ID"] = Dns.GetHostByName ("localhost").HostName;
- }
-
- private void SetProperties (NameValueCollection parameters)
- {
- string value;
- foreach (string name in parameters) {
- value = parameters[name];
-
- switch (name) {
- case "APPLICATION NAME" :
- parms.ApplicationName = value;
- break;
- case "ATTACHDBFILENAME" :
- case "EXTENDED PROPERTIES" :
- case "INITIAL FILE NAME" :
- break;
- case "CONNECT TIMEOUT" :
- case "CONNECTION TIMEOUT" :
- connectionTimeout = Int32.Parse (value);
- break;
- case "CONNECTION LIFETIME" :
- break;
- case "CONNECTION RESET" :
- connectionReset = !(value.ToUpper ().Equals ("FALSE") || value.ToUpper ().Equals ("NO"));
- break;
- case "CURRENT LANGUAGE" :
- parms.Language = value;
- break;
- case "DATA SOURCE" :
- case "SERVER" :
- case "ADDRESS" :
- case "ADDR" :
- case "NETWORK ADDRESS" :
- dataSource = value;
- break;
- case "ENLIST" :
- break;
- case "INITIAL CATALOG" :
- case "DATABASE" :
- parms.Database = value;
- break;
- case "INTEGRATED SECURITY" :
- case "TRUSTED_CONNECTION" :
- break;
- case "MAX POOL SIZE" :
- maxPoolSize = Int32.Parse (value);
- break;
- case "MIN POOL SIZE" :
- minPoolSize = Int32.Parse (value);
- break;
- case "NET" :
- case "NETWORK LIBRARY" :
- if (!value.ToUpper ().Equals ("DBMSSOCN"))
- throw new ArgumentException ("Unsupported network library.");
- break;
- case "PACKET SIZE" :
- packetSize = Int32.Parse (value);
- break;
- case "PASSWORD" :
- case "PWD" :
- parms.Password = value;
- break;
- case "PERSIST SECURITY INFO" :
- break;
- case "POOLING" :
- pooling = !(value.ToUpper ().Equals ("FALSE") || value.ToUpper ().Equals ("NO"));
- break;
- case "USER ID" :
- parms.User = value;
- break;
- case "WORKSTATION ID" :
- parms.Hostname = value;
- break;
- }
+ private void ParseDataSource (string theDataSource, out int thePort, out string theServerName)
+ {
+ theServerName = "";
+ thePort = 2048;
+
+ int idx = 0;
+ if ((idx = theDataSource.IndexOf (",")) > -1) {
+ theServerName = theDataSource.Substring (0, idx);
+ string p = theDataSource.Substring (idx + 1);
+ thePort = Int32.Parse (p);
+ }
+ else {
+ theServerName = theDataSource;
+ }
+ }
+
+ private string ParseValue (string name, string value)
+ {
+ if (name.Length == 0 && value.Length > 0)
+ throw new ArgumentException ("Expected '=' delimiter while parsing connection value pair.");
+ if (name.Length > 0)
+ return value.Trim ();
+ return String.Empty;
+ }
+
+ private void SetConnectionString (string connectionString)
+ {
+ if (connectionString == String.Empty) {
+ this.connectionString = connectionString;
+ return;
+ }
+
+ NameValueCollection parameters = new NameValueCollection ();
+
+ string name = String.Empty;
+ string value = String.Empty;
+ StringBuilder sb = new StringBuilder ();
+
+ char delimiter = '\0';
+
+ foreach (char c in connectionString) {
+ switch (c) {
+ case '\'' :
+ case '"' :
+ if (delimiter.Equals (c))
+ delimiter = '\0';
+ else if (delimiter.Equals ('\0'))
+ delimiter = c;
+ else
+ sb.Append (c);
+ break;
+ case ';' :
+ if (delimiter.Equals ('\0')) {
+ value = ParseValue (name, sb.ToString ());
+ if (!value.Equals (""))
+ parameters [name.ToUpper ().Trim ()] = value;
+ name = String.Empty;
+ sb = new StringBuilder ();
+ }
+ else
+ sb.Append (c);
+ break;
+ case '=' :
+ if (delimiter.Equals ('\0')) {
+ name = sb.ToString ();
+ sb = new StringBuilder ();
+ }
+ else
+ sb.Append (c);
+ break;
+ default:
+ sb.Append (c);
+ break;
+ }
+ }
+
+ if (!delimiter.Equals ('\0'))
+ throw new ArgumentException (String.Format ("Matching end delimiter {0} not found in connection option value.", delimiter));
+
+ value = ParseValue (name, sb.ToString ());
+ if (!value.Equals (""))
+ parameters [name.ToUpper ().Trim ()] = value;
+
+ SetDefaultConnectionParameters (parameters);
+ SetProperties (parameters);
+
+ this.connectionString = connectionString;
+ }
+
+ private void SetDefaultConnectionParameters (NameValueCollection parameters)
+ {
+ if (null == parameters.Get ("APPLICATION NAME"))
+ parameters["APPLICATION NAME"] = "Mono SybaseClient Data Provider";
+ if (null == parameters.Get ("CONNECT TIMEOUT") && null == parameters.Get ("CONNECTION TIMEOUT")) {
+ parameters["CONNECT TIMEOUT"] = "15";
+ connectionTimeout = 15;
+ }
+ if (null == parameters.Get ("CONNECTION LIFETIME"))
+ parameters["CONNECTION LIFETIME"] = "0";
+ if (null == parameters.Get ("CONNECTION RESET"))
+ parameters["CONNECTION RESET"] = "true";
+ if (null == parameters.Get ("ENLIST"))
+ parameters["ENLIST"] = "true";
+ if (null == parameters.Get ("INTEGRATED SECURITY") && null == parameters.Get ("TRUSTED_CONNECTION"))
+ parameters["INTEGRATED SECURITY"] = "false";
+ if (null == parameters.Get ("MAX POOL SIZE")) {
+ parameters["MAX POOL SIZE"] = "100";
+ maxPoolSize = 100;
+ }
+ if (null == parameters.Get ("MIN POOL SIZE")) {
+ parameters["MIN POOL SIZE"] = "0";
+ maxPoolSize = 0;
+ }
+ if (null == parameters.Get ("NETWORK LIBRARY") && null == parameters.Get ("NET"))
+ parameters["NETWORK LIBRARY"] = "dbmssocn";
+ if (null == parameters.Get ("PACKET SIZE")) {
+ parameters["PACKET SIZE"] = "512";
+ packetSize = 512;
}
+ if (null == parameters.Get ("PERSIST SECURITY INFO"))
+ parameters["PERSIST SECURITY INFO"] = "false";
+ if (null == parameters.Get ("POOLING"))
+ parameters["POOLING"] = "true";
+ if (null == parameters.Get ("WORKSTATION ID"))
+ parameters["WORKSTATION ID"] = Dns.GetHostByName ("localhost").HostName;
}
+ private void SetProperties (NameValueCollection parameters)
+ {
+ string value;
+ foreach (string name in parameters) {
+ value = parameters [name];
+
+ switch (name) {
+ case "APPLICATION NAME" :
+ parms.ApplicationName = value;
+ break;
+ case "ATTACHDBFILENAME" :
+ case "EXTENDED PROPERTIES" :
+ case "INITIAL FILE NAME" :
+ break;
+ case "CONNECT TIMEOUT" :
+ case "CONNECTION TIMEOUT" :
+ connectionTimeout = Int32.Parse (value);
+ break;
+ case "CONNECTION LIFETIME" :
+ break;
+ case "CONNECTION RESET" :
+ connectionReset = !(value.ToUpper ().Equals ("FALSE") || value.ToUpper ().Equals ("NO"));
+ break;
+ case "CURRENT LANGUAGE" :
+ parms.Language = value;
+ break;
+ case "DATA SOURCE" :
+ case "SERVER" :
+ case "ADDRESS" :
+ case "ADDR" :
+ case "NETWORK ADDRESS" :
+ dataSource = value;
+ break;
+ case "ENLIST" :
+ break;
+ case "INITIAL CATALOG" :
+ case "DATABASE" :
+ parms.Database = value;
+ break;
+ case "INTEGRATED SECURITY" :
+ case "TRUSTED_CONNECTION" :
+ break;
+ case "MAX POOL SIZE" :
+ maxPoolSize = Int32.Parse (value);
+ break;
+ case "MIN POOL SIZE" :
+ minPoolSize = Int32.Parse (value);
+ break;
+ case "NET" :
+ case "NETWORK LIBRARY" :
+ if (!value.ToUpper ().Equals ("DBMSSOCN"))
+ throw new ArgumentException ("Unsupported network library.");
+ break;
+ case "PACKET SIZE" :
+ packetSize = Int32.Parse (value);
+ break;
+ case "PASSWORD" :
+ case "PWD" :
+ parms.Password = value;
+ break;
+ case "PERSIST SECURITY INFO" :
+ break;
+ case "POOLING" :
+ pooling = !(value.ToUpper ().Equals ("FALSE") || value.ToUpper ().Equals ("NO"));
+ break;
+ case "USER ID" :
+ parms.User = value;
+ break;
+ case "WORKSTATION ID" :
+ parms.Hostname = value;
+ break;
+ }
+ }
+ }
- static bool IsValidDatabaseName (string database)
+ private static bool IsValidDatabaseName (string database)
{
if (database.Length > 32 || database.Length < 1)
return false;