Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
//
// 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 System.Reflection;
using System.Runtime.CompilerServices;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly: AssemblyTitle("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyDelaySign (true)]
[assembly: AssemblyKeyFile ("ibm.pub")]

View File

@@ -0,0 +1,25 @@
./Assembly/AssemblyInfo.cs
./IBM.Data.DB2/DB2ClientUtils.cs
./IBM.Data.DB2/DB2CLIWrapper.cs
./IBM.Data.DB2/DB2Command.cs
./IBM.Data.DB2/DB2CommandBuilder.cs
./IBM.Data.DB2/DB2OpenConnection.cs
./IBM.Data.DB2/DB2Connection.cs
./IBM.Data.DB2/DB2ConnectionPool.cs
./IBM.Data.DB2/DB2ConnectionSettings.cs
./IBM.Data.DB2/DB2Constants.cs
./IBM.Data.DB2/DB2DataAdapter.cs
./IBM.Data.DB2/DB2DataReader.cs
./IBM.Data.DB2/DB2Environment.cs
./IBM.Data.DB2/DB2Error.cs
./IBM.Data.DB2/DB2ErrorCollection.cs
./IBM.Data.DB2/DB2Exception.cs
./IBM.Data.DB2/DB2InfoMessageEventHandler.cs
./IBM.Data.DB2/DB2Parameter.cs
./IBM.Data.DB2/DB2ParameterCollection.cs
./IBM.Data.DB2/DB2RowUpdatedEventArgs.cs
./IBM.Data.DB2/DB2RowUpdatedEventHandler.cs
./IBM.Data.DB2/DB2RowUpdatingEventArgs.cs
./IBM.Data.DB2/DB2RowUpdatingEventHandler.cs
./IBM.Data.DB2/DB2Transaction.cs
./IBM.Data.DB2/DB2Type.cs

View File

@@ -0,0 +1,6 @@
2009-09-01 Gonzalo Paniagua Javier <gonzalo@novell.com>
* DB2CLIWrapper.cs: changed libname to 'db2'. Use 'int' instead of
'IntPtr' for most of the SQL handles. Only SQLPOINTER is 64 bits in
64-bit machines.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,60 @@
//
// 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 System;
namespace IBM.Data.DB2
{
public class DB2ClientUtils
{
#region DB2CheckReturn
public static void DB2CheckReturn(short sqlRet, short handleType, IntPtr handle, string message, DB2Connection connection)
{
switch (sqlRet)
{
case DB2Constants.SQL_SUCCESS_WITH_INFO:
if(connection != null)
{
connection.OnInfoMessage(handleType, handle);
}
goto case DB2Constants.SQL_SUCCESS;
case DB2Constants.SQL_SUCCESS:
case DB2Constants.SQL_NO_DATA:
return;
case DB2Constants.SQL_INVALID_HANDLE:
throw new ArgumentException("Invalid handle");
default:
case DB2Constants.SQL_ERROR:
throw new DB2Exception(handleType, handle, message);
}
}
public static void DB2CheckReturn(short sqlRet, short handleType, IntPtr handle, string message)
{
DB2CheckReturn(sqlRet, handleType, handle, message, null);
}
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,291 @@
//
// 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 System;
using System.Data;
using System.ComponentModel;
namespace IBM.Data.DB2
{
public sealed class DB2CommandBuilder : Component
{
bool disposed = false;
private DB2DataAdapter dataAdapter;
private DB2Command insertCommand;
private DB2Command updateCommand;
private DB2Command deleteCommand;
private string tableName = String.Empty;
public DB2CommandBuilder ()
{}
public DB2CommandBuilder (DB2DataAdapter adapter)
{
DataAdapter = adapter;
}
public DB2DataAdapter DataAdapter
{
get
{
return dataAdapter;
}
set
{
if (dataAdapter != null)
{
throw new Exception ("DataAdapter is already set");
}
dataAdapter = value;
string select_text = dataAdapter.SelectCommand.CommandText;
string[] words = select_text.Split(new char [] {' '});
bool from_found = false;
for (int i = 0; i < words.Length; i++)
{
if (from_found && (words[i] != String.Empty))
{
tableName = words[i];
break;
}
if (words[i].ToLower() == "from")
{
from_found = true;
}
}
}
}
public string QuotePrefix
{
get
{
return "";
}
set
{ }
}
public string QuoteSuffix
{
get
{
return "";
}
set
{ }
}
public static void DeriveParameters (DB2Command command)
{}
public DB2Command GetInsertCommand ()
{
DataTable dt = GetSchema();
if (insertCommand == null)
{
string fields = "";
string values = "";
for (int i = 0; i < dt.Rows.Count; i++)
{
//DataColumn column = dt.Columns[i];
DataRow dr = dt.Rows[i];
DataColumn column = new DataColumn((string)dr["ColumnName"], DB2TypeConverter.GetManagedType((int)dr["ProviderType"]));
if (fields.Length != 0 && !((bool)dr["IsAutoIncrement"]))
{
fields += ", ";
values += ", ";
}
if(!((bool)dr["IsAutoIncrement"]))
{
fields += column.ColumnName;
//values += ":v_" + column.ColumnName;
values += "?";
}
}
if (tableName == String.Empty)
{
tableName = dt.TableName;
}
DB2Command cmdaux = new DB2Command("insert into " + tableName + " (" + fields + ") values (" + values + ")", dataAdapter.SelectCommand.Connection);
for (int i = 0;i < dt.Rows.Count;i++)
{
//DataColumn column = dt.Columns[i];
DataRow dr = dt.Rows[i];
DataColumn column = new DataColumn((string)dr["ColumnName"], DB2TypeConverter.GetManagedType((int)dr["ProviderType"]));
if (!((bool)dr["IsAutoIncrement"]))
{
DB2Parameter aux = new DB2Parameter("v_" + column.ColumnName, column.DataType);
aux.Direction = ParameterDirection.Input;
aux.SourceColumn = column.ColumnName;
cmdaux.Parameters.Add(aux);
}
}
insertCommand = cmdaux;
}
return insertCommand;
}
public DB2Command GetUpdateCommand ()
{
DataTable dt = GetSchema();
if (updateCommand == null)
{
string sets = "";
string wheres = "";
for (int i = 0; i < dt.Rows.Count; i++)
{
if (sets.Length != 0 && !((bool)dt.Rows[i]["IsAutoIncrement"]))
{
sets += ", ";
}
if (i != 0)
{
wheres += " and ";
}
DataRow dr = dt.Rows[i];
DataColumn column = new DataColumn((string)dr["ColumnName"], DB2TypeConverter.GetManagedType((int)dr["ProviderType"]));
if(!((bool)dr["IsAutoIncrement"])){sets += String.Format("{0} = ? ", column.ColumnName);}
wheres += String.Format("(({0} is null) or ({0} = ?))", column.ColumnName);
}
if (tableName == String.Empty)
{
tableName = (string)dt.Rows[0]["BaseTableName"];
}
DB2Command cmdaux = new DB2Command("update " + tableName + " set " + sets + " where ( " + wheres + " )", dataAdapter.SelectCommand.Connection);
for (int i = 0; i < dt.Rows.Count; i++)
{
DataRow dr = dt.Rows[i];
DataColumn column = new DataColumn((string)dr["ColumnName"], DB2TypeConverter.GetManagedType((int)dr["ProviderType"]));
if (!((bool)dr["IsAutoIncrement"]))
{
DB2Parameter aux = new DB2Parameter("s_" + column.ColumnName, column.DataType);
aux.Direction = ParameterDirection.Input;
aux.SourceColumn = column.ColumnName;
aux.SourceVersion = DataRowVersion.Current;
cmdaux.Parameters.Add(aux);
}
}
for (int i = 0; i < dt.Rows.Count; i++)
{
DataRow dr = dt.Rows[i];
DataColumn column = new DataColumn((string)dr["ColumnName"], DB2TypeConverter.GetManagedType((int)dr["ProviderType"]));
DB2Parameter aux = new DB2Parameter("w_" + column.ColumnName, column.DataType);
aux.Direction = ParameterDirection.Input;
aux.SourceColumn = column.ColumnName;
aux.SourceVersion = DataRowVersion.Original;
cmdaux.Parameters.Add(aux);
}
updateCommand = cmdaux;
}
return updateCommand;
}
public DB2Command GetDeleteCommand ()
{
DataTable dt = GetSchema();
if (deleteCommand == null)
{
string wheres = "";
for (int i = 0; i < dt.Rows.Count; i++)
{
//DataColumn column = row.Table.Columns[i];
DataRow dr = dt.Rows[i];
DataColumn column = new DataColumn((string)dr["ColumnName"], DB2TypeConverter.GetManagedType((int)dr["ProviderType"]));
if (i != 0)
{
wheres += " and ";
}
//wheres += String.Format("(({0} is null) or ({0} = v_{0}))", column.ColumnName);
wheres += String.Format("(({0} is null) or ({0} = ?))", column.ColumnName);
}
if (tableName == String.Empty)
{
tableName = (string)dt.Rows[0]["BaseTableName"];
}
DB2Command cmdaux = new DB2Command("delete from " + tableName + " where ( " + wheres + " )", dataAdapter.SelectCommand.Connection);
for (int i = 0; i < dt.Rows.Count; i++)
{
DataRow dr = dt.Rows[i];
DataColumn column = new DataColumn((string)dr["ColumnName"], DB2TypeConverter.GetManagedType((int)dr["ProviderType"]));
DB2Parameter aux = new DB2Parameter("v_" + column.ColumnName, column.DataType);
aux.Direction = ParameterDirection.Input;
aux.SourceColumn = column.ColumnName;
aux.SourceVersion = DataRowVersion.Original;
cmdaux.Parameters.Add(aux);
}
deleteCommand = cmdaux;
}
return deleteCommand;
}
public void RefreshSchema ()
{
insertCommand = null;
updateCommand = null;
deleteCommand = null;
}
private DataTable GetSchema()
{
dataAdapter.SelectCommand.Connection.Open();
DB2Command cmd = new DB2Command(dataAdapter.SelectCommand.CommandText, dataAdapter.SelectCommand.Connection);
DB2DataReader fake = cmd.ExecuteReader(CommandBehavior.KeyInfo);
DataTable dt = fake.GetSchemaTable();
fake.Close();
dataAdapter.SelectCommand.Connection.Close();
return dt;
}
protected override void Dispose (bool disposing)
{
if (!disposed)
{
if (disposing)
{
if (insertCommand != null)
{
insertCommand.Dispose();
}
if (updateCommand != null)
{
updateCommand.Dispose();
}
if (deleteCommand != null)
{
deleteCommand.Dispose();
}
}
}
}
}
}

View File

@@ -0,0 +1,401 @@
//
// 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 System;
using System.Collections;
using System.Collections.Specialized;
using System.Data;
using System.Runtime.InteropServices;
using System.Text;
namespace IBM.Data.DB2
{
public class DB2Connection : System.ComponentModel.Component, IDbConnection, ICloneable
{
#region private data members
private ArrayList refCommands;
private WeakReference refTransaction;
private DB2ConnectionSettings connectionSettings = null;
private int connectionTimeout;
internal DB2OpenConnection openConnection;
private bool disposed = false;
#endregion
#region Constructors
public DB2Connection()
{
connectionTimeout = 15;
}
public DB2Connection(string conString)
{
SetConnectionString(conString);
}
#endregion
#region ConnectionString property
public string ConnectionString
{
get
{
return connectionSettings.ConnectionString;
}
set
{
SetConnectionString(value);
}
}
#endregion
#region ConnectionTimeout property
public int ConnectionTimeout
{
get
{
return connectionTimeout;
}
set
{
connectionTimeout = value;
}
}
#endregion
#region Database property
public string Database
{
get
{
return connectionSettings.DatabaseAlias;
}
}
#endregion
#region State property
unsafe public ConnectionState State
{
get
{
//if ((long)dbHandle.ToPointer() == DB2Constants.SQL_NULL_HANDLE)
if (openConnection == null)
return ConnectionState.Closed;
return ConnectionState.Open;
}
}
#endregion
#region events
public event DB2InfoMessageEventHandler InfoMessage;
public event StateChangeEventHandler StateChange;
internal void OnInfoMessage(short handleType, IntPtr handle)
{
if(InfoMessage != null)
{
// Don't get error information until we know for sure someone is listening
try
{
InfoMessage(this,
new DB2InfoMessageEventArgs(new DB2ErrorCollection(handleType, handle)));
}
catch(Exception)
{}
}
}
private void OnStateChange(StateChangeEventArgs args)
{
if(StateChange != null)
StateChange(this, args);
}
#endregion
#region DBHandle
internal IntPtr DBHandle
{
get
{
return (openConnection == null) ? IntPtr.Zero : openConnection.DBHandle;
}
}
#endregion
#region BeginTransaction Method
IDbTransaction IDbConnection.BeginTransaction()
{
return BeginTransaction();
}
IDbTransaction IDbConnection.BeginTransaction(IsolationLevel isolationL)
{
return BeginTransaction(isolationL);
}
public DB2Transaction BeginTransaction()
{
return BeginTransaction(IsolationLevel.ReadCommitted);
}
public DB2Transaction BeginTransaction(IsolationLevel isolationL)
{
if ((refTransaction != null) && (refTransaction.IsAlive))
throw new InvalidOperationException("Cannot open another transaction");
if(State != ConnectionState.Open)
throw new InvalidOperationException("BeginTransaction needs an open connection");
if(refTransaction != null)
{
if(refTransaction.IsAlive)
throw new InvalidOperationException("Parallel transactions not supported");
openConnection.RollbackDeadTransaction();
refTransaction = null;
}
openConnection.transactionOpen = true;
DB2Transaction tran = new DB2Transaction(this, isolationL);
refTransaction = new WeakReference(tran);
return tran;
}
#endregion
#region ChangeDatabase
unsafe public void ChangeDatabase(string newDBName)
{
if(connectionSettings == null)
{
throw new InvalidOperationException("No connection string");
}
this.Close();
SetConnectionString(connectionSettings.ConnectionString.Replace(connectionSettings.DatabaseAlias, newDBName));
this.Open();
}
#endregion
#region ReleaseObjectPool
public static void ReleaseObjectPool()
{
DB2Environment.Instance.Dispose();
}
#endregion
#region Close
public void Close()
{
DB2Transaction transaction = null;
if(refTransaction != null)
transaction = (DB2Transaction)refTransaction.Target;
if((transaction != null) && refTransaction.IsAlive)
{
transaction.Dispose();
}
if(refCommands != null)
{
for(int i = 0; i < refCommands.Count; i++)
{
DB2Command command = null;
if(refCommands[i] != null)
{
command = (DB2Command)((WeakReference)refCommands[i]).Target;
}
if((command != null) && ((WeakReference)refCommands[i]).IsAlive)
{
try
{
command.ConnectionClosed();
}
catch{}
}
//?? refCommands[i] = null;
}
}
if(openConnection != null)
{
openConnection.Close();
openConnection = null;
}
}
#endregion
#region CreateCommand
IDbCommand IDbConnection.CreateCommand()
{
return CreateCommand();
}
public DB2Command CreateCommand()
{
//CheckState();
return new DB2Command(null, this);
}
#endregion
#region Open
unsafe public void Open()
{
if(disposed)
{
throw new ObjectDisposedException("DB2Connection");
}
if (this.State == ConnectionState.Open || this.State == ConnectionState.Connecting || this.State == ConnectionState.Executing || this.State == ConnectionState.Fetching)
{
throw new InvalidOperationException("Connection already open");
}
try
{
openConnection = connectionSettings.GetRealOpenConnection(this);
}
catch (DB2Exception)
{
Close();
throw;
}
}
#endregion
#region Dispose
public new void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected override void Dispose(bool disposing)
{
if(!disposed)
{
if(disposing)
{
// dispose managed resources
Close();
}
}
base.Dispose(disposing);
disposed = true;
}
~DB2Connection()
{
Dispose(false);
}
#endregion
private void CheckState()
{
if (ConnectionState.Closed == State)
throw new InvalidOperationException("Connection is currently closed.");
}
void SetConnectionString (string connectionString)
{
if (State != ConnectionState.Closed)
throw new InvalidOperationException("Connection is not closed.");
this.connectionSettings = DB2ConnectionSettings.GetConnectionSettings(connectionString);
}
internal WeakReference WeakRefTransaction
{
get
{
return refTransaction;
}
set
{
refTransaction = value;
}
}
internal void AddCommand(DB2Command command)
{
if(refCommands == null)
{
refCommands = new ArrayList();
}
for(int i = 0; i < refCommands.Count; i++)
{
WeakReference reference = (WeakReference)refCommands[i];
if((reference == null) || !reference.IsAlive)
{
refCommands[i] = new WeakReference(command);
return;
}
}
refCommands.Add(new WeakReference(command));
}
internal void RemoveCommand(DB2Command command)
{
for(int i = 0; i < refCommands.Count; i++)
{
WeakReference reference = (WeakReference)refCommands[i];
if(object.ReferenceEquals(reference, command))
{
refCommands[i] = null;
return;
}
}
}
#region ICloneable Members
object ICloneable.Clone()
{
DB2Connection clone = new DB2Connection();
clone.connectionSettings = connectionSettings;
clone.connectionTimeout = connectionTimeout;
return clone;
}
#endregion
}
}

View File

@@ -0,0 +1,214 @@
//
// 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 System;
using System.Collections;
using System.Text;
using System.Threading;
namespace IBM.Data.DB2
{
/// <summary>
///
/// </summary>
/// <remarks>One connection pool per connectionstring</remarks>
internal sealed class DB2ConnectionPool
{
private ArrayList openFreeConnections; // list of pooled connections sorted by age. First connection is present at index 'connectionsUsableOffset'
private Queue openFreeMinimalAllocated;
private int connectionsOpen; // total number of connections open (in pool, an in use by application)
private int connectionsInUse; // total connection in use by application
private int connectionsUsableOffset; // Offset to the first pooled connection in 'openFreeConnections'
private Timer timer;
public string databaseProductName;
public string databaseVersion;
public int majorVersion;
public int minorVersion;
private DB2ConnectionSettings connectionSettings;
public DB2ConnectionPool(DB2ConnectionSettings connectionSettings)
{
this.connectionSettings = connectionSettings;
openFreeConnections = new ArrayList();
}
public DB2ConnectionSettings ConnectionSettings
{
get { return connectionSettings; }
}
public DB2OpenConnection GetOpenConnection(DB2Connection db2Conn)
{
DB2OpenConnection connection = null;
lock(openFreeConnections.SyncRoot)
{
if((connectionSettings.ConnectionPoolSizeMax > 0) &&
(connectionsOpen >= connectionSettings.ConnectionPoolSizeMax))
{
throw new ArgumentException("Maximum connections reached for connectionstring");
}
while(connectionsOpen > connectionsInUse)
{
connection = (DB2OpenConnection)openFreeConnections[openFreeConnections.Count - 1];
openFreeConnections.RemoveAt(openFreeConnections.Count - 1);
// check if connection is dead
int isDead;
short sqlRet = DB2CLIWrapper.SQLGetConnectAttr(connection.DBHandle, DB2Constants.SQL_ATTR_CONNECTION_DEAD, out isDead, 0, IntPtr.Zero);
if(((sqlRet == DB2Constants.SQL_SUCCESS_WITH_INFO) || (sqlRet == DB2Constants.SQL_SUCCESS)) &&
(isDead == DB2Constants.SQL_CD_FALSE))
{
connectionsInUse++;
break;
}
else
{
connectionsOpen--;
connection.Dispose();
connection = null;
}
}
if(connectionsOpen == connectionsInUse)
{
if(timer != null)
{
timer.Dispose();
timer = null;
}
}
}
if(connection == null)
{
openFreeConnections.Clear();
connectionsUsableOffset = 0;
connection = new DB2OpenConnection(connectionSettings, db2Conn);
connectionsOpen++;
connectionsInUse++;
}
return connection;
}
private void DisposeTimedoutConnections(object state)
{
lock(openFreeConnections.SyncRoot)
{
if(timer != null)
{
TimeSpan timeToDispose = TimeSpan.Zero;
DB2OpenConnection connection;
while(connectionsOpen > connectionsInUse)
{
connection = (DB2OpenConnection)openFreeConnections[connectionsUsableOffset];
timeToDispose = connection.poolDisposalTime.Subtract(DateTime.Now);
if((timeToDispose.Ticks < 0) || // time to die
(timeToDispose > connectionSettings.ConnectionLifeTime)) // messing with system clock
{
connection.Dispose();
openFreeConnections[connectionsUsableOffset] = null;
connectionsOpen--;
connectionsUsableOffset++;
}
else
{
break;
}
}
if(connectionsOpen > connectionsInUse)
{
connection = (DB2OpenConnection)openFreeConnections[connectionsUsableOffset];
timer.Change(timeToDispose, new TimeSpan(-1));
}
else
{
timer.Dispose();
timer = null;
}
}
if((connectionsUsableOffset > (openFreeConnections.Capacity / 2)) &&
(connectionsOpen > connectionsInUse))
{
openFreeConnections.RemoveRange(0, connectionsUsableOffset); // cleanup once in a while
connectionsUsableOffset = 0;
}
}
}
public void AddToFreeConnections(DB2OpenConnection connection)
{
lock(openFreeConnections.SyncRoot)
{
connection.poolDisposalTime = DateTime.Now.Add(connectionSettings.ConnectionLifeTime);
if(timer == null)
{
timer = new Timer(new TimerCallback(DisposeTimedoutConnections), null,
connectionSettings.ConnectionLifeTime, new TimeSpan(-1));
}
connectionsInUse--;
openFreeConnections.Add(connection);
}
}
public void OpenConnectionFinalized()
{
lock(openFreeConnections.SyncRoot)
{
connectionsOpen--;
connectionsInUse--;
}
}
/// <summary>
/// Find a specific connection pool
/// </summary>
/// <param name="connectionString"></param>
/// <returns></returns>
static public DB2ConnectionPool FindConnectionPool(string connectionString)
{
return (DB2ConnectionPool)DB2Environment.Instance.connectionPools[connectionString];
}
/// <summary>
/// Get a connection pool. If it doesn't exist yet, create it
/// </summary>
/// <param name="connectionSettings"></param>
/// <returns></returns>
static public DB2ConnectionPool GetConnectionPool(DB2ConnectionSettings connectionSettings)
{
DB2Environment environment = DB2Environment.Instance;
lock(environment.connectionPools.SyncRoot)
{
DB2ConnectionPool pool = (DB2ConnectionPool)environment.connectionPools[connectionSettings.ConnectionString];
if(pool == null)
{
pool = new DB2ConnectionPool(connectionSettings);
environment.connectionPools.Add(connectionSettings.ConnectionString, pool);
}
return pool;
}
}
}
}

View File

@@ -0,0 +1,202 @@
//
// 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 System;
using System.Runtime.InteropServices;
using System.Text;
namespace IBM.Data.DB2
{
internal sealed class DB2ConnectionSettings
{
private string connectionString;
private string userName = "";
private string passWord = "";
private string databaseAlias = "";
private string server = "";
private bool pooling = true;
private TimeSpan connectTimeout = new TimeSpan(0, 0, 15);
private TimeSpan connectionLifeTime = new TimeSpan(0, 0, 15); // 15 seconds
private int connectionPoolSizeMin = 0;
private int connectionPoolSizeMax = -1; // no maximum
private DB2ConnectionPool pool;
private DB2ConnectionSettings(string connectionString)
{
this.connectionString = connectionString;
this.Parse();
}
public static DB2ConnectionSettings GetConnectionSettings(string connectionString)
{
DB2ConnectionPool pool = DB2ConnectionPool.FindConnectionPool(connectionString);
if(pool != null)
{
return pool.ConnectionSettings;
}
DB2ConnectionSettings settings = new DB2ConnectionSettings(connectionString);
if(settings.Pooling)
{
settings.pool = DB2ConnectionPool.GetConnectionPool(settings);
}
return settings;
}
public DB2OpenConnection GetRealOpenConnection(DB2Connection connection)
{
if(pool != null)
{
return pool.GetOpenConnection(connection);
}
else
{
return new DB2OpenConnection(this, connection);
}
}
public DB2ConnectionPool Pool
{
get { return pool; }
}
public string ConnectionString
{
get { return connectionString; }
}
public string UserName
{
get { return userName; }
}
public string PassWord
{
get { return passWord; }
}
/// <summary>
/// database alias (for cataloged database)
/// </summary>
public string DatabaseAlias
{
get { return databaseAlias; }
}
/// <summary>
/// server name with optional port number for direct connection (<server name/ip address>[:<port>])
/// </summary>
public string Server
{
get { return server; }
}
public TimeSpan ConnectTimeout
{
get { return connectTimeout; }
}
/// <summary>
/// Connection pooling yes/no
/// </summary>
public bool Pooling
{
get { return pooling; }
}
public int ConnectionPoolSizeMin
{
get { return connectionPoolSizeMin; }
}
public int ConnectionPoolSizeMax
{
get { return connectionPoolSizeMin; }
}
public TimeSpan ConnectionLifeTime
{
get { return connectionLifeTime; }
}
/// <summary>
/// parsed according to IBM DB2 .NET data provider help
/// </summary>
public void Parse()
{
string[] parts = connectionString.Split(new char[]{';'});
foreach(string part in parts)
{
string[] pairs = part.Split(new char[]{'='});
switch(pairs[0].ToLower())
{
case "database":
case "dsn":
databaseAlias = pairs[1];
break;
case "uid":
case "user id":
userName = pairs[1];
break;
case "pwd":
case "password":
passWord = pairs[1];
break;
case "server":
server = pairs[1];
break;
case "pooling":
pooling = (pairs[1].ToLower() == "true") || (pairs[1]== "1");
break;
case "connect timeout":
case "timeout":
case "connection timeout":
connectTimeout = new TimeSpan(0, 0, int.Parse(pairs[1]));
break;
case "min pool size":
connectionPoolSizeMin = int.Parse(pairs[1]);
break;
case "max pool size":
connectionPoolSizeMax = int.Parse(pairs[1]);
break;
case "connection lifetime":
connectionLifeTime = new TimeSpan(0, 0, int.Parse(pairs[1]));
break;
}
}
if(connectionLifeTime.Ticks <= 0)
{
pooling = false;
}
}
public override int GetHashCode()
{
return connectionString.GetHashCode ();
}
public override bool Equals(object obj)
{
return connectionString.Equals (obj);
}
}
}

View File

@@ -0,0 +1,208 @@
//
// 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 System;
namespace IBM.Data.DB2
{
/// <summary>
/// Summary description for DB2Constants.
/// </summary>
internal sealed class DB2Constants
{
public const short SQL_HANDLE_ENV = 1;
public const short SQL_HANDLE_DBC = 2;
public const short SQL_HANDLE_STMT = 3;
public const short SQL_HANDLE_DESC = 4;
/* RETCODE values */
public const short SQL_SUCCESS = 0;
public const short SQL_SUCCESS_WITH_INFO = 1;
public const short SQL_NEED_DATA = 99;
public const short SQL_NO_DATA = 100;
public const short SQL_STILL_EXECUTING = 2;
public const short SQL_ERROR = -1;
public const short SQL_INVALID_HANDLE = -2;
public const int SQL_NTS = -3;
public const long SQL_NULL_HANDLE = 0L;
public const short SQL_COMMIT = 0;
public const short SQL_ROLLBACK = 1;
public const short SQL_NO_DATA_FOUND = 100;
/* SQLFreeStmt option values */
public const short SQL_CLOSE = 0;
public const short SQL_DROP = 1;
public const short SQL_UNBIND = 2;
public const short SQL_RESET_PARAMS = 3;
/* Isolation levels */
public const long SQL_TXN_READ_UNCOMMITTED = 0x00000001L;
public const long SQL_TXN_READ_COMMITTED = 0x00000002L;
public const long SQL_TXN_REPEATABLE_READ = 0x00000004L;
public const long SQL_TXN_SERIALIZABLE_READ = 0x00000008L;
public const long SQL_TXN_NOCOMMIT = 0x00000020L;
/* Connect options */
public const int SQL_ATTR_TXN_ISOLATION= 108;
public const int SQL_ATTR_AUTOCOMMIT = 102;
/* attribute */
public const int SQL_ATTR_ANSI_APP = 115;
public const int SQL_AA_TRUE = 1; /* the application is an ANSI app */
public const int SQL_AA_FALSE = 0; /* the application is a Unicode app */
public const int SQL_ATTR_CONNECTION_DEAD = 1209; /* GetConnectAttr only */
public const int SQL_CD_TRUE = 1; /* the connection is dead */
public const int SQL_CD_FALSE = 0; /* the connection is not dead */
public const int SQL_ATTR_QUERY_TIMEOUT = 0;
public const int SQL_ATTR_MAX_ROWS = 1;
public const int SQL_ATTR_DEFERRED_PREPARE = 1277;
/*Used for batch operations*/
public const int SQL_ATTR_PARAMSET_SIZE = 22;
public const int SQL_ATTR_PARAM_STATUS_PTR = 20;
public const int SQL_ATTR_PARAMS_PROCESSED_PTR = 21;
public const int SQL_ATTR_PARAM_BIND_TYPE = 18;
public const int SQL_IS_POINTER = -4;
public const int SQL_IS_UINTEGER = -5;
public const int SQL_IS_INTEGER = -6;
public const int SQL_IS_USMALLINT = -7;
public const int SQL_IS_SMALLINT = -8;
public const long SQL_AUTOCOMMIT_OFF = 0L;
public const long SQL_AUTOCOMMIT_ON = 1L;
/* Data Types */
public const int SQL_UNKNOWN_TYPE = 0;
public const int SQL_CHAR = 1;
public const int SQL_NUMERIC = 2;
public const int SQL_DECIMAL = 3;
public const int SQL_INTEGER = 4;
public const int SQL_SMALLINT = 5;
public const int SQL_FLOAT = 6;
public const int SQL_REAL = 7;
public const int SQL_DOUBLE = 8;
public const int SQL_DATETIME = 9;
public const int SQL_VARCHAR = 12;
public const int SQL_VARBINARY = (-3);
public const int SQL_LONGVARBINARY = (-4);
public const int SQL_BIGINT = (-5);
public const int SQL_BIT = (-7);
public const int SQL_WCHAR = (-8);
public const int SQL_WVARCHAR = (-9);
public const int SQL_WLONGVARCHAR = (-10);
public const int SQL_GUID = (-11);
public const int SQL_UTINYINT = (-28);
public const int SQL_TYPE_DATE = 91;
public const int SQL_TYPE_TIME = 92;
public const int SQL_TYPE_TIMESTAMP = 93;
public const int SQL_TYPE_BINARY = -2;
public const int SQL_GRAPHIC = -95;
public const int SQL_VARGRAPHIC = -96;
public const int SQL_LONGVARGRAPHIC = -97;
public const int SQL_TYPE_BLOB = -98;
public const int SQL_TYPE_CLOB = -99;
public const int SQL_DBCLOB = 350;
public const int SQL_C_CHAR = SQL_CHAR;
public const int SQL_C_WCHAR = SQL_WCHAR;
public const int SQL_C_SBIGINT = -25;
public const int SQL_C_SLONG = -16;
public const int SQL_C_SSHORT = -15;
public const int SQL_C_TYPE_BINARY = -2;
public const int SQL_C_DOUBLE = 8;
public const int SQL_C_DECIMAL_IBM = 3;
public const int SQL_C_DECIMAL_OLEDB = 2514;
public const int SQL_C_DEFAULT = 99;
public const int SQL_C_TYPE_DATE = 91;
public const int SQL_C_TYPE_TIME = 92;
public const int SQL_C_TYPE_TIMESTAMP = 93;
public const int SQL_C_TYPE_NUMERIC = 2;
public const int SQL_C_TYPE_REAL = 7;
public const int SQL_BLOB_LOCATOR = 31;
public const int SQL_CLOB_LOCATOR = 41;
public const int SQL_DBCLOB_LOCATOR = -351;
public const int SQL_C_BLOB_LOCATOR = SQL_BLOB_LOCATOR;
public const int SQL_C_CLOB_LOCATOR = SQL_CLOB_LOCATOR;
public const int SQL_C_DBCLOB_LOCATOR = SQL_DBCLOB_LOCATOR;
public const int SQL_USER_DEFINED_TYPE = (-450);
/* Special length values */
public const int SQL_NULL_DATA = -1;
/* SQLDriverConnect Options */
public const int SQL_DRIVER_NOPROMPT = 0;
public const int SQL_DRIVER_COMPLETE = 1;
public const int SQL_DRIVER_PROMPT = 2;
public const int SQL_DRIVER_COMPLETE_REQUIRED = 3;
/* Null settings */
public const int SQL_NO_NULLS = 0;
public const int SQL_NULLABLE = 1;
public const int SQL_NULLABLE_UNKNOWN = 2;
public const int SQL_PARAM_BIND_BY_COLUMN = 0;
/* Defines for SQLBindParameter and SQLProcedureColumns */
public const int SQL_PARAM_TYPE_UNKNOWN = 0;
public const int SQL_PARAM_INPUT = 1;
public const int SQL_PARAM_INPUT_OUTPUT = 2;
public const int SQL_RESULT_COL = 3;
public const int SQL_PARAM_OUTPUT = 4;
public const int SQL_RETURN_VALUE = 5;
/*Defines for SQLColAttributeW*/
public const int SQL_DESC_ALLOC_TYPE = 1099;
public const int SQL_DESC_AUTO_UNIQUE_VALUE = 11;
public const int SQL_DESC_BASE_COLUMN_NAME = 22;
public const int SQL_DESC_BASE_TABLE_NAME = 23;
public const int SQL_DESC_COLUMN_CATALOG_NAME = 17;
public const int SQL_DESC_COLUMN_NAME = 1;
public const int SQL_DESC_SCHEMA_NAME = 16;
public const int SQL_DESC_COLUMN_TABLE_NAME = 15;
public const int SQL_DESC_CONCISE_TYPE = 2;
public const int SQL_DESC_COUNT = 1001;
public const int SQL_DESC_DATA_PTR = 1010;
public const int SQL_DESC_DATETIME_INTERVAL_CODE = 1007;
public const int SQL_DESC_INDICATOR_PTR = 1009;
public const int SQL_DESC_LENGTH = 1003;
public const int SQL_DESC_NAME = 1011;
public const int SQL_DESC_NULLABLE = 1008;
public const int SQL_DESC_OCTET_LENGTH = 1013;
public const int SQL_DESC_OCTET_LENGTH_PTR = 1004;
public const int SQL_DESC_PRECISION = 1005;
public const int SQL_DESC_SCALE = 1006;
public const int SQL_DESC_TYPE = 1002;
public const int SQL_DESC_TYPE_NAME = 14;
public const int SQL_DESC_UNNAMED = 1012;
public const int SQL_DESC_UNSIGNED = 8;
public const int SQL_DESC_UPDATABLE = 10;
}
}

View File

@@ -0,0 +1,184 @@
//
// 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 System;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
namespace IBM.Data.DB2 {
public sealed class DB2DataAdapter : DbDataAdapter, IDbDataAdapter
{
#region Fields
bool disposed = false;
DB2Command deleteCommand;
DB2Command insertCommand;
DB2Command selectCommand;
DB2Command updateCommand;
#endregion
#region Constructors
public DB2DataAdapter ()
: this (new DB2Command ())
{
}
public DB2DataAdapter (DB2Command selectCommand)
{
DeleteCommand = null;
InsertCommand = null;
SelectCommand = selectCommand;
UpdateCommand = null;
}
public DB2DataAdapter (string selectCommandText, DB2Connection selectConnection)
: this (new DB2Command (selectCommandText, selectConnection))
{
}
public DB2DataAdapter (string selectCommandText, string selectConnectionString)
: this (selectCommandText, new DB2Connection (selectConnectionString))
{
}
#endregion
#region Properties
public DB2Command DeleteCommand {
get { return deleteCommand; }
set { deleteCommand = value; }
}
public DB2Command InsertCommand {
get { return insertCommand; }
set { insertCommand = value; }
}
public DB2Command SelectCommand {
get { return selectCommand; }
set { selectCommand = value; }
}
public DB2Command UpdateCommand {
get { return updateCommand; }
set { updateCommand = value; }
}
IDbCommand IDbDataAdapter.DeleteCommand {
get { return DeleteCommand; }
set {
if (!(value is DB2Command))
throw new ArgumentException ();
DeleteCommand = (DB2Command)value;
}
}
IDbCommand IDbDataAdapter.InsertCommand {
get { return InsertCommand; }
set {
if (!(value is DB2Command))
throw new ArgumentException ();
InsertCommand = (DB2Command)value;
}
}
IDbCommand IDbDataAdapter.SelectCommand {
get { return SelectCommand; }
set {
if (!(value is DB2Command))
throw new ArgumentException ();
SelectCommand = (DB2Command)value;
}
}
IDbCommand IDbDataAdapter.UpdateCommand {
get { return UpdateCommand; }
set {
if (!(value is DB2Command))
throw new ArgumentException ();
UpdateCommand = (DB2Command)value;
}
}
ITableMappingCollection IDataAdapter.TableMappings {
get { return TableMappings; }
}
#endregion
#region Methods
protected override RowUpdatedEventArgs CreateRowUpdatedEvent (DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping)
{
return new DB2RowUpdatedEventArgs (dataRow, command, statementType, tableMapping);
}
protected override RowUpdatingEventArgs CreateRowUpdatingEvent (DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping)
{
return new DB2RowUpdatingEventArgs (dataRow, command, statementType, tableMapping);
}
protected override void Dispose (bool disposing)
{
if (!disposed) {
if (disposing) {
}
disposed = true;
}
}
protected override void OnRowUpdated (RowUpdatedEventArgs value)
{
if (RowUpdated != null)
RowUpdated (this, (DB2RowUpdatedEventArgs) value);
}
protected override void OnRowUpdating (RowUpdatingEventArgs value)
{
if (RowUpdating != null)
RowUpdating (this, (DB2RowUpdatingEventArgs) value);
}
#endregion
#region Events and Delegates
public event DB2RowUpdatedEventHandler RowUpdated;
public event DB2RowUpdatingEventHandler RowUpdating;
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,91 @@
//
// 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 System;
using System.Collections;
namespace IBM.Data.DB2
{
internal sealed class DB2Environment : IDisposable
{
volatile static DB2Environment environment;
static readonly object lockobj = new object ();
internal Hashtable connectionPools;
internal IntPtr penvHandle = IntPtr.Zero;
private DB2Environment()
{
connectionPools = Hashtable.Synchronized(new Hashtable());
// short sqlRet = DB2CLIWrapper.SQLAllocHandle(DB2Constants.SQL_HANDLE_ENV, IntPtr.Zero, ref penvHandle);
short sqlRet = DB2CLIWrapper.Initialize(ref penvHandle);
DB2ClientUtils.DB2CheckReturn(sqlRet, 0, IntPtr.Zero, "Unable to allocate Environment handle.", null);
// SQLSetEnvAttr( hEnv=0:1, fAttribute=SQL_ATTR_APP_TYPE 2473, vParam=4, cbParam=0 ) // 4=ADO.NET apptype????
// SQLSetEnvAttr( hEnv=0:1, fAttribute=SQL_ATTR_OUTPUT_NTS 10001, vParam=0, cbParam=0 ) // strings not 0-terminated
}
public static DB2Environment Instance
{
get
{
if(environment == null)
{
lock(lockobj)
{
if(environment == null)
{
environment = new DB2Environment();
}
}
}
return environment;
}
}
#region IDisposable Members
bool disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void Dispose(bool disposing)
{
if(disposed)
{
DB2CLIWrapper.SQLFreeHandle(DB2Constants.SQL_HANDLE_ENV, penvHandle);
environment = null;
}
disposed = true;
}
~DB2Environment()
{
Dispose(false);
}
#endregion
}
}

View File

@@ -0,0 +1,62 @@
//
// 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 System;
using System.Runtime.InteropServices;
using System.Text;
namespace IBM.Data.DB2
{
public sealed class DB2Error
{
string message;
string state;
int nativeerror;
internal DB2Error(string message, string state, int nativeerror)
{
this.message = message;
this.state = state;
this.nativeerror = nativeerror;
}
public override string ToString()
{
return Message;
}
public string Message
{
get { return message; }
}
public int NativeError
{
get { return nativeerror; }
}
public string Source
{
get { return "IBM.Data.DB2"; }
}
public string SQLState
{
get { return state; }
}
}
}

View File

@@ -0,0 +1,132 @@
//
// 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 System;
using System.Collections;
using System.Text;
namespace IBM.Data.DB2
{
[Serializable()]
public class DB2ErrorCollection : CollectionBase
{
public DB2ErrorCollection(short sqlHandleType, IntPtr sqlHandle)
{
StringBuilder sqlState = new StringBuilder(10);
StringBuilder errorMessage = new StringBuilder(1025);
int sqlReturn;
short recNum=1;
do
{
int nativeError;
short errorMessageLength;
sqlReturn = DB2CLIWrapper.SQLGetDiagRec(sqlHandleType, sqlHandle, recNum++, sqlState, out nativeError, errorMessage, errorMessage.Capacity - 1, out errorMessageLength);
if(sqlReturn == 0)
{
Add(new DB2Error(errorMessage.ToString(), sqlState.ToString(), nativeError));
}
}
while (sqlReturn == 0);
}
public DB2Error this[int index]
{
get
{
return ((DB2Error)(List[index]));
}
}
internal int Add(DB2Error value)
{
return List.Add(value);
}
public void CopyTo(DB2Error[] array, int index)
{
List.CopyTo(array, index);
}
/// <summary>
/// <para>Returns an enumerator that can iterate through
/// the <see cref='d.DB2ErrorCollection'/> .</para>
/// </summary>
/// <returns><para>None.</para></returns>
/// <seealso cref='System.Collections.IEnumerator'/>
public new DB2ErrorEnumerator GetEnumerator()
{
return new DB2ErrorEnumerator(this);
}
public class DB2ErrorEnumerator : object, IEnumerator
{
private IEnumerator baseEnumerator;
private IEnumerable temp;
public DB2ErrorEnumerator(DB2ErrorCollection mappings)
{
this.temp = ((IEnumerable)(mappings));
this.baseEnumerator = temp.GetEnumerator();
}
public DB2Error Current
{
get
{
return ((DB2Error)(baseEnumerator.Current));
}
}
object IEnumerator.Current
{
get
{
return baseEnumerator.Current;
}
}
public bool MoveNext()
{
return baseEnumerator.MoveNext();
}
bool IEnumerator.MoveNext()
{
return baseEnumerator.MoveNext();
}
public void Reset()
{
baseEnumerator.Reset();
}
void IEnumerator.Reset()
{
baseEnumerator.Reset();
}
}
}
}

View File

@@ -0,0 +1,87 @@
//
// 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 System;
using System.Runtime.InteropServices;
using System.Text;
using System.Runtime.Serialization;
namespace IBM.Data.DB2
{
[Serializable]
public sealed class DB2Exception : Exception
{
private DB2ErrorCollection errors;
private string message;
public DB2ErrorCollection Errors
{
get
{
return errors;
}
}
public override string Message
{
get
{
if(errors.Count > 0)
{
string result = "";
for(int i = 0; i < errors.Count; i++)
{
if(i > 0)
{
result += " ";
}
result += "ERROR [" + errors[i].SQLState + "] " + errors[i].Message;
}
if(message != null)
{
result += " " + message;
}
return result;
}
return "No error information";
}
}
private DB2Exception(SerializationInfo si, StreamingContext sc)
{
throw new NotImplementedException();
}
public override void GetObjectData(SerializationInfo si, StreamingContext context)
{
throw new NotImplementedException();
}
internal DB2Exception(short sqlHandleType, IntPtr sqlHandle, string message)
{
this.message = message;
errors = new DB2ErrorCollection(sqlHandleType, sqlHandle);
}
}
}

View File

@@ -0,0 +1,69 @@
//
// 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 System;
using System.Data;
using System.Runtime.InteropServices;
namespace IBM.Data.DB2
{
public delegate void DB2InfoMessageEventHandler(object sender, DB2InfoMessageEventArgs e);
public sealed class DB2InfoMessageEventArgs : EventArgs
{
private DB2ErrorCollection errors;
public DB2InfoMessageEventArgs(DB2ErrorCollection errors)
{
this.errors = errors;
}
public DB2ErrorCollection Errors
{
get
{
return errors;
}
}
public string Message
{
get
{
if(errors.Count > 0)
{
string result = "";
for(int i = 0; i < errors.Count; i++)
{
if(i > 0)
{
result += " ";
}
result += "INFO [" + errors[i].SQLState + "] " + errors[i].Message;
}
return result;
}
return "No information";
}
}
}
}

View File

@@ -0,0 +1,211 @@
//
// 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 System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
namespace IBM.Data.DB2
{
internal sealed class DB2OpenConnection : IDisposable
{
private IntPtr dbHandle = IntPtr.Zero;
private DB2ConnectionSettings settings;
private bool disposed = false;
internal DateTime poolDisposalTime; // time to live used for disposal of connections in the connection pool
public bool transactionOpen;
public bool autoCommit = true;
private string databaseProductName;
private string databaseVersion;
private int majorVersion;
private int minorVersion;
public IntPtr DBHandle
{
get { return dbHandle; }
}
public string DatabaseProductName
{
get { return databaseProductName; }
}
public string DatabaseVersion
{
get { return databaseVersion; }
}
public int MajorVersion
{
get { return majorVersion; }
}
public int MinorVersion
{
get { return minorVersion; }
}
public DB2OpenConnection(DB2ConnectionSettings settings, DB2Connection connection)
{
this.settings = settings;
try
{
short sqlRet = DB2CLIWrapper.SQLAllocHandle(DB2Constants.SQL_HANDLE_DBC, DB2Environment.Instance.penvHandle, out dbHandle);
DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_DBC, DB2Environment.Instance.penvHandle, "Unable to allocate database handle in DB2Connection.", connection);
if(settings.Server.Length > 0)
{
StringBuilder outConnectStr = new StringBuilder(60); // TODO: ????
short numOutCharsReturned;
sqlRet = DB2CLIWrapper.SQLDriverConnect(dbHandle, IntPtr.Zero,
settings.ConnectionString, (short)settings.ConnectionString.Length,
outConnectStr, (short)outConnectStr.Length, out numOutCharsReturned,
DB2Constants.SQL_DRIVER_NOPROMPT /*SQL_DRIVER_COMPLETE*/);
}
else
{
sqlRet = DB2CLIWrapper.SQLConnect(dbHandle,
settings.DatabaseAlias, (short)settings.DatabaseAlias.Length,
settings.UserName, (short)settings.UserName.Length,
settings.PassWord, (short)settings.PassWord.Length);
DB2ClientUtils.DB2CheckReturn(sqlRet, DB2Constants.SQL_HANDLE_DBC, dbHandle, "Unable to connect to the database.", connection);
}
if((settings.Pool == null) || (settings.Pool.databaseProductName == null))
{
StringBuilder sb = new StringBuilder(256);
short stringLength;
sqlRet = DB2CLIWrapper.SQLGetInfo(dbHandle, /*SQL_DBMS_NAME*/17, sb, (short)(sb.Capacity / 2), out stringLength);
new DB2ErrorCollection(DB2Constants.SQL_HANDLE_DBC, dbHandle).ToString();
if(sqlRet == 0)
databaseProductName = sb.ToString(0, Math.Min(sb.Capacity, stringLength / 2));
sqlRet = DB2CLIWrapper.SQLGetInfo(dbHandle, /*SQL_DBMS_VER*/18, sb, (short)(sb.Capacity / 2), out stringLength);
if(sqlRet == 0)
{
databaseVersion = sb.ToString(0, Math.Min(sb.Capacity, stringLength / 2));
try
{
string[] splitVersion = databaseVersion.Split('.');
majorVersion = int.Parse(splitVersion[0]);
minorVersion = int.Parse(splitVersion[1]);
}
catch{}
}
if(settings.Pool != null)
{
settings.Pool.databaseProductName = databaseProductName;
settings.Pool.databaseVersion = databaseVersion;
settings.Pool.majorVersion = majorVersion;
settings.Pool.minorVersion = minorVersion;
}
}
else if(settings.Pool != null)
{
if(settings.Pool != null)
{
databaseProductName = settings.Pool.databaseProductName;
databaseVersion = settings.Pool.databaseVersion;
majorVersion = settings.Pool.majorVersion;
minorVersion = settings.Pool.minorVersion;
}
}
}
catch
{
if(dbHandle != IntPtr.Zero)
{
DB2CLIWrapper.SQLFreeHandle(DB2Constants.SQL_HANDLE_DBC, dbHandle);
dbHandle = IntPtr.Zero;
}
throw;
}
}
public void RollbackDeadTransaction()
{
DB2CLIWrapper.SQLEndTran(DB2Constants.SQL_HANDLE_DBC, DBHandle, DB2Constants.SQL_ROLLBACK);
transactionOpen = false;
}
public void Close()
{
if(transactionOpen)
RollbackDeadTransaction();
if(settings.Pool != null)
{
settings.Pool.AddToFreeConnections(this);
}
else
{
Dispose();
}
}
private void FreeHandles()
{
if(dbHandle != IntPtr.Zero)
{
short sqlRet = DB2CLIWrapper.SQLDisconnect(dbHandle);
// Note that SQLDisconnect() automatically drops any statements and
// descriptors open on the connection.
sqlRet = DB2CLIWrapper.SQLFreeHandle(DB2Constants.SQL_HANDLE_DBC, dbHandle);
dbHandle = IntPtr.Zero;
}
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if(!disposed)
{
if(disposing)
{
// dispose managed resources
}
FreeHandles();
}
disposed = true;
}
~DB2OpenConnection()
{
if(settings.Pool != null)
{
settings.Pool.OpenConnectionFinalized();
}
Dispose(false);
}
#endregion
}
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More