211 lines
6.2 KiB
C#
211 lines
6.2 KiB
C#
|
|
//
|
|
// 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
|
|
}
|
|
|
|
|
|
} |