2025-11-28 00:35:46 +09:00

415 lines
17 KiB
C++

//--------------------------------------------------------------------
// Microsoft OLE DB Test
//
// Copyright 1995-2000 Microsoft Corporation.
//
// @doc
//
// @module TXNBASE.HPP | Base classes for transacted rowsets.
//
// @rev 01 | 02-04-96 | Microsoft | Created
// @rev 02 | 12-01-96 | Microsoft | Updated
//
#include "oledb.h" // OLE DB Header Files
#include "oledberr.h"
#include "transact.h"
#include "privlib.h" //Include private library, which includes
#include "msdasql.h" //Kagera specific header file
//--------------------------------------------------------------------
//Externs Defined in TxnBase.cpp
//--------------------------------------------------------------------
extern ULONG g_ulLastActualDelete;
extern ULONG g_ulLastActualInsert;
extern ULONG g_ulFirstRowInTable;
extern void g_DeleteAndInsertIncrement();
extern void g_InsertIncrement();
extern void g_DeleteIncrement();
enum EASYNC
{
EASYNCTRUE,
EASYNCFALSE,
EASYNCNOTSUPPORTED
};
enum ePrptIdx
{
IDX_CommitPreserve=0,
IDX_AbortPreserve,
IDX_OtherUpdateDelete,
IDX_OtherInsert,
IDX_CommandTimeout,
IDX_IRowsetUpdate,
IDX_IRowsetChange
};
const ULONG g_PROPERTY_COUNT = IDX_IRowsetChange+1;
typedef struct tagDBPrptRecord
{
DBPROPID dwPropID;
BOOL fSupported;
VARIANT_BOOL fDefault;
DBPROPFLAGS dwFlags;
BOOL fProviderSupported;
}DBPrptRecord;
extern DBPrptRecord g_rgDBPrpt[g_PROPERTY_COUNT];
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Defines
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//Use a value not valid for DBPROP_SUPPORTEDTXNDDL to represent that it is not a supported property
#define NOT_SUPPORTED DBPROPVAL_TC_NONE | DBPROPVAL_TC_DML | DBPROPVAL_TC_DDL_COMMIT | DBPROPVAL_TC_DDL_IGNORE | DBPROPVAL_TC_ALL
//Number of milliseconds need to wait before Jet refreshes to recognize changes
//There is supposedly only a 2 second lag time in Jet, but wait 5 seconds just to be sure
#define SLEEP_TIME 7000
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Base Class Declarations
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//--------------------------------------------------------------------
// @class CTxnRowset | Transactable rowset to be encapsulated by CTxn
// @base public | CRowsetObject
//--------------------------------------------------------------------
class CTxnRowset : public CRowsetObject
{
// @access public
public:
//@cmember Transaction Local interface for this session
ITransactionLocal *m_pITxnLocal;
//#ifdef TXNJOIN
//@cmember Transaction Join interface for this session
ITransactionJoin *m_pITxnJoin;
//#endif//TXNJOIN
//@cmember Transaction Join interface for this session
CTable *m_pCTable;
//@cmember Count of bindings for GetData
DBCOUNTITEM m_cReadBindings;
//@cmember Array of bindings for GetData
DBBINDING *m_rgReadBindings;
//@cmember Accessor for GetData
HACCESSOR m_hReadAccessor;
//@cmember Row size for GetData
DBLENGTH m_cbReadRowSize;
//@cmember Flag indicating whether rowset is preserved on abort
BOOL m_fAbortPreserve;
//@cmember Flag indicating whether rowset is preserved on commit
BOOL m_fCommitPreserve;
//@cmember Flag indicating what DDL is supported in TXNS
DWORD m_fDDLBehavior;
//NOTE: We use enums for these values so we can have a NOT SUPPORTED
//value (in addition to valid BOOL values) which we check
//in individual test cases later on.
//@cmember Flag indicating whether async commit is supported
EASYNC m_eAsyncCommit;
//@cmember Flag indicating Async Abort support
EASYNC m_eAsyncAbort;
//@cmember CTOR
CTxnRowset(LPWSTR tcName);
//@cmember Initialization
virtual BOOL Init();
//@cmember Termination
virtual BOOL Terminate();
//@cmember Sets the session's autocommit isolation level
HRESULT SetAutoCommitIsoLevel(ULONG IsoLevel);
//@cmember Function to create the rowset and release any property error memory
virtual HRESULT MakeRowset();
//@cmember Function to create the rowset and release any property error memory
virtual HRESULT MakeRowsetReadOnly();
//@cmember Pure virtual function to set the properties to
//generate the correct rowset on CreateRowsetObject
virtual BOOL SetTxnRowsetProperties() = 0;
//@cmember Finds a row and optionally returns the hRow for that row
BOOL FindRow(ULONG ulRowNum, HROW * hRow);
//@cmember Commits current txn, fNewUnitOfWork sets whether
//a new transaction is started, or we revert to autocommit mode.
//fPreserveRowset sets whether or not the rowset is kept after the commit.
virtual HRESULT Commit(BOOL fPreserveRowset = FALSE, BOOL fNewUnitOfWork = FALSE);
//@cmember Aborts current txn, fNewUnitOfWork sets whether
//a new transaction is started, or we revert to autocommit mode.
//fPreserveRowset sets whether or not the rowset is kept after the abort.
virtual HRESULT Abort(BOOL fPreserveRowset = FALSE, BOOL fNewUnitOfWork = FALSE);
//@cmember Commits current txn, fNewUnitOfWork sets whether
//a new transaction is started, or we revert to autocommit mode.
//fPreserveRowset sets whether or not the rowset is kept after the commit.
//#ifdef TXNJOIN
virtual HRESULT CommitCoord(BOOL fNewUnitOfWork = FALSE, ITransaction *pITransaction = NULL,ITransactionJoin *pITransactionJoin=NULL);
//@cmember Aborts current txn, fNewUnitOfWork sets whether
//a new transaction is started, or we revert to autocommit mode.
//fPreserveRowset sets whether or not the rowset is kept after the abort.
virtual HRESULT AbortCoord(BOOL fNewUnitOfWork = FALSE, ITransaction *pITransaction = NULL,ITransactionJoin *pITransactionJoin=NULL);
//@cmember Dummy necessary virtual function needed to
//instantiate since we inherit from CTestCases
//#endif//TXNJOIN
inline void *GetVarInfo(const long){return (void *)NULL; }
//@cmember Dummy necessary virtual function needed to
//instantiate since we inherit from CTestCases
inline const WCHAR *GetCaseDesc(void){return (const WCHAR *)NULL; }
};
//--------------------------------------------------------------------
// @class CTxnRORowset | Transactable Read Only rowset
// @base public | CTxnRowset
//--------------------------------------------------------------------
class CTxnRORowset : public CTxnRowset
{
// @access public
public:
//@cmember CTOR
CTxnRORowset(LPWSTR tcName) : CTxnRowset(tcName){};
//@cmember Initialization - Creates a read only rowset
virtual BOOL Init();
//@cmember Cleans up read only rowset
virtual BOOL Terminate();
//@cmember Sets the properties to generate the correct rowset on CreateRowsetObject
virtual BOOL SetTxnRowsetProperties();
};
//--------------------------------------------------------------------
// @class CTxnChgRowset | Transactable updateable rowset
// @base public | CTxnRowset
//--------------------------------------------------------------------
class CTxnChgRowset : public CTxnRowset
{
// @access public
public:
//@cmember Whether or not to bind long data. By default false
BLOBTYPE m_fBindLongData;
//@cmember Whether or not this provider supports IRowsetChange
BOOL m_fChange;
//@cmember Whether or not this provider supports IRowsetUpdate
BOOL m_fUpdate;
//@cmember Count of updateable columns, to be used for NewRow and Change
DBORDINAL m_cUpdateableCols;
//@cmember Array of updateable columns, to be used for NewRow and Change
DBORDINAL *m_rgUpdateableCols;
//@cmember Count of bindings for NewRow and Change
DBORDINAL m_cUpdateBindings;
//@cmember Array of bindings for NewRow and Change
DBBINDING *m_rgUpdateBindings;
//@cmember Accessor for NewRow and Change
HACCESSOR m_hUpdateAccessor;
//@cmember Row size for NewRow and Change
DBLENGTH m_cbUpdateRowSize;
//@cmember Flag checked at commit time, to determine if an insert
//has been committed.
BOOL m_fTxnPendingInsert;
//@cmember Flag checked at commit time, to determine if a delete
//has been committed.
BOOL m_fTxnPendingDelete;
//@cmember Flag checked at commit time, to determine if a change
//has been committed.
BOOL m_fTxnPendingChange;
//@cmember Whether or not a transaction is started on this DB Session
BOOL m_fTxnStarted;
//@cmember CTOR
CTxnChgRowset(LPWSTR tcName);
//@cmember Initialization - Creates an updateable rowset
virtual BOOL Init();
//Copies pertainent info when two rowsets are sharing the same
//session and txn, and the give rowset has made a change
void CopyTxnInfo(CTxnChgRowset * pTxnChgRowset);
//@cmember Sets the properties to generate the correct rowset on CreateRowsetObject
virtual BOOL SetTxnRowsetProperties();
//@cmember Termination - Cleans up all non base rowset interfaces
virtual BOOL Terminate();
//@cmember Commits current txn, fNewUnitOfWork sets whether
//a new transaction is started, or we revert to autocommit mode.
//fPreserveRowset sets whether or not the rowset is kept after the commit.
virtual HRESULT Commit(BOOL fPreserveRowset = FALSE, BOOL fNewUnitOfWork = FALSE);
//@cmember Starts a txn, setting the m_fTxnStarted flag
virtual HRESULT StartTxn(ISOLEVEL isoLevel);
//#ifdef TXNJOIN
//@cmember Commits current txn, fNewUnitOfWork sets whether
//a new transaction is started, or we revert to autocommit mode.
//fPreserveRowset sets whether or not the rowset is kept after the commit.
virtual HRESULT CommitCoord(BOOL fNewUnitOfWork = FALSE, ITransaction *pITransaction = NULL,ITransactionJoin *pITransactionJoin=NULL);
//@cmember Gets a TransactionJoin interface pointer from a session object
virtual HRESULT GetTxnJoin();
//@cmember Gets a TransactionJoin interface pointer from a session object
virtual BOOL StartCoordTxn(ITransaction **ppITransaction,ISOLEVEL isolevel);
//@cmember Aborts the coordinated transacrtion and frees the pointer to TxnJoin
virtual BOOL FreeJoinTxn();
//@cmember Frees the ITrans interface and cloese connectin to dtc
virtual BOOL FreeCoordTxn(ITransaction *pITransaction);
//#endif//TXNJOIN
//@cmember Aborts current txn, fNewUnitOfWork sets whether
//a new transaction is started, or we revert to autocommit mode.
//fPreserveRowset sets whether or not the rowset is kept after the abort.
virtual HRESULT Abort(BOOL fPreserveRowset = FALSE, BOOL fNewUnitOfWork = FALSE);
//#ifdef TXNJOIN
//@cmember Aborts current txn, fNewUnitOfWork sets whether
//a new transaction is started, or we revert to autocommit mode.
//fPreserveRowset sets whether or not the rowset is kept after the abort.
virtual HRESULT AbortCoord(BOOL fNewUnitOfWork = FALSE, ITransaction *pITransaction = NULL,ITransactionJoin *pITransactionJoin=NULL);
//#endif//TXNJOIN
//@cmember Inserts a row given the row number -- does not explicitly commit
BOOL Insert( ULONG ulRowNum,
HROW *phNewRow = NULL,
BOOL fDEFAULT = FALSE);
//@cmember Deletes a row given the row number -- does not explicitly commit
BOOL Delete(ULONG ulRowNum, HROW * phRow = NULL);
//@cmember Deletes and Inserts (ie, Changes a row) given
//the row numbers -- does not explicitly commit
BOOL Change( ULONG ulDeleteRowNum,
ULONG ulInsertRowNum,
HROW *phRow = NULL,
BOOL fIGNORE = FALSE,
BOOL fDEFAULT = FALSE);
};
//--------------------------------------------------------------------
// @class CTxn | Base Class for Transaction testing.
// @base public | CDataSourceObject
//--------------------------------------------------------------------
class CTxn : public CSessionObject
{
// @access public
public:
//@cmember Row Number which is currently being inserted. This row
//may or may not be committed yet, so it may not be visible to other txns.
ULONG m_ulCurrentInsertRow;
//@cmember Row Number which is currently being deleted. This row
//may or may not be committed yet, so it may not be visible to other txns.
ULONG m_ulCurrentDeleteRow;
//@cmember New Row Number of row which is currently being changed. This change
//may or may not be committed yet, so it may not be visible to other txns.
ULONG m_ulCurrentChangeRow;
//@cmember Whether or not Isolation Level Chaos is supported
BOOL m_fChaos;
//@cmember Whether or not Isolation Level Read Uncommitted is supported
BOOL m_fReadUncommitted;
//@cmember Whether or not Isolation Level Read Committed is supported
BOOL m_fReadCommitted;
//@cmember Whether or not Isolation Level Repeatable Read is supported
BOOL m_fRepeatableRead;
//@cmember Whether or not Isolation Level Serializable is supported
BOOL m_fSerializable;
//@cmember A supported isolation level to use for general purposes
ISOLATIONLEVEL m_fIsoLevel;
//@cmember Whether or not the current datasource is Microsoft Access
//this flag is used to decide if we need to wait a few seconds after an update
//before other connections can see it.
BOOL m_fOnAccess;
//@cmember CTOR
CTxn(LPWSTR tcName);
//@cmember Initialization
virtual BOOL Init();
//@cmember Termination
virtual BOOL Terminate();
//@cmember Gets value to use for next insert
inline ULONG GetNextRowToInsert(){return g_ulLastActualInsert + 1;};
//@cmember Gets value to use for next delete
inline ULONG GetNextRowToDelete(){return g_ulLastActualDelete + 1;};
//@cmember Copies normally initialized by test framework test case info
//into the encapsulated object which inherits from CTestCases.
void CopyTestCaseInfo(CTestCases * pTC);
//@cmember Inserts the next row into the table, on the given txn
BOOL Insert(CTxnChgRowset * pTxnChgRowset);
//@cmember Deletes the next row to delete in the table, on the given txn
BOOL Delete(CTxnChgRowset * pTxnChgRowset, HROW * phRow = NULL);
//@cmember Changes the next row to delete in the table to the values
//based on the next row to insert, on the given txn
BOOL Change(CTxnChgRowset * pTxnChgRowset);
//@cmember Tries to find the current inserted row, which may or may not be commited
inline BOOL FindInsert(CTxnRowset * pRowset)
{ return pRowset->FindRow(m_ulCurrentInsertRow, NULL);};
//@cmember Tries to find the current deleted row, which may or may not be commited
inline BOOL FindDelete(CTxnRowset * pRowset)
{ return pRowset->FindRow(m_ulCurrentDeleteRow, NULL);};
//@cmember Tries to find the current Changed row, which may or may not be commited
inline BOOL FindChange(CTxnRowset * pRowset)
{ return pRowset->FindRow(m_ulCurrentChangeRow, NULL);};
//@cmember Starts the txn with the IsoLevel
HRESULT StartTxn(ITransactionLocal * pITxnLocal, ISOLEVEL IsoLevel);
//@cmember Releases all rowsets associated with any encapsulated objects
virtual void ReleaseAllRowsetsAndTxns()=0;
//@cmember Determines whether or not a new unit of work has begun on txn 1
BOOL NewUnitOfWork(CTxnChgRowset * pTxnChgRowset, CTxnRowset * pTxnRowset);
//#ifdef TXNJOIN
//@cmember Determines whether or not a new unit of work has begun on txn 1
BOOL NewUnitOfWorkCoord(CTxnChgRowset *pTxnChgRowset, CTxnRowset *pTxnRowset, ITransaction *pITransaction,ITransactionJoin *pITransactionJoin);
//@cmember Determines whether or not txn 1 is in autocommit mode
BOOL NoNewUnitOfWorkCoord(CTxnChgRowset *pTxnChgRowset, CTxnRowset *pTxnRowset, ITransaction *pITransaction, BOOL fChange,ITransactionJoin *pITransactionJoin);
//#endif//TXNJOIN
//@cmember Determines whether or not the rowset is functional on txn 1
BOOL RowsetFunctional(CTxnRowset * pTxnRowset);
//@cmember Determines whether or not the rowset is zombied on txn 1
BOOL RowsetZombied(CTxnRowset * pTxnRowset, IRowset ** ppIRowset, HROW * phRow, HACCESSOR hAccessor);
//@cmember Determines whether or not txn 1 is in autocommit mode
BOOL NoNewUnitOfWork(CTxnChgRowset *pTxnChgRowset, CTxnRowset *pTxnRowset);
//@cmember Verifies all transaction info from GetTransactionInfo
BOOL VerifyTxnInfo(ITransaction * pITxn, ISOLEVEL isoLevel, XACTUOW * puow = NULL);
};
//--------------------------------------------------------------------
// @class CUpdateTxn | Base Class for non buffered mode Transaction testing.
// @base public | CTxn
//--------------------------------------------------------------------
class CTxnImmed : public CTxn
{
// @access public
public:
//@cmember CTOR
CTxnImmed(LPWSTR wszTestCaseName);
//@cmember Pointer to Rowset object that supports Changes on TXN_1
CTxnChgRowset * m_pChgRowset1;
//@cmember Pointer to Rowset object that supports Changes on TXN_2
CTxnChgRowset * m_pChgRowset2;
//@cmember Pointer to Rowset object that supports Changes on TXN_3
CTxnChgRowset * m_pChgRowset3;
//@cmember Pointer to Read Only Rowset on TXN_1
CTxnRORowset * m_pRORowset1;
//@cmember Initialization
virtual BOOL Init();
//@cmember Termination
virtual BOOL Terminate();
//@cmember Releases all rowsets associated with any encapsulated objects
virtual void ReleaseAllRowsetsAndTxns();
//@cmember Releases all rowsets associated with any encapsulated objects
virtual void ReleaseAllRowsets();
//@cmember Get DBPROP_SUPPORTEDTXNISOLEVELS
HRESULT GetIsoLevels(ISOLEVEL *pIsoLevel);
};
// This structure keeps the numeric value and description of each isolation level
struct tagIsolation {
char *pszDesc;
ULONG ulIsolation;
};
extern tagIsolation g_IsolationList[];
extern ULONG g_ulTotalIsolations;