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

31704 lines
905 KiB
C++

//--------------------------------------------------------------------
// Microsoft OLE DB Test
//
// Copyright 1995-2000 Microsoft Corporation.
//
// @doc
//
// @module SETDATA.CPP | Source file for test module IRowsetChange
//
#define DBINITCONSTANTS // Must be defined to initialize constants in OLEDB.H
#define INITGUID
#include "modstandard.hpp"
#include "irowchng.h"
#include "extralib.h"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Module Values
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// {{ TCW_MODULE_GLOBALS
DECLARE_MODULE_CLSID = { 0xa41ff7d5, 0x8669, 0x11cf, { 0x89, 0x94, 0x00, 0xaa, 0x00, 0xb5, 0xa9, 0x1b }};
DECLARE_MODULE_NAME("IRowsetChange");
DECLARE_MODULE_OWNER("Microsoft");
DECLARE_MODULE_DESCRIP("The test module for interface IRowsetChange:SetData");
DECLARE_MODULE_VERSION(839035527);
// TCW_WizardVersion(2)
// TCW_Automation(True)
// }} TCW_MODULE_GLOBALS_END
#define TESTC_SetData(exp){TESTB = TEST_PASS; if((TEST_SKIPPED==exp)) {TESTB = TEST_SKIPPED; goto CLEANUP;}}
#ifdef _WIN64
//this would be more descriptive as DBROWCOUNT but since
//privlib want a ULONG for it's GetProperty, eventhough
//properties are unsigned, ULONG to VARIANT will be handled instead
#define V_DBCOUNTITEM(X) V_UNION(X, ullVal)
#else
#define V_DBCOUNTITEM(X) V_UNION(X, ulVal)
#endif // _WIN64
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Globals
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const ULONG g_cPropertyIDs = 3;
DBPROPID g_rgPropertyIDs[g_cPropertyIDs] = { DBPROP_OTHERINSERT, DBPROP_OTHERUPDATEDELETE, DBPROP_OWNUPDATEDELETE};
BOOL g_fMAXPENDINGROWS = FALSE;
DBCOUNTITEM g_lMaxPendRows = -1;
WORD g_ACCESSORDER_VALUE = DBPROPVAL_AO_RANDOM;
DBCOUNTITEM g_ulRowCount;
BOOL g_fUseMaxRows;
//--------------------------------------------------------------------
// @Check if an integer is in the array
//
//--------------------------------------------------------------------
BOOL InArray(ULONG ulNumber, ULONG cCount, ULONG *rgNumber)
{
ULONG cIndex;
for(cIndex=0; cIndex<cCount; cIndex++)
{
if(ulNumber==rgNumber[cIndex])
{
return TRUE;
}
}
return FALSE;
}
//--------------------------------------------------------------------
// @is property call IRowsetIdentity->IsSameRow
//--------------------------------------------------------------------
BOOL fnIsSameRow ( IUnknown *pIUnknown,
HROW *phThisRow,
HROW *phThatRow
)
{
IRowsetIdentity *pIRowsetIdentity = NULL;
//Compare rows, the two row handles should have the same value
//get property info on the rowset
if(!VerifyInterface(pIUnknown, IID_IRowsetIdentity, ROWSET_INTERFACE, (IUnknown**)&pIRowsetIdentity))
goto CLEANUP;
if (!pIRowsetIdentity)
goto CLEANUP;
if (S_OK==pIRowsetIdentity->IsSameRow(*phThisRow,*phThatRow))
{
SAFE_RELEASE(pIRowsetIdentity);
return TRUE;
}
CLEANUP:
SAFE_RELEASE(pIRowsetIdentity);
odtLog<<L"Rows do not compare."<<ENDL;
return FALSE;
}
DBSTATUS GetStatus(void *pData, DBBINDING *pBinding)
{
return STATUS_BINDING(*pBinding,pData);
}
//--------------------------------------------------------------------
// @func Module level initialization routine
//
// @rdesc Success or Failure
// @flag TRUE | Successful initialization
// @flag FALSE | Initialization problems
//
BOOL ModuleInit(CThisTestModule *pThisTestModule)
{
//CommonModuleInit, Verify IRowset is supported, and Create a table
BOOL fPass = CommonModuleInit(pThisTestModule, IID_IRowsetChange, 20);
GetModInfo()->SetCompReadOnlyCols(FALSE);
if (TEST_PASS == fPass)
{
// Reset the global
g_ulRowCount = g_pTable->GetRowsOnCTable();
g_fMAXPENDINGROWS = FALSE;
g_lMaxPendRows = -1;
g_ACCESSORDER_VALUE = DBPROPVAL_AO_RANDOM;
g_fUseMaxRows = FALSE;
}
return fPass;
}
//--------------------------------------------------------------------
// @func Module level termination routine
//
// @rdesc Success or Failure
// @flag TRUE | Successful initialization
// @flag FALSE | Initialization problems
//
BOOL ModuleTerminate(CThisTestModule * pThisTestModule)
{
ULONG cCnt = 0;
if (g_pTable)
{
//if an ini file is being used then delete and repopulate
if(GetModInfo()->GetFileName())
{
//delete all rows in the table.
if(g_pTable->DeleteRows(ALLROWS) == S_OK)
{
// RePopulate table in case an .ini file is being used.
for(cCnt=1; cCnt<=g_ulRowCount; cCnt++)
{
if(g_pTable->Insert(cCnt, PRIMARY) != S_OK)
{
return FALSE;
}
}
}
}
}
return CommonModuleTerminate(pThisTestModule);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Base Test Case Section
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
// TCIRowsetChange: the base class for the rest of test cases in this
// test module.
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
class TCIRowsetChange : public CRowsetObject
{
private:
protected:
//@cmember: interface pointer for IRowsetChange
IRowsetChange *m_pIRowsetChange;
//@cmember: interface pointer for IRowsetUpdate
IRowsetUpdate *m_pIRowsetUpdate;
//@cmember: interface pointer for IRowsetLocate
IRowsetLocate *m_pIRowsetLocate;
//@cmember: interface pointer for IRowset
IRowset *m_pIRowset;
//@cmember: interface pointer for IRowsetIdentity
IRowsetIdentity *m_pIRowsetIdentity;
//@cmember: accessory handle
HACCESSOR m_hAccessor;
//@cmember: the count of rows
DBCOUNTITEM m_cRowsObtained;
//@cmember: the size of a row
DBLENGTH m_cRowSize;
//@cmember: the count of binding structure
DBCOUNTITEM m_cBinding;
//@cmember: the array of binding strucuture
DBBINDING *m_rgBinding;
//@cmember: the column information
DBCOLUMNINFO *m_rgInfo;
//@cmember: the string buffer to hold the name
WCHAR *m_pStringsBuffer;
//@cmember: the pointer to the row buffer
void *m_pData;
//@cmember
DBCOUNTITEM m_ulTableRows;
//@cmember
BOOL m_bIndexExists;
//@cmember: the location of accessor handle
EACCESSORLOCATION m_eAccessorLocation;
//@cmember: The Providers Updatability Flags for DBPROP_UPDATABILITY
ULONG_PTR m_ulpProvUpdFlags;
//@cmember: The Updatability Flags for DBPROP_UPDATABILITY
ULONG_PTR m_ulpUpdFlags;
//@cmember: The Updatability Flags for DBPROP_UPDATABILITY
BOOL m_fUseCmdTmeOut;
//@mfunc: initialialize interface pointers
BOOL Init();
//@mfunc: Terminate
BOOL Terminate();
//@mfunc: Create a command object and set properties, execute a sql statement,
// and create a rowset object. Create an accessor on the rowset
BOOL GetRowsetAndAccessor
(
EQUERY eSQLStmt,
ULONG cProperties =0,
const DBPROPID *rgProperties =NULL,
ULONG cPropertiesUnset =0,
const DBPROPID *rgPropertiesUnset =NULL,
EACCESSORLOCATION eAccessorLocation =NO_ACCESSOR,
BOOL fBindLongColumn =FALSE,
DBACCESSORFLAGS dwAccessorFlags =DBACCESSOR_ROWDATA,
DBPART dwPart =DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
ECOLS_BOUND eColsToBind =ALL_COLS_BOUND,
ECOLUMNORDER eBindingOrder =FORWARD,
ECOLS_BY_REF eColsByRef =NO_COLS_BY_REF,
DBTYPE dbTypeModifier =DBTYPE_EMPTY,
DBCOUNTITEM cColsToBind =0,
ULONG_PTR *rgColsToBind =NULL,
ECOLS_MEM_PROV_OWNED
eColsMemProvOwned =NO_COLS_OWNED_BY_PROV, //@paramopt [IN] Which columns' memory is to be owned by the provider
DBPARAMIO eParamIO = DBPARAMIO_NOTPARAM, //@paramopt [IN] Parameter type to specify for eParmIO
HRESULT *pHResult = NULL,
HRESULT HRPossible = NULL
);
//@mfun: create an accessor on the rowset.
BOOL GetAccessorOnRowset
(
EACCESSORLOCATION eAccessorLocation=ON_ROWSET_ACCESSOR,
BOOL fBindLongColumn=FALSE,
DBACCESSORFLAGS dwAccessorFlags=DBACCESSOR_ROWDATA,
DBPART dwPart=DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
ECOLS_BOUND eColsToBind=ALL_COLS_BOUND,
ECOLUMNORDER eBindingOrder=FORWARD,
ECOLS_BY_REF eColsByRef=NO_COLS_BY_REF,
DBTYPE dbTypeModifier=DBTYPE_EMPTY,
DBORDINAL cColsToBind=0,
DBORDINAL *rgColsToBind=NULL,
ECOLS_MEM_PROV_OWNED
eColsMemProvOwned = NO_COLS_OWNED_BY_PROV, //@paramopt [IN] Which columns' memory is to be owned by the provider
DBPARAMIO eParamIO = DBPARAMIO_NOTPARAM //@paramopt [IN] Parameter type to specify for eParmIO
);
//@mfun: Get the bookmark for the row
BOOL GetBookmark
(
DBROWCOUNT ulRow,
DBBKMARK *pcbBookmark,
BYTE **ppBookmark
);
BOOL GetBookmarkByRow
(
HROW hRow,
DBBKMARK*pcbBookmark,
BYTE **ppBookmark
);
//@mfunc: Get cursor type of the rowset
ECURSOR GetCursorType();
//@mfunc: Return TRUE is we are on QueryBased Update mode
BOOL MultipleChanges();
//@mfun: Return TRUE if we are on buffered update mode
BOOL BufferedUpdate();
BOOL GetProp(DBPROPID DBPropID);
//@mfunc: Get the Nullable and Updatable column
BOOL GetNullableAndUpdatable(DBORDINAL *pcbCol,
DBORDINAL **prgColNum);
//@mfunc: Get the Not-Nullable and Updatable column
BOOL GetNotNullableAndUpdatable( DBORDINAL *pcbCol,
DBORDINAL **prgColNum);
//@mfunc: Get the Numeric and Updatable column
BOOL GetNumericAndUpdatable( DBORDINAL *pcbCol,
DBORDINAL **prgColNum);
//@mfunc: Get the Numeric and Updatable column
BOOL GetFloatAndUpdatable( DBORDINAL *pcbCol,
DBORDINAL **prgColNum);
//@mfunc: Get the Fixed Length and Updatable column
BOOL GetFixedLengthAndUpdatable( DBORDINAL *pcbCol,
DBORDINAL **prgColNum);
//@mfunc: Get the non key non BLOB
BOOL GetNonKeyNonBLOB( DBORDINAL *pcbCol,
DBORDINAL **prgColNum);
//@mfunc: Get the BLOB
BOOL GetBLOB( DBORDINAL *pcbCol,
DBORDINAL **prgColNum);
//@mfunc: Get the BLOB
BOOL GetImage( DBORDINAL *pcbCol,
DBORDINAL **prgColNum);
//@mfunc: Get the Variable Length and Updatable column
BOOL GetVariableLengthAndUpdatable( DBORDINAL *pcbCol,
DBORDINAL **prgColNum,
BOOL fLong=TRUE,
BOOL fBytes=TRUE);
//@mfunc: Get the Variable Length and Updatable column
BOOL GetStr( DBORDINAL *pcbCol,
DBORDINAL **prgColNum);
//@mfunc: Get not updatable column
ULONG GetNotUpdatable( DBORDINAL *pcbCol,
DBORDINAL **prgColNum);
BOOL GetUpdatableCols( DBORDINAL *pcbCol,
DBORDINAL **prgColNum);
ULONG GetAllButFirst( DBORDINAL *pcbCol,
DBORDINAL **prgColNum);
//@mfunc: verify the position of the row handle in the row set
BOOL VerifyRowPosition( HROW hRow, //row handle
ULONG cRow, //potision expected
EVALUE eValue=PRIMARY); //eValue for MakeData
HRESULT SetData(HROW hRow, HACCESSOR hAccessor, void* pData);
HRESULT GetData(HROW hRow, HACCESSOR hAccessor, void* pData);
void fnIgnoreAutoInc(void **pData);
//@mfunc: release the memory referenced by the consumer's buffer
void FreeMemory();
//@mfunc: release the accessor on the rowset
void ReleaseAccessorOnRowset();
//@mfunc: release a rowset object and accessor created on it
void ReleaseRowsetAndAccessor(ULONG RowRefCnt=0, ULONG CmdRefCnt=0);
public:
//constructor
TCIRowsetChange(WCHAR *wstrTestCaseName):CRowsetObject(wstrTestCaseName)
{
m_pIRowsetChange =NULL;
m_pIRowsetUpdate =NULL;
m_pIRowsetLocate =NULL;
m_pIRowsetIdentity =NULL;
m_pIRowset =NULL;
m_hAccessor =NULL;
m_cRowsObtained =0;
m_cRowSize =0;
m_cBinding =0;
m_rgBinding =NULL;
m_rgInfo =NULL;
m_pStringsBuffer =NULL;
m_pData =NULL;
m_eAccessorLocation =NO_ACCESSOR;
m_bIndexExists =FALSE;
m_ulTableRows =0;
m_ulpProvUpdFlags =0;
m_ulpUpdFlags =DBPROPVAL_UP_CHANGE;
m_fUseCmdTmeOut =FALSE;
};
//destructor
virtual ~TCIRowsetChange(){};
};
//--------------------------------------------------------------------
//@mfunc: Init creates a Data Source object, a DB Session object,
//and a command object and initialize corresponding interface pointers.
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::Init()
{
//Init baseclass
CRowsetObject::Init();
//Use the global DSO created in Module init
SetDataSourceObject(g_pIDBInitialize);
//Use the global DB Rowset created in Module init
SetDBSession(g_pIOpenRowset);
//Use the global CTable created in Module init, by default
SetTable(g_pTable, DELETETABLE_NO);
//Use the global C1RowTable for the second table, if ever needed
SetTable2(g_p1RowTable, DELETETABLE_NO);
m_ulTableRows = g_pTable->CountRowsOnTable();
g_ulRowCount = m_ulTableRows;
g_pTable->DoesIndexExist(&m_bIndexExists);
// Get the value for DBPROP_UPDATABILITY if ReadOnly
if( !SettableProperty(DBPROP_UPDATABILITY,DBPROPSET_ROWSET,g_pIDBCreateSession) )
{
// Create a Command object
CreateRowsetObject(USE_OPENROWSET,IID_IRowset,EXECUTE_IFNOERROR);
GetProperty(DBPROP_UPDATABILITY,DBPROPSET_ROWSET,m_pIAccessor,&m_ulpProvUpdFlags);//this should be a long, not a ulong
ReleaseRowsetObject();
}
return TRUE;
}
//--------------------------------------------------------------------
//@mfunc: Terminate release the data source object, DB Session object, Command object
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::Terminate()
{
ULONG cCnt = 0;
if (g_pTable)
{
//if an ini file is being used then delete and repopulate
if(GetModInfo()->GetFileName())
{
//delete all rows in the table.
if(g_pTable->DeleteRows(ALLROWS) == S_OK)
{
// RePopulate table in case an .ini file is being used.
for(cCnt=1; cCnt<=g_ulRowCount; cCnt++)
{
if(g_pTable->Insert(cCnt, PRIMARY) != S_OK)
{
return FALSE;
}
}
}
}
}
ReleaseRowsetObject(); //releases m_pIAccessor
ReleaseCommandObject(); //releases m_pICommand
ReleaseDBSession();
ReleaseDataSourceObject();
return(CRowsetObject::Terminate());
}
HRESULT TCIRowsetChange::SetData(HROW hRow, HACCESSOR hAccessor, void* pData)
{
HRESULT hr = S_OK;
DBACCESSORFLAGS dwAccessorFlags;
DBCOUNTITEM cBindings = 0;
DBBINDING *rgBindings = NULL;
CRowObject RowObject;
//Does the provider support Row Objects?
hr = RowObject.CreateRowObject(m_pIRowset, hRow);
//Verify Results...
if(SUCCEEDED(hr) && hAccessor && hRow && pData)
{
//Obtain the accessor bindings
ASSERT(m_pIAccessor);
QTESTC_(hr = m_pIAccessor->GetBindings(hAccessor, &dwAccessorFlags, &cBindings, &rgBindings),S_OK)
//Obtain the data
hr = RowObject.SetColumns(cBindings, rgBindings, pData);
}
else
{
ASSERT(m_pIRowsetChange);
hr = m_pIRowsetChange->SetData(hRow, hAccessor, pData);
}
if (pData)
{
//Display any binding errors and status'
TESTC(VerifyBindings(hr, m_pIAccessor, hAccessor, pData));
}
CLEANUP:
FreeAccessorBindings(cBindings, rgBindings);
return hr;
}
HRESULT TCIRowsetChange::GetData(HROW hRow, HACCESSOR hAccessor, void* pData)
{
DBACCESSORFLAGS dwAccessorFlags;
DBCOUNTITEM cBindings = 0;
DBBINDING *rgBindings = NULL;
CRowObject RowObject;
HRESULT hr = S_OK;
//Does the provider support Row Objects?
hr = RowObject.CreateRowObject(m_pIRowset, hRow);
//Verify Results...
if(SUCCEEDED(hr) && hAccessor && hRow && pData)
{
//Obtain the accessor bindings
ASSERT(m_pIAccessor);
QTESTC_(hr = m_pIAccessor->GetBindings(hAccessor, &dwAccessorFlags, &cBindings, &rgBindings),S_OK)
//Get the Data for row object
hr = RowObject.GetColumns(cBindings, rgBindings, pData);
}
else
{
ASSERT(m_pIRowset);
hr = m_pIRowset->GetData(hRow, hAccessor, pData);
}
//Display any binding errors and status'
TESTC(VerifyBindings(hr, m_pIAccessor, hAccessor, pData));
CLEANUP:
FreeAccessorBindings(cBindings, rgBindings);
return hr;
}
void TCIRowsetChange::fnIgnoreAutoInc(void **pData)
{
DBORDINAL cColsInTable= 0;
ULONG i = 0;
ULONG j = 0;
DBORDINAL cColOrd = 0;
CCol CurCol; //Current Column
//get the number of columns on the table
cColsInTable = g_pTable->CountColumnsOnTable();
//Copy the provider types from the tables column info.
for(i=0;i<cColsInTable; i++)
{
// get column info for nCol'th column from the global table
g_pTable->GetColInfo(i+1, CurCol);
//if there is an auto inc col
if (CurCol.GetAutoInc())
{
cColOrd = CurCol.GetColNum();
//loop through the bindings looking for the same ordinal
for (j=0;j<m_cBinding;j++)
{
if (m_rgBinding[j].iOrdinal==cColOrd)
{
//set the binding status to ignore
// *(DBSTATUS *)(((DWORD)*pData)+m_rgBinding[j].obStatus)=DBSTATUS_S_IGNORE;
STATUS_BINDING(m_rgBinding[j],pData)=DBSTATUS_S_IGNORE;
break;
}
}
}
}
}
//--------------------------------------------------------------------
//@mfunc: Create a command object and set properties, execute a sql statement,
// and create a rowset object. Create an accessor on the rowset
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::GetRowsetAndAccessor
(
EQUERY eSQLStmt, //the SQL Statement to create
ULONG cProperties, //the count of properties
const DBPROPID *rgProperties, //the array of properties to be set
ULONG cPropertiesUnset, //the count of properties to be unset
const DBPROPID *rgPropertiesUnset, //the array of properties to be unset
EACCESSORLOCATION eAccessorLocation, //where the accessor should be created
BOOL fBindLongColumn, //whether to bind LONG columns
DBACCESSORFLAGS dwAccessorFlags, //the accessor flags
DBPART dwPart, //the type of binding
ECOLS_BOUND eColsToBind, //the columns in accessor
ECOLUMNORDER eBindingOrder, //the order to bind columns
ECOLS_BY_REF eColsByRef, //which columns to bind by reference
DBTYPE dbTypeModifier, //the type modifier used for accessor
DBORDINAL cColsToBind, //the count of columns to bind
DBORDINAL *rgColsToBind, //the array of column ordinals to bind
ECOLS_MEM_PROV_OWNED eColsMemProvOwned, //@paramopt [IN] Which columns' memory is to be owned by the provider
DBPARAMIO eParamIO, //@paramopt [IN] Parameter type to specify for eParmIO
HRESULT *pHResult, //the hresult to return
HRESULT HRPossible //in case an valid error HR might be possible in this method
)
{
IColumnsInfo *pIColumnsInfo = NULL;
IRowset *pIRowset = NULL;
DBCOUNTITEM cRowsObtained = 0;
HROW *pHRow = NULL;
ULONG cDBPropSet = 1;
DBPROPSET rgDBPropSet[2];
ULONG cProp = 0;
HRESULT hr = S_OK;
BOOL fPass = FALSE;
BLOBTYPE blobType;
BOOL fUseServiceComp = GetModInfo()->UseServiceComponents();
ULONG ulIndex = 0;
ULONG ulUpdValue = 0;
DBCOUNTITEM ulMaxPendRows = 0;
ULONG cExtraProps = 1;
ULONG i = 0;
m_pIAccessor = NULL;
if(fBindLongColumn)
blobType=BLOB_LONG;
else
blobType=NO_BLOB_COLS;
//Set up the DB Properties struct
if(cProperties || cPropertiesUnset)
{
//if MaxPendingRows is needed, make sure space is alloicated for it.
if (-1!=g_lMaxPendRows)
{
cExtraProps++;
}
//if m_fUseCmdTmeOut is needed, make sure space is alloicated for it too.
if (m_fUseCmdTmeOut)
{
cExtraProps++;
}
if(fUseServiceComp)
{
cExtraProps++;
}
if(g_fUseMaxRows)
{
cExtraProps++;
}
//init DBPropSet[0]
rgDBPropSet[0].rgProperties = NULL;
rgDBPropSet[0].cProperties = 1;
rgDBPropSet[0].guidPropertySet= DBPROPSET_ROWSET;
//allocate
//Might need an extra for DBPROP_UPDATABILITY (+1)
rgDBPropSet[0].rgProperties=(DBPROP *)PROVIDER_ALLOC
(sizeof(DBPROP) * (cProperties + cPropertiesUnset + cExtraProps));
memset(rgDBPropSet[0].rgProperties,0,sizeof(DBPROP)*(cProperties + cPropertiesUnset + cExtraProps));
if(!rgDBPropSet[0].rgProperties)
goto CLEANUP;
rgDBPropSet[0].rgProperties[0].dwPropertyID = DBPROP_IRowsetFind;
rgDBPropSet[0].rgProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[0].vValue.vt = VT_BOOL;
rgDBPropSet[0].rgProperties[0].colid = DB_NULLID;
V_BOOL(&rgDBPropSet[0].rgProperties[0].vValue) = VARIANT_TRUE;
//make sure the test checks properties against sc/ce
if (fUseServiceComp)
{
//Get Rowset interface so info from RowsetInfo can be obtainied
// call IOpenRowset to return a Rowset
hr = m_pTable->CreateRowset (
USE_OPENROWSET,
IID_IRowset,
1,
rgDBPropSet,
(IUnknown**)&pIRowset,
NULL,
NULL,
NULL
);
}
else
{
//Get Rowset interface so info from RowsetInfo can be obtainied
// call IOpenRowset to return a Rowset
hr = m_pTable->CreateRowset (
USE_OPENROWSET,
IID_IRowset,
0,
NULL,
(IUnknown**)&pIRowset,
NULL,
NULL,
NULL
);
}
if (pIRowset)
{
//go through the loop to set every DB Property required
for(i=0; i<cProperties; i++)
{
//if the property is supported AND
//if the property is writeable OR the default is VARIANT_TRUE
if( SupportedProperty(rgProperties[i],DBPROPSET_ROWSET,g_pIDBCreateSession) &&
(SettableProperty(rgProperties[i],DBPROPSET_ROWSET,g_pIDBCreateSession) ||
GetProperty(rgProperties[i],DBPROPSET_ROWSET,pIRowset)) )
{
rgDBPropSet[0].rgProperties[cProp].dwPropertyID = rgProperties[i];
rgDBPropSet[0].rgProperties[cProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[cProp].colid =DB_NULLID;
//check to see if the DBPROP_ACCESSORDER need to be set
if (rgProperties[i]==DBPROP_ACCESSORDER)
{
rgDBPropSet[0].rgProperties[cProp].vValue.vt = VT_I4;
V_I4(&rgDBPropSet[0].rgProperties[cProp].vValue)= g_ACCESSORDER_VALUE;
}
else
{
rgDBPropSet[0].rgProperties[cProp].vValue.vt = VT_BOOL;
V_BOOL(&rgDBPropSet[0].rgProperties[cProp].vValue)= VARIANT_TRUE;
}
cProp++;
}
else
{
odtLog<<L"A property neccessary to execute this variation was not settable."<<ENDL;
fPass=FALSE;
goto CLEANUP;
}
}
}
else
{
odtLog<<L"this provider is useless."<<ENDL;
goto CLEANUP;
}
//if variation wants MAXPENDINGROWS set to something, it won't be -1 here
if (-1!=g_lMaxPendRows)
{
//if MAXPENDINGROWS is supported
if( SupportedProperty(DBPROP_MAXPENDINGROWS,DBPROPSET_ROWSET,g_pIDBCreateSession))
{
// Figure out the DBPROP_MAXPENDINGRROWS value if ReadOnly
if( !(SettableProperty(DBPROP_MAXPENDINGROWS,DBPROPSET_ROWSET,g_pIDBCreateSession)))
{
//if READ Only then get its value
if(!GetProperty(DBPROP_MAXPENDINGROWS,DBPROPSET_ROWSET,pIRowset,&ulMaxPendRows) )
{
//skip the calling variation
odtLog<<L"DBPROP_MAXPENDINGROWS was not settable."<<ENDL;
fPass=FALSE;
goto CLEANUP;
}
g_lMaxPendRows=ulMaxPendRows;
}
}
else
{
//skip the calling variation
odtLog<<L"DBPROP_MAXPENDINGROWS was not settable."<<ENDL;
fPass=FALSE;
goto CLEANUP;
}
//set DBPROP_MAXPENDINGROWS
rgDBPropSet[0].rgProperties[cProp].dwPropertyID = DBPROP_MAXPENDINGROWS;
rgDBPropSet[0].rgProperties[cProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[cProp].vValue.vt = VT_I4;
rgDBPropSet[0].rgProperties[cProp].colid = DB_NULLID;
V_DBCOUNTITEM(&rgDBPropSet[0].rgProperties[cProp].vValue)=DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
cProp++;
}
//set DBPROP_UPDATABILITY
rgDBPropSet[0].rgProperties[cProp].dwPropertyID = DBPROP_UPDATABILITY;
rgDBPropSet[0].rgProperties[cProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[cProp].vValue.vt = VT_I4;
rgDBPropSet[0].rgProperties[cProp].colid = DB_NULLID;
V_DBCOUNTITEM(&rgDBPropSet[0].rgProperties[cProp].vValue)=m_ulpUpdFlags;
cProp++;
//if service components are request let try hard to give'em
if (fUseServiceComp)
{
//set DBPROP_IRowsetFind
rgDBPropSet[0].rgProperties[cProp].dwPropertyID = DBPROP_IRowsetFind;
rgDBPropSet[0].rgProperties[cProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[cProp].vValue.vt = VT_BOOL;
rgDBPropSet[0].rgProperties[cProp].colid = DB_NULLID;
V_BOOL(&rgDBPropSet[0].rgProperties[cProp].vValue) = VARIANT_TRUE;
cProp++;
}
if (m_fUseCmdTmeOut)
{
//set DBPROP_COMMANDTIMEOUT to 1 second
rgDBPropSet[0].rgProperties[cProp].dwPropertyID = DBPROP_COMMANDTIMEOUT;
rgDBPropSet[0].rgProperties[cProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[cProp].vValue.vt = VT_I4;
rgDBPropSet[0].rgProperties[cProp].colid = DB_NULLID;
rgDBPropSet[0].rgProperties[cProp].vValue.lVal = 1;
cProp++;
}
if (g_fUseMaxRows)
{
//set DBPROP_MAXROWS
rgDBPropSet[0].rgProperties[cProp].dwPropertyID = DBPROP_MAXROWS;
rgDBPropSet[0].rgProperties[cProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[cProp].vValue.vt = VT_I4;
rgDBPropSet[0].rgProperties[cProp].colid = DB_NULLID;
rgDBPropSet[0].rgProperties[cProp].vValue.lVal = 1;
cProp++;
}
//go through the loop to unset every DB Property required
for(i=0; i<cPropertiesUnset; i++)
{
//if the property is NOT writeable (read-only) AND the default is VARIANT_TRUE)
//skip the variation
if (
((! SettableProperty(rgPropertiesUnset[i],DBPROPSET_ROWSET,g_pIDBCreateSession)) &&
GetProperty(rgPropertiesUnset[i],DBPROPSET_ROWSET,pIRowset))
)
{
odtLog<<L"A property neccessary to execute this variation was not settable."<<ENDL;
fPass=FALSE;
goto CLEANUP;
}
else
{
if( SupportedProperty(rgPropertiesUnset[i],DBPROPSET_ROWSET,g_pIDBCreateSession))
{
rgDBPropSet[0].rgProperties[cProp].dwPropertyID = rgPropertiesUnset[i];
rgDBPropSet[0].rgProperties[cProp].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[cProp].vValue.vt = VT_BOOL;
rgDBPropSet[0].rgProperties[cProp].colid = DB_NULLID;
V_BOOL(&rgDBPropSet[0].rgProperties[cProp].vValue) = VARIANT_FALSE;
cProp++;
}
else
{
odtLog<<L"A property neccessary to execute this variation was not settable."<<ENDL;
fPass=FALSE;
goto CLEANUP;
}
}
}
rgDBPropSet[0].cProperties = cProp;
}
//release the rowset on session so no rowset is open on the session
//if there is an open rowset on the session it might cause problem
//if firehose mode is being used
SAFE_RELEASE(pIRowset);
//create an accessor on the command
if(eAccessorLocation==ON_COMMAND_ACCESSOR)
{
if(!m_pICommand)
{
//create the rowset object
TESTC_(CreateRowsetObject(eSQLStmt,IID_IRowset,EXECUTE_IFNOERROR),S_OK);
//release the rowset object, but keep the command around
ReleaseRowsetObject(0);
}
//asked for a command interface. if we don't have it do not continue
if (!m_pICommand)
{
goto CLEANUP;
}
//get the accessor handle
hr = GetAccessorAndBindings(
m_pICommand,
dwAccessorFlags,
&m_hAccessor,
&m_rgBinding,
&m_cBinding,
&m_cRowSize,
dwPart,
eColsToBind,
eBindingOrder,
eColsByRef,
NULL,
NULL,
NULL,
dbTypeModifier,
cColsToBind,
(LONG_PTR *)rgColsToBind,
NULL,
eColsMemProvOwned,
eParamIO,
blobType);
if (DBACCESSOR_PARAMETERDATA&dwAccessorFlags)
{
if (DB_E_BADACCESSORFLAGS==hr)
{
goto CLEANUP;
}
}
if (DBACCESSOR_PASSBYREF&dwAccessorFlags)
{
if (DB_E_BYREFACCESSORNOTSUPPORTED==hr)
{
goto CLEANUP;
}
}
}
if(!SUCCEEDED(SetRowsetProperties(rgDBPropSet, cDBPropSet)))
goto CLEANUP;
//create the rowset object
//May fail due to combinations of properties
if(m_pIDBCreateCommand==NULL && (eSQLStmt== SELECT_ORDERBYNUMERIC
|| eSQLStmt == SELECT_REVCOLLIST
|| eSQLStmt == SELECT_COLLISTFROMTBL))
eSQLStmt = SELECT_ALLFROMTBL;
hr = CreateRowsetObject(eSQLStmt,IID_IUnknown,EXECUTE_IFNOERROR);
if(hr==DB_S_ERRORSOCCURRED || hr==DB_E_ERRORSOCCURRED)
{
for (ulIndex=0;ulIndex<rgDBPropSet[0].cProperties;ulIndex++)
{
//if multiple props were set they might be conflicting on some providers
if (DB_E_ERRORSOCCURRED == hr &&
DBPROPSTATUS_CONFLICTING== rgDBPropSet[0].rgProperties[ulIndex].dwStatus &&
1 < rgDBPropSet[0].cProperties)
{
odtLog<<L"Conflict."<<ENDL;
}
}
goto CLEANUP;
}
if (HRPossible)
{
if (HRPossible==hr)
{
goto CLEANUP;
}
}
TESTC_(hr,S_OK);
//get the IRowsetChange pointer
TESTC_(m_pIAccessor->QueryInterface(IID_IRowsetChange, (LPVOID *)&m_pIRowsetChange),S_OK);
//get the IRowsetUpdate pointer if present
if(!SUCCEEDED(hr=m_pIAccessor->QueryInterface(IID_IRowsetUpdate,(LPVOID *)&m_pIRowsetUpdate)))
TESTC_(hr, E_NOINTERFACE);
//get the IRowsetLocate pointer if present
if(!SUCCEEDED(hr=m_pIAccessor->QueryInterface(IID_IRowsetLocate,(LPVOID *)&m_pIRowsetLocate)))
TESTC_(hr, E_NOINTERFACE);
//get the IRowsetIdentity pointer if present
if(!SUCCEEDED(hr=m_pIAccessor->QueryInterface(IID_IRowsetIdentity,(LPVOID *)&m_pIRowsetIdentity)))
TESTC_(hr, E_NOINTERFACE);
//get the IRowset pointer
TESTC_(m_pIAccessor->QueryInterface(IID_IRowset,(LPVOID *)&m_pIRowset),S_OK);
// get the columns infomation
TESTC_(m_pIAccessor->QueryInterface(IID_IColumnsInfo, (LPVOID *)&pIColumnsInfo),S_OK);
TESTC_(pIColumnsInfo->GetColumnInfo(&m_cRowsetCols,&m_rgInfo, &m_pStringsBuffer),S_OK);
//remember where the accessor handle is created
m_eAccessorLocation=eAccessorLocation;
switch(eAccessorLocation)
{
case ON_COMMAND_ACCESSOR:
//can not create an accessor on the command object if the
//the rowset is a simple rowset
if(eSQLStmt==USE_OPENROWSET)
goto CLEANUP;
break;
case ON_ROWSET_FETCH_ACCESSOR:
//can not create an accessor after the first fetch if no IRowset
//is present on the rowset
if(!m_pIRowset)
goto CLEANUP;
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRowsObtained, &pHRow), S_OK);
case ON_ROWSET_ACCESSOR:
//can not create an accessor on a rowset if no IRowset is present
if(!m_pIRowset)
goto CLEANUP;
//create an accessor on the rowset
hr = GetAccessorAndBindings(m_pIAccessor,dwAccessorFlags,&m_hAccessor,
&m_rgBinding,&m_cBinding,&m_cRowSize,dwPart,eColsToBind,eBindingOrder,
eColsByRef,NULL,NULL,NULL,dbTypeModifier,cColsToBind,(LONG_PTR *)rgColsToBind,
NULL,eColsMemProvOwned,eParamIO,blobType);
//if the test created a NULL accessor
if (!m_cBinding)
{
fPass=TEST_SKIPPED;
goto CLEANUP;
}
if (DBACCESSOR_PARAMETERDATA&dwAccessorFlags)
{
if (DB_E_BADACCESSORFLAGS==hr)
{
goto CLEANUP;
}
}
if (DBACCESSOR_PASSBYREF&dwAccessorFlags)
{
if (DB_E_BYREFACCESSORNOTSUPPORTED==hr)
{
goto CLEANUP;
}
}
break;
case NO_ACCESSOR:
break;
default:
return FALSE;
}
//allocate memory for the row
m_pData=PROVIDER_ALLOC(m_cRowSize);
if(!m_pData)
{
goto CLEANUP;
}
fPass=TRUE;
CLEANUP:
g_fUseMaxRows = FALSE;
if(rgDBPropSet[0].rgProperties)
PROVIDER_FREE(rgDBPropSet[0].rgProperties);
SAFE_RELEASE(pIColumnsInfo);
SAFE_RELEASE(pIRowset);
if(m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(cRowsObtained,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//restart position. The rowset returns to its original state
hr = m_pIRowset->RestartPosition(NULL);
CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE);
}
if( pHResult )
*pHResult = hr;
return fPass;
}
//--------------------------------------------------------------------
//@mfunc: Create an accessor on the rowset
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::GetAccessorOnRowset
(
EACCESSORLOCATION eAccessorLocation, //where the accessor should be created
BOOL fBindLongColumn, //whether to bind the LONG accessor
DBACCESSORFLAGS dwAccessorFlags, //the accessor flags
DBPART dwPart, //the type of binding
ECOLS_BOUND eColsToBind, //the columns in accessor
ECOLUMNORDER eBindingOrder, //the order to bind columns
ECOLS_BY_REF eColsByRef, //which columns to bind by reference
DBTYPE dbTypeModifier, //the type modifier used for accessor
DBORDINAL cColsToBind, //the count of columns to bind
DBORDINAL *rgColsToBind, //the array of column ordinals to bind
ECOLS_MEM_PROV_OWNED eColsMemProvOwned, //@paramopt [IN] Which columns' memory is to be owned by the provider
DBPARAMIO eParamIO //@paramopt [IN] Parameter type to specify for eParmIO
)
{
IUnknown *pIUnknown =NULL;
DBCOUNTITEM cRowsObtained =0;
HROW *pHRow =NULL;
DBORDINAL cCnt =0;
BOOL fPass =FALSE;
BLOBTYPE blobType;
HRESULT hr = S_OK;
if(fBindLongColumn)
blobType=BLOB_LONG;
else
blobType=NO_BLOB_COLS;
//remember where the accessor handle is created
m_eAccessorLocation=eAccessorLocation;
//eAccessorLocation can not be NO_ACCESSOR
if(!COMPARE((eAccessorLocation!=NO_ACCESSOR),TRUE))
{
fPass=FALSE;
goto CLEANUP;
}
switch(eAccessorLocation)
{
case ON_ROWSET_FETCH_ACCESSOR:
//can not create an accessor after the first fetch if no IRowset
//is present on the rowset
if(!m_pIRowset)
goto CLEANUP;
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRowsObtained, &pHRow), S_OK);
pIUnknown=m_pIAccessor;
break;
case ON_ROWSET_ACCESSOR:
//can not create an accessor on a rowset if no IRowset is present
if(!m_pIRowset)
goto CLEANUP;
pIUnknown=m_pIAccessor;
break;
case ON_COMMAND_ACCESSOR:
default:
return FALSE;
}
// Free the bindings if set
if( m_cBinding && m_rgBinding )
FreeAccessorBindings(m_cBinding, m_rgBinding);
SAFE_FREE(m_pData);
//create an accessor on the rowset
hr = GetAccessorAndBindings(pIUnknown,dwAccessorFlags,&m_hAccessor,
&m_rgBinding,&m_cBinding,&m_cRowSize,dwPart,eColsToBind,eBindingOrder,
eColsByRef,NULL,&cCnt,NULL,dbTypeModifier,cColsToBind,(LONG_PTR *) rgColsToBind,
NULL, eColsMemProvOwned,eParamIO,blobType);
//DB_E_ERRORSOCCURRED is temperarily acceptable for providers that don't support provider
//owned memory. a new prop to determine if a provider supports this is on its way
if (DB_E_ERRORSOCCURRED==hr)
{
fPass=TEST_SKIPPED;
goto CLEANUP;
}
if (S_OK!=hr)
{
fPass=FALSE;
goto CLEANUP;
}
//make sure cCnt should be the same as m_cRowsetCols
if(!COMPARE(cCnt, m_cRowsetCols))
goto CLEANUP;
//allocate memory for the row
m_pData=PROVIDER_ALLOC(m_cRowSize);
if(m_pData)
fPass=TRUE;
CLEANUP:
if(eAccessorLocation == ON_ROWSET_FETCH_ACCESSOR)
{
CHECK(m_pIRowset->ReleaseRows(cRowsObtained,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
// restart position. The rowset returns to its original state
hr = m_pIRowset->RestartPosition(NULL);
TEST2C_(hr, S_OK, DB_S_COMMANDREEXECUTED);
}
return fPass;
}
//--------------------------------------------------------------------
//@mfun: Get the bookmark for the row. The function has to be called
// after the GetRowsetAndAccessor that creates an accessor on the
// rowset. The accessor as to binds the 0th column on the rowset.
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::GetBookmark
(
DBROWCOUNT ulRow,
DBBKMARK *pcbBookmark,
BYTE **ppBookmark
)
{
BOOL fPass =FALSE;
HROW hRow[1];
HROW *pHRow =hRow;
DBCOUNTITEM cCount =0;
//the rowset has to expose IRowset in order to have bookmark
if(!m_pIRowset)
return FALSE;
//ulRow has to start with 1
if(!pcbBookmark || !ppBookmark || !ulRow)
return FALSE;
//restart the cursor position
HRESULT hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
return FALSE;
//fetch the row
if(!CHECK(m_pIRowset->GetNextRows(NULL,(ulRow-1),1,&cCount,&pHRow),S_OK))
return FALSE;
//only one row handle is retrieved
COMPARE(cCount, 1);
//get the bookmark by the row handle
fPass=GetBookmarkByRow(*pHRow, pcbBookmark, ppBookmark);
//release the row handle
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
return fPass;
}
//--------------------------------------------------------------------
//@mfun: Get the bookmark for the row. The function has to be called
// after the GetRowsetAndAccessor that creates an accessor on the
// rowset. The accessor as to binds the 0th column on the rowset.
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::GetBookmarkByRow
(
HROW hRow,
DBBKMARK *pcbBookmark,
BYTE **ppBookmark
)
{
BOOL fPass = FALSE;
void *pData = NULL;
HACCESSOR hAccessor = NULL;
DBCOUNTITEM cBinding = 0;
DBLENGTH cbRowSize = 0;
DBBINDING *pBinding = NULL;
DB_LORDINAL ulColToBind = 0;
//the rowset has to expose IRowset in order to have bookmark
if(!m_pIRowset)
return FALSE;
//check the input
if(!pcbBookmark || !ppBookmark)
return FALSE;
//create an accessor to binding the bookmark
TESTC_(GetAccessorAndBindings(m_pIAccessor,
DBACCESSOR_ROWDATA, &hAccessor, &pBinding,
&cBinding,&cbRowSize,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF, NULL, NULL, NULL,
DBTYPE_EMPTY, 1, (DB_LORDINAL *)&ulColToBind),S_OK);
//allocate memory
if(!(pData=PROVIDER_ALLOC(cbRowSize)))
goto CLEANUP;
//get the data
TESTC_(GetData(hRow, hAccessor, pData),S_OK);
//get the length of the bookmark
// *pcbBookmark= *((ULONG *)(dwAddr+pBinding[0].obLength));
*pcbBookmark=LENGTH_BINDING(pBinding[0], pData);
//allocate memory for bookmark
*ppBookmark=(BYTE *)PROVIDER_ALLOC(*pcbBookmark);
if(!(*ppBookmark))
goto CLEANUP;
//copy the value of the bookmark into the consumer's buffer
// memcpy(*ppBookmark, (void *)(dwAddr+pBinding[0].obValue), *pcbBookmark);
memcpy(*ppBookmark, &VALUE_BINDING(pBinding[0], pData), (size_t)*pcbBookmark);
fPass=TRUE;
CLEANUP:
//release the memory
PROVIDER_FREE(pData);
PROVIDER_FREE(pBinding);
//free the accessor
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
return fPass;
}
//--------------------------------------------------------------------
//
//@mfunc: Get cursor type of the rowset. Has to be called after a rowset
// generated.
//
//
//--------------------------------------------------------------------
ECURSOR TCIRowsetChange::GetCursorType()
{
IRowsetInfo *pIRowsetInfo = NULL;
ULONG cProperty = 0;
DBPROPID rgPropertyIDs[3];
DBPROPIDSET DBPropIDSet;
DBPROPSET *pDBPropSet = NULL;
ECURSOR eCursor = FORWARD_ONLY_CURSOR;
//initialization
rgPropertyIDs[0]=DBPROP_OTHERINSERT;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_OWNUPDATEDELETE;
DBPropIDSet.guidPropertySet=DBPROPSET_ROWSET;
DBPropIDSet.cPropertyIDs=3;
DBPropIDSet.rgPropertyIDs=rgPropertyIDs;
//QI for IRowsetInfo interface
TESTC_(m_pIRowset->QueryInterface(IID_IRowsetInfo,(LPVOID *)&pIRowsetInfo),S_OK);
//ask for the 3 properties
pIRowsetInfo->GetProperties(1,&DBPropIDSet,&cProperty,&pDBPropSet);
//only one property set should be returned
if(!COMPARE(cProperty, 1))
goto CLEANUP;
if(V_BOOL(&pDBPropSet[0].rgProperties[0].vValue)==VARIANT_TRUE)
eCursor=DYNAMIC_CURSOR;
else
{
if(V_BOOL(&pDBPropSet[0].rgProperties[1].vValue)==VARIANT_TRUE)
eCursor=KEYSET_DRIVEN_CURSOR;
else
{
if(V_BOOL(&pDBPropSet[0].rgProperties[2].vValue)==VARIANT_TRUE)
eCursor=STATIC_CURSOR;
}
}
CLEANUP:
FreeProperties(&cProperty,&pDBPropSet);
SAFE_RELEASE(pIRowsetInfo);
return eCursor;
}
BOOL TCIRowsetChange::GetProp(DBPROPID DBPropID)
{
IRowsetInfo *pIRowsetInfo=NULL;
ULONG cProperty=0;
DBPROPIDSET DBPropIDSet;
DBPROPSET *pDBPropSet=NULL;
BOOL fSupported=FALSE;
//initialize
DBPropIDSet.guidPropertySet=DBPROPSET_ROWSET;
DBPropIDSet.cPropertyIDs=1;
DBPropIDSet.rgPropertyIDs=&DBPropID;
//QI for IRowsetInfo interface
TESTC_(m_pIRowset->QueryInterface(IID_IRowsetInfo,(LPVOID *)&pIRowsetInfo),S_OK);
//ask for IID_IRowsetUpdate
TESTC_(pIRowsetInfo->GetProperties(1,&DBPropIDSet,&cProperty,&pDBPropSet),S_OK);
if(V_BOOL(&pDBPropSet->rgProperties->vValue)==VARIANT_TRUE)
fSupported=TRUE;
CLEANUP:
FreeProperties(&cProperty,&pDBPropSet);
SAFE_RELEASE(pIRowsetInfo);
return fSupported;
}
//--------------------------------------------------------------------
//
//@mfunc: Return TRUE is we are Mulltiple changes mode. Has to
// to called after a rowset is created.
//
////--------------------------------------------------------------------
BOOL TCIRowsetChange::MultipleChanges()
{
IRowsetInfo *pIRowsetInfo = NULL;
ULONG cProperty = 0;
DBPROPID DBPropID = DBPROP_REPORTMULTIPLECHANGES;
DBPROPIDSET DBPropIDSet;
DBPROPSET *pDBPropSet = NULL;
BOOL fSupported = FALSE;
//initialize
DBPropIDSet.guidPropertySet = DBPROPSET_ROWSET;
DBPropIDSet.cPropertyIDs = 1;
DBPropIDSet.rgPropertyIDs = &DBPropID;
//QI for IRowsetInfo interface
TESTC_(m_pIRowset->QueryInterface(IID_IRowsetInfo,(LPVOID *)&pIRowsetInfo),S_OK);
//ask for DBPROP_REPORTMULTIPLECHANGES
if(!SUCCEEDED(pIRowsetInfo->GetProperties(1,&DBPropIDSet,&cProperty,&pDBPropSet)))
{
goto CLEANUP;
}
if(V_BOOL(&pDBPropSet->rgProperties->vValue)==VARIANT_TRUE)
{
fSupported=TRUE;
}
CLEANUP:
FreeProperties(&cProperty,&pDBPropSet);
SAFE_RELEASE(pIRowsetInfo);
return fSupported;
}
//--------------------------------------------------------------------
//
//@mfun: Return TRUE if we are on buffered update mode
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::BufferedUpdate()
{
IRowsetInfo *pIRowsetInfo = NULL;
ULONG cProperty = 0;
DBPROPID DBPropID = DBPROP_IRowsetUpdate;
DBPROPIDSET DBPropIDSet;
DBPROPSET *pDBPropSet = NULL;
BOOL fSupported = FALSE;
//initialize
DBPropIDSet.guidPropertySet=DBPROPSET_ROWSET;
DBPropIDSet.cPropertyIDs=1;
DBPropIDSet.rgPropertyIDs=&DBPropID;
//QI for IRowsetInfo interface
TESTC_(m_pIRowset->QueryInterface(IID_IRowsetInfo,(LPVOID *)&pIRowsetInfo),S_OK);
//ask for IID_IRowsetUpdate
if(!SUCCEEDED(pIRowsetInfo->GetProperties(1,&DBPropIDSet,&cProperty,&pDBPropSet)))
goto CLEANUP;
if(V_BOOL(&pDBPropSet->rgProperties->vValue)==VARIANT_TRUE)
fSupported=TRUE;
CLEANUP:
FreeProperties(&cProperty,&pDBPropSet);
SAFE_RELEASE(pIRowsetInfo);
return fSupported;
}
//--------------------------------------------------------------------
//
//@mfunc: Get the Nullable and Updatable column ordinals arrays.
// Exclude the first columns
//
// The function allocation memory for the ordinals array. Return
// TURE is one or more nullable and updatable column exists'
// FALSE otherwise.
//
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::GetNullableAndUpdatable(
DBORDINAL *pcbCol, //[out] the count of the rgColNum
DBORDINAL **prgColNum //[out] the col ordinals array
)
{
ULONG cColsCount = 0;
//make sure the columns infomation has been retrieved and
//there is at least one column in the rowset
if(!m_rgInfo || !m_cRowsetCols)
return FALSE;
//initialization
*pcbCol=0;
*prgColNum=(DBORDINAL *)PROVIDER_ALLOC(sizeof(DBORDINAL) * m_cRowsetCols);
for(cColsCount=0;cColsCount<m_cRowsetCols;cColsCount++)
{
//exclude the first column
if(m_rgInfo[cColsCount].iOrdinal==1)
continue;
//if the col is long and not BLOB and either writeable or maybe writeable
//not BLOB because BOLBS are not bound in the accssor in places this function is used
if (
(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_ISNULLABLE) &&
!(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_ISLONG) &&
( (m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITE)||
(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN))
)
{
//copy the column number into the array
(*prgColNum)[*pcbCol]=m_rgInfo[cColsCount].iOrdinal;
//increase the count
(*pcbCol)++;
}
}
if(*pcbCol)
return TRUE;
return FALSE;
}
//--------------------------------------------------------------------
//
//@mfunc: Get the Not-Nullable and Updatable column ordinals arrays.
//
// The function allocation memory for the ordinals array. Return
// TURE is one or more nullable and updatable column exists'
// FALSE otherwise.
//
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::GetNotNullableAndUpdatable(
DBORDINAL *pcbCol, //[out] the count of the rgColNum
DBORDINAL **prgColNum //[out] the col ordinals array
)
{
ULONG cColsCount = 0;
//make sure the columns infomation has been retrieved and
//there is at least one column in the rowset
if(!m_rgInfo || !m_cRowsetCols)
return FALSE;
//initialization
*pcbCol = 0;
*prgColNum =(DBORDINAL *)PROVIDER_ALLOC(sizeof(DBORDINAL) * m_cRowsetCols);
for(cColsCount=0;cColsCount<m_cRowsetCols;cColsCount++)
{
if((!(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_ISNULLABLE)) &&
((m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITE)||
(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN)
)
)
{
//copy the column number into the array
(*prgColNum)[*pcbCol]=m_rgInfo[cColsCount].iOrdinal;
//increase the count
(*pcbCol)++;
}
}
if(*pcbCol)
return TRUE;
return FALSE;
}
//---------------------------------------------------------------------------------
//
// Get the updatable columns.
//
//
//---------------------------------------------------------------------------------
BOOL TCIRowsetChange::GetUpdatableCols( DBORDINAL *pcbCol,
DBORDINAL **prgColNum)
{
ULONG cColsCount=0;
//make sure the columns infomation has been retrieved and
//there is at least one column in the rowset
if(!m_rgInfo || !m_cRowsetCols)
return FALSE;
//initialization
*pcbCol=0;
*prgColNum=(DBORDINAL *)PROVIDER_ALLOC(sizeof(DBORDINAL) * m_cRowsetCols);
for(cColsCount=0;cColsCount<m_cRowsetCols;cColsCount++)
{
if(
(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITE)||
(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN)
)
{
//copy the column number into the array
(*prgColNum)[*pcbCol]=m_rgInfo[cColsCount].iOrdinal;
//increase the count
(*pcbCol)++;
}
}
if(*pcbCol)
return TRUE;
return FALSE;
}
//--------------------------------------------------------------------
//
//@mfunc: Get the Numeric and Updatable column ordinals arrays. The first
// column is excluded.
//
// The function allocation memory for the ordinals array. Return
// TURE is one or more numeric and updatable column exists
// FALSE otherwise.
//
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::GetNumericAndUpdatable(
DBORDINAL *pcbCol, //[out] the count of the rgColNum
DBORDINAL **prgColNum //[out] the col ordinals array
)
{
ULONG cColsCount = 0;
//initialization
*pcbCol=0;
*prgColNum=(DBORDINAL *)PROVIDER_ALLOC(sizeof(DBORDINAL) * m_cRowsetCols);
//make sure the columns infomation has been retrieved and
//there is at least one column in the rowset
if(!m_rgInfo || !m_cRowsetCols)
return FALSE;
for(cColsCount=0;cColsCount<m_cRowsetCols;cColsCount++)
{
//exclude the first column
if(m_rgInfo[cColsCount].iOrdinal==1)
continue;
if((IsNumericType(m_rgInfo[cColsCount].wType)) &&
((m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITE)||
(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN)
)
)
{
//copy the column number into the array
(*prgColNum)[*pcbCol]=m_rgInfo[cColsCount].iOrdinal;
//increase the count
(*pcbCol)++;
}
}
if(*pcbCol)
return TRUE;
return FALSE;
}
//--------------------------------------------------------------------
//
//@mfunc: Get the Numeric and Updatable column ordinals arrays. The first
// column is excluded.
//
// The function allocation memory for the ordinals array. Return
// TURE is one or more numeric and updatable column exists
// FALSE otherwise.
//
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::GetFloatAndUpdatable(
DBORDINAL *pcbCol, //[out] the count of the rgColNum
DBORDINAL **prgColNum //[out] the col ordinals array
)
{
ULONG cColsCount = 0;
//initialization
*pcbCol=0;
*prgColNum=(DBORDINAL *)PROVIDER_ALLOC(sizeof(DBORDINAL) * m_cRowsetCols);
//make sure the columns infomation has been retrieved and
//there is at least one column in the rowset
if(!m_rgInfo || !m_cRowsetCols)
return FALSE;
for(cColsCount=0;cColsCount<m_cRowsetCols;cColsCount++)
{
//exclude the first column
if(m_rgInfo[cColsCount].iOrdinal==1)
continue;
if(
(IsNumericType(m_rgInfo[cColsCount].wType)) &&
( (m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITE)||
(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN)) &&
(m_rgInfo[cColsCount].dwFlags & (~DBCOLUMNFLAGS_ISFIXEDLENGTH))
)
{
//copy the column number into the array
(*prgColNum)[*pcbCol]=m_rgInfo[cColsCount].iOrdinal;
//increase the count
(*pcbCol)++;
}
}
if(*pcbCol)
return TRUE;
return FALSE;
}
//--------------------------------------------------------------------
//
//@mfunc: Get the Fixed Length and Updatable column
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::GetFixedLengthAndUpdatable( DBORDINAL *pcbCol,
DBORDINAL **prgColNum)
{
ULONG cColsCount = 0;
//make sure the columns infomation has been retrieved and
//there is at least one column in the rowset
if(!m_rgInfo || !m_cRowsetCols)
return FALSE;
//initialization
*pcbCol=0;
*prgColNum=(DBORDINAL *)PROVIDER_ALLOC(sizeof(DBORDINAL) * m_cRowsetCols);
for(cColsCount=0;cColsCount<m_cRowsetCols;cColsCount++)
{
if( (IsFixedLength(m_rgInfo[cColsCount].wType)) &&
(m_rgInfo[cColsCount].wType == DBTYPE_I4 || m_rgInfo[cColsCount].wType == DBTYPE_I2) &&
( (m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITE)||
(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN))
)
{
//copy the column number into the array
(*prgColNum)[*pcbCol]=m_rgInfo[cColsCount].iOrdinal;
//increase the count
(*pcbCol)++;
}
}
if(*pcbCol)
return TRUE;
return FALSE;
}
//--------------------------------------------------------------------
//
//@mfunc: Get the NonKeyNonBLOB
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::GetNonKeyNonBLOB( DBORDINAL *pcbCol,
DBORDINAL **prgColNum)
{
ULONG cColsCount = 0;
//make sure the columns infomation has been retrieved and
//there is at least one column in the rowset
if(!m_rgInfo || !m_cRowsetCols)
{
return FALSE;
}
//initialization
*pcbCol=0;
*prgColNum=(DBORDINAL *)PROVIDER_ALLOC(sizeof(DBORDINAL) * m_cRowsetCols);
for(cColsCount=0;cColsCount<m_cRowsetCols;cColsCount++)
{
if(
( !(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_ISLONG)) &&
( (m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITE) ||
(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN))
)
{
//copy the column number into the array
(*prgColNum)[*pcbCol]=m_rgInfo[cColsCount].iOrdinal;
//increase the count
(*pcbCol)++;
}
}
if(*pcbCol)
{
return TRUE;
}
return FALSE;
}
//--------------------------------------------------------------------
//
//@mfunc: Get the Variable Length and Updatable column
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::GetVariableLengthAndUpdatable (
DBORDINAL *pcbCol,
DBORDINAL **prgColNum,
BOOL fLong,
BOOL fBytes
)
{
ULONG cColsCount = 0;
//make sure the columns infomation has been retrieved and
//there is at least one column in the rowset
if(!m_rgInfo || !m_cRowsetCols)
return FALSE;
//initialization
*pcbCol=0;
*prgColNum=(DBORDINAL *)PROVIDER_ALLOC(sizeof(DBORDINAL) * m_cRowsetCols);
for(cColsCount=0;cColsCount<m_cRowsetCols;cColsCount++)
{
if((!IsFixedLength(m_rgInfo[cColsCount].wType)) &&
((m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITE)||
(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN)
)
)
{
//get rid of the long column
if(!fLong && (m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_ISLONG))
continue;
if(!fBytes && (m_rgInfo[cColsCount].wType == DBTYPE_BYTES))
continue;
//copy the column number into the array
(*prgColNum)[*pcbCol]=m_rgInfo[cColsCount].iOrdinal;
//increase the count
(*pcbCol)++;
}
}
if(*pcbCol)
return TRUE;
return FALSE;
}
//--------------------------------------------------------------------
//
//@mfunc: Get the BLOB columns
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::GetBLOB( DBORDINAL *pcbCol,
DBORDINAL **prgColNum)
{
ULONG cColsCount = 0;
//make sure the columns infomation has been retrieved and
//there is at least one column in the rowset
if(!m_rgInfo || !m_cRowsetCols)
{
return FALSE;
}
//initialization
*pcbCol=0;
*prgColNum=(DBORDINAL *)PROVIDER_ALLOC(sizeof(DBORDINAL) * m_cRowsetCols);
for(cColsCount=0;cColsCount<m_cRowsetCols;cColsCount++)
{
if(
( (m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_ISLONG)) &&
( (m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITE) ||
(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN))
)
{
//copy the column number into the array
(*prgColNum)[*pcbCol]=m_rgInfo[cColsCount].iOrdinal;
//increase the count
(*pcbCol)++;
}
}
if(*pcbCol)
{
return TRUE;
}
return FALSE;
}
//--------------------------------------------------------------------
//
//@mfunc: Get an image column
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::GetImage( DBORDINAL *pcbCol,
DBORDINAL **prgColNum)
{
ULONG cColsCount = 0;
//make sure the columns infomation has been retrieved and
//there is at least one column in the rowset
if(!m_rgInfo || !m_cRowsetCols)
{
return FALSE;
}
//initialization
*pcbCol=0;
*prgColNum=(DBORDINAL *)PROVIDER_ALLOC(sizeof(DBORDINAL) * m_cRowsetCols);
for(cColsCount=0;cColsCount<m_cRowsetCols;cColsCount++)
{
if(m_rgInfo[cColsCount].wType == DBTYPE_BYTES)
{
//copy the column number into the array
(*prgColNum)[*pcbCol]=m_rgInfo[cColsCount].iOrdinal;
//increase the count
(*pcbCol)++;
}
}
if(*pcbCol)
{
return TRUE;
}
return FALSE;
}
//--------------------------------------------------------------------
//
//@mfunc: Get str columns
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::GetStr(
DBORDINAL *pcbCol,
DBORDINAL **prgColNum)
{
ULONG cColsCount = 0;
//make sure the columns infomation has been retrieved and
//there is at least one column in the rowset
if(!m_rgInfo || !m_cRowsetCols)
return FALSE;
//initialization
*pcbCol=0;
*prgColNum=(DBORDINAL *)PROVIDER_ALLOC(sizeof(DBORDINAL) * m_cRowsetCols);
for(cColsCount=0;cColsCount<m_cRowsetCols;cColsCount++)
{
if(( m_rgInfo[cColsCount].wType==DBTYPE_STR ||
m_rgInfo[cColsCount].wType==DBTYPE_WSTR
)
&&
((m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITE)||
(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN)
)
)
{
//copy the column number into the array
(*prgColNum)[*pcbCol]=m_rgInfo[cColsCount].iOrdinal;
//increase the count
(*pcbCol)++;
}
}
if(*pcbCol)
{
return TRUE;
}
return FALSE;
}
//--------------------------------------------------------------------
//
//@mfunc: Get not updatable column
//
//--------------------------------------------------------------------
ULONG TCIRowsetChange::GetAllButFirst(DBORDINAL *pcbCol,
DBORDINAL **prgColNum)
{
ULONG cColsCount = 0;
//make sure the columns infomation has been retrieved and
//there is at least one column in the rowset
if(!m_rgInfo || !m_cRowsetCols)
return FALSE;
//initialization
*pcbCol=0;
*prgColNum=(DBORDINAL *)PROVIDER_ALLOC(sizeof(DBORDINAL) * m_cRowsetCols);
for(cColsCount=0;cColsCount<m_cRowsetCols;cColsCount++)
{
if(m_rgInfo[cColsCount].iOrdinal!=1 && m_rgInfo[cColsCount].iOrdinal!=0)
{
//copy the column number into the array
(*prgColNum)[*pcbCol]=m_rgInfo[cColsCount].iOrdinal;
//increase the count
(*pcbCol)++;
}
}
if(*pcbCol)
return TRUE;
return FALSE;
}
//--------------------------------------------------------------------
//
//@mfunc: Get not updatable column
//
//--------------------------------------------------------------------
ULONG TCIRowsetChange::GetNotUpdatable( DBORDINAL *pcbCol,
DBORDINAL **prgColNum)
{
ULONG cColsCount;
//make sure the columns infomation has been retrieved and
//there is at least one column in the rowset
if(!m_rgInfo || !m_cRowsetCols)
return FALSE;
//initialization
*pcbCol=0;
*prgColNum=(DBORDINAL *)PROVIDER_ALLOC(sizeof(DBORDINAL) * m_cRowsetCols);
for(cColsCount=0;cColsCount<m_cRowsetCols;cColsCount++)
{
//skip column 0
if(m_rgInfo[cColsCount].iOrdinal==0)
continue;
if(!(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITE) &&
!(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN)
)
{
//copy the column number into the array
(*prgColNum)[*pcbCol]=m_rgInfo[cColsCount].iOrdinal;
//increase the count
(*pcbCol)++;
}
}
if(*pcbCol)
return TRUE;
return FALSE;
}
//--------------------------------------------------------------------
//
//@mfunc: verify the position of the row handle in the row set
//
// Precondition: The function has to be called after GetRowsetAndAccessor that
// creates a rowset and an accessor
//
//--------------------------------------------------------------------
BOOL TCIRowsetChange::VerifyRowPosition(
HROW hRow, //row handle
ULONG cRow, //potision expected
EVALUE eValue) //eValue for MakeData
{
//m_pIRowset has to be valid
if(!m_pIRowset || !m_pData)
return FALSE;
//Get Data for the row
if(!CHECK(GetData(hRow,m_hAccessor,m_pData),S_OK))
return FALSE;
//compare the data with the row expected in the rowset
if(!CompareData(m_cRowsetCols,m_rgTableColOrds,cRow,m_pData,m_cBinding,
m_rgBinding,m_pTable,m_pIMalloc,eValue))
return FALSE;
return TRUE;
}
//--------------------------------------------------------------------
//@mfunc: free the memory referenced by the consumer's buffer
// The function has to be called after IRowset::GetData()
//
//--------------------------------------------------------------------
void TCIRowsetChange::FreeMemory()
{
//make sure m_pData is not NULL
if(!COMPARE(!m_pData, NULL))
return;
//call compareData with the option to free the memory referenced by the consumer's
//buffer without comparing data
CompareData(m_cRowsetCols,m_rgTableColOrds,1,m_pData,m_cBinding,m_rgBinding,
m_pTable, m_pIMalloc,PRIMARY,FREE_ONLY);
return;
}
//--------------------------------------------------------------------
//@mfunc: release an accessor created on the rowset object
//
//--------------------------------------------------------------------
void TCIRowsetChange::ReleaseAccessorOnRowset()
{
//reset m_cRowset to 0 so that provider will allocate memory for next time
m_cRowSize=0;
m_cBinding=0;
//free the consumer buffer
PROVIDER_FREE(m_pData);
//free accessor handle
if(m_hAccessor)
{
//if the accessor is created on the rowset object, use the IAccssor
//pointer directly to release the accessor handle
if(m_eAccessorLocation!=ON_COMMAND_ACCESSOR)
{
CHECK(m_pIAccessor->ReleaseAccessor(m_hAccessor,NULL), S_OK);
m_hAccessor=NULL;
}
else
odtLog<<L"Error: Can not release accessor on the command object!"<<ENDL;
}
//free binding structure
PROVIDER_FREE(m_rgBinding);
}
//--------------------------------------------------------------------
//@mfunc: release a rowset object and accessor created on it
//
//--------------------------------------------------------------------
void TCIRowsetChange::ReleaseRowsetAndAccessor(ULONG RowRefCnt, ULONG CmdRefCnt)
{
IAccessor *pIAccessor = NULL;
//reset m_cRowset to 0 so that provider will allocate memory for next time
m_cRowSize=0;
m_cBinding=0;
// Set the DBPROP_UPDATABILITY back to DBPROPVAL_UP_CHANGE
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE;
//free the consumer buffer
PROVIDER_FREE(m_pData);
//free accessor handle, if a rowset Accessor
if(m_hAccessor && m_pIAccessor && m_eAccessorLocation!=ON_COMMAND_ACCESSOR)
{
CHECK(m_pIAccessor->ReleaseAccessor(m_hAccessor,NULL), S_OK);
m_hAccessor=NULL;
}
//free accessor handle, if a command Accessor
if(m_hAccessor && m_pICommand && m_eAccessorLocation==ON_COMMAND_ACCESSOR)
{
//QI for the accessor handle on the command object
if(CHECK(m_pICommand->QueryInterface(IID_IAccessor, (void**)&pIAccessor),S_OK))
CHECK(pIAccessor->ReleaseAccessor(m_hAccessor,NULL), S_OK);
}
//Release accessors
SAFE_RELEASE(pIAccessor);
SAFE_RELEASE(m_pIAccessor);
m_hAccessor=NULL;
//release IRowset pointer
SAFE_RELEASE(m_pIRowset);
SAFE_RELEASE(m_pIRowsetChange);
SAFE_RELEASE(m_pIRowsetIdentity);
SAFE_RELEASE(m_pIRowsetUpdate);
SAFE_RELEASE(m_pIRowsetLocate);
//free binding structure
PROVIDER_FREE(m_rgBinding);
PROVIDER_FREE(m_rgInfo);
PROVIDER_FREE(m_pStringsBuffer);
ReleaseRowsetObject(RowRefCnt);
ReleaseCommandObject(CmdRefCnt);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Test Case Section
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// {{ TCW_TEST_CASE_MAP(Boundary)
//--------------------------------------------------------------------
// @class Testing boundary conditions
//
class Boundary : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
DBPROPID m_rgPropertyIDs[3];
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Boundary,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember immediate update mode. Null Accessor, valid pData with DBPROPVAL_UP_CHANGE
int Variation_1();
// @cmember immediate update mode. Null Accessor, NULL pData with DBPROPVAL_UP_CHANGE
int Variation_2();
// @cmember immediate update mode. NULL pData. E_INVALIDARG
int Variation_3();
// @cmember buffered update mode. NULL accessor and NULL pData with DBPROPVAL_UP_CHANGE
int Variation_4();
// @cmember immediate update mode. Null Accessor, valid pData with DBPROPVAL_UP_CHANGE
int Variation_5();
// @cmember buffered update mode. NULL accessor and NULL pData with DBPROPVAL_UP_CHANGE
int Variation_6();
// @cmember immediate update mode. Valid accessor with bad ordinals
int Variation_7();
// @cmember immediate update mode. OPTIMIZED accessor after a Fetch (DB_E_BADACCESSORFLAGS)
int Variation_8();
// @cmember immediate update mode. Valid accessor with different Parameter Accessor Flags
int Variation_9();
// @cmember immediate update mode. Valid accessor with different Row Accessor Flags
int Variation_10();
// @cmember inherited parameter accessors with SetData
int Variation_11();
// @cmember immediate update mode. more Valid accessor with bad ordinals
int Variation_12();
// @cmember immediate update mode. get bookmarks on inheritied accessor
int Variation_13();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Boundary)
#define THE_CLASS Boundary
BEG_TEST_CASE(Boundary, TCIRowsetChange, L"Testing boundary conditions")
TEST_VARIATION(1, L"immediate update mode. Null Accessor, valid pData with DBPROPVAL_UP_CHANGE")
TEST_VARIATION(2, L"immediate update mode. Null Accessor, NULL pData with DBPROPVAL_UP_CHANGE")
TEST_VARIATION(3, L"immediate update mode. NULL pData. E_INVALIDARG")
TEST_VARIATION(4, L"buffered update mode. NULL accessor and NULL pData with DBPROPVAL_UP_CHANGE")
TEST_VARIATION(5, L"immediate update mode. Null Accessor, valid pData with DBPROPVAL_UP_CHANGE")
TEST_VARIATION(6, L"buffered update mode. NULL accessor and NULL pData with DBPROPVAL_UP_CHANGE")
TEST_VARIATION(7, L"immediate update mode. Valid accessor with bad ordinals")
TEST_VARIATION(8, L"immediate update mode. OPTIMIZED accessor after a Fetch (DB_E_BADACCESSORFLAGS)")
TEST_VARIATION(9, L"immediate update mode. Valid accessor with different Parameter Accessor Flags")
TEST_VARIATION(10, L"immediate update mode. Valid accessor with different Row Accessor Flags")
TEST_VARIATION(11, L"inherited parameter accessors with SetData")
TEST_VARIATION(12, L"immediate update mode. more Valid accessor with bad ordinals")
TEST_VARIATION(13, L"immediate update mode. get bookmarks on inheritied accessor")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Rowsets)
//--------------------------------------------------------------------
// @class Testing read-only rowset and empty
//
class Rowsets : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Rowsets,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Read-only rowset with
int Variation_1();
// @cmember Read only rowset with left outer join.DB_E_PROPERTIESNOTAVAILABLE.
int Variation_2();
// @cmember Read only rowset with right outer join.DB_E_PROPERTIESNOTAVAILABLE.
int Variation_3();
// @cmember Empty rowset. S_OK
int Variation_4();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Rowsets)
#define THE_CLASS Rowsets
BEG_TEST_CASE(Rowsets, TCIRowsetChange, L"Testing read-only rowset and empty")
TEST_VARIATION(1, L"Read-only rowset with")
TEST_VARIATION(2, L"Read only rowset with left outer join.DB_E_PROPERTIESNOTAVAILABLE.")
TEST_VARIATION(3, L"Read only rowset with right outer join.DB_E_PROPERTIESNOTAVAILABLE.")
TEST_VARIATION(4, L"Empty rowset. S_OK")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(MayWriteColumn)
//--------------------------------------------------------------------
// @class test DBPROP_MAYWRITECOLUMN
//
class MayWriteColumn : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(MayWriteColumn,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Make sure MSDASQL does not support DBPROP_MAYWRITECOLUMN
int Variation_1();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(MayWriteColumn)
#define THE_CLASS MayWriteColumn
BEG_TEST_CASE(MayWriteColumn, TCIRowsetChange, L"test DBPROP_MAYWRITECOLUMN")
TEST_VARIATION(1, L"Make sure MSDASQL does not support DBPROP_MAYWRITECOLUMN")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(MaxPendingChangeRows)
//--------------------------------------------------------------------
// @class test DBPROP_MAXPENDINGCHANGEROWS
//
class MaxPendingChangeRows : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(MaxPendingChangeRows,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Verify DBPROP_MAXPENDINGROWS
int Variation_1();
// @cmember Verify DBPROP_MAXOPENROWS
int Variation_2();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(MaxPendingChangeRows)
#define THE_CLASS MaxPendingChangeRows
BEG_TEST_CASE(MaxPendingChangeRows, TCIRowsetChange, L"test DBPROP_MAXPENDINGCHANGEROWS")
TEST_VARIATION(1, L"Verify DBPROP_MAXPENDINGROWS")
TEST_VARIATION(2, L"Verify DBPROP_MAXOPENROWS")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(CacheDeferred)
//--------------------------------------------------------------------
// @class test DBPROP_CACHEDEFERRED
//
class CacheDeferred : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(CacheDeferred,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Kagera does not support DBPROP_CACHDEFERRED
int Variation_1();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(CacheDeferred)
#define THE_CLASS CacheDeferred
BEG_TEST_CASE(CacheDeferred, TCIRowsetChange, L"test DBPROP_CACHEDEFERRED")
TEST_VARIATION(1, L"to be coded")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(NoColumn_Row_Restrict)
//--------------------------------------------------------------------
// @class test DBPROP_NOCOLUMNRESTRICT and DBPROP_NOROWRESTRICT
//
class NoColumn_Row_Restrict : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(NoColumn_Row_Restrict,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Select Count(*)
int Variation_1();
// @cmember Select * from Table. Restrict on table. No restrict on column
int Variation_2();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(NoColumn_Row_Restrict)
#define THE_CLASS NoColumn_Row_Restrict
BEG_TEST_CASE(NoColumn_Row_Restrict, TCIRowsetChange, L"test DBPROP_NOCOLUMNRESTRICT and DBPROP_NOROWRESTRICT")
TEST_VARIATION(1, L"Select Count(*)")
TEST_VARIATION(2, L"Select * from Table. Restrict on table. No restrict on column")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Computed_Columns)
//--------------------------------------------------------------------
// @class test rowset with computed columns
//
class Computed_Columns : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Computed_Columns,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Accessor binds the computed column. DB_SEC_E_PERMISSIONDENIED
int Variation_1();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Computed_Columns)
#define THE_CLASS Computed_Columns
BEG_TEST_CASE(Computed_Columns, TCIRowsetChange, L"test rowset with computed columns")
TEST_VARIATION(1, L"Accessor binds the computed column. DB_SEC_E_PERMISSIONDENIED")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Forward_Query)
//--------------------------------------------------------------------
// @class forward only cursor. Query based update
//
class Forward_Query : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Forward_Query,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Immediate update mode. Retrieve a row handle, update a row with some columns set to NULL, and call GetData to see the change.
int Variation_1();
// @cmember Buffered update mode. Retrieve a row handle, update a row with some columns set to NULL, and call GetData to see the change
int Variation_2();
// @cmember Boundary cases with qbu cursor
int Variation_3();
// @cmember DBSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALUE, qbu
int Variation_4();
// @cmember SetData not supported, qbu
int Variation_5();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Forward_Query)
#define THE_CLASS Forward_Query
BEG_TEST_CASE(Forward_Query, TCIRowsetChange, L"forward only cursor. Query based update")
TEST_VARIATION(1, L"Immediate update mode. Retrieve a row handle, update a row with some columns set to NULL, and call GetData to see the change.")
TEST_VARIATION(2, L"Buffered update mode. Retrieve a row handle, update a row with some columns set to NULL, and call GetData to see the change")
TEST_VARIATION(3, L"Boundary cases with qbu cursor")
TEST_VARIATION(4, L"DBSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALUE, qbu")
TEST_VARIATION(5, L"SetData not supported, qbu")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Forward_Cursor)
//--------------------------------------------------------------------
// @class Forward only cursor. Cursor based update.
//
class Forward_Cursor : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Forward_Cursor,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Immediate update mode. Retrieve a row handle, update a row with some columns set to NULL, and call GetData to see the change.
int Variation_1();
// @cmember Buffered update mode. Retrieve a row handle, update a row with some columns set to NULL, and call GetData to see the change
int Variation_2();
// @cmember Change a row with DBTYPE_BYREF. cbMaxLen > string length, no truncation should occur, SetData should return S_OK.
int Variation_3();
// @cmember Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see
int Variation_4();
// @cmember Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see
int Variation_5();
// @cmember Insert a row and check to see it (OWNINSERT is off)
int Variation_6();
// @cmember set ACCESSOR_ORDER to RANDOM with forward only cursor of BLOBS are cached, SetData
int Variation_7();
// @cmember set ACCESSOR_ORDER to RANDOM with forward only cursor of BLOBS are cached, Insert
int Variation_8();
// @cmember Fail the SetData and check that the status of the remaining unset cols is DBSTATUS_E_UNAVAILABLE
int Variation_9();
// @cmember The accessor only has status binding for DBSTATUS_S_OK
int Variation_10();
// @cmember The accessor only has status binding for DBSTATUS_S_ISNULL
int Variation_11();
// @cmember The status flag specified in a binding structure is neither DBSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALUE
int Variation_12();
// @cmember SetData the variable length columns without the length being bound. should be ok
int Variation_13();
// @cmember Buffered update mode. Multiple commands that modify same set of columns in hrow
int Variation_14();
// @cmember SetData in a read only rowset
int Variation_15();
// @cmember The accessor only has length binding. E_FAIL.
int Variation_16();
// @cmember The length binding > cbMaxLen for a variable length column. (DB_S_ERRORSOCCURRED)
int Variation_17();
// @cmember check for truncation in variable length columns
int Variation_18();
// @cmember Delete-Insert-undoDelete-Update
int Variation_19();
// @cmember check status NULL if no row handles used
int Variation_20();
// @cmember The length binding > cbMaxLen for a variable length column with no status bound. (DB_S_ERRORSOCCURRED)
int Variation_21();
// @cmember check for truncation in variable length columns with no status bound.
int Variation_22();
// @cmember QI check
int Variation_23();
// @cmember check for truncation in fixed length columns
int Variation_24();
// @cmember bind BLOBs as IUnKnown
int Variation_25();
// @cmember DBPROP_IRowsetChange FALSE with UPDATABILITY - conflicting
int Variation_26();
// @cmember DBPROP_IRowsetChange and DBPROP_IRowsetUpdate
int Variation_27();
// @cmember change multiple cols with some failures
int Variation_28();
// @cmember set no data in a BLOB column
int Variation_29();
// @cmember InsertRows and DBPROP_MAX
int Variation_30();
// @cmember Insert no BLOB, change BLOB
int Variation_31();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Forward_Cursor)
#define THE_CLASS Forward_Cursor
BEG_TEST_CASE(Forward_Cursor, TCIRowsetChange, L"Forward only cursor. Cursor based update.")
TEST_VARIATION(1, L"Immediate update mode. Retrieve a row handle, update a row with some columns set to NULL, and call GetData to see the change.")
TEST_VARIATION(2, L"Buffered update mode. Retrieve a row handle, update a row with some columns set to NULL, and call GetData to see the change")
TEST_VARIATION(3, L"Change a row with DBTYPE_BYREF. cbMaxLen > string length, no truncation should occur, SetData should return S_OK.")
TEST_VARIATION(4, L"Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see")
TEST_VARIATION(5, L"Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see")
TEST_VARIATION(6, L"Insert a row and check to see it (OWNINSERT is off)")
TEST_VARIATION(7, L"Set ACCESSOR_ORDER to RANDOM with forward only cursor of BLOBS are cached, SetData")
TEST_VARIATION(8, L"Set ACCESSOR_ORDER to RANDOM with forward only cursor of BLOBS are cached, Insert")
TEST_VARIATION(9, L"Fail the SetData and check that the status of the remaining unset cols is DBSTATUS_E_UNAVAILABLE")
TEST_VARIATION(10, L"The accessor only has status binding for DBSTATUS_S_OK")
TEST_VARIATION(11, L"The accessor only has status binding for DBSTATUS_S_ISNULL")
TEST_VARIATION(12, L"The status flag specified in a binding structure is neither DBSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALUE")
TEST_VARIATION(13, L"SetData the variable length columns without the length being bound. should be ok")
TEST_VARIATION(14, L"Buffered update mode. Multiple commands that modify same set of columns in hrow")
TEST_VARIATION(15, L"SetData in a read only rowset")
TEST_VARIATION(16, L"The accessor only has length binding. E_FAIL.")
TEST_VARIATION(17, L"The length binding > cbMaxLen for a variable length column. (DB_S_ERRORSOCCURRED)")
TEST_VARIATION(18, L"check for truncation in variable length columns.")
TEST_VARIATION(19, L"Delete-Insert-undoDelete-Update")
TEST_VARIATION(20, L"check status NULL if no row handles used")
TEST_VARIATION(21, L"The length binding > cbMaxLen for a variable length column with no status bound. (DB_S_ERRORSOCCURRED)")
TEST_VARIATION(22, L"check for truncation in variable length columns with no status bound.")
TEST_VARIATION(23, L"QI check.")
TEST_VARIATION(24, L"check for truncation in fixed length columns.")
TEST_VARIATION(25, L"bind BLOBs as IUnKnown")
TEST_VARIATION(26, L"DBPROP_IRowsetChange FALSE with UPDATABILITY - conflicting")
TEST_VARIATION(27, L"DBPROP_IRowsetChange and DBPROP_IRowsetUpdate")
TEST_VARIATION(28, L"change multiple cols with some failures")
TEST_VARIATION(29, L"set no data in a BLOB column")
TEST_VARIATION(30, L"InsertRows and DBPROP_MAX")
TEST_VARIATION(31, L"Insert no BLOB, change BLOB")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(QueryBaseUpdates)
//--------------------------------------------------------------------
// @class Test QueryBaseUpdates that update more than one rows.
//
class QueryBaseUpdates : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(QueryBaseUpdates,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Immediate update mode. Update one non-key column with values that affect more than one rows. Verify the change is visible
int Variation_1();
// @cmember Buffered update mode. Update one non-key column with values that affect more than one rows. Verify the change is visible the
int Variation_2();
// @cmember Boundary checks from a static cursor
int Variation_3();
// @cmember NEWLYINSERTED from a static cursor
int Variation_4();
// @cmember key non-key cols, set 2 rows the same and delete
int Variation_5();
// @cmember Delete rows from a static cursor/immediate mode, delete not supported
int Variation_6();
// @cmember delete with a row handle from an unallocated rowset
int Variation_7();
// @cmember delete with a row handle from an allocated rowset
int Variation_8();
// @cmember Boundary cases with update pending
int Variation_9();
// @cmember BSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALUE, qbu
int Variation_10();
// @cmember SetData not supported, qbu
int Variation_11();
// @cmember QBU with just floats
int Variation_12();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(QueryBaseUpdates)
#define THE_CLASS QueryBaseUpdates
BEG_TEST_CASE(QueryBaseUpdates, TCIRowsetChange, L"Test QueryBaseUpdates that update more than one rows.")
TEST_VARIATION(1, L"Immediate update mode. Update one non-key column with values that affect more than one rows. Verify the change is visible")
TEST_VARIATION(2, L"Buffered update mode. Update one non-key column with values that affect more than one rows. Verify the change is visible")
TEST_VARIATION(3, L"Boundary checks from a update pending")
TEST_VARIATION(4, L"NEWLYINSERTED from update pending")
TEST_VARIATION(5, L"key non-key cols, set 2 rows the same and delete")
TEST_VARIATION(6, L"Delete rows from a update pending mode, delete not supported")
TEST_VARIATION(7, L"delete with a row handle from an unallocated rowset")
TEST_VARIATION(8, L"delete with a row handle from an allocated rowset")
TEST_VARIATION(9, L"Boundary cases with update pending")
TEST_VARIATION(10, L"BSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALUE, qbu")
TEST_VARIATION(11, L"SetData not supported, qbu")
TEST_VARIATION(12, L"QBU with just floats")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Static_Cursor_Immediate)
//--------------------------------------------------------------------
// @class Static cursor in immediate update mode.
//
class Static_Cursor_Immediate : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Static_Cursor_Immediate,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Update a row to be the first row in the row set with some columns set to NULL, and call GetData to see.
int Variation_1();
// @cmember Retrive a row handle. Move the cursor to the end of the rowset. Retrieve the row handle again.
int Variation_2();
// @cmember Retrive a row handle. Move the cursor to the beginning of the rowset. Retrieve the row handle again
int Variation_3();
// @cmember Create two rowsets on the same table. One rowset changes a value. The other rowset should not see change
int Variation_4();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Static_Cursor_Immediate)
#define THE_CLASS Static_Cursor_Immediate
BEG_TEST_CASE(Static_Cursor_Immediate, TCIRowsetChange, L"Static cursor in immediate update mode.")
TEST_VARIATION(1, L"Update a row to be the first row in the row set with some columns set to NULL, and call GetData to see.")
TEST_VARIATION(2, L"Retrive a row handle. Move the cursor to the end of the rowset. Retrieve the row handle again.")
TEST_VARIATION(3, L"Retrive a row handle. Move the cursor to the beginning of the rowset. Retrieve the row handle again")
TEST_VARIATION(4, L"Create two rowsets on the same table. One rowset changes a value. The other rowset should not see change")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Static_Cursor_Buffered)
//--------------------------------------------------------------------
// @class Static_Cursor_Buffered
//
class Static_Cursor_Buffered : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Static_Cursor_Buffered,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see
int Variation_1();
// @cmember Retrive a row handle. Move the cursor to the end of the rowset. Retrieve the row handle again
int Variation_2();
// @cmember Retrive a row handle. Move the cursor to the beginning of the rowset. Retrieve the row handle again.
int Variation_3();
// @cmember Create two rowsets on the same table. One rowset changes a value. The other rowset should not see change
int Variation_4();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Static_Cursor_Buffered)
#define THE_CLASS Static_Cursor_Buffered
BEG_TEST_CASE(Static_Cursor_Buffered, TCIRowsetChange, L"Static_Cursor_Buffered")
TEST_VARIATION(1, L"Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see")
TEST_VARIATION(2, L"Retrive a row handle. Move the cursor to the end of the rowset. Retrieve the row handle again")
TEST_VARIATION(3, L"Retrive a row handle. Move the cursor to the beginning of the rowset. Retrieve the row handle again.")
TEST_VARIATION(4, L"Create two rowsets on the same table. One rowset changes a value. The other rowset should not see change")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Keyset_Cursor_Buffered)
//--------------------------------------------------------------------
// @class Keyset_Cursor_Buffered
//
class Keyset_Cursor_Buffered : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Keyset_Cursor_Buffered,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see
int Variation_1();
// @cmember Retrive a row handle. Move the cursor to the end of the rowset. Retrieve the row handle again
int Variation_2();
// @cmember Retrive a row handle. Move the cursor to the beginning of the rowset. Retrieve the row handle again.
int Variation_3();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Keyset_Cursor_Buffered)
#define THE_CLASS Keyset_Cursor_Buffered
BEG_TEST_CASE(Keyset_Cursor_Buffered, TCIRowsetChange, L"Keyset_Cursor_Buffered")
TEST_VARIATION(1, L"Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see")
TEST_VARIATION(2, L"Retrive a row handle. Move the cursor to the end of the rowset. Retrieve the row handle again")
TEST_VARIATION(3, L"Retrive a row handle. Move the cursor to the beginning of the rowset. Retrieve the row handle again.")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Keyset_Remove_Cursor_Immediate)
//--------------------------------------------------------------------
// @class Keyset_Remove_Curosr_Buffered
//
class Keyset_Remove_Cursor_Immediate : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Keyset_Remove_Cursor_Immediate,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see
int Variation_1();
// @cmember DBPROP_CHANGEINSERTEDROWS is VARIANT_TRUE, should not see DB_E_NEWLYINSERTED
int Variation_2();
// @cmember DBPROP_SERVERDATAONINSERT is VARIANT_TRUE, should not see DB_E_NEWLYINSERTED
int Variation_3();
// @cmember Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see
int Variation_4();
// @cmember fetch newly deleted row
int Variation_5();
// @cmember Insert a row and check to see it (OWNINSERT is off)
int Variation_6();
// @cmember Boundary cases cursor.
int Variation_7();
// @cmember BSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALUE
int Variation_8();
// @cmember SetData not supported.
int Variation_9();
// @cmember Fetch after a deleted row
int Variation_10();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Keyset_Remove_Cursor_Immediate)
#define THE_CLASS Keyset_Remove_Cursor_Immediate
BEG_TEST_CASE(Keyset_Remove_Cursor_Immediate, TCIRowsetChange, L"Keyset_Remove_Curosr_Buffered")
TEST_VARIATION(1, L"Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see")
TEST_VARIATION(2, L"DBPROP_CHANGEINSERTEDROWS is VARIANT_TRUE, should not see DB_E_NEWLYINSERTED")
TEST_VARIATION(3, L"DBPROP_SERVERDATAONINSERT is VARIANT_TRUE, should not see DB_E_NEWLYINSERTED")
TEST_VARIATION(4, L"Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see")
TEST_VARIATION(5, L"Fetch newly deleted row")
TEST_VARIATION(6, L"Insert a row and check to see it (OWNINSERT is off)")
TEST_VARIATION(7, L"Boundary cases cursor.")
TEST_VARIATION(8, L"BSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALUE")
TEST_VARIATION(9, L"SetData not supported.")
TEST_VARIATION(10, L"Fetch after a deleted row.")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Keyset_Remove_Buffered)
//--------------------------------------------------------------------
// @class Keyset_Remove_Buffered
//
class Keyset_Remove_Buffered : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Keyset_Remove_Buffered,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see
int Variation_1();
// @cmember Retrieve row, update row update pending don't release handle, GetData RETURNPENDINGINSERTS FALSE
int Variation_2();
// @cmember Error should NULL out hRow
int Variation_3();
// @cmember DB_E_ROWSNOTRELEASED
int Variation_4();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Keyset_Remove_Buffered)
#define THE_CLASS Keyset_Remove_Buffered
BEG_TEST_CASE(Keyset_Remove_Buffered, TCIRowsetChange, L"Keyset_Remove_Buffered")
TEST_VARIATION(1, L"Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see")
TEST_VARIATION(2, L"Retrieve row, update row update pending don't release handle, GetData RETURNPENDINGINSERTS FALSE")
TEST_VARIATION(3, L"Error should NULL out hRow")
TEST_VARIATION(4, L"DB_E_ROWSNOTRELEASED")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Dynamic_Cursor_Buffered)
//--------------------------------------------------------------------
// @class Dynamic_Cursor_Buffered
//
class Dynamic_Cursor_Buffered : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Dynamic_Cursor_Buffered,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see
int Variation_1();
// @cmember Retrive a row handle. Move the cursor to the end of the rowset. Retrieve the row handle again
int Variation_2();
// @cmember Retrive a row handle. Move the cursor to the beginning of the rowset. Retrieve the row handle again.
int Variation_3();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Dynamic_Cursor_Buffered)
#define THE_CLASS Dynamic_Cursor_Buffered
BEG_TEST_CASE(Dynamic_Cursor_Buffered, TCIRowsetChange, L"Dynamic_Cursor_Buffered")
TEST_VARIATION(1, L"Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see")
TEST_VARIATION(2, L"Retrive a row handle. Move the cursor to the end of the rowset. Retrieve the row handle again")
TEST_VARIATION(3, L"Retrive a row handle. Move the cursor to the beginning of the rowset. Retrieve the row handle again.")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Visible_Forward_Cursor)
//--------------------------------------------------------------------
// @class visibility of row handles
//
class Visible_Forward_Cursor : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Visible_Forward_Cursor,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember In immediate update mode, call SetData to change a non-key column. Make sure the update is visible after RestartPosition.
int Variation_1();
// @cmember In buffered update mode, call SetData to change a non-key column. Make sure the update is visible after RestartPosition.
int Variation_2();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Visible_Forward_Cursor)
#define THE_CLASS Visible_Forward_Cursor
BEG_TEST_CASE(Visible_Forward_Cursor, TCIRowsetChange, L"visibility of row handles")
TEST_VARIATION(1, L"In immediate update mode, call SetData to change a non-key column. Make sure the update is visible after RestartPosition.")
TEST_VARIATION(2, L"In buffered update mode, call SetData to change a non-key column. Make sure the update is visible after RestartPosition.")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Visible_Static_Cursor)
//--------------------------------------------------------------------
// @class visibility of row handles
//
class Visible_Static_Cursor : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Visible_Static_Cursor,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember In immediate update mode, call SetData to change a non key column. Move the cursor to the end of the rowset. RestartPosition
int Variation_1();
// @cmember In buffered update mode, call SetData to change a non key column. Move the cursor to the end of the rowset. RestartPosition
int Variation_2();
// @cmember In immediate update mode. Create two rowsets on the same table. One rowset changes a key value. The other rowset should no
int Variation_3();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Visible_Static_Cursor)
#define THE_CLASS Visible_Static_Cursor
BEG_TEST_CASE(Visible_Static_Cursor, TCIRowsetChange, L"visibility of row handles")
TEST_VARIATION(1, L"In immediate update mode, call SetData to change a non key column. Move the cursor to the end of the rowset. RestartPosition")
TEST_VARIATION(2, L"In buffered update mode, call SetData to change a non key column. Move the cursor to the end of the rowset. RestartPosition")
TEST_VARIATION(3, L"In immediate update mode. Create two rowsets on the same table. One rowset changes a key value. The other rowset should no")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Visible_Keyset_Command_Cursor)
//--------------------------------------------------------------------
// @class Visible_Keyset_Command_Cursor
//
class Visible_Keyset_Command_Cursor : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Visible_Keyset_Command_Cursor,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember In immediate update mode. Create two rowsets on the same table. The second rowset change a row
int Variation_1();
// @cmember In immediate update mode. Create two rowsets on the same table. The second rowset change a non key column.
int Variation_2();
// @cmember In buffered update mode. Create two rowsets on the same table. The second rowset change a row
int Variation_3();
// @cmember In buffered update mode. Create two rowsets on the same table. The second rowset change a non key column.
int Variation_4();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Visible_Keyset_Command_Cursor)
#define THE_CLASS Visible_Keyset_Command_Cursor
BEG_TEST_CASE(Visible_Keyset_Command_Cursor, TCIRowsetChange, L"Visible_Keyset_Command_Cursor")
TEST_VARIATION(1, L"In immediate update mode. Create two rowsets on the same table. The second rowset change a row")
TEST_VARIATION(2, L"In immediate update mode. Create two rowsets on the same table. The second rowset change a non key column.")
TEST_VARIATION(3, L"In buffered update mode. Create two rowsets on the same table. The second rowset change a row")
TEST_VARIATION(4, L"In buffered update mode. Create two rowsets on the same table. The second rowset change a non key column.")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Visible_Dynamic_Command_Cursor)
//--------------------------------------------------------------------
// @class Visible_Dynamic_Command_Cursor
//
class Visible_Dynamic_Command_Cursor : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Visible_Dynamic_Command_Cursor,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember In immediate update mode. Create two rowsets on the same table. The second rowset change a row
int Variation_1();
// @cmember In buffered update mode. Create two rowsets on the same table. The second rowset change a non-key column.
int Variation_2();
// @cmember Immediate update mode. A second command object deletes one row by SQL text.
int Variation_3();
// @cmember Immediate update mode. A second commnd object changes one row by SQL text.
int Variation_4();
// @cmember Buffered update mode. A second commnd object changes one row by SQL text.
int Variation_5();
// @cmember DBPROP_CHANGEINSERTEDROWS-TRUE.A second commnd object change a row by SQL text.It tries to change same row again-succeeds.
int Variation_6();
// @cmember DBPROP_CHANGEINSERTEDROWS-FALSE.A second commnd object change a row by SQL text.It tries to change same row again-fails.
int Variation_7();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Visible_Dynamic_Command_Cursor)
#define THE_CLASS Visible_Dynamic_Command_Cursor
BEG_TEST_CASE(Visible_Dynamic_Command_Cursor, TCIRowsetChange, L"Visible_Dynamic_Command_Cursor")
TEST_VARIATION(1, L"In immediate update mode. Create two rowsets on the same table. The second rowset change a row")
TEST_VARIATION(2, L"In buffered update mode. Create two rowsets on the same table. The second rowset change a non-key column.")
TEST_VARIATION(3, L"Immediate update mode. A second command object deletes one row by SQL text.")
TEST_VARIATION(4, L"Immediate update mode. A second commnd object changes one row by SQL text.")
TEST_VARIATION(5, L"Buffered update mode. A second commnd object changes one row by SQL text.")
TEST_VARIATION(6, L"DBPROP_CHANGEINSERTEDROWS-TRUE.A second commnd object change a row by SQL text.It tries to change same row again-succeeds.")
TEST_VARIATION(7, L"DBPROP_CHANGEINSERTEDROWS-FALSE.A second commnd object change a row by SQL text.It tries to change same row again-fails.")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Bookmark_Forward)
//--------------------------------------------------------------------
// @class Bookmark_Forward
//
class Bookmark_Forward : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Bookmark_Forward,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember immediate update mode, call SetData on the key value on the first row handle retrieved by IRowsetLocate::GetRowsAt
int Variation_1();
// @cmember buffered udpate mode, call SetData one the whole row on a middle row handle retrieved by IRowsetLocate::GetRowsByBookmark.
int Variation_2();
// @cmember delete last row then make sure BMK_LAST sees the new last row. RD-true,BMS-true
int Variation_3();
// @cmember delete last row then make sure BMK_LAST sees the new last row. RD-false,BMS-true
int Variation_4();
// @cmember delete last row then make sure BMK_LAST sees the new last row. RD-true,BMS-false
int Variation_5();
// @cmember delete last row then make sure BMK_LAST sees the new last row. RD-false,BMS-false
int Variation_6();
// @cmember delete last row then make sure bookmark sees the new last row. RD-true,BMS-true
int Variation_7();
// @cmember delete last row then make sure bookmark sees the new last row. RD-true,BMS-false
int Variation_8();
// @cmember delete last row of 1 row table and try to get BMK_LAST. RD=true,BMS=true
int Variation_9();
// @cmember delete last row of 1 row table and try to get bookmark. RD=true,BMS=true
int Variation_10();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Bookmark_Forward)
#define THE_CLASS Bookmark_Forward
BEG_TEST_CASE(Bookmark_Forward, TCIRowsetChange, L"Bookmark_Forward")
TEST_VARIATION(1, L"immediate update mode, call SetData on the key value on the first row handle retrieved by IRowsetLocate::GetRowsAt")
TEST_VARIATION(2, L"buffered udpate mode, call SetData one the whole row on a middle row handle retrieved by IRowsetLocate::GetRowsByBookmark.")
TEST_VARIATION(3, L"delete last row then make sure BMK_LAST sees the new last row. RD-true,BMS-true")
TEST_VARIATION(4, L"delete last row then make sure BMK_LAST sees the new last row. RD-false,BMS-true")
TEST_VARIATION(5, L"delete last row then make sure BMK_LAST sees the new last row. RD-true,BMS-false")
TEST_VARIATION(6, L"delete last row then make sure BMK_LAST sees the new last row. RD-false,BMS-false")
TEST_VARIATION(7, L"delete last row then make sure bookmark sees the new last row. RD-true,BMS-true")
TEST_VARIATION(8, L"delete last row then make sure bookmark sees the new last row. RD-true,BMS-false")
TEST_VARIATION(9, L"delete last row of 1 row table and try to get BMK_LAST. RD=true,BMS=true")
TEST_VARIATION(10, L"delete last row of 1 row table and try to get bookmark. RD=true,BMS=true")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Bookmark_Static)
//--------------------------------------------------------------------
// @class Bookmark_Static
//
class Bookmark_Static : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Bookmark_Static,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember immediate update mode, call SetData on the key value on the first row handle retrieved by IRowsetLocate::GetRowsAt
int Variation_1();
// @cmember buffered udpate mode, call SetData one the whole row on a middle row handle retrieved by IRowsetLocate::GetRowsByBookmark.
int Variation_2();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Bookmark_Static)
#define THE_CLASS Bookmark_Static
BEG_TEST_CASE(Bookmark_Static, TCIRowsetChange, L"Bookmark_Static")
TEST_VARIATION(1, L"immediate update mode, call SetData on the key value on the first row handle retrieved by IRowsetLocate::GetRowsAt")
TEST_VARIATION(2, L"buffered udpate mode, call SetData one the whole row on a middle row handle retrieved by IRowsetLocate::GetRowsByBookmark.")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Bookmark_Keyset)
//--------------------------------------------------------------------
// @class Bookmark_Keyset
//
class Bookmark_Keyset : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Bookmark_Keyset,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember immediate update mode, call SetData on the key value on the first row handle retrieved by IRowsetLocate::GetRowsAt
int Variation_1();
// @cmember buffered udpate mode, call SetData one the whole row on a middle row handle retrieved by IRowsetLocate::GetRowsByBookmark.
int Variation_2();
// @cmember Immediate update mode. No row revisited.
int Variation_3();
// @cmember Buffered update mode. No row revisited.
int Variation_4();
// @cmember delete last row then make sure BMK_LAST sees the new last row. RD-true,BMS-true
int Variation_5();
// @cmember delete last row then make sure BMK_LAST sees the new last row. RD-true,BMS-false
int Variation_6();
// @cmember delete last row then make sure bookmark sees the new last row. RD-true,BMS-true
int Variation_7();
// @cmember delete last row then make sure bookmark sees the new last row. RD-true,BMS-false
int Variation_8();
// @cmember delete last row of 1 row table and try to get BMK_LAST. RD=true,BMS=true
int Variation_9();
// @cmember delete last row of 1 row table and try to get bookmark. RD=true,BMS=true
int Variation_10();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Bookmark_Keyset)
#define THE_CLASS Bookmark_Keyset
BEG_TEST_CASE(Bookmark_Keyset, TCIRowsetChange, L"Bookmark_Keyset")
TEST_VARIATION(1, L"immediate update mode, call SetData on the key value on the first row handle retrieved by IRowsetLocate::GetRowsAt")
TEST_VARIATION(2, L"buffered udpate mode, call SetData one the whole row on a middle row handle retrieved by IRowsetLocate::GetRowsByBookmark.")
TEST_VARIATION(3, L"Immediate update mode. No row revisited.")
TEST_VARIATION(4, L"Buffered update mode. No row revisited.")
TEST_VARIATION(5, L"delete last row then make sure BMK_LAST sees the new last row. RD-true,BMS-true")
TEST_VARIATION(6, L"delete last row then make sure BMK_LAST sees the new last row. RD-true,BMS-false")
TEST_VARIATION(7, L"delete last row then make sure bookmark sees the new last row. RD-true,BMS-true")
TEST_VARIATION(8, L"delete last row then make sure bookmark sees the new last row. RD-true,BMS-false")
TEST_VARIATION(9, L"delete last row of 1 row table and try to get BMK_LAST. RD=true,BMS=true")
TEST_VARIATION(10, L"delete last row of 1 row table and try to get bookmark. RD=true,BMS=true")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Bookmark_Dynamic)
//--------------------------------------------------------------------
// @class Bookmark_Dynamic
//
class Bookmark_Dynamic : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Bookmark_Dynamic,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember immediate update mode, call SetData on the key value on the first row handle retrieved by IRowsetLocate::GetRowsAt
int Variation_1();
// @cmember buffered udpate mode, call SetData one the whole row on a middle row handle retrieved by IRowsetLocate::GetRowsByBookmark.
int Variation_2();
// @cmember delete last row then make sure BMK_LAST sees the new last row. RD-true,BMS-true
int Variation_3();
// @cmember delete last row then make sure BMK_LAST sees the new last row. RD-true,BMS-false
int Variation_4();
// @cmember delete last row then make sure bookmark sees the new last row. RD-true,BMS-true
int Variation_5();
// @cmember delete last row then make sure bookmark sees the new last row. RD-true,BMS-false
int Variation_6();
// @cmember delete last row of 1 row table and try to get BMK_LAST. RD=true,BMS=true
int Variation_7();
// @cmember delete last row of 1 row table and try to get bookmark. RD=true,BMS=true
int Variation_8();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Bookmark_Dynamic)
#define THE_CLASS Bookmark_Dynamic
BEG_TEST_CASE(Bookmark_Dynamic, TCIRowsetChange, L"Bookmark_Dynamic")
TEST_VARIATION(1, L"immediate update mode, call SetData on the key value on the first row handle retrieved by IRowsetLocate::GetRowsAt")
TEST_VARIATION(2, L"buffered udpate mode, call SetData one the whole row on a middle row handle retrieved by IRowsetLocate::GetRowsByBookmark.")
TEST_VARIATION(3, L"delete last row then make sure BMK_LAST sees the new last row. RD-true,BMS-true")
TEST_VARIATION(4, L"delete last row then make sure BMK_LAST sees the new last row. RD-true,BMS-false")
TEST_VARIATION(5, L"delete last row then make sure bookmark sees the new last row. RD-true,BMS-true")
TEST_VARIATION(6, L"delete last row then make sure bookmark sees the new last row. RD-true,BMS-false")
TEST_VARIATION(7, L"delete last row of 1 row table and try to get BMK_LAST. RD=true,BMS=true")
TEST_VARIATION(8, L"delete last row of 1 row table and try to get bookmark. RD=true,BMS=true")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(OrderedBookmark_Keyset)
//--------------------------------------------------------------------
// @class OrderedBookmark_Keyset
//
class OrderedBookmark_Keyset : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(OrderedBookmark_Keyset,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember immediate update mode. Create two rowsets on the same table. One rowset changes one row.
int Variation_1();
// @cmember buffered update mode. Create two rowsets on the same table. The second row set changed a row.
int Variation_2();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(OrderedBookmark_Keyset)
#define THE_CLASS OrderedBookmark_Keyset
BEG_TEST_CASE(OrderedBookmark_Keyset, TCIRowsetChange, L"OrderedBookmark_Keyset")
TEST_VARIATION(1, L"immediate update mode. Create two rowsets on the same table. One rowset changes one row.")
TEST_VARIATION(2, L"buffered update mode. Create two rowsets on the same table. The second row set changed a row.")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Invalid_Keyset_Cursor_Immediate)
//--------------------------------------------------------------------
// @class Invalid_Keyset_Cursor_Immediate
//
class Invalid_Keyset_Cursor_Immediate : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Invalid_Keyset_Cursor_Immediate,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember The accessor is DBACCESSOR_READ | DBACCCESOR_PASSBYREF. DB_E_READONLYACCESSOR or E_FAIL.
int Variation_1();
// @cmember The accessor is DBACCCESOR_PASSCOLUMNSBYREF. DB_E_READONLYACCESSOR or E_FAIL.
int Variation_2();
// @cmember The status flag specified in a binding structure is neither DBSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALUE
int Variation_3();
// @cmember The column number specified in the last binding structure = # of columns of the rowset+1. DB_E_COLUMNUNAVAILABLE
int Variation_4();
// @cmember Set a duplicate column on which a unique index is created. DB_E_INTEGRITYVIOLATION.
int Variation_5();
// @cmember The accessor sets the status field of non nullable columns NULL. DB_E_SCHEMAVIOLATION. The row goes back to its original sta
int Variation_6();
// @cmember The length binding > cbMaxLen for a variable length column. DB_S_ERRORSOCCURRED. Truncation should occur. Check the status b
int Variation_7();
// @cmember The accessor only has length binding. E_FAIL.(See testing issue #2
int Variation_8();
// @cmember The accessor only has status and length binding. Some the columns are not set to NULL. E_FAIL.
int Variation_9();
// @cmember Set an auto increment column. DB_SEC_E_PERMISSIONDENIED
int Variation_10();
// @cmember Setting a bookmark column DBSTATUS_E_?
int Variation_11();
// @cmember asking for no REMOVEDELETED on dynamic cursor
int Variation_12();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Invalid_Keyset_Cursor_Immediate)
#define THE_CLASS Invalid_Keyset_Cursor_Immediate
BEG_TEST_CASE(Invalid_Keyset_Cursor_Immediate, TCIRowsetChange, L"Invalid_Keyset_Cursor_Immediate")
TEST_VARIATION(1, L"The accessor is DBACCESSOR_READ | DBACCCESOR_PASSBYREF. DB_E_READONLYACCESSOR or E_FAIL.")
TEST_VARIATION(2, L"The accessor is DBACCCESOR_PASSCOLUMNSBYREF. DB_E_READONLYACCESSOR or E_FAIL.")
TEST_VARIATION(3, L"The status flag specified in a binding structure is neither DBSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALUE")
TEST_VARIATION(4, L"The column number specified in the last binding structure = # of columns of the rowset+1. DB_E_COLUMNUNAVAILABLE")
TEST_VARIATION(5, L"Set a duplicate column on which a unique index is created. DB_E_INTEGRITYVIOLATION.")
TEST_VARIATION(6, L"The accessor sets the status field of non nullable columns NULL. DB_E_SCHEMAVIOLATION. The row goes back to its original sta")
TEST_VARIATION(7, L"The length binding > cbMaxLen for a variable length column. DB_S_ERRORSOCCURRED. Truncation should occur. Check the status b")
TEST_VARIATION(8, L"The accessor only has length binding. E_FAIL.(See testing issue #2")
TEST_VARIATION(9, L"The accessor only has status and length binding. Some the columns are not set to NULL. E_FAIL.")
TEST_VARIATION(10, L"Set an auto increment column. DB_SEC_E_PERMISSIONDENIED")
TEST_VARIATION(11, L"Setting a bookmark column DBSTATUS_E_?")
TEST_VARIATION(12, L"asking for no REMOVEDELETED on dynamic cursor")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Invalid_Keyset_Cursor_Buffered)
//--------------------------------------------------------------------
// @class Invalid_Keyset_Cursor_Buffered
//
class Invalid_Keyset_Cursor_Buffered : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Invalid_Keyset_Cursor_Buffered,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember The Accessor is read-only accessor. DB_E_READONLYACCESSOR or E_FAIL.
int Variation_1();
// @cmember The accessor is DBACCESSOR_READ | DBACCCESOR_PASSCOLUMNSBYREF. DB_E_READONLYACCESSOR or E_FAIL.
int Variation_2();
// @cmember Set an auto increment column. DB_SEC_E_PERMISSIONDENIED
int Variation_3();
// @cmember The status flag specified in a binding structure is MAX(DWORD
int Variation_4();
// @cmember Change the primary key of two rows to be the same. DB_E_INTEGRITYVIOLATION.
int Variation_5();
// @cmember The accessor sets the status field of non nullable columns NULL. DB_E_SCHEMAVIOLATION. The row goes back to its original sta
int Variation_6();
// @cmember The length binding > cbMaxLen for a variable length column. DB_S_ERRORSOCCURRED. Truncation should occur. Check the status b
int Variation_7();
// @cmember The accessor only has status binding for DBSTATUS_S_OK. E_FAIL.
int Variation_8();
// @cmember The accessor is not a row accessor. DB_E_BADACCESSORTYPE.
int Variation_9();
// @cmember REMOVEDELTED FALSE, LITERALIDENITTY TRUE in buffered mode.
int Variation_10();
// @cmember REMOVEDELTED FALSE, LITERALIDENITTY FALSE in buffered mode.
int Variation_11();
// @cmember REMOVEDELTED TRUE, LITERALIDENITTY TRUE in buffered mode.
int Variation_12();
// @cmember REMOVEDELTED TRUE, LITERALIDENITTY FALSE in buffered mode.
int Variation_13();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Invalid_Keyset_Cursor_Buffered)
#define THE_CLASS Invalid_Keyset_Cursor_Buffered
BEG_TEST_CASE(Invalid_Keyset_Cursor_Buffered, TCIRowsetChange, L"Invalid_Keyset_Cursor_Buffered")
TEST_VARIATION(1, L"The Accessor is read-only accessor. DB_E_READONLYACCESSOR or E_FAIL.")
TEST_VARIATION(2, L"The accessor is DBACCESSOR_READ | DBACCCESOR_PASSCOLUMNSBYREF. DB_E_READONLYACCESSOR or E_FAIL.")
TEST_VARIATION(3, L"Set an auto increment column. DB_SEC_E_PERMISSIONDENIED")
TEST_VARIATION(4, L"The status flag specified in a binding structure is MAX(DWORD")
TEST_VARIATION(5, L"Change the primary key of two rows to be the same. DB_E_INTEGRITYVIOLATION.")
TEST_VARIATION(6, L"The accessor sets the status field of non nullable columns NULL. DB_E_SCHEMAVIOLATION. The row goes back to its original sta")
TEST_VARIATION(7, L"The length binding > cbMaxLen for a variable length column. DB_S_ERRORSOCCURRED. Truncation should occur. Check the status b")
TEST_VARIATION(8, L"The accessor only has status binding for DBSTATUS_S_OK. E_FAIL.")
TEST_VARIATION(9, L"The accessor is not a row accessor. DB_E_BADACCESSORTYPE.")
TEST_VARIATION(10, L"REMOVEDELTED FALSE, LITERALIDENITTY TRUE in buffered mode.")
TEST_VARIATION(11, L"REMOVEDELTED FALSE, LITERALIDENITTY FALSE in buffered mode.")
TEST_VARIATION(12, L"REMOVEDELTED TRUE, LITERALIDENITTY TRUE in buffered mode.")
TEST_VARIATION(13, L"REMOVEDELTED TRUE, LITERALIDENITTY FALSE in buffered mode.")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Valid_Keyset_Cursor_Immediate)
//--------------------------------------------------------------------
// @class Valid_Keyset_Cursor_Immediate
//
class Valid_Keyset_Cursor_Immediate : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
DBPROPID m_rgPropertyIDs[3];
ULONG m_cGuid;
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Valid_Keyset_Cursor_Immediate,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Change fixed length columns, in FORWARD order of the rowset.
int Variation_1();
// @cmember Change the fixed length data type columns with bogus length information.
int Variation_2();
// @cmember Change the variable length columns with only value binding.
int Variation_3();
// @cmember Change the whole row with status and value binding. Set some columns to NULL.
int Variation_4();
// @cmember Change a row with DBTYPE_BYREF.
int Variation_5();
// @cmember Change a row with DBTYPE_ARRAY.
int Variation_6();
// @cmember Change a row with DBTYPE_VECTOR.
int Variation_7();
// @cmember Duplicate column bindings in the same accessor.
int Variation_8();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Valid_Keyset_Cursor_Immediate)
#define THE_CLASS Valid_Keyset_Cursor_Immediate
BEG_TEST_CASE(Valid_Keyset_Cursor_Immediate, TCIRowsetChange, L"Valid_Keyset_Cursor_Immediate")
TEST_VARIATION(1, L"Change fixed length columns, in FORWARD order of the rowset.")
TEST_VARIATION(2, L"Change the fixed length data type columns with bogus length information.")
TEST_VARIATION(3, L"Change the variable length columns with only value binding.")
TEST_VARIATION(4, L"Change the whole row with status and value binding. Set some columns to NULL.")
TEST_VARIATION(5, L"Change a row with DBTYPE_BYREF.")
TEST_VARIATION(6, L"Change a row with DBTYPE_ARRAY.")
TEST_VARIATION(7, L"Change a row with DBTYPE_VECTOR.")
TEST_VARIATION(8, L"Duplicate column bindings in the same accessor.")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Related_Delete_NewRow)
//--------------------------------------------------------------------
// @class Related interfaces with IRowsetDelete and IRowsetNewRow
//
class Related_Delete_NewRow : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Related_Delete_NewRow,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Delete one row. Add a new row and change it. Immediate update mode.
int Variation_1();
// @cmember Delete one row. Add a new row and change it. Query and buffered update mode.
int Variation_2();
// @cmember Delete rows from a static cursor/immediate update mode.
int Variation_3();
// @cmember Boundary checks from a static cursor.
int Variation_4();
// @cmember NEWLYINSERTED from a static cursor.
int Variation_5();
// @cmember key non-key cols, set 2 rows the same and delete
int Variation_6();
// @cmember Delete rows from a static cursor/immediate mode, delete not supported
int Variation_7();
// @cmember delete with a row handle from an unallocated row handle
int Variation_8();
// @cmember delete with a row handle from an allocated row handle
int Variation_9();
// @cmember insert a row update then Hard Delete the row
int Variation_10();
// @cmember delete the same row handle
int Variation_11();
//
//
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Related_Delete_NewRow)
#define THE_CLASS Related_Delete_NewRow
BEG_TEST_CASE(Related_Delete_NewRow, TCIRowsetChange, L"Related interfaces with IRowsetDelete and IRowsetNewRow")
TEST_VARIATION(1, L"Delete one row. Add a new row and change it. Immediate update mode.")
TEST_VARIATION(2, L"Delete one row. Add a new row and change it. Query and buffered update mode.")
TEST_VARIATION(3, L"Delete rows from a static cursor/immediate update mode.")
TEST_VARIATION(4, L"Boundary checks from a static cursor.")
TEST_VARIATION(5, L"NEWLYINSERTED from a static cursor.")
TEST_VARIATION(6, L"key non-key cols, set 2 rows the same and delete.")
TEST_VARIATION(7, L"Delete rows from a static cursor/immediate mode, delete not supported")
TEST_VARIATION(8, L"delete with a row handle from an unallocated row handle")
TEST_VARIATION(9, L"delete with a row handle from an allocated row handle")
TEST_VARIATION(10, L"insert a row update then Hard Delete the row,")
TEST_VARIATION(11, L"delete the same row handle")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Sequence)
//--------------------------------------------------------------------
// @class sequence testing
//
class Sequence : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Sequence,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Call SetData three times on the same row in an immediately update mode. One attempt is not successful.
int Variation_1();
// @cmember Call SetData on two different row handles in an immediately update mode. One attempt is not successful
int Variation_2();
// @cmember Call SetData twice on the same row in a buffered update mode. The second attempt is not successful.
int Variation_3();
// @cmember In buffered update mode, retrieve 50 row handles, call IRowsetChange on each row handle, then call IRowstUpdate::Update
int Variation_4();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Sequence)
#define THE_CLASS Sequence
BEG_TEST_CASE(Sequence, TCIRowsetChange, L"sequence testing")
TEST_VARIATION(1, L"Call SetData three times on the same row in an immediately update mode. One attempt is not successful.")
TEST_VARIATION(2, L"Call SetData on two different row handles in an immediately update mode. One attempt is not successful")
TEST_VARIATION(3, L"Call SetData twice on the same row in a buffered update mode. The second attempt is not successful.")
TEST_VARIATION(4, L"In buffered update mode, retrieve 50 row handles, call IRowsetChange on each row handle, then call IRowstUpdate::Update")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Transaction)
//--------------------------------------------------------------------
// @class Testing IRowsetChange within a transaction
//
class Transaction : public CTransaction {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
DBPROPSET m_DBPropSet;
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Transaction,CTransaction);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Commit with fRetaining=TRUE. Cursor based.
int Variation_1();
// @cmember Commit with fRetaining=FALSE. Query based.
int Variation_2();
// @cmember Abort with fRetaining=TRUE. Query based.
int Variation_3();
// @cmember Abort with fRetaining=FALSE. Cursor based.
int Variation_4();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Transaction)
#define THE_CLASS Transaction
BEG_TEST_CASE(Transaction, CTransaction, L"Testing IRowsetChange within a transaction")
TEST_VARIATION(1, L"Commit with fRetaining=TRUE. Cursor based.")
TEST_VARIATION(2, L"Commit with fRetaining=FALSE. Query based.")
TEST_VARIATION(3, L"Abort with fRetaining=TRUE. Query based.")
TEST_VARIATION(4, L"Abort with fRetaining=FALSE. Cursor based.")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(ExtendedErrors)
//--------------------------------------------------------------------
// @class Extended Errors
//
class ExtendedErrors : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(ExtendedErrors,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Valid DeleteRows calls with previous error object existing.
int Variation_1();
// @cmember Invalid DeleteRows calls with previous error object existing
int Variation_2();
// @cmember Invalid DeleteRows calls with no previous error object existing
int Variation_3();
// @cmember Valid SetData calls with previous error object existing.
int Variation_4();
// @cmember Invalid SetData calls with previous error object existing
int Variation_5();
// @cmember Invalid SetData calls with no previous error object existing
int Variation_6();
// @cmember Valid InsertRow calls with previous error object existing.
int Variation_7();
// @cmember Invalid InsertRow calls with previous error object existing
int Variation_8();
// @cmember Invalid InsertRow calls with no previous error object existing
int Variation_9();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(ExtendedErrors)
#define THE_CLASS ExtendedErrors
BEG_TEST_CASE(ExtendedErrors, TCIRowsetChange, L"Extended Errors")
TEST_VARIATION(1, L"Valid DeleteRows calls with previous error object existing.")
TEST_VARIATION(2, L"Invalid DeleteRows calls with previous error object existing")
TEST_VARIATION(3, L"Invalid DeleteRows calls with no previous error object existing")
TEST_VARIATION(4, L"Valid SetData calls with previous error object existing.")
TEST_VARIATION(5, L"Invalid SetData calls with previous error object existing")
TEST_VARIATION(6, L"Invalid SetData calls with no previous error object existing")
TEST_VARIATION(7, L"Valid InsertRow calls with previous error object existing.")
TEST_VARIATION(8, L"Invalid InsertRow calls with previous error object existing")
TEST_VARIATION(9, L"Invalid InsertRow calls with no previous error object existing")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(ProviderOwnedMem)
//--------------------------------------------------------------------
// @class Use ProviderOwned Memory for SetData
//
class ProviderOwnedMem : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(ProviderOwnedMem,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember ProdiverOwnedMem for SetData. Keyset_Query_Buffered
int Variation_1();
// @cmember ProdiverOwnedMem for SetData. Keyset_Cursor_Imm
int Variation_2();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(ProviderOwnedMem)
#define THE_CLASS ProviderOwnedMem
BEG_TEST_CASE(ProviderOwnedMem, TCIRowsetChange, L"Use ProviderOwned Memory for SetData")
TEST_VARIATION(1, L"ProdiverOwnedMem for SetData. Keyset_Query_Buffered")
TEST_VARIATION(2, L"ProdiverOwnedMem for SetData. Keyset_Cursor_Imm")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(SetDefault)
//*-----------------------------------------------------------------------
// @class Default value in data setting operations
//
class SetDefault : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
protected:
CTable *m_pCustomTable; // a custom table (ask for def cols, etc)
BOOL *m_rgbDefault; // array indicating the defaltable types
ULONG m_nRows; // initial number of rows in the table
BOOL m_fCustomTables; // if customized tables can be built
ULONG m_cSeed; // seed used to build default values
// @cmember Builds a list of info about the default property of the columns
BOOL GetDefaultColumns();
// @cmember mask the m_fHasDefault field of columns in m_pTable
void MaskDefColumns(BOOL fMask);
// @cmember Creates a rowset, accessors and fill input bindings
BOOL PrepareForSetData(
DBORDINAL cSelectedColumn, // [in] the ordinal of the selected column (1 based)
DBSTATUS Status, // [in] the status value for the selected column
DBCOUNTITEM lRowsOffset, // [in] row number for data creation
BYTE **ppData // [out] data buffer
);
// @cmember SetData, check it, get data, check it
virtual BOOL SetAndCheckDefault(
BYTE *pData, // [in] buffer for IRowsetChange::SetData
HRESULT hrSetDataExpected, // [in] expected hr for IRowsetChange::SetData
BOOL fValidate = TRUE, // [in] validation flag
HRESULT *hrSetData = NULL // [out] actual result of IRowsetChange::SetData
);
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(SetDefault,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Set default values on all default columns
int Variation_1();
// @cmember Set default value on a default column; set many columns, one is asked default
int Variation_2();
// @cmember Set default value on a not nullable default column
int Variation_3();
// @cmember Set default value on a nullable default column (def == NULL)
int Variation_4();
// @cmember Set default value on a nullable default column (def != NULL)
int Variation_5();
// @cmember Set default value on a not default column
int Variation_6();
// @cmember Set default value on a unique default value
int Variation_7();
// }} TCW_TESTVARS_END
} ;
// {{ TCW_TESTCASE(SetDefault)
#define THE_CLASS SetDefault
BEG_TEST_CASE(SetDefault, TCIRowsetChange, L"Default value in data setting operations")
TEST_VARIATION(1, L"Set default values on all default columns")
TEST_VARIATION(2, L"Set default value on a default column; set many columns, one is asked default")
TEST_VARIATION(3, L"Set default value on a not nullable default column")
TEST_VARIATION(4, L"Set default value on a nullable default column (def == NULL)")
TEST_VARIATION(5, L"Set default value on a nullable default column (def != NULL)")
TEST_VARIATION(6, L"Set default value on a not default column")
TEST_VARIATION(7, L"Set default value on a unique default value")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(SetIgnore)
//*-----------------------------------------------------------------------
// @class Ignore data in SetData
//
class SetIgnore : public SetDefault {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
protected:
// @cmember SetData, check it, get data, check it
BOOL SetAndCheckDefault(
BYTE *pData, // [in] buffer for IRowsetChange::SetData
HRESULT hrSetDataExpected, // [in] expected hr for IRowsetChange::SetData
BOOL fValidate = TRUE, // [in] validation flag
HRESULT *hrSetData = NULL, // [out] actual result of IRowsetChange::SetData
BOOL fCheck = TRUE // [in] whether to do a check a GetData
);
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(SetIgnore,SetDefault);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Set ignore values on all updateable columns
int Variation_1();
// @cmember Set ignore value on a column; set many columns, one is asked ignored
int Variation_2();
// @cmember Set ignore value on a not nullable default column
int Variation_3();
// @cmember Set ignore value on a nullable default column (def == NULL)
int Variation_4();
// @cmember Set ignore value on a nullable default column (def != NULL)
int Variation_5();
// @cmember Set ignore value on a not default column
int Variation_6();
// @cmember Bind a single column and set status to DBSTATUS_S_IGNORE
int Variation_7();
// @cmember Bind all updateable cols, set status to DBSTATUS_S_IGNORE for half of them
int Variation_8();
// @cmember Bind a single read only column and set status to DBSTATUS_S_IGNORE
int Variation_9();
// @cmember SetData(IGNORE)/SetData()
int Variation_10();
// }} TCW_TESTVARS_END
} ;
// {{ TCW_TESTCASE(SetIgnore)
#define THE_CLASS SetIgnore
BEG_TEST_CASE(SetIgnore, SetDefault, L"Ignore data in SetData")
TEST_VARIATION(1, L"Set ignore values on all updateable columns")
TEST_VARIATION(2, L"Set ignore value on a column; set many columns, one is asked ignored")
TEST_VARIATION(3, L"Set ignore value on a not nullable default column")
TEST_VARIATION(4, L"Set ignore value on a nullable default column (def == NULL)")
TEST_VARIATION(5, L"Set ignore value on a nullable default column (def != NULL)")
TEST_VARIATION(6, L"Set ignore value on a not default column")
TEST_VARIATION(7, L"Bind a single column and set status to DBSTATUS_S_IGNORE")
TEST_VARIATION(8, L"Bind all updateable cols, set status to DBSTATUS_S_IGNORE for half of them")
TEST_VARIATION(9, L"Bind a single read only column and set status to DBSTATUS_S_IGNORE")
TEST_VARIATION(10, L"SetData(IGNORE)/SetData()/GPF")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Invalid_Keyset_Cursor_Buffered)
//--------------------------------------------------------------------
// @class Invalid_Keyset_Cursor_Buffered
//
class DeleteRows : public TCIRowsetChange {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(DeleteRows,TCIRowsetChange);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember delete array of handles that point to one row
int Variation_1();
// @cmember DB_S_ERRORSOCCURRED status check all rows, DBROWSTATUS_S_MULTIPLECHANGES
int Variation_2();
// @cmember DB_S_ERRORSOCCURRED status check all rows, DBROWSTATUS_E_INVALID
int Variation_3();
// @cmember use rows with immediate deletes in other methods
int Variation_4();
// @cmember DB_S_ERRORSOCCURRED status check all rows, DBROWSTATUS_E_MAXPENDCHANGESEXCEEDED
int Variation_5();
// @cmember DB_S_ERRORSOCCURRED status check all rows, DBROWSTATUS_E_NEWLYINSERTED
int Variation_6();
// @cmember DeleteRows from a zombie
int Variation_7();
// @cmember DB_S_ERRORSOCCURRED status check all rows, DBROWSTATUS_E_PENDINGINSERT
int Variation_8();
// @cmember use pending deletes by using them in other methods (RESYNC)
int Variation_9();
// @cmember use pending deletes by using them in other methods
int Variation_10();
// @cmember delete pending insert, Change
int Variation_11();
// @cmember delete pending insert, Update
int Variation_12();
// @cmember delete pending insert, Resync
int Variation_13();
// @cmember check for pending delete, LITERALIDENTITY - FALSE
int Variation_14();
// @cmember check for pending delete, LITERALIDENTITY - TRUE
int Variation_15();
// @cmember Deleted handle, no status
int Variation_16();
// @cmember Invalid handle, no status
int Variation_17();
// @cmember DB_S_OK when deleting an inserted/trasmitted row from a pending rowset
int Variation_18();
// @cmember delete/update/reposition cursor
int Variation_19();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(DeleteRows)
#define THE_CLASS DeleteRows
BEG_TEST_CASE(DeleteRows, TCIRowsetChange, L"DeleteRows")
TEST_VARIATION(1, L"delete array of handles that point to one row")
TEST_VARIATION(2, L"DB_S_ERRORSOCCURRED status check all rows, DBROWSTATUS_S_MULTIPLECHANGES")
TEST_VARIATION(3, L"DB_S_ERRORSOCCURRED status check all rows, DBROWSTATUS_E_INVALID")
TEST_VARIATION(4, L"use rows with immediate deletes in other methods")
TEST_VARIATION(5, L"DB_S_ERRORSOCCURRED status check all rows, DBROWSTATUS_E_MAXPENDCHANGESEXCEEDED")
TEST_VARIATION(6, L"DB_S_ERRORSOCCURRED status check all rows, DBROWSTATUS_E_NEWLYINSERTED")
TEST_VARIATION(7, L"DeleteRows from a zombie.")
TEST_VARIATION(8, L"DB_S_ERRORSOCCURRED status check all rows, DBROWSTATUS_E_PENDINGINSERT")
TEST_VARIATION(9, L"use pending deletes by using them in other methods (RESYNC)")
TEST_VARIATION(10, L"use pending deletes by using them in other methods.")
TEST_VARIATION(11, L"delete pending insert, Change.")
TEST_VARIATION(12, L"delete pending insert, Update")
TEST_VARIATION(13, L"delete pending insert, Resync.")
TEST_VARIATION(14, L"check for pending delete, LITERALIDENTITY - FALSE")
TEST_VARIATION(15, L"check for pending delete, LITERALIDENTITY - TRUE")
TEST_VARIATION(16, L"Deleted handle, no status")
TEST_VARIATION(17, L"Invalid handle, no status")
TEST_VARIATION(18, L"DB_S_OK when deleting an inserted/trasmitted row from a pending rowset")
TEST_VARIATION(19, L"delete/update/reposition cursor")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// }} END_DECLARE_TEST_CASES()
// {{ TCW_TESTMODULE(ThisModule)
TEST_MODULE(36, ThisModule, gwszModuleDescrip)
TEST_CASE(1, Boundary)
TEST_CASE(2, Rowsets)
TEST_CASE(3, MayWriteColumn)
TEST_CASE(4, MaxPendingChangeRows)
TEST_CASE(5, CacheDeferred)
TEST_CASE(6, NoColumn_Row_Restrict)
TEST_CASE(7, Computed_Columns)
TEST_CASE(8, Forward_Query)
TEST_CASE(9, Forward_Cursor)
TEST_CASE(10, QueryBaseUpdates)
TEST_CASE(11, Static_Cursor_Immediate)
TEST_CASE(12, Static_Cursor_Buffered)
TEST_CASE(13, Keyset_Cursor_Buffered)
TEST_CASE(14, Keyset_Remove_Cursor_Immediate)
TEST_CASE(15, Keyset_Remove_Buffered)
TEST_CASE(16, Dynamic_Cursor_Buffered)
TEST_CASE(17, Visible_Forward_Cursor)
TEST_CASE(18, Visible_Static_Cursor)
TEST_CASE(19, Visible_Keyset_Command_Cursor)
TEST_CASE(20, Visible_Dynamic_Command_Cursor)
TEST_CASE(21, Bookmark_Forward)
TEST_CASE(22, Bookmark_Static)
TEST_CASE(23, Bookmark_Keyset)
TEST_CASE(24, Bookmark_Dynamic)
TEST_CASE(25, OrderedBookmark_Keyset)
TEST_CASE(26, Invalid_Keyset_Cursor_Immediate)
TEST_CASE(27, Invalid_Keyset_Cursor_Buffered)
TEST_CASE(28, Valid_Keyset_Cursor_Immediate)
TEST_CASE(29, Related_Delete_NewRow)
TEST_CASE(30, Sequence)
TEST_CASE(31, Transaction)
TEST_CASE(32, ExtendedErrors)
TEST_CASE(33, ProviderOwnedMem)
TEST_CASE(34, SetDefault)
TEST_CASE(35, SetIgnore)
TEST_CASE(36, DeleteRows)
END_TEST_MODULE()
// }} TCW_TESTMODULE_END
// {{ TCW_TC_PROTOTYPE(Boundary)
//*-----------------------------------------------------------------------
//| Test Case: Boundary - Testing boundary conditions
//| Created: 04/05/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Boundary::Init()
{
return TCIRowsetChange::Init();
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc immediate update mode. Null Accessor, valid pData with DBPROPVAL_UP_CHANGE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Boundary::Variation_1()
{
HROW hRow[1];
HROW *pHRow = hRow;
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
BOOL fPass = TEST_SKIPPED;
// Initialize
m_cRowsObtained = 0;
m_rgPropertyIDs[0] = DBPROP_IRowsetChange;
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,m_rgPropertyIDs,0,NULL,
ON_ROWSET_ACCESSOR,TRUE));
QTESTC(m_pIRowsetChange != NULL);
fPass = FALSE;
//get data for the first row
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&m_cRowsObtained,&pHRow),S_OK);
TESTC(m_cRowsObtained == 1);
TESTC_(GetData(hRow[0],m_hAccessor,m_pData),S_OK);
//create an NULL accessor
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,&hAccessor,NULL),S_OK);
//use NULL hRow
TESTC_(SetData(DB_NULL_HROW,hAccessor,m_pData),DB_E_BADROWHANDLE);
TESTC_(SetData(NULL,hAccessor,m_pData),DB_E_BADROWHANDLE);
//use NULL hAccessor
TESTC_(SetData(hRow[0],DB_NULL_HACCESSOR,m_pData),DB_E_BADACCESSORHANDLE);
TESTC_(SetData(hRow[0],NULL,m_pData),DB_E_BADACCESSORHANDLE);
//use valid hAccessor
TESTC_(SetData(hRow[0],hAccessor,m_pData),S_OK);
//make sure the data is not changed
TESTC(CompareData(m_cRowsetCols,m_rgTableColOrds,1,m_pData,m_cBinding,m_rgBinding,m_pTable,NULL));
fPass = TRUE;
CLEANUP:
//release objects
if( m_pIRowset )
CHECK(m_pIRowset->ReleaseRows(m_cRowsObtained,hRow,NULL,NULL,NULL),S_OK);
if( m_pIAccessor && hAccessor )
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
ReleaseRowsetAndAccessor();
return fPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc immediate update mode. Null Accessor, NULL pData with DBPROPVAL_UP_CHANGE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Boundary::Variation_2()
{
HROW hRow[1];
HROW *pHRow = hRow;
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
BOOL fPass = TEST_SKIPPED;
// Initialize
m_cRowsObtained = 0;
m_rgPropertyIDs[0] = DBPROP_IRowsetChange;
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,m_rgPropertyIDs,0,NULL,
ON_ROWSET_ACCESSOR));
QTESTC(m_pIRowsetChange != NULL);
fPass = FALSE;
//create an NULL accessor
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,&hAccessor,NULL),S_OK);
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&m_cRowsObtained, &pHRow),S_OK);
TESTC(m_cRowsObtained == 1);
//use NULL hRow
TESTC_(SetData(DB_NULL_HROW,hAccessor,m_pData),DB_E_BADROWHANDLE);
TESTC_(SetData(NULL,hAccessor,m_pData),DB_E_BADROWHANDLE);
//use NULL hAccessor
TESTC_(SetData(hRow[0],DB_NULL_HACCESSOR,m_pData),DB_E_BADACCESSORHANDLE);
TESTC_(SetData(hRow[0],NULL,m_pData),DB_E_BADACCESSORHANDLE);
//use valid hAccessor
TESTC_(SetData(hRow[0],hAccessor,NULL),S_OK);
fPass=TRUE;
CLEANUP:
//release objects
if( m_pIRowset )
CHECK(m_pIRowset->ReleaseRows(m_cRowsObtained,hRow,NULL,NULL,NULL),S_OK);
if( m_pIAccessor && hAccessor )
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
ReleaseRowsetAndAccessor();
return fPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc immediate update mode. NULL pData. E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Boundary::Variation_3()
{
HROW hRow[1];
HROW *pHRow = hRow;
BOOL fPass = TEST_SKIPPED;
// Initialize
m_cRowsObtained = 0;
m_rgPropertyIDs[0] = DBPROP_IRowsetChange;
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,m_rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR,
TRUE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND));
QTESTC(m_pIRowsetChange != NULL);
fPass = FALSE;
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&m_cRowsObtained, &pHRow),S_OK);
TESTC(m_cRowsObtained == 1);
//use NULL hRow
TESTC_(SetData(DB_NULL_HROW,m_hAccessor,m_pData),DB_E_BADROWHANDLE);
TESTC_(SetData(hRow[0],DB_NULL_HACCESSOR,m_pData),DB_E_BADACCESSORHANDLE);
TESTC_(SetData(hRow[0],m_hAccessor,NULL),E_INVALIDARG);
fPass=TRUE;
CLEANUP:
//release objects
if( m_pIRowset )
CHECK(m_pIRowset->ReleaseRows(m_cRowsObtained,hRow,NULL,NULL,NULL),S_OK);
ReleaseRowsetAndAccessor();
return fPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc buffered update mode. NULL accessor and NULL pData with DBPROPVAL_UP_CHANGE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Boundary::Variation_4()
{
HROW hRow[1];
HROW *pHRow = hRow;
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
BOOL fPass = TEST_SKIPPED;
// Initialize
m_cRowsObtained = 0;
m_rgPropertyIDs[0] = DBPROP_IRowsetChange;
m_rgPropertyIDs[1] = DBPROP_IRowsetUpdate;
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,m_rgPropertyIDs,0,NULL,
ON_ROWSET_ACCESSOR,TRUE));
QTESTC(m_pIRowsetChange != NULL);
fPass = FALSE;
//create an NULL accessor
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,&hAccessor,NULL),S_OK);
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&m_cRowsObtained, &pHRow),S_OK);
TESTC(m_cRowsObtained == 1);
TESTC_(SetData(hRow[0],hAccessor,NULL),S_OK);
fPass=TRUE;
CLEANUP:
//release objects
if( m_pIRowset )
CHECK(m_pIRowset->ReleaseRows(m_cRowsObtained,hRow,NULL,NULL,NULL),S_OK);
if( m_pIAccessor && hAccessor )
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
ReleaseRowsetAndAccessor();
return fPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc immediate update mode. Null Accessor, valid pData with DBPROPVAL_UP_CHANGE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Boundary::Variation_5()
{
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
BOOL fPass = TEST_SKIPPED;
ULONG_PTR ulUpdValue = 0;
// Initialize
m_rgPropertyIDs[0] = DBPROP_IRowsetChange;
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,m_rgPropertyIDs,0,NULL,
ON_ROWSET_ACCESSOR,TRUE));
QTESTC(m_pIRowsetChange != NULL);
fPass = FALSE;
//Get the value for DBPROP_UPDATABILITY
GetProperty(DBPROP_UPDATABILITY,DBPROPSET_ROWSET,m_pIRowsetChange,&ulUpdValue);
//create an NULL accessor
if( ulUpdValue & DBPROPVAL_UP_INSERT )
CHECK(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,
&hAccessor,NULL),S_OK);
else
CHECK(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,
&hAccessor,NULL),DB_E_NULLACCESSORNOTSUPPORTED);
fPass = TRUE;
CLEANUP:
// Release the Accessor
if( m_pIAccessor && hAccessor )
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
ReleaseRowsetAndAccessor();
return fPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc buffered update mode. NULL accessor and NULL pData with DBPROPVAL_UP_CHANGE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Boundary::Variation_6()
{
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
BOOL fPass = TEST_SKIPPED;
ULONG_PTR ulUpdValue = 0;
// Initialize
m_rgPropertyIDs[0] = DBPROP_IRowsetChange;
m_rgPropertyIDs[1] = DBPROP_IRowsetUpdate;
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,m_rgPropertyIDs,0,NULL,
ON_ROWSET_ACCESSOR,TRUE));
QTESTC(m_pIRowsetChange != NULL);
fPass = FALSE;
//Get the value for DBPROP_UPDATABILITY
GetProperty(DBPROP_UPDATABILITY,DBPROPSET_ROWSET,m_pIRowsetChange,&ulUpdValue);
//create an NULL accessor
if( ulUpdValue & DBPROPVAL_UP_INSERT )
CHECK(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,
&hAccessor,NULL),S_OK);
else
CHECK(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,
&hAccessor,NULL),DB_E_NULLACCESSORNOTSUPPORTED);
fPass = TRUE;
CLEANUP:
// Release the Accessor
if( m_pIAccessor && hAccessor )
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
ReleaseRowsetAndAccessor();
return fPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc immediate update mode. Valid accessor with bad ordinals
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Boundary::Variation_7()
{
HROW hRow[1];
HROW *pHRow = hRow;
IAccessor *pIAccessor = NULL;
HACCESSOR hAccessor1 = DB_NULL_HACCESSOR;
HACCESSOR hAccessor2 = DB_NULL_HACCESSOR;
HRESULT hr = E_FAIL;
BOOL fPass = TEST_SKIPPED;
// Initialize
m_cRowsObtained = 0;
m_rgPropertyIDs[0] = DBPROP_IRowsetChange;
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,m_rgPropertyIDs,0,NULL,ON_COMMAND_ACCESSOR,
TRUE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND));
QTESTC(m_pICommand != NULL);
QTESTC(m_pIRowsetChange != NULL);
fPass = FALSE;
//create an accessor with invalid ordinals
TESTC(VerifyInterface(m_pICommand,IID_IAccessor,COMMAND_INTERFACE,(IUnknown**)&pIAccessor));
// Verify we've got at least one binding
QTESTC(m_cBinding != 0);
//bind ordinals out of bounds
m_rgBinding[0].iOrdinal = 0;
TESTC_(pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,
m_cBinding,m_rgBinding,0,&hAccessor1,NULL),S_OK);
m_rgBinding[0].iOrdinal = m_rgBinding[m_cBinding-1].iOrdinal;
m_rgBinding[0].iOrdinal++;
TESTC_(pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,
m_cBinding,m_rgBinding,0,&hAccessor2,NULL),S_OK);
//Release the first Rowset and Command
ReleaseRowsetAndAccessor(0,1);
TESTC(VerifyInterface(pIAccessor,IID_ICommand,COMMAND_INTERFACE,(IUnknown**)&m_pICommand));
// Fixup the Updatablity flag agian
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
if(!GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,m_rgPropertyIDs,0,NULL,ON_COMMAND_ACCESSOR,
TRUE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND,
FORWARD,NO_COLS_BY_REF,0,0,NULL,NO_COLS_OWNED_BY_PROV,DBPARAMIO_NOTPARAM,&hr))
{
TESTC_(hr, DB_E_BADORDINAL);
fPass=TRUE;
goto CLEANUP;
}
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&m_cRowsObtained, &pHRow),S_OK);
TESTC(m_cRowsObtained == 1);
TESTC_(GetData(hRow[0],m_hAccessor,m_pData),S_OK);
//use valid hRow with bad ordinals
TEST2C_(SetData(hRow[0],hAccessor1,m_pData),DB_E_BADORDINAL,DB_E_ERRORSOCCURRED);
TEST2C_(SetData(hRow[0],hAccessor2,m_pData),DB_E_BADORDINAL,DB_E_ERRORSOCCURRED);
fPass=TRUE;
CLEANUP:
//release objects
if( m_pIRowset )
CHECK(m_pIRowset->ReleaseRows(m_cRowsObtained,hRow,NULL,NULL,NULL),S_OK);
if( pIAccessor && hAccessor1 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor1,NULL),S_OK);
if( pIAccessor && hAccessor2 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor2,NULL),S_OK);
SAFE_RELEASE(pIAccessor);
ReleaseRowsetAndAccessor();
return fPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc immediate update mode. OPTIMIZED accessor after a Fetch (DB_E_BADACCESSORFLAGS)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Boundary::Variation_8()
{
HROW *pHRow = NULL;
HACCESSOR hAccessor1 = DB_NULL_HACCESSOR;
HACCESSOR hAccessor2 = DB_NULL_HACCESSOR;
BOOL fPass = TEST_SKIPPED;
// Initialize
m_cRowsObtained = 0;
m_rgPropertyIDs[0] = DBPROP_IRowsetChange;
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,m_rgPropertyIDs,0,NULL,
ON_ROWSET_ACCESSOR,TRUE));
QTESTC(m_pIRowsetChange != NULL);
fPass = FALSE;
//create an Optimized accessor before the GetNextRows
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA|DBACCESSOR_OPTIMIZED,
m_cBinding,m_rgBinding,0,&hAccessor1,NULL), S_OK);
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&m_cRowsObtained, &pHRow),S_OK);
TESTC(m_cRowsObtained == 1);
//release the row just fetched and the first accessor
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(m_cRowsObtained,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if( m_pIAccessor && hAccessor1 )
{
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor1,NULL),S_OK);
hAccessor1 = DB_NULL_HACCESSOR;
}
//create an Optimized accessor after the GetNextRows
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA|DBACCESSOR_OPTIMIZED,
m_cBinding,m_rgBinding,0,&hAccessor2,NULL),DB_E_BADACCESSORFLAGS);
//should return a NULL handle
TESTC(hAccessor2 == NULL);
fPass=TRUE;
CLEANUP:
//release objects
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(m_cRowsObtained,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if( m_pIAccessor && hAccessor1 )
{
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor1,NULL),S_OK);
hAccessor1 = DB_NULL_HACCESSOR;
}
if( m_pIAccessor && hAccessor2 )
{
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor2,NULL),S_OK);
hAccessor2 = DB_NULL_HACCESSOR;
}
ReleaseRowsetAndAccessor();
return fPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc immediate update mode. Valid accessor with different Parameter Accessor Flags
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Boundary::Variation_9()
{
HROW hRow[1];
HROW *pHRow = hRow;
IAccessor *pIAccessor = NULL;
HACCESSOR hAccessor1 = DB_NULL_HACCESSOR;
HACCESSOR hAccessor2 = DB_NULL_HACCESSOR;
HACCESSOR hAccessor3 = DB_NULL_HACCESSOR;
HACCESSOR hAccessor4 = DB_NULL_HACCESSOR;
HACCESSOR hAccessor5 = DB_NULL_HACCESSOR;
HACCESSOR hAccessor6 = DB_NULL_HACCESSOR;
HRESULT hr = E_FAIL;
BOOL fPass = TEST_SKIPPED;
// Initialize
m_cRowsObtained = 0;
m_rgPropertyIDs[0] = DBPROP_IRowsetChange;
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
//Note: we should use DBACCESSOR_ROWDATA instead of DBACCESSOR_PARAMETERDATA so that ordinals in m_rgBinding structures
// match the ones used for GetData(hRow[0],m_hAccessor,m_pData) later in the variation
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,m_rgPropertyIDs,0,NULL,ON_COMMAND_ACCESSOR,
TRUE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND,
FORWARD,NO_COLS_BY_REF,0,0,NULL,NO_COLS_OWNED_BY_PROV,DBPARAMIO_INPUT));
QTESTC(m_pICommand != NULL);
QTESTC(m_pIRowsetChange != NULL);
fPass = FALSE;
//create an accessor
TESTC(VerifyInterface(m_pICommand,IID_IAccessor,COMMAND_INTERFACE,(IUnknown**)&pIAccessor));
//create accessor with different Parameter accessor flags
TEST2C_(hr=pIAccessor->CreateAccessor(DBACCESSOR_PARAMETERDATA,
m_cBinding,m_rgBinding,0,&hAccessor1,NULL),S_OK,DB_E_BADACCESSORFLAGS);
TEST2C_(hr=pIAccessor->CreateAccessor(DBACCESSOR_PARAMETERDATA|DBACCESSOR_ROWDATA,
m_cBinding,m_rgBinding,0,&hAccessor2,NULL),S_OK,DB_E_BADACCESSORFLAGS);
TEST2C_(hr=pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA|DBACCESSOR_PARAMETERDATA,
m_cBinding,m_rgBinding,0,&hAccessor3,NULL),S_OK,DB_E_BADACCESSORFLAGS);
TEST2C_(hr=pIAccessor->CreateAccessor(DBACCESSOR_PARAMETERDATA|DBACCESSOR_OPTIMIZED,
m_cBinding,m_rgBinding,0,&hAccessor4,NULL),S_OK,DB_E_BADACCESSORFLAGS);
TEST3C_(hr=pIAccessor->CreateAccessor(DBACCESSOR_PARAMETERDATA|DBACCESSOR_PASSBYREF,
m_cBinding,m_rgBinding,0,&hAccessor5,NULL),
S_OK,DB_E_BYREFACCESSORNOTSUPPORTED,DB_E_BADACCESSORFLAGS);
TEST3C_(hr=pIAccessor->CreateAccessor(DBACCESSOR_PARAMETERDATA|DBACCESSOR_PASSBYREF|DBACCESSOR_OPTIMIZED,
m_cBinding,m_rgBinding,0,&hAccessor6,NULL),
S_OK,DB_E_BYREFACCESSORNOTSUPPORTED,DB_E_BADACCESSORFLAGS);
//Release the first Rowset and Command
ReleaseRowsetAndAccessor(0,1);
TESTC(VerifyInterface(pIAccessor,IID_ICommand,COMMAND_INTERFACE,(IUnknown**)&m_pICommand));
// Fixup the Updatablity flag again
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
if(!GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,m_rgPropertyIDs,0,NULL,ON_COMMAND_ACCESSOR,
TRUE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND,
FORWARD,NO_COLS_BY_REF,0,0,NULL,NO_COLS_OWNED_BY_PROV,DBPARAMIO_INPUT,NULL,DB_E_BYREFACCESSORNOTSUPPORTED))
{
fPass=TRUE;
goto CLEANUP;
}
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&m_cRowsObtained, &pHRow),S_OK);
TESTC(m_cRowsObtained == 1);
TESTC_(GetData(hRow[0],m_hAccessor,m_pData),S_OK);
fnIgnoreAutoInc(&m_pData);
//use valid hRow
if( hAccessor1 )
TEST2C_(SetData(hRow[0],hAccessor1,m_pData),DB_E_BADACCESSORTYPE,DB_E_BADACCESSORHANDLE);
if( hAccessor2 )
TEST3C_(SetData(hRow[0],hAccessor2,m_pData),S_OK,DB_E_BADACCESSORTYPE,DB_E_BADACCESSORHANDLE);
if( hAccessor3 )
TEST3C_(SetData(hRow[0],hAccessor3,m_pData),DB_E_BADACCESSORTYPE,DB_E_ERRORSOCCURRED,DB_E_BADACCESSORHANDLE);
if( hAccessor4 )
TEST2C_(SetData(hRow[0],hAccessor4,m_pData),DB_E_BADACCESSORTYPE,DB_E_BADACCESSORHANDLE);
if( hAccessor5 )
TEST2C_(SetData(hRow[0],hAccessor5,m_pData),DB_E_BADACCESSORTYPE,DB_E_BADACCESSORHANDLE);
if( hAccessor6 )
TEST2C_(SetData(hRow[0],hAccessor6,m_pData),DB_E_BADACCESSORTYPE,DB_E_BADACCESSORHANDLE);
fPass=TRUE;
CLEANUP:
//release objects
if( m_pIRowset )
CHECK(m_pIRowset->ReleaseRows(m_cRowsObtained,hRow,NULL,NULL,NULL),S_OK);
if( pIAccessor && hAccessor1 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor1,NULL),S_OK);
if( pIAccessor && hAccessor2 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor2,NULL),S_OK);
if( pIAccessor && hAccessor3 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor3,NULL),S_OK);
if( pIAccessor && hAccessor4 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor4,NULL),S_OK);
if( pIAccessor && hAccessor5 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor5,NULL),S_OK);
if( pIAccessor && hAccessor6 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor6,NULL),S_OK);
SAFE_RELEASE(pIAccessor);
ReleaseRowsetAndAccessor();
return fPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc immediate update mode. Valid accessor with different Row Accessor Flags
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Boundary::Variation_10()
{
HROW hRow[1];
HROW *pHRow = hRow;
IAccessor *pIAccessor = NULL;
HACCESSOR hAccessor1 = DB_NULL_HACCESSOR;
HACCESSOR hAccessor2 = DB_NULL_HACCESSOR;
HACCESSOR hAccessor3 = DB_NULL_HACCESSOR;
HACCESSOR hAccessor4 = DB_NULL_HACCESSOR;
HRESULT hr = E_FAIL;
BOOL fPass = TEST_SKIPPED;
// Initialize
m_cRowsObtained = 0;
m_rgPropertyIDs[0] = DBPROP_IRowsetChange;
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;;//DBPROPVAL_UP_CHANGE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,m_rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR,TRUE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
QTESTC(m_pICommand != NULL);
QTESTC(m_pIRowsetChange != NULL);
fPass = FALSE;
//create an accessor off the command
TESTC(VerifyInterface(m_pICommand,IID_IAccessor,COMMAND_INTERFACE,(IUnknown**)&pIAccessor));
//create accessor with different Row accessor flags
TESTC_(pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,0,&hAccessor1,NULL),S_OK);
TESTC_(pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA|DBACCESSOR_OPTIMIZED,
m_cBinding,m_rgBinding,0,&hAccessor2,NULL),S_OK);
TEST2C_(pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA|DBACCESSOR_PASSBYREF,
m_cBinding,m_rgBinding,0,&hAccessor3,NULL),S_OK,DB_E_BYREFACCESSORNOTSUPPORTED);
TEST2C_(pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA|DBACCESSOR_PASSBYREF|DBACCESSOR_OPTIMIZED,
m_cBinding,m_rgBinding,0,&hAccessor4,NULL),S_OK,DB_E_BYREFACCESSORNOTSUPPORTED);
//Release the first Rowset and Command
ReleaseRowsetAndAccessor(0,1);
TESTC(VerifyInterface(pIAccessor,IID_ICommand,COMMAND_INTERFACE,(IUnknown**)&m_pICommand));
// Fixup the Updatablity flag again
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
//DB_E_BYREFACCESSORNOTSUPPORTED could be returned here becasue m_pICommand is inheritted from the
//pIAccessor which could have been created with DBACCESSOR_PASSBYREF
if(!GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,m_rgPropertyIDs,0,NULL,ON_COMMAND_ACCESSOR,
TRUE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND,
FORWARD,NO_COLS_BY_REF,0,0,NULL,NO_COLS_OWNED_BY_PROV,DBPARAMIO_NOTPARAM,NULL,DB_E_BYREFACCESSORNOTSUPPORTED))
{
fPass=TRUE;
goto CLEANUP;
}
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&m_cRowsObtained, &pHRow),S_OK);
TESTC(m_cRowsObtained == 1);
TESTC_(GetData(hRow[0],hAccessor1,m_pData),S_OK);
fnIgnoreAutoInc(&m_pData);
//use valid hRow
if( hAccessor1 )
TESTC_(SetData(hRow[0],hAccessor1,m_pData),S_OK);
if( hAccessor2 )
TESTC_(SetData(hRow[0],hAccessor2,m_pData),S_OK);
if( hAccessor3 )
TEST2C_(SetData(hRow[0],hAccessor3,m_pData),S_OK,DB_E_BADACCESSORTYPE);
if( hAccessor4 )
TEST2C_(SetData(hRow[0],hAccessor4,m_pData),S_OK,DB_E_BADACCESSORTYPE);
fPass=TRUE;
CLEANUP:
//release objects
if( m_pIRowset )
CHECK(m_pIRowset->ReleaseRows(m_cRowsObtained,hRow,NULL,NULL,NULL),S_OK);
if( pIAccessor && hAccessor1 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor1,NULL),S_OK);
if( pIAccessor && hAccessor2 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor2,NULL),S_OK);
if( pIAccessor && hAccessor3 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor3,NULL),S_OK);
if( pIAccessor && hAccessor4 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor4,NULL),S_OK);
SAFE_RELEASE(pIAccessor);
ReleaseRowsetAndAccessor();
return fPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc inherited parameter accessors with SetData
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Boundary::Variation_11()
{
HROW hRow[1];
HROW *pHRow = hRow;
IAccessor *pIAccessor = NULL;
HACCESSOR hAccessor1 = DB_NULL_HACCESSOR;
void *pData1 = NULL;
void *pData2 = NULL;
HRESULT hr = E_FAIL;
BOOL fPass = TEST_SKIPPED;
DBACCESSORFLAGS dwAccessorFlags;
DBCOUNTITEM cBindings = 0;
DBBINDING *rgBindings = NULL;
// Initialize
m_cRowsObtained = 0;
m_rgPropertyIDs[0] = DBPROP_IRowsetChange;
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,m_rgPropertyIDs,0,NULL,ON_COMMAND_ACCESSOR,
TRUE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND,
FORWARD,NO_COLS_BY_REF,0,0,NULL,NO_COLS_OWNED_BY_PROV,DBPARAMIO_INPUT));
QTESTC(m_pICommand != NULL);
QTESTC(m_pIRowsetChange != NULL);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData1,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData2,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
fnIgnoreAutoInc(&pData1);
fnIgnoreAutoInc(&pData2);
fPass = TEST_FAIL;
//create an accessor object
TESTC(VerifyInterface(m_pICommand,IID_IAccessor,COMMAND_INTERFACE,(IUnknown**)&pIAccessor));
//create accessor with different Parameter AND Rowset accessor flags
// TESTC_(hr=pIAccessor->CreateAccessor(DBACCESSOR_PARAMETERDATA | DBACCESSOR_ROWDATA,
// m_cBinding,m_rgBinding,0,&hAccessor1,NULL),S_OK);//,DB_E_BADACCESSORFLAGS);
hr=pIAccessor->CreateAccessor(DBACCESSOR_PARAMETERDATA | DBACCESSOR_ROWDATA,
m_cBinding,m_rgBinding,0,&hAccessor1,NULL);
if (hr == DB_E_BADACCESSORFLAGS)
{
// Provider may not support PARAMETER accessors - verify it
hr = pIAccessor->CreateAccessor(DBACCESSOR_PARAMETERDATA, m_cBinding, m_rgBinding, 0, &hAccessor1, NULL);
TESTC_(hr, DB_E_BADACCESSORFLAGS);
// Now create only Rowset accessor
hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, m_cBinding, m_rgBinding, 0, &hAccessor1, NULL);
TESTC_(hr, S_OK);
}
else
TESTC_(hr, S_OK);
//get a row
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&m_cRowsObtained, &pHRow),S_OK);
TESTC(m_cRowsObtained == 1);
//set data with row/param accessor
if( hAccessor1 )
TEST2C_(SetData(hRow[0],hAccessor1,pData1),DB_E_BADACCESSORTYPE,DB_E_BADACCESSORHANDLE);
//Release the first Rowset and Command
ReleaseRowsetAndAccessor(0,1);
//get a new command object of the accessor
TESTC(VerifyInterface(pIAccessor,IID_ICommand,COMMAND_INTERFACE,(IUnknown**)&m_pICommand));
// Fixup the Updatablity flag again
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset without an accessor on the rowset,(use inherited accessor)
if(!GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,m_rgPropertyIDs,0,NULL,NO_ACCESSOR,
TRUE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND,
FORWARD,NO_COLS_BY_REF,0,0,NULL,NO_COLS_OWNED_BY_PROV,0,NULL,DB_E_BYREFACCESSORNOTSUPPORTED))
{
fPass=TEST_PASS;
goto CLEANUP;
}
//get a row
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&m_cRowsObtained, &pHRow),S_OK);
TESTC(m_cRowsObtained == 1);
//set data with inherited row/param accessor from command
if( hAccessor1 )
TESTC_(SetData(hRow[0],hAccessor1,pData2),S_OK);
QTESTC_(hr = pIAccessor->GetBindings(hAccessor1, &dwAccessorFlags, &cBindings, &rgBindings),S_OK);
COMPARE(dwAccessorFlags, (DBACCESSOR_PARAMETERDATA | DBACCESSOR_ROWDATA));
//create an accessor object from the rowset object (should be the accessor that the rowset inherited)
if( pIAccessor && hAccessor1 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor1,NULL),S_OK);
SAFE_RELEASE(pIAccessor);
FreeAccessorBindings(cBindings, rgBindings);
TESTC(VerifyInterface(m_pIRowset,IID_IAccessor,COMMAND_INTERFACE,(IUnknown**)&pIAccessor));
QTESTC_(hr = pIAccessor->GetBindings(hAccessor1, &dwAccessorFlags, &cBindings, &rgBindings),S_OK);
COMPARE(dwAccessorFlags, (DBACCESSOR_PARAMETERDATA | DBACCESSOR_ROWDATA));
fPass=TEST_PASS;
CLEANUP:
//release objects
if( m_pIRowset )
CHECK(m_pIRowset->ReleaseRows(m_cRowsObtained,hRow,NULL,NULL,NULL),S_OK);
if( pIAccessor && hAccessor1 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor1,NULL),S_OK);
FreeAccessorBindings(cBindings, rgBindings);
PROVIDER_FREE(pData1);
PROVIDER_FREE(pData2);
SAFE_RELEASE(pIAccessor);
ReleaseRowsetAndAccessor();
return fPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc immediate update mode. more Valid accessor with bad ordinals
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Boundary::Variation_12()
{
HROW hRow[1];
HROW *pHRow = hRow;
IAccessor *pIAccessor = NULL;
HACCESSOR hAccessor1 = DB_NULL_HACCESSOR;
HACCESSOR hAccessor2 = DB_NULL_HACCESSOR;
HRESULT hr = E_FAIL;
BOOL fPass = TEST_SKIPPED;
// Initialize
m_cRowsObtained = 0;
m_rgPropertyIDs[0] = DBPROP_IRowsetChange;
m_rgPropertyIDs[1] = DBPROP_BOOKMARKS;
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,m_rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR,
TRUE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND));
QTESTC(m_pICommand != NULL);
QTESTC(m_pIRowsetChange != NULL);
fPass = FALSE;
//create an accessor with invalid ordinals
TESTC(VerifyInterface(m_pICommand,IID_IAccessor,COMMAND_INTERFACE,(IUnknown**)&pIAccessor));
m_rgBinding[0].iOrdinal = 9999;
TESTC_(pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,
m_cBinding,m_rgBinding,0,&hAccessor1,NULL),S_OK);
m_rgBinding[0].iOrdinal = m_rgBinding[m_cBinding-1].iOrdinal++;
TESTC_(pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,
m_cBinding,m_rgBinding,0,&hAccessor2,NULL),S_OK);
//Release the first Rowset and Command
ReleaseRowsetAndAccessor(0,1);
TESTC(VerifyInterface(pIAccessor,IID_ICommand,COMMAND_INTERFACE,(IUnknown**)&m_pICommand));
// Fixup the Updatablity flag agian
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
if(!GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,m_rgPropertyIDs,0,NULL,ON_COMMAND_ACCESSOR,
TRUE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND,
FORWARD,NO_COLS_BY_REF,0,0,NULL,NO_COLS_OWNED_BY_PROV,DBPARAMIO_NOTPARAM,&hr))
{
TEST2C_(hr, DB_E_BADORDINAL,DB_E_ERRORSOCCURRED);
fPass=TRUE;
goto CLEANUP;
}
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&m_cRowsObtained, &pHRow),S_OK);
TESTC(m_cRowsObtained == 1);
TESTC_(GetData(hRow[0],m_hAccessor,m_pData),S_OK);
//use valid hRow with bad ordinals
TEST2C_(SetData(hRow[0],hAccessor1,m_pData),DB_E_BADORDINAL,DB_E_ERRORSOCCURRED);
TEST2C_(SetData(hRow[0],hAccessor2,m_pData),DB_E_BADORDINAL,DB_E_ERRORSOCCURRED);
fPass=TRUE;
CLEANUP:
//release objects
if( m_pIRowset )
CHECK(m_pIRowset->ReleaseRows(m_cRowsObtained,hRow,NULL,NULL,NULL),S_OK);
if( pIAccessor && hAccessor1 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor1,NULL),S_OK);
if( pIAccessor && hAccessor2 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor2,NULL),S_OK);
SAFE_RELEASE(pIAccessor);
ReleaseRowsetAndAccessor();
return fPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc immediate update mode. get bookmarks on inheritied accessor
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Boundary::Variation_13()
{
HROW hRow[1];
HROW *pHRow = hRow;
IAccessor *pIAccessor = NULL;
HACCESSOR hAccessor1 = DB_NULL_HACCESSOR;
HRESULT hr = E_FAIL;
BOOL fPass = TEST_SKIPPED;
// Initialize
m_cRowsObtained = 0;
m_rgPropertyIDs[0] = DBPROP_IRowsetChange;
m_rgPropertyIDs[1] = DBPROP_BOOKMARKS;
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,m_rgPropertyIDs,0,NULL,ON_COMMAND_ACCESSOR,
TRUE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND));
QTESTC(m_pICommand != NULL);
QTESTC(m_pIRowsetChange != NULL);
fPass = FALSE;
//create an accessor with invalid ordinals
TESTC(VerifyInterface(m_pIRowset,IID_IAccessor,COMMAND_INTERFACE,(IUnknown**)&pIAccessor));
// Verify we've got at least one binding
QTESTC(m_cBinding != 0);
m_rgBinding[0].iOrdinal = 0;
TESTC_(pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,
m_cBinding,m_rgBinding,0,&hAccessor1,NULL),S_OK);
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&m_cRowsObtained, &pHRow),S_OK);
TESTC(m_cRowsObtained == 1);
//use valid hRow with bad ordinals
TESTC_(GetData(hRow[0],hAccessor1,m_pData),S_OK);
fPass = TEST_PASS;
CLEANUP:
//release objects
if( m_pIRowset )
CHECK(m_pIRowset->ReleaseRows(m_cRowsObtained,hRow,NULL,NULL,NULL),S_OK);
if( pIAccessor && hAccessor1 )
CHECK(pIAccessor->ReleaseAccessor(hAccessor1,NULL),S_OK);
SAFE_RELEASE(pIAccessor);
ReleaseRowsetAndAccessor();
return fPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Boundary::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// {{ TCW_TC_PROTOTYPE(Rowsets)
//*-----------------------------------------------------------------------
//| Test Case: Rowsets - Testing read-only rowset and empty
//| Created: 04/08/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Rowsets::Init()
{
return TCIRowsetChange::Init();
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Read-only rowset with
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Rowsets::Variation_1()
{
IUnknown *pIRowset = NULL;
BOOL fTestPass = TEST_SKIPPED;
if (!m_pIDBCreateCommand ||
!SupportedProperty(DBPROP_IRowsetChange,DBPROPSET_ROWSET,g_pIDBCreateSession))
goto CLEANUP;
fTestPass=FALSE;
//open an empty rowset, asking for IRowsetChange interface pointer
m_hr = g_pTable->ExecuteCommand(SELECT_COUNT, IID_IRowsetChange,NULL,NULL,NULL,NULL,
EXECUTE_IFNOERROR,0,NULL,NULL,&pIRowset,NULL);
TESTC(m_hr == S_OK ||m_hr ==DB_E_ERRORSOCCURRED);
fTestPass=TRUE;
CLEANUP:
SAFE_RELEASE(pIRowset);
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Read only rowset with left outer join.DB_E_PROPERTIESNOTAVAILABLE.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Rowsets::Variation_2()
{
IUnknown *pIRowset = NULL;
BOOL fTestPass = TEST_SKIPPED;
size_t fEscapeClauses = FALSE;
size_t fODBCExt = FALSE;
size_t fANSI = FALSE;
ULONG_PTR ulSQLSupportMask = 0;
DBPROPSET rgDBPropSet[1];
LPWSTR pwsz2ndTName = NULL;
rgDBPropSet[0].cProperties = 1;
rgDBPropSet[0].guidPropertySet= DBPROPSET_ROWSET;
rgDBPropSet[0].rgProperties=(DBPROP *)PROVIDER_ALLOC(sizeof(DBPROP) * (1));
memset(rgDBPropSet[0].rgProperties,0,sizeof(DBPROP)*(1));
if(!rgDBPropSet[0].rgProperties)
goto CLEANUP;
rgDBPropSet[0].rgProperties[0].dwPropertyID = DBPROP_IRowsetChange;
rgDBPropSet[0].rgProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[0].vValue.vt = VT_BOOL;
rgDBPropSet[0].rgProperties[0].colid = DB_NULLID;
V_BOOL(&rgDBPropSet[0].rgProperties[0].vValue) = VARIANT_TRUE;
if (!m_pIDBCreateCommand ||
!SupportedProperty(DBPROP_IRowsetChange,DBPROPSET_ROWSET, g_pIDBCreateSession))
goto CLEANUP;
// skip variation if there is no SQL Support
QTESTC(GetProperty(DBPROP_SQLSUPPORT, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &ulSQLSupportMask));
fTestPass=FALSE;
fEscapeClauses = DBPROPVAL_SQL_ESCAPECLAUSES & ulSQLSupportMask;
fODBCExt = DBPROPVAL_SQL_ODBC_EXTENDED & ulSQLSupportMask;
fANSI = DBPROPVAL_SQL_ANSI92_INTERMEDIATE & ulSQLSupportMask;
pwsz2ndTName = g_p1RowTable->GetTableName();
if (fEscapeClauses)
{
//open a left outer join, asking for IRowsetChange interface pointer
m_hr=g_pTable->ExecuteCommand(SELECT_LEFTOUTERJOIN_ESC, IID_IRowsetChange,pwsz2ndTName,
NULL,NULL,NULL,EXECUTE_IFNOERROR,1,rgDBPropSet,NULL,&pIRowset,NULL);
}
else
{
//open a left outer join, asking for IRowsetChange interface pointer
m_hr=g_pTable->ExecuteCommand(SELECT_LEFTOUTERJOIN, IID_IRowsetChange,pwsz2ndTName,
NULL,NULL,NULL,EXECUTE_IFNOERROR,1,rgDBPropSet,NULL,&pIRowset,NULL);
}
m_pIRowset=(IRowset*)pIRowset;
//S_OK is ok here because a provider may not support the whole extended level
// but might suport some SQL syntax that is part of the extended level
//DB_E_ERRORSOCCURRED because change to a temp table might not be possilbe
//DB_E_ERRORSINCOMMAND because join might not be supported
if ( fODBCExt || fANSI)
{
TESTC( m_hr == S_OK || m_hr == DB_E_ERRORSOCCURRED )
}
else
{
TESTC( m_hr == S_OK || m_hr == DB_E_ERRORSOCCURRED || m_hr == DB_E_ERRORSINCOMMAND)
}
fTestPass = TRUE;
CLEANUP:
if(rgDBPropSet[0].rgProperties)
PROVIDER_FREE(rgDBPropSet[0].rgProperties);
SAFE_RELEASE(pIRowset);
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Read only rowset with right outer join.DB_E_PROPERTIESNOTAVAILABLE.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Rowsets::Variation_3()
{
IUnknown *pIRowset = NULL;
BOOL fTestPass = TEST_SKIPPED;
size_t fEscapeClauses = FALSE;
ULONG_PTR ulSQLSupportMask = 0;
size_t fODBCExt = FALSE;
size_t fANSI = FALSE;
DBPROPSET rgDBPropSet[1];
rgDBPropSet[0].cProperties = 1;
rgDBPropSet[0].guidPropertySet= DBPROPSET_ROWSET;
rgDBPropSet[0].rgProperties=(DBPROP *)PROVIDER_ALLOC(sizeof(DBPROP) * (1));
memset(rgDBPropSet[0].rgProperties,0,sizeof(DBPROP)*(1));
if(!rgDBPropSet[0].rgProperties)
goto CLEANUP;
rgDBPropSet[0].rgProperties[0].dwPropertyID = DBPROP_IRowsetChange;
rgDBPropSet[0].rgProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[0].vValue.vt = VT_BOOL;
rgDBPropSet[0].rgProperties[0].colid = DB_NULLID;
V_BOOL(&rgDBPropSet[0].rgProperties[0].vValue) = VARIANT_TRUE;
if (!m_pIDBCreateCommand ||
!SupportedProperty(DBPROP_IRowsetChange,DBPROPSET_ROWSET,g_pIDBCreateSession))
goto CLEANUP;
// skip variation if there is no SQL Support
QTESTC(GetProperty(DBPROP_SQLSUPPORT, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &ulSQLSupportMask));
fTestPass=FALSE;
fEscapeClauses = DBPROPVAL_SQL_ESCAPECLAUSES & ulSQLSupportMask;
fODBCExt = DBPROPVAL_SQL_ODBC_EXTENDED & ulSQLSupportMask;
fANSI = DBPROPVAL_SQL_ANSI92_INTERMEDIATE & ulSQLSupportMask;
if (fEscapeClauses)
{
//open a rightouter join, asking for IRowsetChange interface pointer
m_hr=g_pTable->ExecuteCommand(SELECT_RIGHTOUTERJOIN_ESC, IID_IRowsetChange,g_p1RowTable->GetTableName(),
NULL,NULL,NULL,EXECUTE_IFNOERROR,1,rgDBPropSet,NULL,&pIRowset,NULL);
}
else
{
//open a rightouter, asking for IRowsetChange interface pointer
m_hr=g_pTable->ExecuteCommand(SELECT_RIGHTOUTERJOIN, IID_IRowsetChange,g_p1RowTable->GetTableName(),
NULL,NULL,NULL,EXECUTE_IFNOERROR,1,rgDBPropSet,NULL,&pIRowset,NULL);
}
//S_OK is ok here because a provider may not support the whole extended level
// but might suport some SQL syntax that is part of the extended level
//DB_E_ERRORSOCCURRED because change to a temp table might not be possilbe
//DB_E_ERRORSINCOMMAND because join might not be supported
if ( fODBCExt || fANSI)
{
TESTC( m_hr == S_OK || m_hr == DB_E_ERRORSOCCURRED )
}
else
{
TESTC( m_hr == S_OK || m_hr == DB_E_ERRORSOCCURRED || m_hr == DB_E_ERRORSINCOMMAND)
}
fTestPass = TRUE;
CLEANUP:
SAFE_RELEASE(pIRowset);
PROVIDER_FREE(rgDBPropSet[0].rgProperties);
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Empty rowset. S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Rowsets::Variation_4()
{
IUnknown *pIRowset = NULL;
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr = E_FAIL;
if (!m_pIDBCreateCommand ||
!SupportedProperty(DBPROP_IRowsetChange,DBPROPSET_ROWSET,g_pIDBCreateSession))
goto CLEANUP;
fTestPass=FALSE;
//open an empty rowset, asking for IRowsetChange interface pointer
hr = g_pTable->ExecuteCommand(SELECT_EMPTYROWSET, IID_IRowsetChange,
NULL,NULL,NULL,NULL,EXECUTE_IFNOERROR,0,NULL,NULL,&pIRowset,NULL);
if (FAILED(hr))
TESTC_(hr, DB_E_NOTSUPPORTED)
else
TESTC_(hr, S_OK)
fTestPass=TRUE;
CLEANUP:
if(pIRowset)
COMPARE(pIRowset->Release(), 0);
return fTestPass;
}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Rowsets::Terminate()
{
return(TCIRowsetChange::Terminate());
}
// {{ TCW_TC_PROTOTYPE(MayWriteColumn)
//*-----------------------------------------------------------------------
//| Test Case: MayWriteColumn - test DBPROP_MAYWRITECOLUMN
//| Created: 04/08/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL MayWriteColumn::Init()
{
return TCIRowsetChange::Init();
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Make sure MSDASQL does not support DBPROP_MAYWRITECOLUMN
//
// @rdesc TEST_PASS or TEST_FAIL
//
int MayWriteColumn::Variation_1()
{
return TEST_PASS;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL MayWriteColumn::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(MaxPendingChangeRows)
//*-----------------------------------------------------------------------
//| Test Case: MaxPendingChangeRows - test DBPROP_MAXPENDINGCHANGEROWS
//| Created: 04/08/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL MaxPendingChangeRows::Init()
{
return TCIRowsetChange::Init();
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Verify DBPROP_MAXPENDINGROWS
//
// @rdesc TEST_PASS or TEST_FAIL
//
int MaxPendingChangeRows::Variation_1()
{
IRowsetInfo *pIRowsetInfo=NULL;
ULONG cProperties=0;
DBPROPSET *pDBPropSet=NULL;
DBPROPIDSET DBPropIDSet;
DBPROPID DBPropID=DBPROP_IRowsetChange;
BOOL fTestPass=TEST_SKIPPED;
ULONG ulPendingChanges=0;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,&DBPropID));
if (!m_pIRowsetChange)
goto CLEANUP;
// Set to FALSE
fTestPass = FALSE;
//get the IRowsetInfo pointer
TESTC_(m_pIRowsetChange->QueryInterface(IID_IRowsetInfo,(LPVOID *)&pIRowsetInfo),S_OK);
//ask for information on DBPROP_MAXPENDINGROWS
DBPropIDSet.guidPropertySet=DBPROPSET_ROWSET;
DBPropIDSet.cPropertyIDs=1;
DBPropIDSet.rgPropertyIDs=&DBPropID;
//ask for information on DBPROP_MAXPENDINGROWS
DBPropID=DBPROP_MAXPENDINGROWS;
m_hr=pIRowsetInfo->GetProperties(1,&DBPropIDSet,&cProperties,&pDBPropSet);
if(m_hr == S_OK && pDBPropSet->rgProperties->dwStatus == DBPROPSTATUS_OK)
{
odtLog <<L"DBPROP_MAXPENDINGROWS is set to " <<V_I4(&pDBPropSet->rgProperties->vValue) <<ENDL;
fTestPass = TRUE;
}
else
{
odtLog <<L"DBPROP_MAXPENDINGROWS is not supported" <<ENDL;
fTestPass=TEST_SKIPPED;
}
CLEANUP:
//free the memory
FreeProperties(&cProperties,&pDBPropSet);
SAFE_RELEASE(pIRowsetInfo);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Verify DBPROP_MAXOPENROWS
//
// @rdesc TEST_PASS or TEST_FAIL
//
int MaxPendingChangeRows::Variation_2()
{
IRowsetInfo *pIRowsetInfo=NULL;
ULONG cProperties=0;
DBPROPSET *pDBPropSet=NULL;
DBPROPIDSET DBPropIDSet;
DBPROPID DBPropID=DBPROP_IRowsetChange;
BOOL fTestPass=TEST_SKIPPED;
ULONG ulMaxOpenRows=0;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,&DBPropID));
if (!m_pIRowsetChange)
goto CLEANUP;
// Set to FALSE
fTestPass = FALSE;
//get the IRowsetInfo pointer
TESTC_(m_pIRowsetChange->QueryInterface(IID_IRowsetInfo,(LPVOID *)&pIRowsetInfo),S_OK);
//ask for information on DBPROP_MAXPENDINGCHNAGEROWS
DBPropIDSet.guidPropertySet=DBPROPSET_ROWSET;
DBPropIDSet.cPropertyIDs=1;
DBPropIDSet.rgPropertyIDs=&DBPropID;
//ask for information on DBPROP_MAXOPENROWS
DBPropID=DBPROP_MAXOPENROWS;
m_hr=pIRowsetInfo->GetProperties(1,&DBPropIDSet,&cProperties,&pDBPropSet);
if(m_hr == S_OK && pDBPropSet->rgProperties->dwStatus == DBPROPSTATUS_OK)
{
odtLog <<L"DBPROP_MAXOPENROWS is set to " <<V_I4(&pDBPropSet->rgProperties->vValue) <<ENDL;
fTestPass = TRUE;
}
else
{
odtLog <<L"DBPROP_MAXOPENROWS is not supported" <<ENDL;
fTestPass=TEST_SKIPPED;
}
CLEANUP:
//free the memory
FreeProperties(&cProperties,&pDBPropSet);
SAFE_RELEASE(pIRowsetInfo);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL MaxPendingChangeRows::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(CacheDeferred)
//*-----------------------------------------------------------------------
//| Test Case: CacheDeferred - test DBPROP_CACHEDEFERRED
//| Created: 04/08/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL CacheDeferred::Init()
{
return TCIRowsetChange::Init();
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc to be coded DBPROP_CACHDEFERRED
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CacheDeferred::Variation_1()
{
return TEST_PASS;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL CacheDeferred::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(NoColumn_Row_Restrict)
//*-----------------------------------------------------------------------
//| Test Case: NoColumn_Row_Restrict - test DBPROP_NOCOLUMNRESTRICT and DBPROP_NOROWRESTRICT
//| Created: 04/08/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL NoColumn_Row_Restrict::Init()
{
return TCIRowsetChange::Init();
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Select Count(*
//
// @rdesc TEST_PASS or TEST_FAIL
//
int NoColumn_Row_Restrict::Variation_1()
{
BOOL fTestPass=TEST_SKIPPED;
ULONG cProperties=0;
IRowsetInfo *pIRowsetInfo=NULL;
DBPROPID DBPropIDColumn=DBPROP_COLUMNRESTRICT;
DBPROPID DBPropIDRow=DBPROP_ROWRESTRICT;
DBPROPIDSET DBPropIDSet;
DBPROPSET *pDBPropSet=NULL;
//open the rowset
TESTC_PROVIDER(CreateRowsetObject(SELECT_EMPTYROWSET,IID_IRowset,EXECUTE_IFNOERROR)==S_OK);
if(!SupportedProperty(DBPROP_COLUMNRESTRICT,DBPROPSET_ROWSET,g_pIDBCreateSession))
{
odtLog<<L"DBPROP_COLUMNRESTRICT not supported, test Skipped."<<ENDL;
goto CLEANUP;
}
if(!SupportedProperty(DBPROP_ROWRESTRICT,DBPROPSET_ROWSET,g_pIDBCreateSession))
{
odtLog<<L"DBPROP_ROWRESTRICT not supported, test Skipped."<<ENDL;
goto CLEANUP;
}
fTestPass = FALSE;
//QI for IRowsetInfo
TESTC_(m_pIAccessor->QueryInterface(IID_IRowsetInfo,(LPVOID *)&pIRowsetInfo),S_OK);
//init
DBPropIDSet.guidPropertySet=DBPROPSET_ROWSET;
DBPropIDSet.cPropertyIDs=1;
DBPropIDSet.rgPropertyIDs=NULL;
DBPropIDSet.rgPropertyIDs=&DBPropIDColumn;
TESTC_(pIRowsetInfo->GetProperties(1,&DBPropIDSet,&cProperties,&pDBPropSet),S_OK);
//no column restrict on this rowset
if( (V_BOOL(&pDBPropSet->rgProperties->vValue)!=VARIANT_TRUE) &&
(V_BOOL(&pDBPropSet->rgProperties->vValue)!=VARIANT_FALSE) )
goto CLEANUP;
//free the memory
FreeProperties(&cProperties,&pDBPropSet);
DBPropIDSet.rgPropertyIDs=&DBPropIDRow;
TESTC_(pIRowsetInfo->GetProperties(1,&DBPropIDSet,&cProperties,&pDBPropSet),S_OK);
//no row restrict on this rowset
if( (V_BOOL(&pDBPropSet->rgProperties->vValue)!=VARIANT_TRUE) &&
(V_BOOL(&pDBPropSet->rgProperties->vValue)!=VARIANT_FALSE) )
goto CLEANUP;
fTestPass=TRUE;
CLEANUP:
//free the memory
FreeProperties(&cProperties,&pDBPropSet);
SAFE_RELEASE(pIRowsetInfo);
ReleaseRowsetObject();
ReleaseCommandObject();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Select * from Table. Restrict on table. No restrict on column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int NoColumn_Row_Restrict::Variation_2()
{
BOOL fTestPass=TEST_SKIPPED;
ULONG cProperties=0;
IRowsetInfo *pIRowsetInfo=NULL;
DBPROPID DBPropIDColumn=DBPROP_COLUMNRESTRICT;
DBPROPID DBPropIDRow=DBPROP_ROWRESTRICT;
DBPROPIDSET DBPropIDSet;
DBPROPSET *pDBPropSet=NULL;
//open the rowset with IOpenRowset
TESTC_PROVIDER(CreateRowsetObject(SELECT_ALLFROMTBL,IID_IRowset,EXECUTE_IFNOERROR)==S_OK);
if(!SupportedProperty(DBPROP_COLUMNRESTRICT,DBPROPSET_ROWSET,g_pIDBCreateSession))
{
odtLog<<L"DBPROP_COLUMNRESTRICT not supported, test Skipped."<<ENDL;
goto CLEANUP;
}
if(!SupportedProperty(DBPROP_ROWRESTRICT,DBPROPSET_ROWSET,g_pIDBCreateSession))
{
odtLog<<L"DBPROP_ROWRESTRICT not supported, test Skipped."<<ENDL;
goto CLEANUP;
}
fTestPass = FALSE;
//QI for IRowsetInfo
TESTC_(m_pIAccessor->QueryInterface(IID_IRowsetInfo,(LPVOID *)&pIRowsetInfo),S_OK);
//init
DBPropIDSet.guidPropertySet=DBPROPSET_ROWSET;
DBPropIDSet.cPropertyIDs=1;
DBPropIDSet.rgPropertyIDs=NULL;
DBPropIDSet.rgPropertyIDs=&DBPropIDColumn;
TESTC_(pIRowsetInfo->GetProperties(1,&DBPropIDSet,&cProperties,&pDBPropSet),S_OK);
//there is column restrict on this rowset
if( V_BOOL(&pDBPropSet->rgProperties->vValue)!=VARIANT_TRUE &&
V_BOOL(&pDBPropSet->rgProperties->vValue)!=VARIANT_FALSE )
goto CLEANUP;
//free the memory
FreeProperties(&cProperties,&pDBPropSet);
DBPropIDSet.rgPropertyIDs=&DBPropIDRow;
TESTC_(pIRowsetInfo->GetProperties(1,&DBPropIDSet,&cProperties,&pDBPropSet),S_OK);
//no row restrict on this rowset
if( V_BOOL(&pDBPropSet->rgProperties->vValue)!=VARIANT_TRUE &&
V_BOOL(&pDBPropSet->rgProperties->vValue)!=VARIANT_FALSE )
goto CLEANUP;
fTestPass=TRUE;
CLEANUP:
//free the memory
FreeProperties(&cProperties,&pDBPropSet);
SAFE_RELEASE(pIRowsetInfo);
ReleaseRowsetObject();
ReleaseCommandObject();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL NoColumn_Row_Restrict::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Computed_Columns)
//*-----------------------------------------------------------------------
//| Test Case: Computed_Columns - test rowset with computed columns
//| Created: 04/08/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Computed_Columns::Init()
{
DBPROPID DBPropID=DBPROP_IRowsetChange;
BOOL fPass = TEST_SKIPPED;
if(!TCIRowsetChange::Init())
return FALSE;
if(!m_pIDBCreateCommand)
{
odtLog << "Command Not Supported Skipping Variations"<<ENDL;
return TEST_SKIPPED;
}
//create an accessor with IRowsetChange. Immediately update mode.
//create an accessor with value binding only
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_COMPUTEDCOLLIST,1,&DBPropID,
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH));
fPass = TRUE;
CLEANUP:
return fPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Accessor binds the computed column. DB_SEC_E_PERMISSIONDENIED
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Computed_Columns::Variation_1()
{
return TEST_PASS;
//TODO no way to test since different driver behave differently
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Computed_Columns::Terminate()
{
ReleaseRowsetAndAccessor();
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Forward_Query)
//*-----------------------------------------------------------------------
//| Test Case: Forward_Query - forward only cursor. Query based update
//| Created: 04/09/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Forward_Query::Init()
{
return TCIRowsetChange::Init();
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Immediate update mode. Retrieve a row handle, update a row with some columns set to NULL, and call GetData to see the change.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Query::Variation_1()
{
DBPROPID rgPropertyIDs[1];
DBCOUNTITEM cRows = 0;
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber= NULL;
HROW *pHRow = NULL;
ULONG cCount = 0;
BYTE *pData = NULL;
BOOL fTestPass = TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,
2,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass = FALSE;
//ReleaseRowsetAndAccessor() so that an accessor handle can be created on the command
ReleaseRowsetAndAccessor();
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,
2, g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND))
//get an array of nullable and updatable columns
GetNullableAndUpdatable(&cCol,&rgColNumber);
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get a new data buffer to set the data
TESTC_(FillInputBindings( m_pTable,
DBACCESSOR_ROWDATA,
m_cBinding,
m_rgBinding,
&pData,
g_ulNextRow++,
m_cRowsetCols,
m_rgTableColOrds,
PRIMARY),S_OK);
//set a nullable and updatble columns to NULL
if(cCol)
{
for(cCount=0;cCount<m_cBinding;cCount++)
{
if(m_rgBinding[cCount].iOrdinal==rgColNumber[cCol-1])
{
// *(ULONG *)(dwAddr+m_rgBinding[cCount].obStatus)=DBSTATUS_S_ISNULL;
STATUS_BINDING(m_rgBinding[cCount],pData)=DBSTATUS_S_ISNULL;
break;
}
}
}
//has to find such a column
if(cCount==m_cBinding)
goto CLEANUP;
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//get the data for the row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//make sure GetData should be able to see the change
if(COMPARE(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
{
fTestPass=TRUE;
}
CLEANUP:
PROVIDER_FREE(rgColNumber);
PROVIDER_FREE(pData);
if(m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Buffered update mode. Retrieve a row handle, update a row with some columns set to NULL, and call GetData to see the change
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Query::Variation_2()
{
DBPROPID rgPropertyIDs[2];
DBCOUNTITEM cRows =0;
DBORDINAL cCol =0;
DBORDINAL *rgColNumber=NULL;
HROW *pHRow =NULL;
ULONG cCount =0;
BYTE *pData =NULL;
BOOL fTestPass =TEST_SKIPPED;
DBROWSTATUS *DBRowStatus;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
//create an accessor with IRowsetChange. Buffered update mode.
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,2,
g_rgPropertyIDs, ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate) || (!m_cBinding))
{
goto CLEANUP;
}
fTestPass = FALSE;
//get an array of nullable and updatable columns
GetNullableAndUpdatable(&cCol,&rgColNumber);
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows,&pHRow),S_OK);
//get a new data buffer to set the data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,&pData,g_ulNextRow++,
m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set a nullable and updatble columns to NULL
if(cCol)
{
for(cCount=0;cCount<m_cBinding;cCount++)
{
if(m_rgBinding[cCount].iOrdinal==rgColNumber[cCol-1])
{
// *(ULONG *)(dwAddr+m_rgBinding[cCount].obStatus)=DBSTATUS_S_ISNULL;
STATUS_BINDING(m_rgBinding[cCount],pData)=DBSTATUS_S_ISNULL;
break;
}
}
}
//has to find such a column
if(cCount==m_cBinding)
{
goto CLEANUP;
}
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//get the data for the row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//call update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,&DBRowStatus),S_OK);
//make sure GetData should be able to see the change
if(COMPARE(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
PROVIDER_FREE(pData);
if(m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Boundary cases with qbu cursor.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Query::Variation_3()
{
DBPROPID rgPropertyIDs[1];
DBCOUNTITEM cRows = 0;
DBORDINAL *rgColNumber= NULL;
HROW *pHRow = NULL;
BOOL fTestPass = TEST_SKIPPED;
BYTE *pData = NULL;
HACCESSOR hAccessor = NULL;
DBORDINAL cCol = 0;
DBORDINAL ulCol = 0;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
//No accessor to be created.
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,2,g_rgPropertyIDs,NO_ACCESSOR));
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
//get an array of fixed length and updatable columns
if(!COMPARE(GetNonKeyNonBLOB(&cCol,&rgColNumber),TRUE))
{
goto CLEANUP;
}
//pick the third column. if there is not 3 columns use the last one
if(cCol<3)
{
ulCol=cCol-1;
}
else
{
ulCol=3;
}
//create an accessor to the first numeric and updatable column.
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,1,(&rgColNumber[ulCol]) ))
fTestPass = FALSE;
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get a new data buffer to set the data
TESTC_(FillInputBindings( m_pTable,
DBACCESSOR_ROWDATA,
m_cBinding,
m_rgBinding,
(BYTE **)&pData,
g_ulNextRow++,
m_cRowsetCols,
m_rgTableColOrds,
PRIMARY),S_OK);
//create an NULL accessor
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,&hAccessor,NULL),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,NULL),E_INVALIDARG);
TESTC_(SetData(*pHRow,NULL,pData),DB_E_BADACCESSORHANDLE);
TESTC_(SetData(NULL,m_hAccessor,pData),DB_E_BADROWHANDLE);
TESTC_(SetData(*pHRow,hAccessor,NULL),S_OK);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
PROVIDER_FREE(rgColNumber);
if (hAccessor)
{
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
}
if(m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc BSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALUE, qbu
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Query::Variation_4()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
void *pData = NULL;
void *pGetData = NULL;
DBPROPID rgPropertyIDs[1];
DBSTATUS dbsSecondColStatus;
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber = NULL;
DBORDINAL ulCol = 0;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,2,g_rgPropertyIDs,NO_ACCESSOR));
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
//get an array of fixed length and updatable columns
if(!COMPARE(GetNonKeyNonBLOB(&cCol,&rgColNumber),TRUE))
{
goto CLEANUP;
}
//pick the third column. if there is not 3 columns use the last one
if(cCol<3)
{
ulCol=cCol-1;
}
else
{
ulCol=3;
}
fTestPass=FALSE;
//create an accessor to the first numeric and updatable column.
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,1,&(rgColNumber[ulCol]) ))
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//change the second status binding to anything other than _OK or NULL
// *(DBSTATUS *)(((DWORD)pData)+ m_rgBinding[0].obStatus)=DBSTATUS_S_TRUNCATED;
STATUS_BINDING(m_rgBinding[0],pData)=DBSTATUS_S_TRUNCATED;
// keep track of colstatus
// dbsSecondColStatus = *(DBSTATUS *)(((DWORD)pData)+ m_rgBinding[0].obStatus);
dbsSecondColStatus = STATUS_BINDING(m_rgBinding[0],pData);
//set data should fail
m_hr=SetData(*pHRow,m_hAccessor,pData);
if ( !COMPARE(m_hr == DB_E_ERRORSOCCURRED || m_hr == DB_S_ERRORSOCCURRED, TRUE) )
goto CLEANUP;
TESTC_(GetStatus(pData, &(m_rgBinding[0])),DBSTATUS_E_BADSTATUS);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if ( m_hr == DB_S_ERRORSOCCURRED )
{
if(m_cBinding > 1)
TESTC_(GetStatus(pData, &(m_rgBinding[0])),dbsSecondColStatus);
}
else
{
if(m_cBinding > 1)
TESTC_(GetStatus(pData, &(m_rgBinding[0])),DBSTATUS_E_UNAVAILABLE);
//allocate memory for getting data again
pGetData=PROVIDER_ALLOC(m_cRowSize);
if(!pGetData)
goto CLEANUP;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, pGetData),S_OK);
//columns should not be changed
if(!COMPARE(CompareBuffer(pGetData, m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
PROVIDER_FREE(pGetData);
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc SetData not supported, qbu
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Query::Variation_5()
{
DBPROPID rgPropertyIDs[1];
DBCOUNTITEM cRows = 0;
ULONG *rgColNumber= NULL;
HROW *pHRow = NULL;
BOOL fTestPass = TEST_SKIPPED;
BYTE *pData = NULL;
HACCESSOR hAccessor = NULL;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,
2,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass = FALSE;
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get a new data buffer to set the data
TESTC_(FillInputBindings( m_pTable,
DBACCESSOR_ROWDATA,
m_cBinding,
m_rgBinding,
(BYTE **)&pData,
g_ulNextRow++,
m_cRowsetCols,
m_rgTableColOrds,
PRIMARY),S_OK);
//create an NULL accessor
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,&hAccessor,NULL),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),DB_E_NOTSUPPORTED);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
PROVIDER_FREE(rgColNumber);
if (hAccessor)
{
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
}
if(m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Forward_Query::Terminate()
{
return(TCIRowsetChange::Terminate());
}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Forward_Cursor)
//*-----------------------------------------------------------------------
//| Test Case: Forward_Cursor - Forward only cursor. Cursor based update.
//| Created: 04/09/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Forward_Cursor::Init()
{
return TCIRowsetChange::Init();
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Immediate update mode. Retrieve a row handle, update a row with some columns set to NULL, and call GetData to see the change.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_1()
{
DBCOUNTITEM cRows =0;
DBPROPID DBPropIDSet =DBPROP_IRowsetChange;
HROW *pHRow =NULL;
BYTE *pData =NULL;
BOOL fTestPass =TEST_SKIPPED;
ULONG rgNumber=1;
TESTC_PROVIDER((SELECT_ALLFROMTBL,1,&DBPropIDSet,2,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,USE_COLS_TO_BIND_ARRAY,
FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,&rgNumber));
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass = FALSE;
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get a new data buffer to set the data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//get the data for the row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//make sure GetData should be able to see the change
if(COMPARE(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Buffered update mode. Retrieve a row handle, update a row with some columns set to NULL, and call GetData to see the change
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_2()
{
DBCOUNTITEM cRows =0;
DBORDINAL cCol =0;
DBORDINAL *rgColNumber=NULL;
HROW *pHRow =NULL;
ULONG cCount =0;
BYTE *pData =NULL;
DBPROPID DBPropIDSet =DBPROP_IRowsetUpdate;
BOOL fTestPass =TEST_SKIPPED;
//create an accessor with IRowsetChange. Buffered update mode.
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,&DBPropIDSet,2,
g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//get an array of nullable and updatable columns
GetNullableAndUpdatable(&cCol,&rgColNumber);
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//get a new data buffer to set the data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set a first nullable and updatble columns to NULL
if(cCol)
{
for(cCount=0;cCount<m_cBinding;cCount++)
{
if(m_rgBinding[cCount].iOrdinal==rgColNumber[cCol-1])
{
// *(ULONG *)(dwAddr+m_rgBinding[cCount].obStatus)=DBSTATUS_S_ISNULL;
STATUS_BINDING(m_rgBinding[cCount],pData)=DBSTATUS_S_ISNULL;
break;
}
}
}
//has to find such a column
if(cCount==m_cBinding)
goto CLEANUP;
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//call update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//get the data for the row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//make sure GetData should be able to see the change
if(COMPARE(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
PROVIDER_FREE(pData);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Change a row with DBTYPE_BYREF. cbMaxLen > string length, no truncation should occur, SetData should return S_OK.
// no truncation should occur, SetData should return S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_3()
{
HRESULT hr = S_OK;
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
DBORDINAL cCnt = 0;
DBORDINAL ulCol = 0;
DBORDINAL *rgColNumber = NULL;
void *pData = NULL;
DBORDINAL rgColToBind[1];
DBPROPID rgPropertyIDs[1];
rgPropertyIDs[0]=DBPROP_IRowsetChange;
//the first col here is the index
rgColToBind[0]=1;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,0,NULL,NO_ACCESSOR));
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass = FALSE;
//Get a variable length column. .
if(!GetVariableLengthAndUpdatable(&ulCol, &rgColNumber))
{
odtLog << "no variable length updateable columns available"<<ENDL;
fTestPass = TRUE;
goto CLEANUP;
}
//find a data type that is not ORed with DBTYPE_ARRAY or DBTYPE_VECTOR
for(cCnt=0; cCnt<ulCol; cCnt++)
{
if( ((m_rgInfo[rgColNumber[cCnt]].wType & DBTYPE_ARRAY) == 0) &&
((m_rgInfo[rgColNumber[cCnt]].wType & DBTYPE_VECTOR) == 0) )
break;
}
if(cCnt==ulCol)
{
odtLog << "no variable length updateable columns that is not ORed with DBTYPE_ARRAY or DBTYPE_VECTOR available"<<ENDL;
fTestPass = TRUE;
goto CLEANUP;
}
//this is the variable length updateable column
rgColToBind[0]=m_rgInfo[rgColNumber[cCnt]].iOrdinal;
//accessor on 1st variable length and updatable column
TESTC_PROVIDER(GetAccessorOnRowset( ON_ROWSET_ACCESSOR,
TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,
FORWARD,
VARIABLE_LEN_COLS_BY_REF,
DBTYPE_EMPTY,
1,
rgColToBind))
//restartPosition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
goto CLEANUP;
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
m_rgBinding[0].cbMaxLen=0;
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data should fail
hr=SetData(*pHRow,m_hAccessor,pData);
if(CHECK(hr==S_OK, TRUE))
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
//release the row handle
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseAccessorOnRowset();
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_4()
{
BYTE *pData =NULL;
DBCOUNTITEM cRows =0;
HROW *pHRow =NULL;
HROW *pHRowSecond =NULL;
ULONG cRefCount =0;
DBPROPID rgPropertyIDs[1];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass =TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgUnPropertyIDs[0]=DBPROP_REMOVEDELETED;
HRESULT hr = S_OK;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow,NULL),S_OK);
//make changes to the row. Make its value as the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),DB_E_DELETEDROW);
//release the row & data
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL, &cRefCount, NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pData);
//make data and insert it in a new row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,NULL),S_OK);
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//should be delete and here because DBPROP_REMOVEDELETED is variant_false
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),DB_E_DELETEDROW);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//Since GetData is expected to fail we do not need to release this memory
//ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)m_pData);
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
//free the memory used by pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_5()
{
BYTE *pData =NULL;
DBCOUNTITEM cRows =0;
HROW *pHRow =NULL;
HROW *pHRowSecond =NULL;
ULONG cRefCount =0;
DBPROPID rgPropertyIDs[3];
BOOL fTestPass =TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_REMOVEDELETED;
rgPropertyIDs[2]=DBPROP_IConnectionPointContainer;
HRESULT hr = S_OK;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow,NULL),S_OK);
//make changes to the row. Make its value as the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),DB_E_DELETEDROW);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL, &cRefCount, NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pData);
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,NULL),S_OK);
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//should be S_OK here because DBPROP_REMOVEDELETED is variant_true
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)m_pData);
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
//free the memory used by pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Insert a row and check to see it (OWNINSERT is off)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_6()
{
BYTE *pData =NULL;
DBCOUNTITEM cRows =0;
HROW *pHRow =NULL;
DBPROPID rgPropertyIDs[2];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass =TEST_SKIPPED;
HRESULT hr = S_OK;
HRESULT RPhr = S_OK;
BOOL fFound = FALSE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_LITERALIDENTITY;
rgUnPropertyIDs[0]=DBPROP_OWNINSERT;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//get a new data buffer to set the data a row.
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//insert a row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,NULL),S_OK);
m_ulTableRows++;
//restart
RPhr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(RPhr==S_OK || RPhr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//loop through rowset searching for the inserted row
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(m_pIRowset->GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fFound = TRUE;
}
}
//OWNINSERT is FALSE, if the test sees the row, FAIL
//only if the command was not re-ececuted because if it was re-exectued the rowset is new
//and the props do not apply so see the row
if (RPhr==DB_S_COMMANDREEXECUTED)
{
if(fFound)
{
fTestPass = TRUE;
}
}
else
{
if(!fFound)
{
fTestPass = TRUE;
}
}
CLEANUP:
//free the memory used by pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc set ACCESSOR_ORDER to RANDOM with forward only cursor of BLOBS are cached, SetData
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_7()
{
DBCOUNTITEM cRows = 0;
const ULONG cRowsToSet = 5;
HROW *pHRow = NULL;
BYTE *pData = NULL;
BOOL fTestPass = TEST_SKIPPED;
DBPROPID rgPropertyIDs[4];
void *rgpData[cRowsToSet] = {NULL,NULL,NULL,NULL,NULL};
ULONG cCount = 0;
BOOL fFound = FALSE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_ACCESSORDER;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
//set the value for DBPROP_ACCESSORDER
g_ACCESSORDER_VALUE = DBPROPVAL_AO_RANDOM;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,3,rgPropertyIDs,2,g_rgPropertyIDs,
ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
//make data for SetData
for(cCount=0; cCount<cRowsToSet; cCount++)
{
//make data for the last row handle
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&(rgpData[cCount]),g_ulNextRow++,m_cRowsetCols,
m_rgTableColOrds,PRIMARY),S_OK);
}
fTestPass = FALSE;
//get the row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,cRowsToSet,&cRows,&pHRow),S_OK);
//set data on these handles
for(cCount=0; cCount<cRowsToSet; cCount++)
{
//set data
TESTC_(SetData(pHRow[cCount],m_hAccessor,rgpData[cCount]),S_OK);
}
//release the row handles
TESTC_(m_pIRowset->ReleaseRows(cRowsToSet, pHRow, NULL,NULL,NULL),S_OK);
//back to the top of the rowset
m_hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(m_hr==S_OK || m_hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the first row handle that was just Set
while (S_OK==(m_hr=m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || m_hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
{
break;
}
//Get the data for the row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should see the data
if(CompareBuffer(m_pData,rgpData[0],m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fFound=TRUE;
break;
}
}
if (!fFound)
{
goto CLEANUP;
}
//check data on these handles
for(cCount=1; cCount<cRowsToSet; cCount++)
{
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get the data for the row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change/data
if(!COMPARE(CompareBuffer(m_pData,rgpData[cCount],m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
{
goto CLEANUP;
}
}
fTestPass=TRUE;
CLEANUP:
//Release the row handle and memory
for(cCount=0; cCount<cRowsToSet; cCount++)
{
if(rgpData[cCount])
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)rgpData[cCount], TRUE);
}
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc set ACCESSOR_ORDER to RANDOM with forward only cursor of BLOBS are cached, Insert
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_8()
{
DBCOUNTITEM cRows = 0;
const ULONG cRowsToSet = 5;
HROW *pHRow = NULL;
BYTE *pData = NULL;
BOOL fTestPass = TEST_SKIPPED;
DBPROPID rgPropertyIDs[4];
void *rgpData[cRowsToSet] = {NULL,NULL,NULL,NULL,NULL};
ULONG cCount = 0;
BOOL fFound = FALSE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_ACCESSORDER;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
//set the value for DBPROP_ACCESSORDER
g_ACCESSORDER_VALUE = DBPROPVAL_AO_RANDOM;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
//make data for Insert
for(cCount=0; cCount<cRowsToSet; cCount++)
{
//make data for the last row handle
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&(rgpData[cCount]),g_ulNextRow++,m_cRowsetCols,
m_rgTableColOrds,PRIMARY),S_OK);
}
fTestPass = FALSE;
//get some row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,cRowsToSet,&cRows,&pHRow),S_OK);
//set data on these handles
for(cCount=0; cCount<cRowsToSet; cCount++)
{
//insert row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,rgpData[cCount],NULL),S_OK);
}
//release the row handles
TESTC_(m_pIRowset->ReleaseRows(cRowsToSet, pHRow, NULL,NULL,NULL),S_OK);
//back to the top of the rowset
m_hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(m_hr==S_OK || m_hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the first row handle that was just inserted
while (S_OK==(m_hr=m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || m_hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
{
break;
}
//Get the data for the row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should see the data
if(CompareBuffer(m_pData,rgpData[0],m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fFound=TRUE;
break;
}
}
if (!fFound)
{
goto CLEANUP;
}
//check data on these handles
for(cCount=1; cCount<cRowsToSet; cCount++)
{
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get the data for the row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change/data
if(!COMPARE(CompareBuffer(m_pData,rgpData[cCount],m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
{
goto CLEANUP;
}
}
fTestPass=TRUE;
CLEANUP:
//Release the row handle and memory
for(cCount=0; cCount<cRowsToSet; cCount++)
{
if(rgpData[cCount])
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)rgpData[cCount], TRUE);
}
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc Fail the SetData and check that the status of the remaining unset cols is DBSTATUS_E_UNAVAILABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_9()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
ULONG cCount = 0;
HROW *pHRow = NULL;
BYTE *pData = NULL;
DBPROPID rgPropertyIDs[2];
HRESULT hr;
DBSTATUS sCheckStatus;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR,FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//acceesor with only length binding
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
//get a new data buffer to set the data for a row.
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
// *(ULONG *)((DWORD)pData+m_rgBinding[0].obStatus)=DBSTATUS_E_BADSTATUS;
STATUS_BINDING(m_rgBinding[0],pData)=DBSTATUS_E_BADSTATUS;
//set data should fail
hr=SetData(*pHRow,m_hAccessor,pData);
if (DB_E_ERRORSOCCURRED==hr)
{
sCheckStatus = DBSTATUS_E_UNAVAILABLE;
}
else
{
if(DB_S_ERRORSOCCURRED==hr)
{
sCheckStatus = DBSTATUS_S_OK;
}
else
{
goto CLEANUP;
}
}
//the first col should fail
//the other col should be OK or UNAVAILABLE depending on the provider
for(cCount=1;cCount<m_cBinding;cCount++)
{
//GetColInfo will return info on the bookmark col but the bookmark probablly won't be bound
//by the accessor, if so the arrays will be off by one.
if (m_rgInfo[cCount].iOrdinal==m_rgBinding[cCount].iOrdinal)
{
if (m_rgInfo[cCount].dwFlags&DBCOLUMNFLAGS_WRITEUNKNOWN)
{
continue;
}
}
else
{
if (m_rgInfo[cCount+1].dwFlags&DBCOLUMNFLAGS_WRITEUNKNOWN)
{
continue;
}
}
if(!COMPARE(GetStatus(pData, &(m_rgBinding[cCount])),sCheckStatus))
{
goto CLEANUP;
}
}
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
//
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc The accessor only has status binding for DBSTATUS_S_OK.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_10()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
ULONG cCount;
HROW *pHRow = NULL;
void *pData = NULL;
DBPROPID rgPropertyIDs[2];
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create a rowset so the test can pick not nullable updatable cols
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
//get an array of numeric and updatable columns
GetNullableAndUpdatable(&cCol,&rgColNumber);
//has to find such a column
if(!cCol)
{
goto CLEANUP;
}
fTestPass=FALSE;
//Create a new accessor that binds only the nullable updatable cols
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_STATUS, USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,cCol,rgColNumber))
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//get some data to insert
pData=PROVIDER_ALLOC(m_cRowSize);
for(cCount=0; cCount<m_cBinding; cCount++)
{
// *(DBSTATUS *)((DWORD)pData+m_rgBinding[cCount].obStatus)=DBSTATUS_S_OK;
STATUS_BINDING(m_rgBinding[cCount],pData)=DBSTATUS_S_OK;
}
//set data should fail
TEST2C_(SetData(*pHRow,m_hAccessor,pData),DB_E_ERRORSOCCURRED, E_FAIL);
for(cCount=0; cCount<m_cBinding; cCount++)
{
if(!COMPARE(GetStatus(pData, &(m_rgBinding[cCount])),DBSTATUS_E_UNAVAILABLE))
{
goto CLEANUP;
}
}
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc The accessor only has status binding for DBSTATUS_S_ISNULL.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_11()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
ULONG cCount;
HROW *pHRow = NULL;
void *pData = NULL;
DBPROPID rgPropertyIDs[2];
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create a rowset so the test can pick not nullable updatable cols
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
//get an array of numeric and updatable columns
GetNullableAndUpdatable(&cCol,&rgColNumber);
//has to find such a column
if(!cCol)
{
goto CLEANUP;
}
fTestPass=FALSE;
//Create a new accessor that binds only the not nullable updatable cols
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_STATUS, USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,cCol,rgColNumber))
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//get some data to insert
pData=PROVIDER_ALLOC(m_cRowSize);
for(cCount=0; cCount<m_cBinding; cCount++)
{
// *(DBSTATUS *)((DWORD)pData+m_rgBinding[cCount].obStatus)=DBSTATUS_S_ISNULL;
STATUS_BINDING(m_rgBinding[cCount],pData)=DBSTATUS_S_ISNULL;
}
//set data should pass
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
for(cCount=0; cCount<m_cBinding; cCount++)
{
if(!COMPARE(GetStatus(pData, &(m_rgBinding[cCount])),DBSTATUS_S_ISNULL))
{
goto CLEANUP;
}
}
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc The status flag specified in a binding structure is neither DBSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALUE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_12()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
DBORDINAL rgColNumber[2];
HROW *pHRow = NULL;
void *pData = NULL;
void *pGetData = NULL;
DBPROPID rgPropertyIDs[3];
DBSTATUS dbsSecondColStatus;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
HRESULT hr = S_OK;
rgColNumber[0]=1;
rgColNumber[1]=3;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,0,NULL,NO_ACCESSOR));
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
fTestPass=FALSE;
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//create an accessor on the command object on updatable columns
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,
2,rgColNumber))
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//change the second status binding to anything other than _OK or NULL
// *(DBSTATUS *)(((DWORD)pData)+ m_rgBinding[0].obStatus)=DBSTATUS_S_TRUNCATED;
STATUS_BINDING(m_rgBinding[0],pData)=DBSTATUS_S_TRUNCATED;
// keep track of 2nd colstatus
// dbsSecondColStatus = *(DBSTATUS *)(((DWORD)pData)+ m_rgBinding[1].obStatus);
dbsSecondColStatus = STATUS_BINDING(m_rgBinding[1],pData);
//set data should fail
m_hr=SetData(*pHRow,m_hAccessor,pData);
if ( !COMPARE(m_hr == DB_E_ERRORSOCCURRED || m_hr == DB_S_ERRORSOCCURRED, TRUE) )
goto CLEANUP;
TESTC_(GetStatus(pData, &(m_rgBinding[0])),DBSTATUS_E_BADSTATUS);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if ( m_hr == DB_S_ERRORSOCCURRED )
{
if(m_cBinding > 1)
TESTC_(GetStatus(pData, &(m_rgBinding[1])),dbsSecondColStatus);
}
else
{
if(m_cBinding > 1)
TESTC_(GetStatus(pData, &(m_rgBinding[1])),DBSTATUS_E_UNAVAILABLE);
//allocate memory for getting data again
pGetData=PROVIDER_ALLOC(m_cRowSize);
if(!pGetData)
goto CLEANUP;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, pGetData),S_OK);
//columns should not be changed
if(!COMPARE(CompareBuffer(pGetData, m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
PROVIDER_FREE(pGetData);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc SetData the variable length columns without the length being bound. should be ok
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_13()
{
HROW hRow = NULL;
HROW *pHRow = NULL;
DBCOUNTITEM cRows = 0;
void *pData = NULL;
BOOL fTestPass = TEST_SKIPPED;
DBORDINAL *rgColsToBind = NULL;
ULONG cColsNumber = 0;
ULONG cCount = 0;
DBPROPID rgDBPROPID[2];
HRESULT hr;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
rgDBPROPID[0]=DBPROP_IRowsetChange;
rgDBPROPID[1]=DBPROP_CANHOLDROWS;
//get a rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,0,NULL,ON_ROWSET_ACCESSOR));
rgColsToBind=(DBORDINAL *)PROVIDER_ALLOC(sizeof(DBORDINAL) * m_cBinding);
//get variable length string cols and not nullable cols
//also grab cols that are not nullable so they won't cause the insert to fail
for (cCount=0;cCount<m_cRowsetCols;cCount++)
{
if ( (m_rgInfo[cCount].wType == DBTYPE_WSTR || m_rgInfo[cCount].wType == DBTYPE_STR) ||
!(m_rgInfo[cCount].dwFlags & DBCOLUMNFLAGS_ISNULLABLE) &&
( (m_rgInfo[cCount].dwFlags & DBCOLUMNFLAGS_WRITE)||
(m_rgInfo[cCount].dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN)
) )
{
if (0==m_rgInfo[cCount].iOrdinal)
{
continue;
}
rgColsToBind[cColsNumber]=m_rgInfo[cCount].iOrdinal;
cColsNumber++;
}
}
if(!cColsNumber)
{
goto CLEANUP;
}
ReleaseRowsetAndAccessor();
//reset this global. hack for now
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
fTestPass = TEST_FAIL;
//value and status binding only
TESTC(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgDBPROPID,
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS,USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF, DBTYPE_EMPTY, cColsNumber, rgColsToBind));
//make data for setdata
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//SetData should be successful, variable length cols can use the NULL terminated string
//they do not need the length
hr=SetData(*pHRow,m_hAccessor,pData);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(S_OK!=hr)
{
//debug this a bit
for(cCount=0;cCount<m_cBinding;cCount++)
{
// COMPARE(*(DBSTATUS *)((DWORD)pData+m_rgBinding[cCount].obStatus),DBSTATUS_S_OK);
COMPARE(STATUS_BINDING(m_rgBinding[cCount],pData),DBSTATUS_S_OK);
}
goto CLEANUP;
}
//check the row is inserted
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
{
break;
}
//Get the data for the row handle
hr = GetData(*pHRow,m_hAccessor,m_pData);
//Taking cares of SQL Providers for keyset cursor
TESTC(hr == S_OK || hr == DB_E_DELETEDROW);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
PROVIDER_FREE(rgColsToBind);
ReleaseRowsetAndAccessor();
return fTestPass;
}
//}
// {{ TCW_VAR_PROTOTYPE(14)
//*-----------------------------------------------------------------------
// @mfunc Buffered update mode. Multiple commands that modify same set of columns in hrow
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_14()
{
const ULONG cRowsToUse = 5;
DBCOUNTITEM cRows = 0;
ULONG cCol = 0;
HROW *pHRow = NULL;
ULONG cCount = 0;
BYTE *pData0 = NULL;
BYTE *pData1 = NULL;
BYTE *pData4 = NULL;
BOOL fTestPass = TEST_SKIPPED;
void *rgpData[cRowsToUse]= {NULL,NULL,NULL,NULL,NULL};
HRESULT hr;
DBPROPID DBPropIDSet =DBPROP_IRowsetUpdate;
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE;
//create an accessor with IRowsrretChange. Buffered update mode.
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,&DBPropIDSet,2,
g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate) || (!m_cBinding))
{
goto CLEANUP;
}
fTestPass = FALSE;
//alloc data to get orig. rows
for(cCount=0; cCount<cRowsToUse; cCount++)
{
if(!(rgpData[cCount]=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
}
//get the row handles
TESTC_(m_pIRowset->GetNextRows(NULL,1,cRowsToUse,&cRows,&pHRow),S_OK);
//get the data for the rows
TESTC_(GetData(pHRow[0],m_hAccessor,rgpData[0]),S_OK);
TESTC_(GetData(pHRow[1],m_hAccessor,rgpData[1]),S_OK);
TESTC_(GetData(pHRow[2],m_hAccessor,rgpData[2]),S_OK);
TESTC_(GetData(pHRow[3],m_hAccessor,rgpData[3]),S_OK);
TESTC_(GetData(pHRow[4],m_hAccessor,rgpData[4]),S_OK);
//get a new data buffer to set the data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData0,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//get a new data buffer to set the data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData1,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//get a new data buffer to set the data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData4,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data on a few rows
TESTC_(SetData(pHRow[0],m_hAccessor,pData0),S_OK);
TESTC_(SetData(pHRow[4],m_hAccessor,pData4),S_OK);
TESTC_(SetData(pHRow[1],m_hAccessor,pData1),S_OK);
//call update
TESTC_(m_pIRowsetUpdate->Update(NULL,cRows,pHRow,NULL,NULL,NULL),S_OK);
//release all held row handles
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
//restartPosition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
goto CLEANUP;
//get the row handles
TESTC_(m_pIRowset->GetNextRows(NULL,1,cRowsToUse,&cRows,&pHRow),S_OK);
//get the data for the row and check GetData should have the correct changes
TESTC_(GetData(pHRow[0],m_hAccessor,m_pData),S_OK);
if(!COMPARE(CompareBuffer(m_pData,pData0,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
//get the data for the row and check GetData should have the correct changes
TESTC_(GetData(pHRow[1],m_hAccessor,m_pData),S_OK);
if(!COMPARE(CompareBuffer(m_pData,pData1,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
//get the data for the row and check GetData should have the correct changes
TESTC_(GetData(pHRow[2],m_hAccessor,m_pData),S_OK);
if(!COMPARE(CompareBuffer(m_pData,rgpData[2],m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
TESTC_(GetData(pHRow[3],m_hAccessor,m_pData),S_OK);
if(!COMPARE(CompareBuffer(m_pData,rgpData[3],m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
TESTC_(GetData(pHRow[4],m_hAccessor,m_pData),S_OK);
if(!COMPARE(CompareBuffer(m_pData,pData4,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData0);
PROVIDER_FREE(pData1);
PROVIDER_FREE(pData4);
//Release the row handle and memory
for(cCount=0; cCount<cRowsToUse; cCount++)
{
if(rgpData[cCount])
{
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)rgpData[cCount], TRUE);
}
}
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(15)
//*-----------------------------------------------------------------------
// @mfunc SetData in a read only rowset (system table)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_15()
{
DBCOUNTITEM cRows = 0;
ULONG cCol = 0;
HROW *pHRow = NULL;
BOOL fTestPass = TEST_SKIPPED;
void *pData = NULL;
void *pData1 = NULL;
HRESULT hr;
IDBSchemaRowset *pIDBSchemaRowset = NULL;
IRowset *pTypesRowset = NULL;
WCHAR *pwszSySTableName = NULL;
IRowset *pIRowset = NULL;
IRowsetChange *pIRowsetChange = NULL;
DBPROPSET rgDBPROPSET[1] = {NULL};
DBPROP rgDBPROP[3] = {NULL};
DBID TableID = DB_NULLID;
IColumnsInfo *pIColumnsInfo = NULL;
DBORDINAL cColumns = 0;
DBCOLUMNINFO *prgInfo = NULL;
WCHAR *pStringsBuffer = NULL;
ULONG cTypeCol = 0;
ULONG cNameCol = 0;
ULONG i = 0;
// Initialize updatability and set some rowset properties
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
rgDBPROP[0].dwPropertyID = DBPROP_IRowsetChange;
rgDBPROP[0].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPROP[0].vValue.vt = VT_BOOL;
rgDBPROP[0].colid = DB_NULLID;
V_BOOL(&rgDBPROP[0].vValue) = VARIANT_TRUE;
rgDBPROP[1].dwPropertyID = DBPROP_CANHOLDROWS;
rgDBPROP[1].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPROP[1].vValue.vt = VT_BOOL;
rgDBPROP[1].colid = DB_NULLID;
V_BOOL(&rgDBPROP[1].vValue) = VARIANT_TRUE;
rgDBPROP[2].dwPropertyID = DBPROP_UPDATABILITY;
rgDBPROP[2].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPROP[2].colid = DB_NULLID;
rgDBPROP[2].vValue.vt = VT_I4;
V_I4(&rgDBPROP[2].vValue)=DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
rgDBPROPSET[0].rgProperties = &rgDBPROP[0];
rgDBPROPSET[0].cProperties = 3;
rgDBPROPSET[0].guidPropertySet = DBPROPSET_ROWSET;
//get the schema interface
if(!VerifyInterface(m_pIOpenRowset, IID_IDBSchemaRowset, SESSION_INTERFACE,(IUnknown**)&pIDBSchemaRowset))
{
goto CLEANUP;
}
//get a rowset of the schema table of system tables
if (!CHECK(hr = pIDBSchemaRowset->GetRowset(
NULL, // aggregation
DBSCHEMA_TABLES, // REFGUID
0, // count of restrictions (1:types)
NULL, // list of restrictions
IID_IRowset, // REFFID
0, // count of properties
NULL, // range of properties
(IUnknown**)&pTypesRowset // returned result set
),S_OK))
{
goto CLEANUP;
}
// get bindings and column info for the schema table of system tables
if(!CHECK(hr=GetAccessorAndBindings(
pTypesRowset, // @parmopt [IN] Rowset to create Accessor for
DBACCESSOR_ROWDATA, // @parmopt [IN] Properties of the Accessor
&m_hAccessor, // @parmopt [OUT] Accessor created
&m_rgBinding, // @parmopt [OUT] Array of DBBINDINGS
&m_cBinding, // @parmopt [OUT] Count of bindings
&m_cRowSize, // @parmopt [OUT] Length of a row, DATA
DBPART_VALUE|DBPART_STATUS |DBPART_LENGTH,
ALL_COLS_BOUND, // @parmopt [IN] Which columns will be used in the bindings
FORWARD, // @parmopt [IN] Order to bind columns in accessor
NO_COLS_BY_REF, // @parmopt [IN] Which column types to bind by reference
NULL, // @parmopt [OUT] Array of DBCOLUMNINFO
NULL, // @parmopt [OUT] Count of Columns, also count of ColInfo elements
&m_pStringsBuffer,
DBTYPE_EMPTY, // @parmopt [IN] Modifier to be OR'd with each binding type.
0, // @parmopt [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
NULL, // @parmopt [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
NULL, // @parmopt [IN] Corresponds to what ordinals are specified for each binding, if
NO_COLS_OWNED_BY_PROV, // @parmopt [IN] Which columns' memory is to be owned by the provider
DBPARAMIO_NOTPARAM, // @parmopt [IN] Parameter kind specified for all bindings
BLOB_LONG, // @parmopt [IN] how to bind BLOB Columns
NULL),S_OK)) // @parmopt [OUT] returned status array from CreateAccessor
{
goto CLEANUP;
}
//alloc memory buffer
if(!(pData=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
//get the colinfo interface
if(!VerifyInterface(pTypesRowset, IID_IColumnsInfo, ROWSET_INTERFACE,(IUnknown**)&pIColumnsInfo))
{
goto CLEANUP;
}
//get the position of the table-name and the table-type
if (!CHECK(pIColumnsInfo->GetColumnInfo(&cColumns, &prgInfo,&pStringsBuffer), S_OK))
{
goto CLEANUP;
}
for (i=0;i<cColumns;i++)
{
if (prgInfo[i].pwszName)
{
if(wcsstr(prgInfo[i].pwszName, L"TABLE_TYPE"))
{
cTypeCol = i;
}
if(wcsstr(prgInfo[i].pwszName, L"TABLE_NAME"))
{
cNameCol = i;
}
}
}
hr=pTypesRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//skip the first one just cause
hr = pTypesRowset->GetNextRows(NULL,0,1,&cRows, &pHRow);
if (hr!=S_OK && hr != DB_S_ENDOFROWSET)
{
goto CLEANUP;
}
if( cRows ==0)
{
fTestPass = TEST_SKIPPED;
goto CLEANUP;
}
TESTC_(pTypesRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//retrieve the row handles
while (S_OK==(hr = pTypesRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
{
fTestPass = TEST_SKIPPED;
goto CLEANUP;
}
//Get the data for the row handle
TESTC_(pTypesRowset->GetData(pHRow[0],m_hAccessor,pData),S_OK);
TESTC_(pTypesRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//figure out which are system tables (looking for a read only table)
if( wcsstr(((WCHAR*)((BYTE*)pData + m_rgBinding[cTypeCol].obValue)), L"SYSTEM TABLE") ||
wcsstr(((WCHAR*)((BYTE*)pData + m_rgBinding[cTypeCol].obValue)), L"SYSTEM VIEW"))
{
//get the system table name
// pwszSySTableName = (WCHAR *) PROVIDER_ALLOC(sizeof(WCHAR) + (*(ULONG *)((DWORD)pData + m_rgBinding[cNameCol].obLength)));
pwszSySTableName = (WCHAR *) PROVIDER_ALLOC(sizeof(WCHAR) + (LENGTH_BINDING(m_rgBinding[cNameCol],pData)));
// wcscpy(pwszSySTableName, ((WCHAR*)((BYTE*)pData + m_rgBinding[cNameCol].obValue)));
wcscpy(pwszSySTableName, (WCHAR*)&VALUE_BINDING(m_rgBinding[cNameCol], pData));
//Try to open a rowset on this table and break when we do this successfully
//set table name to that of the system table
TableID.uGuid.guid = GUID_NULL;
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = wcsDuplicate(pwszSySTableName);
//get the system table rowset
hr = g_pIOpenRowset->OpenRowset( NULL,
&TableID,
NULL,
IID_IRowset,
1,
rgDBPROPSET,
(IUnknown **)&pIRowset
);
if (DB_SEC_E_PERMISSIONDENIED==hr)
{
fTestPass = TEST_PASS;
goto CLEANUP;
}
if (S_OK==hr)
break;
else //continue loop
SAFE_RELEASE(pIRowset);
}
}
//free memory
if (pData)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
}
pData=NULL;
ReleaseRowsetAndAccessor();
if(pHRow && pTypesRowset)
{
CHECK(pTypesRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
//if we could not find a read-only table then skip the test
if(!pIRowset)
{
fTestPass = TEST_SKIPPED;
goto CLEANUP;
}
//get the IRowsetChange pointer
TESTC_(pIRowset->QueryInterface(IID_IRowsetChange, (LPVOID *)&pIRowsetChange),S_OK);
if (!pIRowsetChange)
{
goto CLEANUP;
}
fTestPass = FALSE;
// get bindings and column info for the system table
if(!CHECK(hr=GetAccessorAndBindings(
pIRowset, // @parmopt [IN] Rowset to create Accessor for
DBACCESSOR_ROWDATA, // @parmopt [IN] Properties of the Accessor
&m_hAccessor, // @parmopt [OUT] Accessor created
&m_rgBinding, // @parmopt [OUT] Array of DBBINDINGS
&m_cBinding, // @parmopt [OUT] Count of bindings
&m_cRowSize, // @parmopt [OUT] Length of a row, DATA
DBPART_VALUE|DBPART_STATUS |DBPART_LENGTH,
UPDATEABLE_COLS_BOUND, // @parmopt [IN] Which columns will be used in the bindings
FORWARD, // @parmopt [IN] Order to bind columns in accessor
NO_COLS_BY_REF, // @parmopt [IN] Which column types to bind by reference
NULL, // @parmopt [OUT] Array of DBCOLUMNINFO
NULL, // @parmopt [OUT] Count of Columns, also count of ColInfo elements
&m_pStringsBuffer,
DBTYPE_EMPTY, // @parmopt [IN] Modifier to be OR'd with each binding type.
0, // @parmopt [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
NULL, // @parmopt [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
NULL, // @parmopt [IN] Corresponds to what ordinals are specified for each binding, if
NO_COLS_OWNED_BY_PROV, // @parmopt [IN] Which columns' memory is to be owned by the provider
DBPARAMIO_NOTPARAM, // @parmopt [IN] Parameter kind specified for all bindings
BLOB_LONG, // @parmopt [IN] how to bind BLOB Columns
NULL),S_OK)) // @parmopt [OUT] returned status array from CreateAccessor
{
goto CLEANUP;
}
//alloc memory buffer
if(!(pData1=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
hr=pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
hr = pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow);
//if the table has no rows lets end right here
if(DB_S_ENDOFROWSET == hr || DB_E_BADSTARTPOSITION == hr)
{
fTestPass = TEST_SKIPPED;
goto CLEANUP;
}
TESTC_(hr,S_OK);
//get the data for the rows
TESTC_(pIRowset->GetData(pHRow[0],m_hAccessor,pData1),S_OK);
//set data
m_hr = pIRowsetChange->SetData(*pHRow,m_hAccessor,pData1);
//Do extended check following SetData
XCHECK(pIRowsetChange, IID_IRowsetChange, E_FAIL);
if (E_FAIL == m_hr)
{
fTestPass=TRUE;
}
CLEANUP:
//free the memory used by pData
if (pData)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
}
if (pData1)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData1,TRUE);
}
if(pHRow && pIRowset)
{
CHECK(pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
PROVIDER_FREE(TableID.uName.pwszName);
PROVIDER_FREE(pStringsBuffer);
PROVIDER_FREE(prgInfo);
PROVIDER_FREE(m_pStringsBuffer);
PROVIDER_FREE(pwszSySTableName);
//release rowsets
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pIRowsetChange);
SAFE_RELEASE(pIColumnsInfo);
SAFE_RELEASE(pTypesRowset);
SAFE_RELEASE(pIDBSchemaRowset);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc The accessor only has length binding. E_FAIL.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_16()
{
BOOL fTestPass=TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
ULONG cCount=0;
HROW *pHRow=NULL;
void *pData=NULL;
DBPROPID rgPropertyIDs[1];
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,0,NULL,NO_ACCESSOR));
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass=FALSE;
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//acceesor with only length binding
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, TRUE,DBACCESSOR_ROWDATA,
DBPART_LENGTH,UPDATEABLE_COLS_BOUND))
//get some data to insert
pData=PROVIDER_ALLOC(m_cRowSize);
for(cCount=0; cCount<m_cBinding; cCount++)
{
// *(ULONG *)((DWORD)pData+m_rgBinding[cCount].obLength)=2;
LENGTH_BINDING(m_rgBinding[cCount],pData)=2;
}
//set data should fail
TEST2C_(SetData(*pHRow,m_hAccessor,pData),DB_E_ERRORSOCCURRED, E_FAIL);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseAccessorOnRowset();
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(17)
//*-----------------------------------------------------------------------
// @mfunc The length binding > cbMaxLen for a variable length column. (DB_S_ERRORSOCCURRED)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_17()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
ULONG cCnt = 0;
DBORDINAL ulCol = 0;
DBORDINAL *rgColNumber = NULL;
DBORDINAL rgColToBind[2];
void *pData = NULL;
DBPROPID rgPropertyIDs[1];
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgColToBind[0]=1;
rgColToBind[1]=1;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,0,NULL,NO_ACCESSOR));
//Get a variable length column. .
if(!GetVariableLengthAndUpdatable(&ulCol, &rgColNumber))
{
odtLog << "no variable length updateable columns available"<<ENDL;
fTestPass = TRUE;
goto CLEANUP;
}
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
fTestPass=FALSE;
//find a data type that is not ORed with DBTYPE_ARRAY or DBTYPE_VECTOR
for(cCnt=0; cCnt<ulCol; cCnt++)
{
if( ((m_rgInfo[(rgColNumber[cCnt]-1)].wType & DBTYPE_ARRAY) == 0) &&
((m_rgInfo[(rgColNumber[cCnt]-1)].wType & DBTYPE_VECTOR) == 0)
)
{
break;
}
}
if(cCnt==ulCol)
{
odtLog << "no variable length updateable columns that is not ORed with DBTYPE_ARRAY or DBTYPE_VECTOR available"<<ENDL;
fTestPass = TEST_SKIPPED;
goto CLEANUP;
}
//if this is a bookmarked rowset account for the first ordinal being zero
if (m_rgInfo[0].iOrdinal==1)
{
rgColNumber[cCnt]--;
}
rgColToBind[1]=m_rgInfo[rgColNumber[cCnt]].iOrdinal;
//accessor on 1st variable length and updatable column
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,
2,rgColToBind))
//restartPosition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//change the data length to cbMaxLen + 1
// *(ULONG *)((DWORD)pData+m_rgBinding[1].obLength)=m_rgBinding[1].cbMaxLen+1;
LENGTH_BINDING(m_rgBinding[1],pData)=m_rgBinding[1].cbMaxLen+2; // WCHAR length assert
//set data should fail
hr = SetData(*pHRow,m_hAccessor,pData);
if (DB_E_ERRORSOCCURRED==hr)
{
// if(!COMPARE(DBSTATUS_E_CANTCONVERTVALUE, *(DBSTATUS *)((DWORD)pData+m_rgBinding[1].obStatus)))
if(!COMPARE(STATUS_BINDING(m_rgBinding[1],pData),DBSTATUS_E_CANTCONVERTVALUE))
{
goto CLEANUP;
}
//check the staus for the 1st column
// if(!COMPARE(DBSTATUS_E_UNAVAILABLE, *(DBSTATUS *)((DWORD)pData+m_rgBinding[0].obStatus)))
if(!COMPARE(STATUS_BINDING(m_rgBinding[0],pData),DBSTATUS_E_UNAVAILABLE))
{
goto CLEANUP;
}
}
else
{
if (DB_S_ERRORSOCCURRED==hr)
{
// if(!COMPARE(DBSTATUS_E_CANTCONVERTVALUE, *(DBSTATUS *)((DWORD)pData+m_rgBinding[1].obStatus)))
if(!COMPARE(STATUS_BINDING(m_rgBinding[1],pData),DBSTATUS_E_CANTCONVERTVALUE))
{
goto CLEANUP;
}
//check the staus for the 1st column
// if(!COMPARE(DBSTATUS_S_OK, *(DBSTATUS *)((DWORD)pData+m_rgBinding[0].obStatus)))
if(!COMPARE(STATUS_BINDING(m_rgBinding[0],pData),DBSTATUS_S_OK))
{
goto CLEANUP;
}
}
else
{
TEST2C_(hr, DB_E_CANTCONVERTVALUE, E_FAIL);
}
}
//release the row handle
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//Make sure no row is inserted
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows,1,&cRows,&pHRow),DB_S_ENDOFROWSET);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseAccessorOnRowset();
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(18)
//*-----------------------------------------------------------------------
// @mfunc check for truncation in variable length columns
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_18()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
ULONG cCnt = 0;
DBORDINAL ulCol = 0;
DBORDINAL *rgColNumber = NULL;
DBORDINAL rgColToBind[2];
void *pData = NULL;
DBPROPID rgPropertyIDs[1];
HACCESSOR hAccessor = NULL;
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgColToBind[0]=1;
rgColToBind[1]=1;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,0,NULL,NO_ACCESSOR));
//Get a variable length column. .
if(!GetVariableLengthAndUpdatable(&ulCol, &rgColNumber,FALSE,FALSE))
{
odtLog << "no variable length updateable columns available"<<ENDL;
fTestPass = TRUE;
goto CLEANUP;
}
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
fTestPass=FALSE;
//find a data type that is not ORed with DBTYPE_ARRAY or DBTYPE_VECTOR
//and not long
for(cCnt=0; cCnt<ulCol; cCnt++)
{
if( ( ((m_rgInfo[(rgColNumber[cCnt]-1)].wType & DBTYPE_ARRAY) == 0) &&
((m_rgInfo[(rgColNumber[cCnt]-1)].wType & DBTYPE_VECTOR) == 0)) &&
((m_rgInfo[(rgColNumber[cCnt]-1)].dwFlags & DBCOLUMNFLAGS_ISLONG) == 0)
)
{
break;
}
}
if(cCnt==ulCol)
{
odtLog << "no variable length updateable columns that is not ORed with DBTYPE_ARRAY or DBTYPE_VECTOR available"<<ENDL;
fTestPass = TEST_SKIPPED;
goto CLEANUP;
}
//if this is a bookmarked rowset account for the first ordinal being zero
if (m_rgInfo[0].iOrdinal==1)
{
rgColNumber[cCnt]--;
}
rgColToBind[1]=m_rgInfo[rgColNumber[cCnt]].iOrdinal;
//accessor on 1st variable length and updatable column
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,
2,rgColToBind))
//reset the cbMaxLen to cbMaxLen + 2
m_rgBinding[1].cbMaxLen+=2;
//create an accessor
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,m_cBinding, m_rgBinding, 0, &hAccessor,NULL),S_OK);
//restartPosition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//change the data length to cbMaxLen + 2
// *(ULONG *)((DWORD)pData+m_rgBinding[1].obLength)=m_rgBinding[1].cbMaxLen;
LENGTH_BINDING(m_rgBinding[1],pData)=m_rgBinding[1].cbMaxLen+2;
//set data should fail
hr = SetData(*pHRow,hAccessor,pData);
if (DB_E_ERRORSOCCURRED==hr)
{
// if ( DBSTATUS_E_CANTCONVERTVALUE != *(DBSTATUS *)((DWORD)pData+m_rgBinding[1].obStatus) &&
// DBSTATUS_E_SCHEMAVIOLATION != *(DBSTATUS *)((DWORD)pData+m_rgBinding[1].obStatus)
if ( DBSTATUS_E_CANTCONVERTVALUE != STATUS_BINDING(m_rgBinding[1],pData) &&
DBSTATUS_E_SCHEMAVIOLATION != STATUS_BINDING(m_rgBinding[1],pData)
)
{
goto CLEANUP;
}
//check the staus for the 1st column
// if(!COMPARE(DBSTATUS_E_UNAVAILABLE,*(DBSTATUS *)((DWORD)pData+m_rgBinding[0].obStatus)))
if(!COMPARE(DBSTATUS_E_UNAVAILABLE,STATUS_BINDING(m_rgBinding[0],pData)))
{
goto CLEANUP;
}
}
else
{
if (DB_S_ERRORSOCCURRED==hr)
{
// if ( DBSTATUS_E_CANTCONVERTVALUE != *(DBSTATUS *)((DWORD)pData+m_rgBinding[1].obStatus) &&
// DBSTATUS_E_SCHEMAVIOLATION != *(DBSTATUS *)((DWORD)pData+m_rgBinding[1].obStatus)
if ( DBSTATUS_E_CANTCONVERTVALUE != STATUS_BINDING(m_rgBinding[1],pData) &&
DBSTATUS_E_SCHEMAVIOLATION != STATUS_BINDING(m_rgBinding[1],pData)
)
{
goto CLEANUP;
}
//check the staus for the 1st column
// if(!COMPARE(DBSTATUS_S_OK,*(DBSTATUS *)((DWORD)pData+m_rgBinding[0].obStatus)))
if(!COMPARE(DBSTATUS_S_OK,STATUS_BINDING(m_rgBinding[0],pData)))
{
goto CLEANUP;
}
}
else
{
TEST2C_(hr,DB_E_CANTCONVERTVALUE, E_FAIL);
}
}
//release the row handle
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//Make sure no row is inserted
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows,1,&cRows,&pHRow),DB_S_ENDOFROWSET);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
//release the accessor
if(hAccessor)
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
ReleaseAccessorOnRowset();
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(19)
//*-----------------------------------------------------------------------
// @mfunc Delete-Insert-undoDelete-Update
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_19()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
DBORDINAL *rgColNumber = NULL;
DBPROPID rgPropertyIDs[3];
DBROWSTATUS *prgRowStatus = NULL;
HROW *rgUpdatedRows = NULL;
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
HRESULT hr = S_OK;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,3,rgPropertyIDs,0,
NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//restartPosition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get the data for the row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow,NULL),S_OK);
//insert a row with the same data
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,m_pData,NULL),S_OK);
//undo the delete, leaving 2 of the same row
TESTC_(m_pIRowsetUpdate->Undo(NULL,1,pHRow, NULL, NULL, NULL),S_OK);
//transmitt all the changes (just the insert should be transmitted)
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,&cRows,&rgUpdatedRows,&prgRowStatus),DB_E_ERRORSOCCURRED);
COMPARE(prgRowStatus[0],DBROWSTATUS_E_INTEGRITYVIOLATION);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(prgRowStatus);
PROVIDER_FREE(rgUpdatedRows);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseAccessorOnRowset();
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(20)
//*-----------------------------------------------------------------------
// @mfunc check status NULL if no row handles used
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_20()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
DBORDINAL *rgColNumber = NULL;
DBPROPID rgPropertyIDs[3];
DBROWSTATUS *prgRowStatus = NULL;
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
HRESULT hr = S_OK;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,3,rgPropertyIDs,0,
NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//restartPosition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get the data for the row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//insert a row with the same data
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,m_pData,NULL),S_OK);
//transmitt all the changes (just the insert should be transmitted)
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,&prgRowStatus),DB_E_ERRORSOCCURRED);
//this has a 1 to 1 correspondance with rghRows or *prgRows
//is both are null there is no correspondance so this should be NULL
if (prgRowStatus)
{
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
if (prgRowStatus)
{
PROVIDER_FREE(prgRowStatus);
}
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseAccessorOnRowset();
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(21)
//*-----------------------------------------------------------------------
// @mfunc The length binding > cbMaxLen for a variable length column with no status bound. (DB_S_ERRORSOCCURRED)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_21()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
ULONG cCnt = 0;
DBORDINAL ulCol = 0;
DBORDINAL *rgColNumber = NULL;
DBORDINAL rgColToBind[2];
void *pData = NULL;
DBPROPID rgPropertyIDs[1];
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgColToBind[0]=1;
rgColToBind[1]=1;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,0,NULL,NO_ACCESSOR));
//Get a variable length column. .
if(!GetVariableLengthAndUpdatable(&ulCol, &rgColNumber))
{
odtLog << "no variable length updateable columns available"<<ENDL;
fTestPass = TRUE;
goto CLEANUP;
}
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
fTestPass=FALSE;
//find a data type that is not ORed with DBTYPE_ARRAY or DBTYPE_VECTOR
for(cCnt=0; cCnt<ulCol; cCnt++)
{
if( ((m_rgInfo[(rgColNumber[cCnt]-1)].wType & DBTYPE_ARRAY) == 0) &&
((m_rgInfo[(rgColNumber[cCnt]-1)].wType & DBTYPE_VECTOR) == 0)
)
{
break;
}
}
if(cCnt==ulCol)
{
odtLog << "no variable length updateable columns that is not ORed with DBTYPE_ARRAY or DBTYPE_VECTOR available"<<ENDL;
fTestPass = TEST_SKIPPED;
goto CLEANUP;
}
//if this is a bookmarked rowset account for the first ordinal being zero
if (m_rgInfo[0].iOrdinal==1)
{
rgColNumber[cCnt]--;
}
rgColToBind[1]=m_rgInfo[rgColNumber[cCnt]].iOrdinal;
//accessor on 1st variable length and updatable column
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,
2,rgColToBind))
//restartPosition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//change the data length to cbMaxLen + 1
// *(ULONG *)((DWORD)pData+m_rgBinding[1].obLength)=m_rgBinding[1].cbMaxLen+1;
LENGTH_BINDING(m_rgBinding[1],pData)=m_rgBinding[1].cbMaxLen+2; //WCHAR length assert
//set data should fail
hr = SetData(*pHRow,m_hAccessor,pData);
// Check for valid returncodes
TEST4C_(hr,DB_E_ERRORSOCCURRED,DB_S_ERRORSOCCURRED,DB_E_CANTCONVERTVALUE, E_FAIL);
//release the row handle
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//Make sure no row is inserted
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows,1,&cRows,&pHRow),DB_S_ENDOFROWSET);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseAccessorOnRowset();
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(22)
//*-----------------------------------------------------------------------
// @mfunc check for truncation in variable length columns with no status bound.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_22()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
ULONG cCnt = 0;
DBORDINAL ulCol = 0;
DBORDINAL *rgColNumber = NULL;
DBORDINAL rgColToBind[2];
void *pData = NULL;
DBPROPID rgPropertyIDs[1];
HACCESSOR hAccessor = NULL;
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgColToBind[0]=1;
rgColToBind[1]=1;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,0,NULL,NO_ACCESSOR));
//Get a variable length column. .
if(!GetVariableLengthAndUpdatable(&ulCol, &rgColNumber))
{
odtLog << "no variable length updateable columns available"<<ENDL;
fTestPass = TRUE;
goto CLEANUP;
}
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
fTestPass=FALSE;
//find a data type that is not ORed with DBTYPE_ARRAY or DBTYPE_VECTOR
for(cCnt=0; cCnt<ulCol; cCnt++)
{
if( ( ((m_rgInfo[(rgColNumber[cCnt]-1)].wType & DBTYPE_ARRAY) == 0) &&
((m_rgInfo[(rgColNumber[cCnt]-1)].wType & DBTYPE_VECTOR) == 0)) &&
((m_rgInfo[(rgColNumber[cCnt]-1)].dwFlags & DBCOLUMNFLAGS_ISLONG) == 0)
)
{
break;
}
}
if(cCnt==ulCol)
{
odtLog << "no variable length updateable columns that is not ORed with DBTYPE_ARRAY or DBTYPE_VECTOR available."<<ENDL;
fTestPass = TEST_SKIPPED;
goto CLEANUP;
}
//if this is a bookmarked rowset account for the first ordinal being zero
if (m_rgInfo[0].iOrdinal==1)
{
rgColNumber[cCnt]--;
}
rgColToBind[1]=m_rgInfo[rgColNumber[cCnt]].iOrdinal;
//accessor on 1st variable length and updatable column
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,2,rgColToBind))
//reset the cbMaxLen to cbMaxLen + 2
m_rgBinding[1].cbMaxLen+=2;
//create an accessor
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,m_cBinding, m_rgBinding, 0, &hAccessor,NULL),S_OK);
//restartPosition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//change the data length to cbMaxLen
// *(ULONG *)((DWORD)pData+m_rgBinding[1].obLength)=m_rgBinding[1].cbMaxLen;
LENGTH_BINDING(m_rgBinding[1],pData)=m_rgBinding[1].cbMaxLen;
//set data should fail
hr = SetData(*pHRow,hAccessor,pData);
// Check for valid returncodes
TEST4C_(hr,DB_E_ERRORSOCCURRED,DB_S_ERRORSOCCURRED,DB_E_CANTCONVERTVALUE, E_FAIL);
//release the row handle
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//Make sure no row is inserted
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows,1,&cRows,&pHRow),DB_S_ENDOFROWSET);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
//release the accessor
if(hAccessor)
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
ReleaseAccessorOnRowset();
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(23)
//*-----------------------------------------------------------------------
// @mfunc QI check
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_23()
{
BOOL fTestPass = TEST_FAIL;
ULONG cDBPropSet = 1;
DBPROPSET rgDBPropSet[1];
HRESULT hr;
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE;
//init DBPropSet with FALSE DBPROP_IRowsetChange
rgDBPropSet[0].rgProperties = NULL;
rgDBPropSet[0].cProperties = cDBPropSet;
rgDBPropSet[0].guidPropertySet = DBPROPSET_ROWSET;
rgDBPropSet[0].rgProperties = (DBPROP *)PROVIDER_ALLOC(sizeof(DBPROP)*(1));
memset(rgDBPropSet[0].rgProperties,0,sizeof(DBPROP)*(1));
if(!rgDBPropSet[0].rgProperties)
{
goto CLEANUP;
}
rgDBPropSet[0].rgProperties[0].dwPropertyID = DBPROP_IRowsetChange;
rgDBPropSet[0].rgProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[0].vValue.vt = VT_BOOL;
rgDBPropSet[0].rgProperties[0].colid = DB_NULLID;
V_BOOL(&rgDBPropSet[0].rgProperties[0].vValue) = VARIANT_FALSE;
//create a rowset without an accessor
if(!SUCCEEDED(SetRowsetProperties(rgDBPropSet, cDBPropSet)))
{
goto CLEANUP;
}
hr=CreateRowsetObject(SELECT_ALLFROMTBL,IID_IRowset,EXECUTE_IFNOERROR);
//check for DB_E_ERRORSOCCURED in case DBPROP_IRowsetChange is not settable to FALSE
if (S_OK==hr)
{
//get the IRowsetChange pointer
TESTC_(m_pIAccessor->QueryInterface(IID_IRowsetChange, (LPVOID *)&m_pIRowsetChange),E_NOINTERFACE);
}
else
{
if (DB_E_ERRORSOCCURRED!=hr)
{
goto CLEANUP;
}
}
fTestPass = TEST_PASS;
CLEANUP:
if(rgDBPropSet[0].rgProperties)
{//
PROVIDER_FREE(rgDBPropSet[0].rgProperties);
}
ReleaseAccessorOnRowset();
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(24)
//*-----------------------------------------------------------------------
// @mfunc check for truncation in fixed length columns
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_24()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
ULONG cCnt = 0;
ULONG ulCol = 0;
DBORDINAL *rgColNumber = NULL;
// DBORDINAL rgColToBind[2];
void *pData = NULL;
// DBPROPID rgPropertyIDs[1];
HACCESSOR hAccessor = NULL;
/*
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgColToBind[0]=1;
rgColToBind[1]=1;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,0,NULL,NO_ACCESSOR));
//Get a variable length column. .
if(!GetFixedLengthAndUpdatable(&ulCol, &rgColNumber))
{
odtLog << "no fixed length updateable columns available"<<ENDL;
fTestPass = TRUE;
goto CLEANUP;
}
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
fTestPass=FALSE;
//if this is a bookmarked rowset account for the first ordinal being zero
if (m_rgInfo[0].iOrdinal==1)
{
rgColNumber[cCnt]--;
}
//find a data type that is not ORed with DBTYPE_ARRAY or DBTYPE_VECTOR
//and not long
for(cCnt=0; cCnt<ulCol; cCnt++)
{
if( ((m_rgInfo[(rgColNumber[cCnt]-1)].wType & DBTYPE_ARRAY) == 0) &&
((m_rgInfo[(rgColNumber[cCnt]-1)].wType & DBTYPE_VECTOR) == 0) &&
(m_rgInfo[rgColNumber[cCnt]].iOrdinal) //not the bookmark value
)
{
break;
}
}
if(cCnt==ulCol)
{
odtLog << "no fixed length updateable columns that is not ORed with DBTYPE_ARRAY or DBTYPE_VECTOR available"<<ENDL;
fTestPass = TEST_SKIPPED;
goto CLEANUP;
}
rgColToBind[1]=m_rgInfo[rgColNumber[cCnt]].iOrdinal;
//accessor on 1st variable length and updatable column
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,
2,rgColToBind))
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
m_rgBinding[1].wType = DBTYPE_I8;
//create an accessor
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,m_cBinding, m_rgBinding, 0, &hAccessor,NULL),S_OK);
//restartPosition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//set data should fail
hr = SetData(*pHRow,hAccessor,pData);
if (DB_E_ERRORSOCCURRED==hr)
{
// if ( DBSTATUS_E_DATAOVERFLOW != *(DBSTATUS *)((DWORD)pData+m_rgBinding[1].obStatus) &&
// DBSTATUS_E_SCHEMAVIOLATION != *(DBSTATUS *)((DWORD)pData+m_rgBinding[1].obStatus)
if ( DBSTATUS_E_DATAOVERFLOW != STATUS_BINDING(m_rgBinding[1],pData) &&
DBSTATUS_E_SCHEMAVIOLATION != STATUS_BINDING(m_rgBinding[1],pData)
)
)
{
goto CLEANUP;
}
//check the staus for the 1st column
// if(!COMPARE(DBSTATUS_E_UNAVAILABLE,*(DBSTATUS *)((DWORD)pData+m_rgBinding[0].obStatus)))
if(!COMPARE(DBSTATUS_E_UNAVAILABLE,STATUS_BINDING(m_rgBinding[0],pData)))
{
goto CLEANUP;
}
}
else
{
if (DB_S_ERRORSOCCURRED==hr)
{
// if ( DBSTATUS_E_DATAOVERFLOW != *(DBSTATUS *)((DWORD)pData+m_rgBinding[1].obStatus) &&
// DBSTATUS_E_SCHEMAVIOLATION != *(DBSTATUS *)((DWORD)pData+m_rgBinding[1].obStatus)
if ( DBSTATUS_E_DATAOVERFLOW != STATUS_BINDING(m_rgBinding[1],pData) &&
DBSTATUS_E_SCHEMAVIOLATION != STATUS_BINDING(m_rgBinding[1],pData)
)
{
goto CLEANUP;
}
//check the staus for the 1st column
// if(!COMPARE(DBSTATUS_S_OK,*(DBSTATUS *)((DWORD)pData+m_rgBinding[0].obStatus)))
if(!COMPARE(DBSTATUS_S_OK,STATUS_BINDING(m_rgBinding[0],pData)))
{
goto CLEANUP;
}
}
else
{
TESTC_(hr,DB_E_DATAOVERFLOW);
}
}
//release the row handle
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//Make sure no row is inserted
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows,1,&cRows,&pHRow),DB_S_ENDOFROWSET);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
//release the accessor
if(hAccessor)
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
ReleaseAccessorOnRowset();
ReleaseRowsetAndAccessor();
*/ return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(25)
//*-----------------------------------------------------------------------
// @mfunc bind BLOBs as IUnKnown
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_25()
{
HRESULT hr = S_OK;
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
ULONG cCnt = 0;
ULONG ulCol = 0;
DBORDINAL *rgColNumber = NULL;
void *pData = NULL;
void *pData1 = NULL;
DBORDINAL rgColToBind[1];
DBPROPID rgPropertyIDs[1];
HACCESSOR hAccessor = NULL;
DBLENGTH cbRowSize = 0;
ULONG i = 0;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
//the first col here is the index
rgColToBind[0]=1;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,0,NULL,NO_ACCESSOR));
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
fTestPass = FALSE;
//Create Accessor with a binding using length, status and value.
//This accessor binds all columns. Include BLOB_IID_ISEQSTREAM
//and BLOB_BIND_STR.
TESTC_(GetAccessorAndBindings( m_pIRowset,
DBACCESSOR_ROWDATA,
&hAccessor,
&m_rgBinding,
&m_cBinding,
&cbRowSize,
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
UPDATEABLE_COLS_BOUND,
FORWARD,
NO_COLS_BY_REF,
NULL,
NULL,
NULL,
DBTYPE_EMPTY,
0,
NULL,
NULL,
NO_COLS_OWNED_BY_PROV,
DBPARAMIO_NOTPARAM,
BLOB_IID_ISEQSTREAM|BLOB_BIND_STR,
NULL),S_OK);
//restartPosition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
goto CLEANUP;
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//allocate memory for the row
if(!(pData1=PROVIDER_ALLOC(cbRowSize)))
{
goto CLEANUP;
}
//Get the data for the row handle
TESTC_(GetData(*pHRow,hAccessor,pData1),S_OK);
m_rgBinding[0].cbMaxLen=0;
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data should fail
hr=SetData(*pHRow,hAccessor,pData);
if (E_UNEXPECTED == hr)
{
if(!GetProperty(DBPROP_BLOCKINGSTORAGEOBJECTS, DBPROPSET_ROWSET, (IUnknown*)m_pIRowset))
{
goto CLEANUP;
}
}
else
{
CHECK(hr==S_OK, TRUE);
}
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
IUnknown* pIUnknown = NULL;
if(pData)
{
//Get our storage object first
COMPARE(GetStorageObject(m_cBinding, m_rgBinding, pData, IID_ISequentialStream, &pIUnknown),TRUE);
SAFE_RELEASE(pIUnknown);
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
}
if(pData1)
{
//Get our storage object first
COMPARE(GetStorageObject(m_cBinding, m_rgBinding, pData1, IID_ISequentialStream, &pIUnknown),TRUE);
SAFE_RELEASE(pIUnknown);
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData1,TRUE);
}
//release the row handle
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
for (i=1;i<m_cBinding;i++)
{
PROVIDER_FREE(m_rgBinding[i].pObject);
}
//release the accessor
ReleaseAccessorOnRowset();
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(26)
//*-----------------------------------------------------------------------
// @mfunc DBPROP_IRowsetChange FALSE with UPDATABILITY - conflicting
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_26()
{
BOOL fTestPass = TEST_FAIL;
ULONG cDBPropSet = 1;
DBPROPSET rgDBPropSet[1];
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE;
//init DBPropSet with FALSE DBPROP_IRowsetChange
rgDBPropSet[0].rgProperties = NULL;
rgDBPropSet[0].cProperties = 2;
rgDBPropSet[0].guidPropertySet = DBPROPSET_ROWSET;
rgDBPropSet[0].rgProperties = (DBPROP *)PROVIDER_ALLOC(sizeof(DBPROP)*(2));
memset(rgDBPropSet[0].rgProperties,0,sizeof(DBPROP)*(2));
if(!rgDBPropSet[0].rgProperties)
{
goto CLEANUP;
}
rgDBPropSet[0].rgProperties[0].dwPropertyID = DBPROP_IRowsetChange;
rgDBPropSet[0].rgProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[0].vValue.vt = VT_BOOL;
rgDBPropSet[0].rgProperties[0].colid = DB_NULLID;
V_BOOL(&rgDBPropSet[0].rgProperties[0].vValue) = VARIANT_FALSE;
rgDBPropSet[0].rgProperties[1].dwPropertyID = DBPROP_UPDATABILITY;
rgDBPropSet[0].rgProperties[1].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[1].vValue.vt = VT_I4;
rgDBPropSet[0].rgProperties[1].colid = DB_NULLID;
V_I4(&rgDBPropSet[0].rgProperties[1].vValue) = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create a rowset without an accessor
if(!SUCCEEDED(SetRowsetProperties(rgDBPropSet, cDBPropSet)))
{
goto CLEANUP;
}
TEST2C_(CreateRowsetObject(SELECT_ALLFROMTBL,IID_IRowset,EXECUTE_IFNOERROR),DB_E_ERRORSOCCURRED,DB_S_ERRORSOCCURRED);
if(DBPROPSTATUS_CONFLICTING == m_rgPropSets[0].rgProperties[1].dwStatus)
{
fTestPass = TEST_PASS;
}
fTestPass = TEST_PASS;
CLEANUP:
if(rgDBPropSet[0].rgProperties)
{
PROVIDER_FREE(rgDBPropSet[0].rgProperties);
}
ReleaseAccessorOnRowset();
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(27)
//*-----------------------------------------------------------------------
// @mfunc DBPROP_IRowsetChange and DBPROP_IRowsetUpdate
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_27()
{
BOOL fTestPass = TEST_FAIL;
ULONG cDBPropSet = 1;
DBPROPSET rgDBPropSet[1];
HRESULT hr;
//make sure change is supported so DB+E+ERRORSOCCURRED can not be returned
if (!SupportedInterface(IID_IRowsetChange,ROWSET_INTERFACE))
{
odtLog << L"IRowsetChange is not supported.\n";
return TEST_SKIPPED;
}
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE;
//init DBPropSet with FALSE DBPROP_IRowsetChange
rgDBPropSet[0].rgProperties = NULL;
rgDBPropSet[0].cProperties = 3;
rgDBPropSet[0].guidPropertySet = DBPROPSET_ROWSET;
rgDBPropSet[0].rgProperties = (DBPROP *)PROVIDER_ALLOC(sizeof(DBPROP)*(3));
memset(rgDBPropSet[0].rgProperties,0,sizeof(DBPROP)*(3));
if(!rgDBPropSet[0].rgProperties)
{
goto CLEANUP;
}
rgDBPropSet[0].rgProperties[0].dwPropertyID = DBPROP_IRowsetChange;
rgDBPropSet[0].rgProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[0].vValue.vt = VT_BOOL;
rgDBPropSet[0].rgProperties[0].colid = DB_NULLID;
V_BOOL(&rgDBPropSet[0].rgProperties[0].vValue) = VARIANT_TRUE;
rgDBPropSet[0].rgProperties[1].dwPropertyID = DBPROP_UPDATABILITY;
rgDBPropSet[0].rgProperties[1].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[1].vValue.vt = VT_I4;
rgDBPropSet[0].rgProperties[1].colid = DB_NULLID;
V_DBCOUNTITEM(&rgDBPropSet[0].rgProperties[1].vValue) = m_ulpUpdFlags;
rgDBPropSet[0].rgProperties[2].dwPropertyID = DBPROP_IRowsetUpdate;
rgDBPropSet[0].rgProperties[2].dwOptions = DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[2].vValue.vt = VT_BOOL;
rgDBPropSet[0].rgProperties[2].colid = DB_NULLID;
V_BOOL(&rgDBPropSet[0].rgProperties[2].vValue) = VARIANT_TRUE;
//create a rowset without an accessor
if(!SUCCEEDED(SetRowsetProperties(rgDBPropSet, cDBPropSet)))
{
goto CLEANUP;
}
if(g_pTable->GetCommandSupOnCTable())
{
//allow DB_S_ERRORSOCCURRED here in case DBPROP_IRowsetUpdate is not supported but even if
//DBPROP_IRowsetUpdate is not supported DB_E_ERRORSOCCURRED should not be returned on call to
//SetProperties.
TEST2C_(hr=CreateRowsetObject(SELECT_ALLFROMTBL,IID_IRowset,EXECUTE_IFNOERROR),S_OK,DB_S_ERRORSOCCURRED);
TEST3C_(m_rgPropSets[0].rgProperties[2].dwStatus,DBPROPSTATUS_NOTSUPPORTED,DBPROPSTATUS_NOTSETTABLE,DBPROPSTATUS_OK);
}
else
{
//allow DB_E_ERRORSOCCURRED here in case DBPROP_IRowsetUpdate is not supported but even if
//DBPROP_IRowsetUpdate is not supported DB_S_ERRORSOCCURRED should not be returned on call to
//OpenRowset
TEST2C_(hr=CreateRowsetObject(SELECT_ALLFROMTBL,IID_IRowset,EXECUTE_IFNOERROR),S_OK,DB_E_ERRORSOCCURRED);
TEST3C_(m_rgPropSets[0].rgProperties[2].dwStatus,DBPROPSTATUS_NOTSUPPORTED,DBPROPSTATUS_NOTSETTABLE,DBPROPSTATUS_OK);
}
fTestPass = TEST_PASS;
CLEANUP:
if(rgDBPropSet[0].rgProperties)
{
PROVIDER_FREE(rgDBPropSet[0].rgProperties);
}
ReleaseAccessorOnRowset();
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(28)
//*-----------------------------------------------------------------------
// @mfunc change multiple cols with some failures
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_28()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
DBCOUNTITEM cNotUpdateCol = 0;
DBORDINAL *rgNotUpdateColNumber = NULL;
DBCOUNTITEM cUpdateCol = 0;
DBORDINAL *rgUpdateColNumber = NULL;
DBCOUNTITEM cCol = 0;
DBORDINAL rgColNumber[2] = {NULL,NULL};
ULONG cCount = 0;
ULONG cBinding = 0;
void *pData = NULL;
void *pGetData = NULL;
DBPROPID rgPropertyIDs[1];
ULONG i = 0;
ULONG j = 0;
HRESULT hr = S_OK;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
//create a rowset on all columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR,
TRUE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, ALL_COLS_BOUND));
//Get Non Updatable column. If all columns are updatable, exit.
GetNotUpdatable(&cNotUpdateCol,&rgNotUpdateColNumber);
if (!cNotUpdateCol)
{
goto CLEANUP;
}
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass=FALSE;
/* //create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,0,NULL,NO_ACCESSOR));
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass=FALSE;
//Get Non Updatable column. If all columns are updatable, exit.
GetNotUpdatable(&cNotUpdateCol,&rgNotUpdateColNumber);
if (!cNotUpdateCol)
{
goto CLEANUP;
}
//get updateable columns
if(!GetUpdatableCols(&cUpdateCol, &rgUpdateColNumber))
{
goto CLEANUP;
}
//use one from each array
cCol = 2;
rgColNumber[0] = rgNotUpdateColNumber[0];
rgColNumber[1] = rgUpdateColNumber[0];
//create an accessor on the rowset object on the all the columns
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF,
DBTYPE_EMPTY, cCol, rgColNumber))
*/
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//make new data to set
TESTC_(FillInputBindings( m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,
m_rgTableColOrds, PRIMARY),S_OK);
for (i=0;i<m_cBinding;i++)
{
//force SetData to use the read only (FillBindings will ignore read only cols)
// *(DBSTATUS *)((DWORD)pData+m_rgBinding[i].obStatus) = DBSTATUS_S_OK;
STATUS_BINDING(m_rgBinding[i],pData)=DBSTATUS_S_OK;
}
//set data should fail
hr = SetData(*pHRow,m_hAccessor,pData);
if (hr==DB_E_ERRORSOCCURRED)
{
//this is acceptable but it is not what is being tested
fTestPass = TEST_SKIPPED;
goto CLEANUP;
}
TESTC_(DB_S_ERRORSOCCURRED,hr);
//allocate memory for the row
if(!(pGetData=PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, pGetData),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
for (i=0;i<cNotUpdateCol;i++)
{
for (j=0;j<m_cBinding;j++)
{
//if this is a read only column that was bound
if (rgNotUpdateColNumber[i]==m_rgBinding[j].iOrdinal)
{
//don't check timestamp columns
if (m_rgInfo[j].dwFlags & DBCOLUMNFLAGS_ISROWVER)
{
continue;
}
//check the failed status
// if (!COMPARE(*(DBSTATUS *)((DWORD)pData+m_rgBinding[j].obStatus), DBSTATUS_E_PERMISSIONDENIED))
if(!COMPARE(DBSTATUS_E_PERMISSIONDENIED,STATUS_BINDING(m_rgBinding[j],pData)))
{
goto CLEANUP;
}
//make sure the GetData for the read only column doesn't have the value that failed in SetData
// if ( *(BYTE *)((DWORD)pGetData+m_rgBinding[j].obValue) ==
// *(BYTE *)((DWORD)pData+m_rgBinding[j].obValue)
if ( &VALUE_BINDING(m_rgBinding[j], pGetData) ==
&VALUE_BINDING(m_rgBinding[j], pData)
)
{
goto CLEANUP;
}
//GetData for the read only column should be the same as from the first GetData call
// if (!COMPARE( *(BYTE *)((DWORD)pGetData+m_rgBinding[j].obValue),
// *(BYTE *)((DWORD)m_pData+m_rgBinding[j].obValue)
if (!COMPARE( &VALUE_BINDING(m_rgBinding[j], pGetData),
&VALUE_BINDING(m_rgBinding[j], m_pData)
))
{
goto CLEANUP;
}
}
}
}
fTestPass=TEST_PASS;
CLEANUP:
CoTaskMemFree(pData); pData = NULL; //PROVIDER_FREE(pData);
PROVIDER_FREE(pGetData);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(rgNotUpdateColNumber);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(29)
//*-----------------------------------------------------------------------
// @mfunc set no data in a BLOB column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_29()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
void *pData = NULL;
DBPROPID rgPropertyIDs[2];
DBORDINAL cColNum = 0;
DBORDINAL *rgColNumberNum = NULL;
DBORDINAL cColBLOB = 0;
DBORDINAL *rgColNumberBLOB = NULL;
DBORDINAL rgColNumber[2] = {0,0};
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create a rowset so the test can pick not nullable updatable cols
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_LENGTH | DBPART_VALUE | DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
//get an array of numeric and updatable columns
GetImage(&cColBLOB,&rgColNumberBLOB);
//has to find such a column
if(!cColBLOB)
{
goto CLEANUP;
}
//get an array of numeric and updatable columns
GetNumericAndUpdatable(&cColNum,&rgColNumberNum);
//has to find such a column
if(!cColNum)
{
goto CLEANUP;
}
rgColNumber[0]=rgColNumberNum[0];
rgColNumber[1]=rgColNumberBLOB[0];
fTestPass=FALSE;
//Create a new accessor that binds a fixed length and a BLOB
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_LENGTH | DBPART_VALUE | DBPART_STATUS, USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,2,rgColNumber))
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//get a new data buffer to set the data a row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//make sure and put the empty string in the BLOB
if ( IsNumericType(m_rgBinding[0].wType))
{
//fill the BLOB buffer with empty string
// *(ULONG *)((DWORD)pData+m_rgBinding[1].obLength)= 0;
LENGTH_BINDING(m_rgBinding[1],pData)=0;
}
else
{
//fill the BLOB buffer with empty string
// *(ULONG *)((DWORD)pData+m_rgBinding[0].obLength)= 0;
LENGTH_BINDING(m_rgBinding[0],pData)=0;
}
//set data, should pass
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//Get the data for a row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//set the data again, should pass
TESTC_(SetData(*pHRow,m_hAccessor,m_pData),S_OK);
fTestPass=TRUE;
CLEANUP:
if(m_pIRowsetChange&&pHRow)
{
//delete the row so it doesn't cause problems later for providers that fail this variation
CHECK(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow,NULL),S_OK);
}
PROVIDER_FREE(pData);
PROVIDER_FREE(rgColNumberBLOB);
PROVIDER_FREE(rgColNumberNum);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(30)
//*-----------------------------------------------------------------------
// @mfunc InsertRows and DBPROP_MAX
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_30()
{
BYTE *pData = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
ULONG cRefCount = 0;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass = TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
//sets the prop DBPROP_MAXROWS to 1 for the rowset
g_fUseMaxRows = TRUE;
HRESULT hr = S_OK;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass = TEST_FAIL;
//make changes to the row. Make its value as the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,NULL),S_OK);
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//try to get 2 row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,2,&cRows,&pHRow),DB_S_ROWLIMITEXCEEDED);
if (1==cRows)
{
fTestPass = TEST_PASS;
}
CLEANUP:
//free the memory used by pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(31)
//*-----------------------------------------------------------------------
// @mfunc insert no BLOB, change BLOB
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Forward_Cursor::Variation_31()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
// HROW *pHRow = NULL;
void *pData = NULL;
DBPROPID rgPropertyIDs[3];
DBORDINAL cColNum = 0;
DBORDINAL *rgColNumberNum = NULL;
DBORDINAL cColBLOB = 0;
DBORDINAL *rgColNumberBLOB = NULL;
DBORDINAL rgColNumber[2] = {0,0};
HROW HRowNew = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_CHANGEINSERTEDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create a rowset so the test can pick not nullable updatable cols
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_LENGTH | DBPART_VALUE | DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
//amke data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//insert a new row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,&HRowNew),S_OK);
PROVIDER_FREE(pData);
//get an array of BLOBs
GetImage(&cColBLOB,&rgColNumberBLOB);
//has to find such a BLOB column
if(!cColBLOB)
{
goto CLEANUP;
}
//get an array of numeric and updatable columns
GetNumericAndUpdatable(&cColNum,&rgColNumberNum);
//has to find such a column
if(!cColNum)
{
goto CLEANUP;
}
rgColNumber[0]=rgColNumberNum[0];
rgColNumber[1]=rgColNumberBLOB[0];
fTestPass=FALSE;
//Create a new accessor that now binds a fixed length and a BLOB
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_LENGTH | DBPART_VALUE | DBPART_STATUS, USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,2,rgColNumber))
//get a new data buffer to set the data a row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data, should pass
TESTC_(SetData(HRowNew,m_hAccessor,pData),S_OK);
//Get the data for a row handle
TESTC_(GetData(HRowNew,m_hAccessor,m_pData),S_OK);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
}
CLEANUP:
PROVIDER_FREE(pData);
PROVIDER_FREE(rgColNumberBLOB);
PROVIDER_FREE(rgColNumberNum);
if(HRowNew && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,&HRowNew,NULL,NULL,NULL),S_OK);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Forward_Cursor::Terminate()
{
return(TCIRowsetChange::Terminate());
}
// {{ TCW_TC_PROTOTYPE(QueryBaseUpdates)
//*-----------------------------------------------------------------------
//| Test Case: QueryBaseUpdates - Test QueryBaseUpdates that update more than one rows.
//| Created: 04/09/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL QueryBaseUpdates::Init()
{
BOOL fPass = FALSE;
if(!TCIRowsetChange::Init())
return FALSE;
fPass = TRUE;
return fPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Immediate update mode. Update one non-key column with values that affect more than one rows. Verify the change is visible
//
// @rdesc TEST_PASS or TEST_FAIL
//
int QueryBaseUpdates::Variation_1()
{
DBPROPID rgPropertyIDs[1];
DBCOUNTITEM cRows = 0;
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber= NULL;
HROW *pHRow = NULL;
BYTE *pData = NULL;
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr = S_OK;
DBCOUNTITEM ulCol = 0;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
//No accessor to be created.
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,0,NULL,NO_ACCESSOR));
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
fTestPass = FALSE;
//get an array of fixed length and updatable columns
if(!COMPARE(GetNonKeyNonBLOB(&cCol,&rgColNumber),TRUE))
{
goto CLEANUP;
}
//pick the third column. if there is not 3 columns use the last one
if(cCol<3)
{
ulCol=cCol-1;
}
else
{
ulCol=3;
}
//create an accessor to the first numeric and updatable column.
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,1,&(rgColNumber[ulCol])))
//get the a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//get a new data buffer to set the data a row. Set
//the data to be the same as the another row handle
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,(g_ulNextRow-1),m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data. Change the row to the same as the other handle's data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//release the memory
PROVIDER_FREE(pData);
//get a new data buffer with new data.
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//Set the data to be the same row handle, should have another row that has matching data in this column
//some provider MIGHT do query based upadtes which would affect both rows
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
goto CLEANUP;
//retrieve the row handles
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change, twice
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
//free the memory used by pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Buffered update mode. Update one non-key column with values that affect more than one rows. Verify the change is visible the
//
// @rdesc TEST_PASS or TEST_FAIL
//
int QueryBaseUpdates::Variation_2()
{
DBPROPID rgPropertyIDs[2];
DBCOUNTITEM cRows = 0;
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber= NULL;
HROW *pHRow = NULL;
BYTE *pData = NULL;
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr = S_OK;
DBCOUNTITEM ulCol = 0;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
//create an accessor with IRowsetChange. Buffered update mode.
//No accessor to be created.
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,0,NULL,NO_ACCESSOR));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate))
goto CLEANUP;
fTestPass = FALSE;
//get an array of fixed length and updatable columns
if(!COMPARE(GetNonKeyNonBLOB(&cCol,&rgColNumber),TRUE))
goto CLEANUP;
//pick the third column. if there is not 3 columns use the last one
if(cCol<3)
ulCol=cCol-1;
else
ulCol=3;
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//create an accessor to the first numeric and updatable column.
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,1,&(rgColNumber[ulCol])))
//get a new data buffer to set the data a row. Set
//the data to be the same as the another row handle
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data. Change the row to the same as the other handle's data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//release the memory
PROVIDER_FREE(pData);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//Set the data to be the same row handle, should have another row that has matching data in this column
//some provider MIGHT do query based upadtes which would affect both rows
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,&pData,g_ulNextRow++,
m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data. Change the row to the same as the other handle's data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
goto CLEANUP;
//retrieve a row handle
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for a row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
//free the memory used by pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Boundary checks from update pending
//
// @rdesc TEST_PASS or TEST_FAIL
//
int QueryBaseUpdates::Variation_3()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRowDelete = NULL;
HROW *pHRowNew = NULL;
void *pData = NULL;
DBPROPID rgPropertyIDs[2]={NULL,NULL};
ULONG uRefCount1 = 0;
ULONG uRefCount2 = 0;
DBROWSTATUS DBRowStatus[3];
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//open a rowset with an accessor on all updatable columns with a static cursor
TESTC_PROVIDER( GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,2,g_rgPropertyIDs,
ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//get row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,3,&cRows, &pHRowDelete),S_OK);
//delete the rows
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,NULL,DBRowStatus),E_INVALIDARG);
//no op
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,0,pHRowDelete,DBRowStatus),S_OK);
//no op
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,0,NULL,DBRowStatus),S_OK);
//delete the rows
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,2,pHRowDelete,DBRowStatus),S_OK);
//delete the rows again
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,cRows,pHRowDelete,DBRowStatus),DB_S_ERRORSOCCURRED);
COMPARE(DBRowStatus[0], DBROWSTATUS_E_DELETED);
COMPARE(DBRowStatus[1], DBROWSTATUS_E_DELETED);
COMPARE(DBRowStatus[2], DBROWSTATUS_S_OK);
fTestPass = TEST_PASS;
CLEANUP:
if(pData)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
}
if(pHRowDelete && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRowDelete, NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRowDelete);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc NEWLYINSERTED from update pending
//
// @rdesc TEST_PASS or TEST_FAIL
//
int QueryBaseUpdates::Variation_4()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW HRowNew = NULL;
void *pData = NULL;
DBPROPID rgPropertyIDs[2] = {NULL,NULL};
DBPROPID rgUnPropertyIDs[3] = {NULL,NULL,NULL};
DBROWSTATUS DBRowStatus;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
rgUnPropertyIDs[0]=DBPROP_OTHERINSERT;
rgUnPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgUnPropertyIDs[2]=DBPROP_CHANGEINSERTEDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//open a rowset with an accessor on all updatable columns with a static cursor
TESTC_PROVIDER( GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,3,rgUnPropertyIDs,
ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//fillup input data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//insert a new row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,&HRowNew),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,&HRowNew,&DBRowStatus),DB_E_ERRORSOCCURRED);
if(!COMPARE(DBRowStatus, DBROWSTATUS_E_NEWLYINSERTED))
{
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
if(pData)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
}
if(&HRowNew && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,&HRowNew, NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc key non-key cols, set 2 rows the same and delete
//
// @rdesc TEST_PASS or TEST_FAIL
//
int QueryBaseUpdates::Variation_5()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
void *pData = NULL;
void *pData1 = NULL;
DBPROPID rgPropertyIDs[2]= {NULL,NULL};
DBROWSTATUS DBRowStatus;
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber = NULL;
DBORDINAL ulCol = 0;
HRESULT hr;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//open a rowset with an accessor on all updatable columns with a static cursor
//create an accessor with IRowsetChange. Buffered update mode.
//No accessor to be created.
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_UPDATEABLE,2,rgPropertyIDs,2,g_rgPropertyIDs,NO_ACCESSOR));
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
//get an array of fixed length and updatable columns
if(!COMPARE(GetNonKeyNonBLOB(&cCol,&rgColNumber),TRUE))
{
goto CLEANUP;
}
fTestPass = FALSE;
//pick the third column. if there is not 3 columns use the last one
if(cCol<3)
ulCol=cCol-1;
else
ulCol=3;
//get 2 row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,2,&cRows,&pHRow),S_OK);
//create an accessor to the first numeric and updatable column.
TESTC_PROVIDER(GetAccessorOnRowset( ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,1,&(rgColNumber[ulCol])))
//get a new data buffer to set the data a row. Set
//the data to be the same as the another row handle
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data. Change the row to the same as the other handle's data
TESTC_(SetData(pHRow[0],m_hAccessor,pData),S_OK);
TESTC_(SetData(pHRow[1],m_hAccessor,pData),S_OK);
//delete the row, first one only
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,&pHRow[0],&DBRowStatus),S_OK);
if(!COMPARE(DBRowStatus, DBROWSTATUS_S_OK))
{
goto CLEANUP;
}
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if (S_OK!=hr && DB_S_COMMANDREEXECUTED!=hr)
{
if (DB_E_ROWSNOTRELEASED==hr)
{
//if CANHOLDROWS is TRUE and RestartPosition returns DB_E_ROWSNOTRELEASED
//then check DBPROP_QUICKRESTART.
//if DBPROP_QUICKRESTART is FALSE (command re-executed) this could be valid
//but if DBPROP_QUICKRESTART is TRUE DB_E_ROWSNOTRELEASED should not be
//returned from RestartPosition if CANHOLDROWS is requested
if(GetProperty(DBPROP_QUICKRESTART, DBPROPSET_ROWSET, (IUnknown*)m_pIRowset))
{
goto CLEANUP;
}
else
{
//if here then DBPROP_QUICKRESTART is TRUE
fTestPass = TEST_SKIPPED;
goto CLEANUP;
}
}
}
//get 2 row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,2,&cRows,&pHRow),S_OK);
//allocate memory for GetData
if(!(pData1=PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
//get the first 2 rows
//row 1
hr=m_pIRowset->GetData(pHRow[0],m_hAccessor,pData1);
//DBPROP_REMOVEDELETEDROWS maybe false
if(DB_E_DELETEDROW==hr)
{
TESTC_(m_pIRowset->GetData(pHRow[1],m_hAccessor,pData1),S_OK);
//second row here (pData1) should match the changed data
if(!CompareBuffer(pData,pData1,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
goto CLEANUP;
}
}
//DBPROP_REMOVEDELETEDROWS maybe true
if(S_OK==hr)
{
//the deleted row was removed so the first row fetch should now be the seond changed row
if(!CompareBuffer(pData1,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->GetData(pHRow[1],m_hAccessor,pData1),S_OK);
//second row here (pData1) should now not match the changed data
if(CompareBuffer(pData1,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
goto CLEANUP;
}
}
fTestPass=TRUE;
CLEANUP:
if(pData)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
}
if(pData1)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData1,TRUE);
}
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Delete rows from update pending, delete not supported
//
// @rdesc TEST_PASS or TEST_FAIL
//
int QueryBaseUpdates::Variation_6()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRowDelete = NULL;
DBPROPID rgPropertyIDs[1]= {NULL};
DBROWSTATUS DBRowStatus;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,
2,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//get row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,3,&cRows, &pHRowDelete),S_OK);
//delete the rows
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,cRows,pHRowDelete,&DBRowStatus),DB_E_NOTSUPPORTED);
fTestPass=TRUE;
CLEANUP:
if(pHRowDelete && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRowDelete, NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRowDelete);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc delete with a row handle from an unallocated rowset
//
//
// @rdesc TEST_PASS or TEST_FAIL
//
int QueryBaseUpdates::Variation_7()
{
HROW HRow = 27;
DBPROPID rgPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgDBRowStatus[1];
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create an accessor on the command object on the numeric and updatable column only
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,2,g_rgPropertyIDs,
ON_COMMAND_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange || !m_cBinding))
{
goto CLEANUP;
}
fTestPass = FALSE;
//get row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,3,&cRows, &pHRow),S_OK);
//delete the row using different row handle
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,&HRow,rgDBRowStatus),DB_E_ERRORSOCCURRED);
TESTC(COMPARE(rgDBRowStatus[0], DBROWSTATUS_E_INVALID));
fTestPass = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc delete with a row handle from an allocated rowset
//
//
// @rdesc TEST_PASS or TEST_FAIL
//
int QueryBaseUpdates::Variation_8()
{
HROW HRow = 27;
DBPROPID rgPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgDBRowStatus[1];
rgPropertyIDs[0]=DBPROP_IRowsetChange;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create an accessor on the command object on the numeric and updatable column only
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,2,g_rgPropertyIDs,
ON_COMMAND_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange || !m_cBinding))
{
goto CLEANUP;
}
fTestPass = FALSE;
//delete the row using different row handle
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,&HRow,rgDBRowStatus),DB_E_ERRORSOCCURRED);
TESTC(COMPARE(rgDBRowStatus[0], DBROWSTATUS_E_INVALID));
fTestPass = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc Boundary cases with update pending
//
// @rdesc TEST_PASS or TEST_FAIL
//
int QueryBaseUpdates::Variation_9()
{
DBPROPID rgPropertyIDs[2];
DBCOUNTITEM cRows = 0;
DBORDINAL *rgColNumber= NULL;
HROW *pHRow = NULL;
BOOL fTestPass = TEST_SKIPPED;
BYTE *pData = NULL;
HACCESSOR hAccessor = NULL;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,
2,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate) || (!m_cBinding))
{
goto CLEANUP;
}
fTestPass = FALSE;
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//get a new data buffer to set the data
TESTC_(FillInputBindings( m_pTable,
DBACCESSOR_ROWDATA,
m_cBinding,
m_rgBinding,
(BYTE **)&pData,
g_ulNextRow++,
m_cRowsetCols,
m_rgTableColOrds,
PRIMARY),S_OK);
//create an NULL accessor
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,&hAccessor,NULL),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,NULL),E_INVALIDARG);
TESTC_(SetData(*pHRow,NULL,pData),DB_E_BADACCESSORHANDLE);
TESTC_(SetData(NULL,m_hAccessor,pData),DB_E_BADROWHANDLE);
TESTC_(SetData(*pHRow,hAccessor,NULL),S_OK);
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
PROVIDER_FREE(rgColNumber);
if (hAccessor)
{
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
}
if(m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc BSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALUE, qbu
//
// @rdesc TEST_PASS or TEST_FAIL
//
int QueryBaseUpdates::Variation_10()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
void *pData = NULL;
void *pGetData = NULL;
DBPROPID rgPropertyIDs[2];
DBSTATUS dbsSecondColStatus;
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber = NULL;
DBORDINAL ulCol = 0;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,2,g_rgPropertyIDs,NO_ACCESSOR));
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
//get an array of fixed length and updatable columns
if(!COMPARE(GetNonKeyNonBLOB(&cCol,&rgColNumber),TRUE))
{
goto CLEANUP;
}
//pick the third column. if there is not 3 columns use the last one
if(cCol<3)
{
ulCol=cCol-1;
}
else
{
ulCol=3;
}
fTestPass=FALSE;
//create an accessor to the first numeric and updatable column.
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,1,&(rgColNumber[ulCol])))
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//change the second status binding to anything other than _OK or NULL
// *(DBSTATUS *)(((DWORD)pData)+ m_rgBinding[0].obStatus)=DBSTATUS_S_TRUNCATED;
STATUS_BINDING(m_rgBinding[0],pData)=DBSTATUS_S_TRUNCATED;
// keep track of colstatus
// dbsSecondColStatus = *(DBSTATUS *)(((DWORD)pData)+ m_rgBinding[0].obStatus);
dbsSecondColStatus = STATUS_BINDING(m_rgBinding[0],pData);
//set data should fail
m_hr=SetData(*pHRow,m_hAccessor,pData);
if ( !COMPARE(m_hr == DB_E_ERRORSOCCURRED || m_hr == DB_S_ERRORSOCCURRED, TRUE) )
goto CLEANUP;
TESTC_(GetStatus(pData, &(m_rgBinding[0])),DBSTATUS_E_BADSTATUS);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if ( m_hr == DB_S_ERRORSOCCURRED )
{
if(m_cBinding > 1)
{
TESTC_(GetStatus(pData, &(m_rgBinding[0])),dbsSecondColStatus);
}
}
else
{
if(m_cBinding > 1)
{
TESTC_(GetStatus(pData, &(m_rgBinding[0])),DBSTATUS_E_UNAVAILABLE);
}
//allocate memory for getting data again
pGetData=PROVIDER_ALLOC(m_cRowSize);
if(!pGetData)
{
goto CLEANUP;
}
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, pGetData),S_OK);
//columns should not be changed
if(!COMPARE(CompareBuffer(pGetData, m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
{
goto CLEANUP;
}
}
fTestPass=TRUE;
CLEANUP:
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
PROVIDER_FREE(pGetData);
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc SetData not supported, qbu
//
// @rdesc TEST_PASS or TEST_FAIL
//
int QueryBaseUpdates::Variation_11()
{
DBPROPID rgPropertyIDs[2];
DBCOUNTITEM cRows = 0;
DBORDINAL *rgColNumber= NULL;
HROW *pHRow = NULL;
BOOL fTestPass = TEST_SKIPPED;
BYTE *pData = NULL;
HACCESSOR hAccessor = NULL;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_INSERT;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,
2,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass = FALSE;
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get a new data buffer to set the data
TESTC_(FillInputBindings( m_pTable,
DBACCESSOR_ROWDATA,
m_cBinding,
m_rgBinding,
(BYTE **)&pData,
g_ulNextRow++,
m_cRowsetCols,
m_rgTableColOrds,
PRIMARY),S_OK);
//create an NULL accessor
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,&hAccessor,NULL),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),DB_E_NOTSUPPORTED);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
PROVIDER_FREE(rgColNumber);
if (hAccessor)
{
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
}
if(m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc QBU with just floats
//
// @rdesc TEST_PASS or TEST_FAIL
//
int QueryBaseUpdates::Variation_12()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
DBPROPID rgPropertyIDs[2]= {NULL,NULL};
DBORDINAL *rgColsToBind = NULL;
DBORDINAL cColsNumber = 0;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
{
m_ulpUpdFlags = m_ulpProvUpdFlags;
}
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=KAGPROP_INCLUDENONEXACT;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,0,NULL,NO_ACCESSOR));
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
//Get a variable length column. .
if(!GetFloatAndUpdatable(&cColsNumber, &rgColsToBind))
{
odtLog << "no float updateable columns available"<<ENDL;
fTestPass = TRUE;
goto CLEANUP;
}
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=KAGPROP_INCLUDENONEXACT;
//get an accessor with just the floats
GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,
cColsNumber, rgColsToBind);
fTestPass=FALSE;
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow),S_OK);
//get a new data buffer to set the data.
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&m_pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,m_pData),S_OK);
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
PROVIDER_FREE(m_pData);
PROVIDER_FREE(rgColsToBind);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL QueryBaseUpdates::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Static_Cursor_Immediate)
//*-----------------------------------------------------------------------
//| Test Case: Static_Cursor_Immediate - Static cursor in immediate update mode.
//| not visible - OTHERUPDATEDELETE is VARIANT_FALSE
//| Created: 04/09/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Static_Cursor_Immediate::Init()
{
DBPROPID rgPropertyIDs[2];
BOOL fTestPass=TEST_SKIPPED;
if(!TCIRowsetChange::Init())
{
return FALSE;
}
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetLocate;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,
g_cPropertyIDs,g_rgPropertyIDs,NO_ACCESSOR));
//for static cursor
COMPARE(BufferedUpdate(),FALSE);
fTestPass=TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Update a row to be the first row in the row set with some columns set to NULL, and call GetData to see.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Static_Cursor_Immediate::Variation_1()
{
DBCOUNTITEM cRows = 0;
ULONG cCol = 0;
DBORDINAL *rgColNumber = NULL;
HROW *pHRow = NULL;
ULONG cCount = 0;
BYTE *pDataNoFetch = NULL;
BYTE *pData = NULL;
BYTE *pBackEndData = NULL;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr = S_OK;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetLocate;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,
g_cPropertyIDs,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
//get an array of nullable and updatable columns
(&cCol,&rgColNumber);
if(!cCol)
goto CLEANUP;
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass = FALSE;
//get the row handle
TESTC_(m_hr=m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get the data for the row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//get a new data buffer to set the data. The data is for first row.
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set the first nullable and updatble columns to NULL
if(cCol)
{
for(cCount=0;cCount<m_cBinding;cCount++)
{
if(m_rgBinding[cCount].iOrdinal==rgColNumber[0])
{
// *(ULONG *)(dwAddr+m_rgBinding[cCount].obStatus)=DBSTATUS_S_ISNULL;
STATUS_BINDING(m_rgBinding[cCount],pData)=DBSTATUS_S_ISNULL;
break;
}
}
}
//has to find such a column
if(cCount==m_cBinding)
goto CLEANUP;
if(!(pDataNoFetch=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//get the data for the row
TESTC_(GetData(*pHRow,m_hAccessor,pDataNoFetch),S_OK);
//make sure GetData should be able to see the change
if(!COMPARE(CompareBuffer(pDataNoFetch,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
//release the row handle
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//allocate another buffer
pBackEndData=(BYTE *)PROVIDER_ALLOC(m_cRowSize);
if(!pBackEndData)
goto CLEANUP;
//release the rowset
ReleaseRowsetAndAccessor();
//reexecute the query
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,g_cPropertyIDs,g_rgPropertyIDs,
ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND))
//refetch the row handles
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if(cRows == 0)
break;
//Get the data for the row handle
TESTC_(GetData(*pHRow,m_hAccessor,pBackEndData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change, DBPROP_OWNUPDATEDELETE is FALSE
//but query is re executed
if(CompareBuffer(pBackEndData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pBackEndData,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
CLEANUP:
//free the memory used by pBackEndData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pBackEndData,TRUE);
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pData);
PROVIDER_FREE(pDataNoFetch);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Retrive a row handle. Move the cursor to the end of the rowset. Retrieve the row handle again.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Static_Cursor_Immediate::Variation_2()
{
BYTE *pData = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowDuplicate = NULL;
DBPROPID rgPropertyIDs[6];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hrRP = S_OK;
HRESULT hr = S_OK;
BYTE *pBackEndData = NULL;
BYTE *pDataNoFetch = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetIdentity;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
rgPropertyIDs[3]=DBPROP_CANFETCHBACKWARDS;
rgPropertyIDs[4]=DBPROP_CANSCROLLBACKWARDS;
rgPropertyIDs[5]=DBPROP_IRowsetLocate;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,6,rgPropertyIDs,
g_cPropertyIDs,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass = FALSE;
//retrieve the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get the data for the row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//move the cursor away
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows-2,1,&cRows,&pHRowDuplicate),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDuplicate);
//retrieve the row handle again
TESTC_(m_pIRowset->GetNextRows(NULL,-(LONG)m_ulTableRows +1,-1,&cRows,&pHRowDuplicate),S_OK);
//Compare rows, the two row handles should have the same value
if (GetProperty(DBPROP_LITERALIDENTITY, DBPROPSET_ROWSET, g_pIDBInitialize))
{
COMPARE((DWORD)(*pHRow), (DWORD)(*pHRowDuplicate));
}
else
{
if (!fnIsSameRow(m_pIRowset,pHRow,pHRowDuplicate))
{
goto CLEANUP;
}
}
if(!(pDataNoFetch=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
//make changes to the row. Make its value as the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//make sure the change is visiable throught the other row handle
TESTC_(GetData(*pHRowDuplicate,m_hAccessor,pDataNoFetch),S_OK);
//the change is only gaurenteed to be visible if LITERALIDENTITY is TRUE
if (GetProperty(DBPROP_LITERALIDENTITY, DBPROPSET_ROWSET, g_pIDBInitialize))
{
//make sure GetData should be able to see the change, row has not been refetched
if(!COMPARE(CompareBuffer(pDataNoFetch,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
{
goto CLEANUP;
}
}
//Release the row handle
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
CHECK(m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDuplicate);
//restart position
hrRP=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hrRP==S_OK || hrRP==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
if(!(pBackEndData=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET)
{
if( cRows ==0)
{
break;
}
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,pBackEndData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//if the command was re-executed the change will be visible
if (DB_S_COMMANDREEXECUTED==hrRP)
{
//make sure GetData should be able to see the change - command was re-executed
if(CompareBuffer(pBackEndData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pBackEndData,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
else
{
//make sure GetData shouldn't be able to see the change (it should see old data)
//OWNUPADTEDELETE is off
if(CompareBuffer(pBackEndData,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pBackEndData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
}
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowDuplicate && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDuplicate);
PROVIDER_FREE(pData);
PROVIDER_FREE(pBackEndData);
PROVIDER_FREE(pDataNoFetch);
PROVIDER_FREE(pBackEndData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Retrive a row handle. Move the cursor to the beginning of the rowset. Retrieve the row handle again
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Static_Cursor_Immediate::Variation_3()
{
BYTE *pData = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowDuplicate = NULL;
DBPROPID rgPropertyIDs[5];
BOOL fTestPass = TEST_SKIPPED;
BYTE *pDataNoFetch = NULL;
BYTE *pBackEndData = NULL;
HRESULT hrRP = S_OK;
HRESULT hr = S_OK;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetLocate;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
rgPropertyIDs[3]=DBPROP_CANFETCHBACKWARDS;
rgPropertyIDs[4]=DBPROP_IRowsetIdentity;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,5,rgPropertyIDs,g_cPropertyIDs,g_rgPropertyIDs,
ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass = FALSE;
//retrieve the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//make sure the change is visiable throught the other row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//move the cursor away
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows-2,1,&cRows,&pHRowDuplicate),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDuplicate);
//retrieve the row handle again
TESTC_(m_pIRowset->GetNextRows(NULL,-(LONG)(m_ulTableRows)+1,-1,&cRows,&pHRowDuplicate),S_OK);
//the two row handles should have the same value
//Compare rows, the two row handles should have the same value
if (GetProperty(DBPROP_LITERALIDENTITY, DBPROPSET_ROWSET, g_pIDBInitialize))
{
COMPARE((DWORD)(*pHRow), (DWORD)(*pHRowDuplicate));
}
else
{
if (!fnIsSameRow(m_pIRowset,pHRow,pHRowDuplicate))
{
goto CLEANUP;
}
}
if(!(pDataNoFetch=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
//make changes to the row. Make its value as the 3th row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//make sure the change is visiable throught the other row handle
TESTC_(GetData(*pHRowDuplicate,m_hAccessor,pDataNoFetch),S_OK);
//the change is only gaurenteed to be visible if LITERALIDENTITY is TRUE
if (GetProperty(DBPROP_LITERALIDENTITY, DBPROPSET_ROWSET, g_pIDBInitialize))
{
//make sure GetData should be able to see the change, row has not been refetched
if(!COMPARE(CompareBuffer(pDataNoFetch,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
{
goto CLEANUP;
}
}
//Release the row handle
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
CHECK(m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDuplicate);
//restart position
hrRP=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hrRP==S_OK || hrRP==DB_S_COMMANDREEXECUTED, TRUE))
goto CLEANUP;
if(!(pBackEndData=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRowDuplicate)) || hr == DB_S_ENDOFROWSET)
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(GetData(*pHRowDuplicate,m_hAccessor,pBackEndData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDuplicate);
//if the command was re-executed the change will be visible
if (DB_S_COMMANDREEXECUTED==hrRP)
{
//make sure GetData should be able to see the change - command was re-executed
if(CompareBuffer(pBackEndData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pBackEndData,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
else
{
//make sure GetData shouldn't be able to see the change (it should see old data)
//OWNUPADTEDELETE is off
if(CompareBuffer(pBackEndData,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pBackEndData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
}
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowDuplicate && m_pIRowset)
m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL,NULL,NULL);
PROVIDER_FREE(pHRowDuplicate);
PROVIDER_FREE(pData);
PROVIDER_FREE(pDataNoFetch);
PROVIDER_FREE(pBackEndData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Create two rowsets on the same table. One rowset changes a value. The other rowset should not see change
// One rowset changes a key value. The other rowset should no
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Static_Cursor_Immediate::Variation_4()
{
HROW *pHRow = NULL;
HROW *pHRowSecond = NULL;
DBCOUNTITEM cRows = 0;
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber = NULL;
void *pData = NULL;
void *pDataSecond = NULL;
IRowsetInfo *pIRowsetInfo = NULL;
ICommand *pICommand = NULL;
IUnknown *pIRowset = NULL;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass = TEST_SKIPPED;
BYTE *pDataNoFetch = NULL;
HRESULT hrRP = S_OK;
HRESULT hr = S_OK;
rgPropertyIDs[0]=DBPROP_LITERALIDENTITY;//DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,g_cPropertyIDs,g_rgPropertyIDs,NO_ACCESSOR));
//get an array of numeric and updatable columns
GetNumericAndUpdatable(&cCol,&rgColNumber);
//has to find such a column
if(!cCol)
goto CLEANUP;
//release the row set
ReleaseRowsetAndAccessor();
if ((!m_pIDBCreateCommand) || (!m_pIRowsetChange))
goto CLEANUP;
fTestPass = FALSE;
//create an accessor on the command object on the numeric and updatable column only
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,g_cPropertyIDs,g_rgPropertyIDs,
ON_COMMAND_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, USE_COLS_TO_BIND_ARRAY,
FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,rgColNumber));
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,9,1,&cRows,&pHRow),S_OK);
//get a copy of the data on row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
if(!(pDataNoFetch=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//create a new data buffer to set the data for ther numeric and updatable
//column
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,1,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//create another rowset object on the same command object//QI for IRowsetInfo pointer
TESTC_(m_pIAccessor->QueryInterface(IID_IRowsetInfo, (LPVOID *)&pIRowsetInfo),S_OK);
//get the ICommand pointer
TESTC_(pIRowsetInfo->GetSpecification(IID_ICommand,(IUnknown **)&pICommand),S_OK);
//exeute the same command object
TESTC_(pICommand->Execute(NULL,IID_IRowset,NULL,NULL,&pIRowset),S_OK);
//set data on the first rowset
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
//get data on the first rowset.
TESTC_(GetData(*pHRow,m_hAccessor,pDataNoFetch),S_OK);
//make sure GetData should be able to see the change, row has not been refetched
if(!COMPARE(CompareBuffer(pDataNoFetch,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
//Release the row handle
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//alloc new memory
if(!(pDataSecond=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//restart position on a completly different rowset
hrRP=((IRowset *)(pIRowset))->RestartPosition(NULL);
if(!CHECK(hrRP==S_OK || hrRP==DB_S_COMMANDREEXECUTED, TRUE))
goto CLEANUP;
while (S_OK==(hr = ((IRowset *)(pIRowset))->GetNextRows(NULL,0,1,&cRows, &pHRowSecond)) || hr == DB_S_ENDOFROWSET)
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(((IRowset *)(pIRowset))->GetData(*pHRowSecond,m_hAccessor,pDataSecond),S_OK);
TESTC_(((IRowset *)(pIRowset))->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
//if the command was re-executed the change will be visible
if (DB_S_COMMANDREEXECUTED==hrRP)
{
//the second rowset should see the change if rexeccuted
if(CompareBuffer(pDataSecond,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pDataSecond,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
else
{
//the second rowset should NOT see the change (it should see old data)
if(CompareBuffer(pDataSecond,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pDataSecond,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
}
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(((IRowset *)(pIRowset))->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(pData);
PROVIDER_FREE(pDataNoFetch);
PROVIDER_FREE(pDataSecond);
SAFE_RELEASE(pIRowsetInfo);
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pICommand);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Static_Cursor_Immediate::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Static_Cursor_Buffered)
//*-----------------------------------------------------------------------
//| Test Case: Static_Cursor_Buffered - Static_Cursor_Buffered
//| not visible - OTHERUPDATEDELETE is VARIANT_FALSE
//| Created: 04/09/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Static_Cursor_Buffered::Init()
{
DBPROPID rgPropertyIDs[2];
BOOL fTestPass =TEST_SKIPPED;
if(!TCIRowsetChange::Init())
return FALSE;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_IRowsetLocate;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_COLLISTFROMTBL,2,rgPropertyIDs,g_cPropertyIDs,g_rgPropertyIDs,NO_ACCESSOR));
//for static cursor
COMPARE(BufferedUpdate(),TRUE);
fTestPass=TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Static_Cursor_Buffered::Variation_1()
{
DBCOUNTITEM cRows = 0;
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber = NULL;
HROW *pHRow = NULL;
ULONG cCount = 0;
BYTE *pData = NULL;
BYTE *pBackEndData = NULL;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr = S_OK;
BYTE *pDataNoFetch = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_IRowsetLocate;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,
g_cPropertyIDs,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate)|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass = FALSE;
//get an array of nullable and updatable columns
GetNullableAndUpdatable(&cCol,&rgColNumber);
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get the data for the row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//get a new data buffer to set the data. The data is for first row.
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set a first nullable and updatble columns to NULL
if(cCol)
{
for(cCount=0;cCount<m_cBinding;cCount++)
{
if(m_rgBinding[cCount].iOrdinal==rgColNumber[cCol-1])
{
// *(ULONG *)(dwAddr+m_rgBinding[cCount].obStatus)=DBSTATUS_S_ISNULL;
STATUS_BINDING(m_rgBinding[cCount],pData)=DBSTATUS_S_ISNULL;
break;
}
}
}
if(!(pDataNoFetch=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//has to find such a column
if(cCount==m_cBinding)
goto CLEANUP;
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//get the data for the row
TESTC_(GetData(*pHRow,m_hAccessor,pDataNoFetch),S_OK);
//make sure GetData should be able to see the change
if(!COMPARE(CompareBuffer(pDataNoFetch,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//allocate another buffer
pBackEndData=(BYTE *)PROVIDER_ALLOC(m_cRowSize);
if(!pBackEndData)
goto CLEANUP;
//release the rowset
ReleaseRowsetAndAccessor();
//reexecute the query
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,
g_cPropertyIDs,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND))
//retrieve the row handles
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the row handle
TESTC_(GetData(*pHRow,m_hAccessor,pBackEndData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData shouldbe able to see the change, OTHERUPDATEDELETE is FALSE
if(CompareBuffer(pBackEndData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pBackEndData,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pData);
PROVIDER_FREE(pDataNoFetch);
PROVIDER_FREE(pBackEndData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Retrive a row handle. Move the cursor to the end of the rowset. Retrieve the row handle again
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Static_Cursor_Buffered::Variation_2()
{
BYTE *pData = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowDuplicate = NULL;
DBPROPID rgPropertyIDs[5];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr = S_OK;
BYTE *pBackEndData = NULL;
BYTE *pDataNoFetch = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_IRowsetLocate;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
rgPropertyIDs[3]=DBPROP_CANSCROLLBACKWARDS;
rgPropertyIDs[4]=DBPROP_IRowsetIdentity;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,5,rgPropertyIDs,
g_cPropertyIDs,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate)|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass = FALSE;
//retrieve the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get the data for the row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//move the cursor away to the row
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows-2,1,&cRows,&pHRowDuplicate),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDuplicate);
//retrieve the row handle again
TESTC_(m_pIRowset->GetNextRows(NULL,-(LONG)(m_ulTableRows)+1,-1,&cRows,&pHRowDuplicate),S_OK);
//the two row handles should have the same value
//Compare rows, the two row handles should have the same value
if (GetProperty(DBPROP_LITERALIDENTITY, DBPROPSET_ROWSET, g_pIDBInitialize))
{
COMPARE((DWORD)(*pHRow), (DWORD)(*pHRowDuplicate));
}
else
{
if (!fnIsSameRow(m_pIRowset,pHRow,pHRowDuplicate))
{
goto CLEANUP;
}
}
if(!(pDataNoFetch=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
//make changes to the row. Make its value as the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//make sure the change is visiable throught the other row handle
TESTC_(GetData(*pHRowDuplicate,m_hAccessor,pDataNoFetch),S_OK);
//make sure GetData should be able to see the change, no fetch yet
if(!COMPARE(CompareBuffer(pDataNoFetch,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
//free the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
CHECK(m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDuplicate);
//release the rowset
ReleaseRowsetAndAccessor();
//reexecute the query
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,5,rgPropertyIDs,
g_cPropertyIDs,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND))
if(!(pBackEndData=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//retrieve the row handles
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
{
break;
}
//Get the data for the row handle
TESTC_(GetData(*pHRow,m_hAccessor,pBackEndData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change - query was re-exed
if(CompareBuffer(pBackEndData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pBackEndData,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pData);
PROVIDER_FREE(pDataNoFetch);
PROVIDER_FREE(pBackEndData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Retrive a row handle. Move the cursor to the beginning of the rowset. Retrieve the row handle again.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Static_Cursor_Buffered::Variation_3()
{
BYTE *pData = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowDuplicate = NULL;
BYTE *pBackEndData = NULL;
DBPROPID rgPropertyIDs[5];
BOOL fTestPass = TEST_SKIPPED;
BYTE *pDataNoFetch = NULL;
HRESULT hrRP = S_OK;
HRESULT hr = S_OK;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_IRowsetLocate;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
rgPropertyIDs[3]=DBPROP_CANFETCHBACKWARDS;
rgPropertyIDs[4]=DBPROP_IRowsetIdentity;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,5,rgPropertyIDs,g_cPropertyIDs,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate)|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass = FALSE;
//retrieve the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get the data for the row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//move the cursor away to the 1 row handle
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows-2,1,&cRows,&pHRowDuplicate),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDuplicate);
//retrieve the row handle again
TESTC_(m_pIRowset->GetNextRows(NULL,-(LONG)m_ulTableRows+1,-1,&cRows,&pHRowDuplicate),S_OK);
//the two row handles should have the same value
//Compare rows, the two row handles should have the same value
if (GetProperty(DBPROP_LITERALIDENTITY, DBPROPSET_ROWSET, g_pIDBInitialize))
{
COMPARE((DWORD)(*pHRow), (DWORD)(*pHRowDuplicate));
}
else
{
if (!fnIsSameRow(m_pIRowset,pHRow,pHRowDuplicate))
goto CLEANUP;
}
if(!(pDataNoFetch=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//make changes to the row. Make its value as the 3th row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//make sure the change is visiable throught the other row handle
TESTC_(GetData(*pHRowDuplicate,m_hAccessor,pDataNoFetch),S_OK);
//make sure GetData should be able to see the change, row has not been refetched
if(!COMPARE(CompareBuffer(pDataNoFetch,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
//Release the row handle
CHECK(m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDuplicate);
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//restart position
hrRP=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hrRP==S_OK || hrRP==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
if(!(pBackEndData=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRowDuplicate)) || hr == DB_S_ENDOFROWSET)
{
if( cRows ==0)
{
break;
}
//Get the data for the ith row handle
TESTC_(GetData(*pHRowDuplicate,m_hAccessor,pBackEndData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDuplicate);
//if the command was re-executed the change will be visible
if (DB_S_COMMANDREEXECUTED==hrRP)
{
//make sure GetData should be able to see the change - command was re-executed
if(CompareBuffer(pBackEndData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pBackEndData,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
else
{
//make sure GetData shouldn't be able to see the change
//OWNUPADTEDELETE is off
if(CompareBuffer(pBackEndData,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pBackEndData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
}
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowDuplicate && m_pIRowset)
m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL,NULL,NULL);
PROVIDER_FREE(pHRowDuplicate);
PROVIDER_FREE(pDataNoFetch);
PROVIDER_FREE(pBackEndData);
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Create two rowsets on the same table. One rowset changes a value. The other rowset should not see change
// One rowset changes a key value. The other rowset should no
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Static_Cursor_Buffered::Variation_4()
{
HROW *pHRow = NULL;
HROW *pHRowSecond = NULL;
DBCOUNTITEM cRows = 0;
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber = NULL;
void *pData = NULL;
void *pDataSecond = NULL;
IRowsetInfo *pIRowsetInfo = NULL;
ICommand *pICommand = NULL;
IUnknown *pIRowset = NULL;
DBPROPID rgPropertyIDs[3];
BOOL fTestPass = TEST_SKIPPED;
BYTE *pDataNoFetch = NULL;
HRESULT hrRP = S_OK;
HRESULT hr = S_OK;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetUpdate;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,3,rgPropertyIDs,g_cPropertyIDs,g_rgPropertyIDs,NO_ACCESSOR));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate))
{
goto CLEANUP;
}
fTestPass = FALSE;
//get an array of numeric and updatable columns
GetNumericAndUpdatable(&cCol,&rgColNumber);
//has to find such a column
if(!cCol)
{
goto CLEANUP;
}
//release the row set
ReleaseRowsetAndAccessor();
if(!m_pIDBCreateCommand)
return TEST_PASS;
//create an accessor on the command object on the numeric and updatable column only
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,3,rgPropertyIDs,g_cPropertyIDs,g_rgPropertyIDs,
ON_COMMAND_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, USE_COLS_TO_BIND_ARRAY,
FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,rgColNumber));
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,9,1,&cRows,&pHRow),S_OK);
//get a copy of the data on row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
if(!(pDataNoFetch=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//create a new data buffer to set the data for the numeric and updatable
//column
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,1,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//create another rowset object on the same command object//QI for IRowsetInfo pointer
TESTC_(m_pIAccessor->QueryInterface(IID_IRowsetInfo, (LPVOID *)&pIRowsetInfo),S_OK);
//get the ICommand pointer
TESTC_(pIRowsetInfo->GetSpecification(IID_ICommand,(IUnknown **)&pICommand),S_OK);
//execute the same command object to get a DIFFERENT ROWSET POINTER
TESTC_(pICommand->Execute(NULL,IID_IRowset,NULL,NULL,&pIRowset),S_OK);
//set data on the FIRST rowset
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
//update the FIRST rowset
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//get data on the FIRST rowset
TESTC_(GetData(*pHRow,m_hAccessor,pDataNoFetch),S_OK);
//make sure GetData should be able to see the change, row has not been refetched
if(!COMPARE(CompareBuffer(pDataNoFetch,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
//Release the 1st row handle (test is now holding no row handles)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//alloc new memory
if(!(pDataSecond=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//restart position of SECOND (OTHER) rowset
hrRP=((IRowset *)(pIRowset))->RestartPosition(NULL);
if(!CHECK(hrRP==S_OK || hrRP==DB_S_COMMANDREEXECUTED, TRUE))
goto CLEANUP;
//Fetch through SECOND rowset from a different rowset pointer
while (S_OK==(hr = ((IRowset *)(pIRowset))->GetNextRows(NULL,0,1,&cRows, &pHRowSecond)) || hr == DB_S_ENDOFROWSET)
{
if( cRows ==0)
{
break;
}
//Get the data for the ith row handle (2nd rowset from 2nd rowset pointer)
TESTC_(((IRowset *)(pIRowset))->GetData(*pHRowSecond,m_hAccessor,pDataSecond),S_OK);
TESTC_(((IRowset *)(pIRowset))->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
//if the command was re-executed the change will not be visible
if (DB_S_COMMANDREEXECUTED==hrRP)
{
//the second rowset should see the change if reexecuted, it should see the old row
if(CompareBuffer(pDataSecond,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pDataSecond,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
else
{
//the second rowset should NOT see the change, it should see the old row
if(CompareBuffer(pDataSecond,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pDataSecond,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
}
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(((IRowset *)(pIRowset))->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(pData);
PROVIDER_FREE(pDataNoFetch);
PROVIDER_FREE(pDataSecond);
SAFE_RELEASE(pIRowsetInfo);
pIRowset->Release();;
//SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pICommand);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Static_Cursor_Buffered::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Keyset_Cursor_Buffered)
//*-----------------------------------------------------------------------
//| Test Case: Keyset_Cursor_Buffered - Keyset_Cursor_Buffered
//| Created: 04/09/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Keyset_Cursor_Buffered::Init()
{
DBPROPID rgPropertyIDs[2];
BOOL fTestPass=TEST_SKIPPED;
if(!TCIRowsetChange::Init())
return FALSE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,0,NULL,NO_ACCESSOR));
fTestPass = TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Cursor_Buffered::Variation_1()
{
BYTE *pData = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond = NULL;
HROW *pHRowDuplicate = NULL;
ULONG cRefCount;
DBPROPID rgPropertyIDs[6];
BOOL fTestPass = TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
rgPropertyIDs[3]=DBPROP_CANFETCHBACKWARDS;
rgPropertyIDs[4]=DBPROP_CANSCROLLBACKWARDS;
rgPropertyIDs[5]=DBPROP_IRowsetIdentity;
HRESULT hr = S_OK;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,6,rgPropertyIDs,0,NULL,
ON_ROWSET_ACCESSOR, TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//Identity is level 0 and required
if (!m_pIRowsetIdentity)
{
goto CLEANUP;
}
//retrieve the ith row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows-2,1,&cRows,&pHRowSecond),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
//retrieve the ith row handle again
TESTC_(m_pIRowset->GetNextRows(NULL,-(LONG)m_ulTableRows+1,-1,&cRows,&pHRowDuplicate),S_OK);
//the two row handles should have the same value
TESTC_(m_hr=m_pIRowsetIdentity->IsSameRow(*pHRow, *pHRowDuplicate),S_OK);
//make changes to the 5th row. Make its value as the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//free the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL, &cRefCount, NULL),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL, &cRefCount, NULL),S_OK);
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
hr = GetData(*pHRow,m_hAccessor,m_pData);
//Taking cares of SQL Providers for keyset cursor
TESTC(hr==S_OK || hr == DB_E_DELETEDROW);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(pHRowDuplicate);
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Retrive a row handle. Move the cursor to the end of the rowset. Retrieve the row handle again
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Cursor_Buffered::Variation_2()
{
DBCOUNTITEM cRows = 0;
DBORDINAL cCol =0;
DBORDINAL *rgColNumber =NULL;
HROW *pHRow =NULL;
DBCOUNTITEM cCount;
ULONG cColNull =0;
BYTE *pData =NULL;
BYTE *pBackEndData =NULL;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass =TEST_SKIPPED;
HRESULT hr =S_OK;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,
ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass=FALSE;
//get an array of nullable and updatable columns
GetNullableAndUpdatable(&cCol,&rgColNumber);
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get a new data buffer to set the data. The data is for first row.
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set a nullable and updatble columns to NULL
while(cCol)
{
for(cCount=0;cCount<m_cBinding;cCount++)
{
if(m_rgBinding[cCount].iOrdinal==rgColNumber[cCol-1])
{
// *(DBSTATUS *)(dwAddr+m_rgBinding[cCount].obStatus)=DBSTATUS_S_ISNULL;
STATUS_BINDING(m_rgBinding[cCount],pData)=DBSTATUS_S_ISNULL;
cColNull++;
cCount=m_cBinding;
}
}
cCol--;
}
//has to find such a column
if(!cColNull)
{
fTestPass = TRUE;
goto CLEANUP;
}
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//release the row handle
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
//allocate another buffer
pBackEndData=(BYTE *)PROVIDER_ALLOC(m_cRowSize);
if(!pBackEndData)
goto CLEANUP;
//release the rowset
ReleaseRowsetAndAccessor();
//reexecute the query
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND))
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,pBackEndData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(pBackEndData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
//free the memory used by m_pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pBackEndData,TRUE);
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Retrive a row handle. Move the cursor to the beginning of the rowset. Retrieve the row handle again.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Cursor_Buffered::Variation_3()
{
BYTE *pData =NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow =NULL;
HROW *pHRowSecond =NULL;
HROW *pHRowDuplicate =NULL;
DBPROPID rgPropertyIDs[6];
ULONG cRefCount =0;
BOOL fTestPass =TEST_SKIPPED;
HRESULT hr;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
rgPropertyIDs[3]=DBPROP_CANFETCHBACKWARDS;
rgPropertyIDs[4]=DBPROP_CANSCROLLBACKWARDS;
rgPropertyIDs[5]=DBPROP_IRowsetIdentity;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,6,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//Identity is level 0 and required
if (!m_pIRowsetIdentity)
{
goto CLEANUP;
}
//retrieve the ith row handle
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows-1,1,&cRows,&pHRow),S_OK);
//move the cursor away to the 1 row handle
TESTC_(m_pIRowset->GetNextRows(NULL,-(LONG)(m_ulTableRows)+1,-1,&cRows,&pHRowSecond),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if (S_OK!=hr && DB_S_COMMANDREEXECUTED!=hr)
{
if (DB_E_ROWSNOTRELEASED==hr)
{
//if CANHOLDROWS is TRUE and RestartPosition returns DB_E_ROWSNOTRELEASED
//then check DBPROP_QUICKRESTART.
//if DBPROP_QUICKRESTART is FALSE (command re-executed) this could be valid
//but if DBPROP_QUICKRESTART is TRUE DB_E_ROWSNOTRELEASED should not be
//returned from RestartPosition if CANHOLDROWS is requested
if(GetProperty(DBPROP_QUICKRESTART, DBPROPSET_ROWSET, (IUnknown*)m_pIRowset))
{
goto CLEANUP;
}
else
{
//if here then DBPROP_QUICKRESTART is TRUE
fTestPass = TEST_SKIPPED;
goto CLEANUP;
}
}
}
//retrieve the ith row handle again
TESTC_(m_pIRowset->GetNextRows(NULL,0,-1,&cRows,&pHRowDuplicate),S_OK);
//the two row handles should have the same value
TESTC_(m_hr=m_pIRowsetIdentity->IsSameRow(*pHRow, *pHRowDuplicate),S_OK);
//make changes to the 20th row. Make its value as the 3th row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
if(pHRowDuplicate && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDuplicate);
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Keyset_Cursor_Buffered::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// {{ TCW_TC_PROTOTYPE(Keyset_Remove_Cursor_Immediate)
//*-----------------------------------------------------------------------
//| Test Case: Keyset_Remove_Cursor_Immediate - Keyset_Remove_Curosr_Buffered
//| Created: 04/09/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Keyset_Remove_Cursor_Immediate::Init()
{
DBPROPID rgPropertyIDs[2];
BOOL fTestPass =TEST_SKIPPED;
if(!TCIRowsetChange::Init())
return FALSE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_COLLISTFROMTBL,2,rgPropertyIDs,0,NULL,NO_ACCESSOR));
fTestPass=TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Remove_Cursor_Immediate::Variation_1()
{
BYTE *pData =NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow =NULL;
HROW *pHRowSecond =NULL;
ULONG cRefCount =0;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass =TEST_SKIPPED;
IRowsetInfo *pIRowsetInfo = NULL;
ULONG cProperty = 0;
DBPROPIDSET DBPropIDSet;
DBPROPID DBPropID = DBPROP_REMOVEDELETED;
DBPROPSET *pDBPropSet = NULL;
BOOL fRemoveDeleteRows;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
HRESULT hr = S_OK;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//initialize
DBPropIDSet.guidPropertySet=DBPROPSET_ROWSET;
DBPropIDSet.cPropertyIDs=1;
DBPropIDSet.rgPropertyIDs=&DBPropID;
if(!VerifyInterface(m_pIRowset, IID_IRowsetInfo, ROWSET_INTERFACE, (IUnknown**)&pIRowsetInfo))
{
goto CLEANUP;
}
//get default value for REMOVEDELTED
TESTC_(pIRowsetInfo->GetProperties(1,&DBPropIDSet,&cProperty,&pDBPropSet),S_OK);
fRemoveDeleteRows = ((*((*pDBPropSet).rgProperties)).vValue).boolVal;
//retrieve the ith row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow,NULL),S_OK);
//make changes to the ith row. Make its value as the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),DB_E_DELETEDROW);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL, &cRefCount, NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pData);
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,NULL),S_OK);
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//do the first row first out of the loop
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow),S_OK);
//Get the data for the 1st row handle
if (fRemoveDeleteRows)
{
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
}
else
{
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),DB_E_DELETEDROW);
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
{
break;
}
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
//free the memory used by pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(m_pData);
if(pDBPropSet)
PROVIDER_FREE(pDBPropSet->rgProperties);
PROVIDER_FREE(pDBPropSet);
SAFE_RELEASE(pIRowsetInfo);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc DBPROP_CHANGEINSERTEDROWS is VARIANT_TRUE, should not see DB_E_NEWLYINSERTED
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Remove_Cursor_Immediate::Variation_2()
{
BYTE *pDataA = NULL;
BYTE *pDataB = NULL;
DBPROPID rgPropertyIDs[3];
BOOL fTestPass = TEST_SKIPPED;
HROW HRowX = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
rgPropertyIDs[2]=DBPROP_CHANGEINSERTEDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass=FALSE;
//make data buffers
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pDataA,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pDataB,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//insert a new row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pDataA,&HRowX),S_OK);
//set data,
//DBPROP_CHANGEINSERTEDROWS is VARIANT_TRUE, should not see DB_E_NEWLYINSERTED
TESTC_(SetData(HRowX,m_hAccessor,pDataB),S_OK);
fTestPass=TRUE;
//free the memory used by pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pDataA,TRUE);
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pDataB,TRUE);
CLEANUP:
if(HRowX)
{
CHECK(m_pIRowset->ReleaseRows(1,&HRowX,NULL,NULL,NULL),S_OK);
HRowX = NULL;
}
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc DBPROP_SERVERDATAONINSERT is VARIANT_TRUE, should not see DB_E_NEWLYINSERTED
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Remove_Cursor_Immediate::Variation_3()
{
BYTE *pDataX = NULL;
BYTE *pDataY = NULL;
BYTE *pDataXX = NULL;
DBPROPID rgPropertyIDs[4];
BOOL fTestPass = TEST_SKIPPED;
HROW HRowX = NULL;
HROW HRowY = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[3]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
rgPropertyIDs[2]=DBPROP_SERVERDATAONINSERT;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass=FALSE;
//create buffers
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pDataX,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pDataY,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pDataXX,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//insert a new row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pDataX,&HRowX),S_OK);
//insert a second row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pDataY,&HRowY),S_OK);
//set data on the first inserted row
//should now see this row cause SERVERDATAONINSERT is TRUE
TESTC_(SetData(HRowX,m_hAccessor,pDataXX),S_OK);
fTestPass = TEST_PASS;
CLEANUP:
if(HRowY)
{
CHECK(m_pIRowset->ReleaseRows(1,&HRowY,NULL,NULL,NULL),S_OK);
HRowY = NULL;
}
if(HRowX)
{
CHECK(m_pIRowset->ReleaseRows(1,&HRowX,NULL,NULL,NULL),S_OK);
HRowX = NULL;
}
PROVIDER_FREE(pDataX);
PROVIDER_FREE(pDataY);
PROVIDER_FREE(pDataXX);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Remove_Cursor_Immediate::Variation_4()
{
BYTE *pData =NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow =NULL;
HROW *pHRowSecond =NULL;
ULONG cRefCount =0;
DBPROPID rgPropertyIDs[2];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass =TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgUnPropertyIDs[0]=DBPROP_REMOVEDELETED;
HRESULT hr = S_OK;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow,NULL),S_OK);
//make changes to the row. Make its value as the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),DB_E_DELETEDROW);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL, &cRefCount, NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pData);
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,NULL),S_OK);
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//should be delete and here because DBPROP_REMOVEDELETED is variant_false
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),DB_E_DELETEDROW);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//Since GetData is expected to fail we do not need to release this memory
//ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)m_pData);
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
//free the memory used by pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(m_pData);
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc fetch newly deleted row
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Remove_Cursor_Immediate::Variation_5()
{
DBPROPID rgPropertyIDs[3];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
HROW *pHRow =NULL;
HROW *pHRowSecond=NULL;
DBCOUNTITEM cRows = 0;
HRESULT hr =S_OK;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
rgUnPropertyIDs[0]=DBPROP_REMOVEDELETED;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//release the rows
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get the data for the row, return DB_E_DELETEDROW
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),DB_E_DELETEDROW);
fTestPass = TEST_PASS;
CLEANUP:
//release the row handle
if (m_pIRowset)
{
//release the row handle
CHECK(m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Insert a row and check to see it (OWNINSERT is off)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Remove_Cursor_Immediate::Variation_6()
{
BYTE *pData =NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow =NULL;
DBPROPID rgPropertyIDs[4];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass =TEST_SKIPPED;
HRESULT hr = S_OK;
HRESULT RPhr = S_OK;
BOOL fFound = FALSE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_LITERALIDENTITY;
rgPropertyIDs[2]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgUnPropertyIDs[0]=DBPROP_OWNINSERT;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgPropertyIDs,1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//get a new data buffer to set the data a row.
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//insert a row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,NULL),S_OK);
//restart
RPhr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(RPhr==S_OK || RPhr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//loop through rowset searching for the inserted row
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(m_pIRowset->GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fFound = TRUE;
}
}
//OWNINSERT is FALSE, if the test sees the row, FAIL
//only if the command was not re-ececuted because if it was re-exectued the rowset is new
//and the props do not apply so see the row
if (RPhr==DB_S_COMMANDREEXECUTED)
{
if(fFound)
{
fTestPass = TRUE;
}
}
else
{
if(!fFound)
{
fTestPass = TRUE;
}
}
CLEANUP:
//free the memory used by pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Boundary cases cursor.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Remove_Cursor_Immediate::Variation_7()
{
DBPROPID rgPropertyIDs[1];
DBCOUNTITEM cRows = 0;
DBORDINAL *rgColNumber= NULL;
HROW *pHRow = NULL;
BOOL fTestPass = TEST_SKIPPED;
BYTE *pData = NULL;
HACCESSOR hAccessor = NULL;
DBORDINAL cCol = 0;
DBORDINAL ulCol = 0;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
//No accessor to be created.
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,2,g_rgPropertyIDs,NO_ACCESSOR));
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
//get an array of fixed length and updatable columns
if(!COMPARE(GetNonKeyNonBLOB(&cCol,&rgColNumber),TRUE))
{
goto CLEANUP;
}
//pick the third column. if there is not 3 columns use the last one
if(cCol<3)
{
ulCol=cCol-1;
}
else
{
ulCol=3;
}
//create an accessor to the first numeric and updatable column.
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,1,&(rgColNumber[ulCol])))
fTestPass = FALSE;
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get a new data buffer to set the data
TESTC_(FillInputBindings( m_pTable,
DBACCESSOR_ROWDATA,
m_cBinding,
m_rgBinding,
(BYTE **)&pData,
g_ulNextRow++,
m_cRowsetCols,
m_rgTableColOrds,
PRIMARY),S_OK);
//create an NULL accessor
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,&hAccessor,NULL),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,NULL),E_INVALIDARG);
TESTC_(SetData(*pHRow,NULL,pData),DB_E_BADACCESSORHANDLE);
TESTC_(SetData(NULL,m_hAccessor,pData),DB_E_BADROWHANDLE);
TESTC_(SetData(*pHRow,hAccessor,NULL),S_OK);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
PROVIDER_FREE(rgColNumber);
if (hAccessor)
{
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
}
if(m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc BSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALUE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Remove_Cursor_Immediate::Variation_8()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
void *pData = NULL;
void *pGetData = NULL;
DBPROPID rgPropertyIDs[1];
DBSTATUS dbsSecondColStatus;
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber = NULL;
DBORDINAL ulCol = 0;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,2,g_rgPropertyIDs,NO_ACCESSOR));
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
//get an array of fixed length and updatable columns
if(!COMPARE(GetNonKeyNonBLOB(&cCol,&rgColNumber),TRUE))
{
goto CLEANUP;
}
//pick the third column. if there is not 3 columns use the last one
if(cCol<3)
{
ulCol=cCol-1;
}
else
{
ulCol=3;
}
fTestPass=FALSE;
//create an accessor to the first numeric and updatable column.
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,1,&(rgColNumber[ulCol])))
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//change the second status binding to anything other than _OK or NULL
// *(DBSTATUS *)(((DWORD)pData)+ m_rgBinding[0].obStatus)=DBSTATUS_S_TRUNCATED;
STATUS_BINDING(m_rgBinding[0],pData)=DBSTATUS_S_TRUNCATED;
// keep track of colstatus
// dbsSecondColStatus = *(DBSTATUS *)(((DWORD)pData)+ m_rgBinding[0].obStatus);
dbsSecondColStatus = STATUS_BINDING(m_rgBinding[0],pData);
//set data should fail
m_hr=SetData(*pHRow,m_hAccessor,pData);
if ( !COMPARE(m_hr == DB_E_ERRORSOCCURRED || m_hr == DB_S_ERRORSOCCURRED, TRUE) )
goto CLEANUP;
TESTC_(GetStatus(pData, &(m_rgBinding[0])),DBSTATUS_E_BADSTATUS);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if ( m_hr == DB_S_ERRORSOCCURRED )
{
if(m_cBinding > 1)
{
TESTC_(GetStatus(pData, &(m_rgBinding[0])),dbsSecondColStatus);
}
}
else
{
if(m_cBinding > 1)
{
TESTC_(GetStatus(pData, &(m_rgBinding[0])),DBSTATUS_E_UNAVAILABLE);
}
//allocate memory for getting data again
pGetData=PROVIDER_ALLOC(m_cRowSize);
if(!pGetData)
goto CLEANUP;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, pGetData),S_OK);
//columns should not be changed
if(!COMPARE(CompareBuffer(pGetData, m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
{
goto CLEANUP;
}
}
fTestPass=TRUE;
CLEANUP:
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
PROVIDER_FREE(pGetData);
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc SetData not supported,
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Remove_Cursor_Immediate::Variation_9()
{
DBPROPID rgPropertyIDs[1];
DBCOUNTITEM cRows = 0;
DBORDINAL *rgColNumber= NULL;
HROW *pHRow = NULL;
BOOL fTestPass = TEST_SKIPPED;
BYTE *pData = NULL;
HACCESSOR hAccessor = NULL;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_INSERT;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,
2,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass = FALSE;
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get a new data buffer to set the data
TESTC_(FillInputBindings( m_pTable,
DBACCESSOR_ROWDATA,
m_cBinding,
m_rgBinding,
(BYTE **)&pData,
g_ulNextRow++,
m_cRowsetCols,
m_rgTableColOrds,
PRIMARY),S_OK);
//create an NULL accessor
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,&hAccessor,NULL),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),DB_E_NOTSUPPORTED);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
PROVIDER_FREE(rgColNumber);
if (hAccessor)
{
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
}
if(m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc Fetch after a deleted row
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Remove_Cursor_Immediate::Variation_10()
{
DBPROPID rgPropertyIDs[5];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
HROW *pHRow2 = NULL;
HROW *pHRow3 = NULL;
BYTE *pData = NULL;
DBCOUNTITEM cRows = 0;
HRESULT hr;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
rgPropertyIDs[2]=DBPROP_CANFETCHBACKWARDS;
rgPropertyIDs[3]=DBPROP_CANSCROLLBACKWARDS;
rgPropertyIDs[4]=DBPROP_IRowsetLocate;
rgUnPropertyIDs[0]=DBPROP_REMOVEDELETED;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,5,rgPropertyIDs,1,rgUnPropertyIDs,
ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass=FALSE;
//get the 3rd row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow3),S_OK);
//get the data for the 3rd row
TESTC_(GetData(*pHRow3,m_hAccessor,m_pData),S_OK);
//get the row just before the one deleted
TESTC_(m_pIRowset->GetNextRows(NULL,-2,1,&cRows,&pHRow2),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow2, NULL),S_OK);
//try to retrieve the row handle again. For keyset cursor, the change should
//be in place or at the end of the rowset
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow3),S_OK);
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow3),S_OK);
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow3),S_OK);
//allocation memory
pData=(BYTE *)PROVIDER_ALLOC(m_cRowSize);
//get the data for the 3rd row
TESTC_(GetData(*pHRow3,m_hAccessor,pData),S_OK);
//make sure GetData see the third row
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
}
CLEANUP:
if(pHRow2 && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow2,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow2);
if(pHRow3 && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow3,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow3);
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Keyset_Remove_Cursor_Immediate::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Keyset_Remove_Buffered)
//*-----------------------------------------------------------------------
//| Test Case: Keyset_Remove_Buffered - Keyset_Remove_Buffered
//| Created: 04/09/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Keyset_Remove_Buffered::Init()
{
DBPROPID rgPropertyIDs[3];
BOOL fTestPass = TEST_SKIPPED;
if(!TCIRowsetChange::Init())
return FALSE;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_REMOVEDELETED;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,3,rgPropertyIDs,0,NULL,NO_ACCESSOR));
fTestPass=FALSE;
COMPARE(BufferedUpdate(),TRUE);
fTestPass=TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Remove_Buffered::Variation_1()
{
BYTE *pData=NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow=NULL;
HROW *pHRowSecond=NULL;
HROW *pHRowDuplicate=NULL;
ULONG cRefCount;
DBPROPID rgPropertyIDs[7];
BOOL fTestPass=TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
rgPropertyIDs[2]=DBPROP_CANFETCHBACKWARDS;
rgPropertyIDs[3]=DBPROP_CANSCROLLBACKWARDS;
rgPropertyIDs[4]=DBPROP_IRowsetIdentity;
rgPropertyIDs[5]=DBPROP_REMOVEDELETED;
rgPropertyIDs[6]=DBPROP_OTHERUPDATEDELETE;
HRESULT hr = S_OK;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,7,rgPropertyIDs,0,NULL,
ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate)|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
//identity is level 0 and required
if (!m_pIRowsetIdentity)
goto CLEANUP;
//retrieve the ith row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//move the cursor away to the ith row
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows-2,1,&cRows,&pHRowSecond),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
//retrieve the ith row handle again
TESTC_(m_pIRowset->GetNextRows(NULL,-(LONG)m_ulTableRows+1,-1,&cRows,&pHRowDuplicate),S_OK);
//the two row handles should have the same value
TESTC_(m_hr=m_pIRowsetIdentity->IsSameRow(*pHRow, *pHRowDuplicate),S_OK);
//make changes to the ith row. Make its value as the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//make sure the change is visiable throught the other row handle
TESTC_(GetData(*pHRowDuplicate,m_hAccessor,m_pData),S_OK);
//make sure GetData should be able to see the change on cursor based update
if(!COMPARE(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
{
goto CLEANUP;
}
//free the memory used by m_pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)m_pData);
//free the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL, &cRefCount, NULL),S_OK);
PROVIDER_FREE(pHRowDuplicate);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL, &cRefCount, NULL),S_OK);
PROVIDER_FREE(pHRow);
//try to retrieve the row handle again. For keyset cursor, the change should
//be in place or at the end of the rowset
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
//free the memory used by m_pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)m_pData);
//release the rowset
ReleaseRowsetAndAccessor();
//reexecute the query
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
if(pHRowDuplicate && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowDuplicate,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDuplicate);
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Retrieve row, update row update pending don't release handle, GetData RETURNPENDINGINSERTS FALSE
// don't release the row handle, call GetData to See the row
// eventhough RETURNPENDINGINSERTS is FALSE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Remove_Buffered::Variation_2()
{
BYTE *pData = NULL;
DBCOUNTITEM cRows = 0;
HROW hRow = NULL;
HROW *pHRow = NULL;
DBPROPID rgPropertyIDs[4];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass =TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_OTHERUPDATEDELETE;
rgUnPropertyIDs[0]=DBPROP_CANHOLDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_INSERT;;
HRESULT hr = S_OK;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,4,rgPropertyIDs,1, rgUnPropertyIDs,
ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate)|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
//identity is level 0 and required
if (!m_pIRowsetIdentity)
{
goto CLEANUP;
}
//make a buffer
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//Now Insert the row
TESTC_(m_pIRowsetChange->InsertRow(NULL, m_hAccessor,pData, &hRow),S_OK)
//release the row
if(hRow)
{
CHECK(m_pIRowset->ReleaseRows(1,&hRow,NULL,NULL,NULL),S_OK);
hRow = NULL;
}
//row still not released until pending change is trasmitted to the data source
TESTC_(m_pIRowset->RestartPosition(NULL),DB_E_ROWSNOTRELEASED);
//transmit the changes, now everythign should work ok
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),S_OK);
//restart
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//find the row
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
{
break;
}
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
if(hRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,&hRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Error should NULL out hRow
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Remove_Buffered::Variation_3()
{
BYTE *pData = NULL;
HROW hRow = NULL;
HROW hRow2 = NULL;
DBPROPID rgPropertyIDs[4];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass =TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_OTHERUPDATEDELETE;
rgUnPropertyIDs[0]=DBPROP_CANHOLDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_INSERT;;
HRESULT hr = S_OK;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,4,rgPropertyIDs,1, rgUnPropertyIDs,
ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate)|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
//identity is level 0 and required
if (!m_pIRowsetIdentity)
{
goto CLEANUP;
}
//make a buffer
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//Now Insert the row with ERROR
TESTC_(m_pIRowsetChange->InsertRow(NULL, m_hAccessor,NULL, &hRow),E_INVALIDARG)
//this has to be NULLed out on error from InsertRow
if(hRow)
{
goto CLEANUP;
}
//Now Insert the row with ERROR
TESTC_(m_pIRowsetChange->InsertRow(NULL, 0,pData, &hRow),DB_E_BADACCESSORHANDLE)
//this has to be NULLed out on error from InsertRow
if(hRow)
{
goto CLEANUP;
}
//Now Insert the row
TESTC_(m_pIRowsetChange->InsertRow(NULL, m_hAccessor,pData, &hRow),S_OK)
//Now Insert the row in error
TESTC_(m_pIRowsetChange->InsertRow(NULL, m_hAccessor,pData, &hRow2),DB_E_ROWSNOTRELEASED)
//this has to be NULLed out on error from InsertRow
if(hRow2)
{
goto CLEANUP;
}
fTestPass = TEST_PASS;
CLEANUP:
if(hRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,&hRow,NULL,NULL,NULL),S_OK);
}
if(hRow2 && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,&hRow2,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc DB_E_ROWSNOTRELEASED
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Keyset_Remove_Buffered::Variation_4()
{
DBPROPID rgPropertyIDs[3];
DBPROPID rgUnPropertyIDs[2];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgRowStatus[1];
HRESULT hr = S_OK;
HROW *pHRow = NULL;
DBCOUNTITEM cRows = 0;
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0] = DBPROP_IRowsetChange;
rgPropertyIDs[1] = DBPROP_IRowsetUpdate;
rgPropertyIDs[2] = DBPROP_REMOVEDELETED;
rgUnPropertyIDs[0] = DBPROP_LITERALIDENTITY;
rgUnPropertyIDs[1] = DBPROP_CANHOLDROWS;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,2,rgUnPropertyIDs,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_pIRowsetUpdate || (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
//retrieve row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow,rgRowStatus),S_OK);
COMPARE(rgRowStatus[0], DBROWSTATUS_S_OK);
//release the row handle
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//row still not released until pending change is trasmitted to the data source
TESTC_(m_pIRowset->RestartPosition(NULL),DB_E_ROWSNOTRELEASED);
//transmitt the changes, now everything should work ok
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),S_OK);
//restart position.
hr = m_pIRowset->RestartPosition(NULL);
CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE);
fTestPass = TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Keyset_Remove_Buffered::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Dynamic_Cursor_Buffered)
//*-----------------------------------------------------------------------
//| Test Case: Dynamic_Cursor_Buffered - Dynamic_Cursor_Buffered
//| Created: 04/09/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Dynamic_Cursor_Buffered::Init()
{
DBPROPID rgPropertyIDs[4];
BOOL fTestPass=TEST_SKIPPED;
if(!TCIRowsetChange::Init())
return FALSE;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_OTHERINSERT;
rgPropertyIDs[2]=DBPROP_CANSCROLLBACKWARDS;
rgPropertyIDs[3]=DBPROP_CANFETCHBACKWARDS;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,4,rgPropertyIDs,
0,NULL,NO_ACCESSOR));
fTestPass=FALSE;
COMPARE(BufferedUpdate(),TRUE);
COMPARE(GetProp(DBPROP_CANSCROLLBACKWARDS),TRUE);
COMPARE(GetProp(DBPROP_CANFETCHBACKWARDS),TRUE);
fTestPass=TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Retrieve a row handle, update a row to be the first row in the row set with some columns set to NULL, and call GetData to see
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Dynamic_Cursor_Buffered::Variation_1()
{
DBCOUNTITEM cRows = 0;
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber = NULL;
HROW *pHRow = NULL;
ULONG cCount = 0;
BYTE *pData = NULL;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass = TRUE;
HRESULT hr = S_OK;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_OTHERINSERT;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate)|| (!m_cBinding))
goto CLEANUP;
fTestPass=FALSE;
//get an array of nullable and updatable columns
GetNullableAndUpdatable(&cCol,&rgColNumber);
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get a new data buffer to set the data. The data is for first row.
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set a first nullable and updatble columns to NULL
if(cCol)
{
for(cCount=0;cCount<m_cBinding;cCount++)
{
if(m_rgBinding[cCount].iOrdinal==rgColNumber[0])
{
// *(ULONG *)(dwAddr+m_rgBinding[cCount].obStatus)=DBSTATUS_S_ISNULL;
STATUS_BINDING(m_rgBinding[cCount],pData)=DBSTATUS_S_ISNULL;
break;
}
}
}
//has to find such a column
if(cCount==m_cBinding)
goto CLEANUP;
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//get the data for the row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//make sure GetData should be able to see the change
if(!COMPARE(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
//free the memory used by m_pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)m_pData);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
//release the rowset
ReleaseRowsetAndAccessor();
//reexecute the query
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
//free the memory used by m_pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)m_pData);
break;
}
//free the memory used by m_pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)m_pData);
}
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Retrive a row handle. Move the cursor to the end of the rowset. Retrieve the row handle again
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Dynamic_Cursor_Buffered::Variation_2()
{
BYTE *pData=NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow=NULL;
DBPROPID rgPropertyIDs[4];
BOOL fTestPass=TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_OTHERINSERT;
rgPropertyIDs[2]=DBPROP_CANSCROLLBACKWARDS;
rgPropertyIDs[3]=DBPROP_CANFETCHBACKWARDS;
HRESULT hr = S_OK;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,4,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate) || (!m_cBinding))
goto CLEANUP;
fTestPass=FALSE;
//retrieve the 5th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,4,1,&cRows,&pHRow),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL, NULL),S_OK);
//retrieve another row handle
TESTC_(m_pIRowset->GetNextRows(NULL,-1,-1,&cRows,&pHRow),S_OK);
if(!COMPARE(cRows, 1))
goto CLEANUP;
//make changes to the 5th row. Make its value as the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//make sure the change is visiable throught the other row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),S_OK);
//make sure GetData should be able to see the change
if(!COMPARE(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
//free the memory used by m_pData
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)m_pData);
//release the rowset
ReleaseRowsetAndAccessor();
//reexecute the query
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,0,NULL,
ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Retrive a row handle. Move the cursor to the beginning of the rowset. Retrieve the row handle again.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Dynamic_Cursor_Buffered::Variation_3()
{
BYTE *pData=NULL;
BYTE *pGetData=NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow=NULL;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass=TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_OTHERINSERT;
HRESULT hr = S_OK;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate) || (!m_cBinding))
goto CLEANUP;
fTestPass=FALSE;
//allocation memory
pGetData=(BYTE *)PROVIDER_ALLOC(m_cRowSize);
if(!pGetData)
goto CLEANUP;
//retrieve the 3rd row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//Keep a copy of the original data
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//make changes to the 3rdth row. Make its value as the 1st row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//make sure the change is visiable throught the other row handle
TESTC_(GetData(*pHRow,m_hAccessor,pGetData),S_OK);
//make sure GetData should be able to see the changed data
//all I need to do is check for the 1st long column
if(!COMPARE(CompareBuffer(pGetData,pData,1,&(m_rgBinding[3]),m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
//undo the change
TESTC_(m_pIRowsetUpdate->Undo(NULL,1,pHRow, NULL, NULL, NULL),S_OK);
//make sure the change is visiable throught the other row handle
TESTC_(GetData(*pHRow,m_hAccessor,pGetData),S_OK);
//make sure GetData should be able to see the original data
if(!COMPARE(CompareBuffer(m_pData,pGetData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
//free the memory used by pGetData
// ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pGetData);
//free the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,pGetData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pGetData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pData);
PROVIDER_FREE(pGetData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Dynamic_Cursor_Buffered::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// {{ TCW_TC_PROTOTYPE(Visible_Forward_Cursor)
//*-----------------------------------------------------------------------
//| Test Case: Visible_Forward_Cursor - visibility of row handles
//| Created: 04/11/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Visible_Forward_Cursor::Init()
{
return TCIRowsetChange::Init();
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc In immediate update mode, call SetData to change a non-key column. Make sure the update is visible after RestartPosition.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Visible_Forward_Cursor::Variation_1()
{
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
BYTE *pData = NULL;
DBPROPID rgDBPropID[1];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr = S_OK;
IRowsetInfo *pIRowsetInfo = NULL;
ULONG cProperty = 0;
DBPROPIDSET DBPropIDSet;
DBPROPID DBPropID = DBPROP_REMOVEDELETED;
DBPROPSET *pDBPropSet = NULL;
BOOL fRemoveDeleteRows;
rgDBPropID[0] = DBPROP_IRowsetChange;
//create a rowset and create a read/write accessor. Forward only binding
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgDBPropID,
2,g_rgPropertyIDs,NO_ACCESSOR));
//Create a new accessor that binds only to the changed column
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass = FALSE;
//initialize
DBPropIDSet.guidPropertySet=DBPROPSET_ROWSET;
DBPropIDSet.cPropertyIDs=1;
DBPropIDSet.rgPropertyIDs=&DBPropID;
if(!VerifyInterface(m_pIRowset, IID_IRowsetInfo, ROWSET_INTERFACE, (IUnknown**)&pIRowsetInfo))
{
goto CLEANUP;
}
//get default value for REMOVEDELTED
TESTC_(pIRowsetInfo->GetProperties(1,&DBPropIDSet,&cProperty,&pDBPropSet),S_OK);
fRemoveDeleteRows = ((*((*pDBPropSet).rgProperties)).vValue).boolVal;
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get the data
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//create a new data buffer to set the data for the numeric and updatable
//column
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//Release the row
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//restart position
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//do the first row first out of the loop
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow),S_OK);
//Get the data for the 1st row handle
if (fRemoveDeleteRows)
{
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
goto CLEANUP;
}
}
else
{
hr=GetData(*pHRow,m_hAccessor,m_pData);
if (S_OK==hr)
{
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
goto CLEANUP;
}
}
else
{
//this could be DB_E_DELETEDROW if DBPROP_REMOVEDELETED is FALSE and
//backend does delete/insert for its updates
if (DB_E_DELETEDROW!=hr)
{
goto CLEANUP;
}
}
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pData);
PROVIDER_FREE(m_pData);
if(pDBPropSet)
PROVIDER_FREE(pDBPropSet->rgProperties);
PROVIDER_FREE(pDBPropSet);
SAFE_RELEASE(pIRowsetInfo);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc In buffered update mode, call SetData to change a non-key column. Make sure the update is visible after RestartPosition.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Visible_Forward_Cursor::Variation_2()
{
DBCOUNTITEM cRows = 0;
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber = NULL;
HROW *pHRow = NULL;
BYTE *pData = NULL;
DBCOUNTITEM cUpdatedRows = 0;
HROW *rgUpdatedRows = NULL;
ULONG cRefCount = 0;
DBPROPID rgDBPropIDSet[1];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr = S_OK;
IRowsetInfo *pIRowsetInfo = NULL;
ULONG cProperty = 0;
DBPROPIDSET DBPropIDSet;
DBPROPID DBPropID = DBPROP_REMOVEDELETED;
DBPROPSET *pDBPropSet = NULL;
BOOL fRemoveDeleteRows;
rgDBPropIDSet[0] = DBPROP_IRowsetUpdate;
//create a rowset and create a read/write accessor. Forward only binding
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_COLLISTFROMTBL,1,rgDBPropIDSet,
2,g_rgPropertyIDs,NO_ACCESSOR));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate) || (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//get an array of numeric and updatable columns
GetUpdatableCols(&cCol,&rgColNumber);
//has to find such a column
if(!cCol)
goto CLEANUP;
//Create a new accessor that binds only to the changed column
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,cCol,rgColNumber))
//initialize
DBPropIDSet.guidPropertySet=DBPROPSET_ROWSET;
DBPropIDSet.cPropertyIDs=1;
DBPropIDSet.rgPropertyIDs=&DBPropID;
if(!VerifyInterface(m_pIRowset, IID_IRowsetInfo, ROWSET_INTERFACE, (IUnknown**)&pIRowsetInfo))
{
goto CLEANUP;
}
//get default value for REMOVEDELTED
TESTC_(pIRowsetInfo->GetProperties(1,&DBPropIDSet,&cProperty,&pDBPropSet),S_OK);
fRemoveDeleteRows = ((*((*pDBPropSet).rgProperties)).vValue).boolVal;
//get the third row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get the data
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//create a new data buffer to set the data for the numeric and updatable
//column
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//Release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,&cUpdatedRows,&rgUpdatedRows,NULL),S_OK);
//update should be successful and no row handle should be returned
//as the row handle is released with pending change status
COMPARE(cUpdatedRows, 1);
//release the rgUpdatedRows
TESTC_(m_pIRowset->ReleaseRows(1,rgUpdatedRows,NULL, &cRefCount, NULL),S_OK);
//restart position
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//do the first row first out of the loop
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow),S_OK);
//Get the data for the 1st row handle
if (fRemoveDeleteRows)
{
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
goto CLEANUP;
}
}
else
{
hr=GetData(*pHRow,m_hAccessor,m_pData);
if (S_OK==hr)
{
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
goto CLEANUP;
}
}
else
{
//this could be DB_E_DELETEDROW if DBPROP_REMOVEDELETED is FALSE and
//backend does delete/insert for its updates
if (DB_E_DELETEDROW!=hr)
{
goto CLEANUP;
}
}
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pData);
PROVIDER_FREE(m_pData);
PROVIDER_FREE(rgUpdatedRows);
if(pDBPropSet)
PROVIDER_FREE(pDBPropSet->rgProperties);
PROVIDER_FREE(pDBPropSet);
SAFE_RELEASE(pIRowsetInfo);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Visible_Forward_Cursor::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Visible_Static_Cursor)
//*-----------------------------------------------------------------------
//| Test Case: Visible_Static_Cursor - visibility of row handles
//| OWNUPDATEDELETE is VARIANT_TRUE, changes are visible to self
//| Created: 04/11/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Visible_Static_Cursor::Init()
{
return TCIRowsetChange::Init();
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc In immediate update mode, call SetData to change a non key column.
// Move the cursor to the end of the rowset. RestartPosition
//
// @rdesc TEST_PASS or TEST_FAIL
//
// @mfunc In immediate update mode, call SetData to change a non key column. Move the cursor to the end of the rowset. RestartPosition
int Visible_Static_Cursor::Variation_1()
{
DBCOUNTITEM cRows = 0;
DBORDINAL cCol;
DBORDINAL *rgColNumber =NULL;
HROW *pHRow =NULL;
BYTE *pData =NULL;
BYTE *pBackEndData =NULL;
DBPROPID rgPropertyIDs[3];
BOOL fTestPass =TEST_SKIPPED;
BYTE *pDataNoFetch = NULL;
HRESULT hrRP = S_OK;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetLocate;
rgPropertyIDs[2]=DBPROP_OWNUPDATEDELETE;
HRESULT hr = S_OK;
//create a rowset and create a read/write accessor. Forward only binding
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,3,rgPropertyIDs,
2,g_rgPropertyIDs,NO_ACCESSOR));
//get an array of numeric and updatable columns
GetNumericAndUpdatable(&cCol,&rgColNumber);
//has to find such a column
if(!cCol)
goto CLEANUP;
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
//Create a new accessor that binds only to the changed column
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,cCol,rgColNumber))
//get the third row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get the data
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
if(!(pDataNoFetch=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//create a new data buffer to set the data for the numeric and updatable
//column
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//make sure the change is visiable throught the other row handle
TESTC_(GetData(*pHRow,m_hAccessor,pDataNoFetch),S_OK);
//make sure GetData should be able to see the change, row has not been refetched
if(!COMPARE(CompareBuffer(pDataNoFetch,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
//Release the row handle
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//restart position
hrRP=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hrRP==S_OK || hrRP==DB_S_COMMANDREEXECUTED, TRUE))
goto CLEANUP;
if(!(pBackEndData=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,pBackEndData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
//OWNUPADTEDELETE is on
if(CompareBuffer(pBackEndData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pBackEndData,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pData);
PROVIDER_FREE(pDataNoFetch);
PROVIDER_FREE(pBackEndData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc In buffered update mode, call SetData to change a non key column. Move the cursor to the end of the rowset. RestartPosition
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Visible_Static_Cursor::Variation_2()
{
DBCOUNTITEM cRows = 0;
DBORDINAL cCol;
DBORDINAL *rgColNumber =NULL;
HROW *pHRow =NULL;
BYTE *pData =NULL;
BYTE *pBackEndData =NULL;
DBPROPID rgPropertyIDs[4];
BOOL fTestPass =TEST_SKIPPED;
HRESULT hrRP =S_OK;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_IRowsetLocate;
rgPropertyIDs[2]=DBPROP_IRowsetChange;
rgPropertyIDs[3]=DBPROP_OWNUPDATEDELETE;
HRESULT hr = S_OK;
//create a rowset and create a read/write accessor. Forward only binding
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_COLLISTFROMTBL,4,rgPropertyIDs,
2,g_rgPropertyIDs,NO_ACCESSOR));
//get an array of numeric and updatable columns
GetNumericAndUpdatable(&cCol,&rgColNumber);
//has to find such a column
if(!cCol)
goto CLEANUP;
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//Create a new accessor that binds only to the changed column
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,cCol,rgColNumber))
//get the third row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get the data
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//create a new data buffer to set the data for the numeric and updatable
//column
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//Release the row handle
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),S_OK);
//restart position
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hrRP==S_OK || hrRP==DB_S_COMMANDREEXECUTED, TRUE))
goto CLEANUP;
//allocate memory
if(!(pBackEndData=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(GetData(*pHRow,m_hAccessor,pBackEndData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
//OWNUPADTEDELETE is on
if(CompareBuffer(pBackEndData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pBackEndData,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pData);
PROVIDER_FREE(pBackEndData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc In immediate update mode. Create two rowsets on the same table. One rowset changes a key value. The other rowset should no
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Visible_Static_Cursor::Variation_3()
{
HROW *pHRow = NULL;
HROW *pHRowSecond = NULL;
DBCOUNTITEM cRows = 0;
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber = NULL;
void *pData = NULL;
void *pDataSecond = NULL;
IRowsetInfo *pIRowsetInfo = NULL;
ICommand *pICommand = NULL;
IUnknown *pIRowset = NULL;
DBPROPID rgPropertyIDs[3];
BOOL fTestPass = TEST_SKIPPED;
BYTE *pDataNoFetch = NULL;
HRESULT hrRP = S_OK;
HRESULT hr = S_OK;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_OWNUPDATEDELETE;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,3,rgPropertyIDs,2,g_rgPropertyIDs,NO_ACCESSOR));
//get an array of numeric and updatable columns
GetNumericAndUpdatable(&cCol,&rgColNumber);
//has to find such a column
if(!cCol)
goto CLEANUP;
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass = FALSE;
//release the row set
ReleaseRowsetAndAccessor();
if(!m_pIDBCreateCommand)
return TEST_PASS;
//create an accessor on the command object on the numeric and updatable column only
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,3,rgPropertyIDs,2,g_rgPropertyIDs,
ON_COMMAND_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, USE_COLS_TO_BIND_ARRAY,
FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,rgColNumber));
//get the row handle
TESTC_(m_pIRowset->GetNextRows(NULL,9,1,&cRows,&pHRow),S_OK);
//get a copy of the data on row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
if(!(pDataNoFetch=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//create a new data buffer to set the data for the numeric and updatable
//column
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,1,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//create another rowset object on the same command object//QI for IRowsetInfo pointer
TESTC_(m_pIAccessor->QueryInterface(IID_IRowsetInfo, (LPVOID *)&pIRowsetInfo),S_OK);
//get the ICommand pointer
TESTC_(pIRowsetInfo->GetSpecification(IID_ICommand,(IUnknown **)&pICommand),S_OK);
//exeute the same command object
TESTC_(pICommand->Execute(NULL,IID_IRowset,NULL,NULL,&pIRowset),S_OK);
//set data on the first rowset
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
//get data on the first rowset.
TESTC_(GetData(*pHRow,m_hAccessor,pDataNoFetch),S_OK);
//make sure GetData should be able to see the change, row has not been refetched
if(!COMPARE(CompareBuffer(pDataNoFetch,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
//restart position
hrRP=((IRowset *)(pIRowset))->RestartPosition(NULL);
if(!CHECK(hrRP==S_OK || hrRP==DB_S_COMMANDREEXECUTED, TRUE))
goto CLEANUP;
if(!(pDataSecond=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
while (S_OK==(hr = ((IRowset *)(pIRowset))->GetNextRows(NULL,0,1,&cRows, &pHRowSecond)) || hr == DB_S_ENDOFROWSET)
{
if( cRows ==0)
{
break;
}
//Get the data for the ith row handle
TESTC_(((IRowset *)(pIRowset))->GetData(*pHRowSecond,m_hAccessor,pDataSecond),S_OK);
TESTC_(((IRowset *)(pIRowset))->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
//if the command was re-executed the change will be visible
if (DB_S_COMMANDREEXECUTED==hrRP)
{
//the second rowset should see the change if rexeccuted
if(CompareBuffer(pDataSecond,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pDataSecond,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
else
{
//the second rowset should NOT see the change (it should see old data)
if(CompareBuffer(pDataSecond,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
if(CompareBuffer(pDataSecond,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
odtLog << "Error - this row should not be visible"<<ENDL;
break;
}
}
}
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(((IRowset *)(pIRowset))->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(pData);
PROVIDER_FREE(pDataNoFetch);
PROVIDER_FREE(pDataSecond);
SAFE_RELEASE(pIRowsetInfo);
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pICommand);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Visible_Static_Cursor::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Visible_Keyset_Command_Cursor)
//*-----------------------------------------------------------------------
//| Test Case: Visible_Keyset_Command_Cursor - Visible_Keyset_Command_Cursor
//| Created: 04/15/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Visible_Keyset_Command_Cursor::Init()
{
DBPROPID rgPropertyIDs[2];
BOOL fTestPass=TEST_SKIPPED;
if(!TCIRowsetChange::Init())
return FALSE;
if(!m_pIDBCreateCommand)
{
odtLog << "Command Not Supported Skipping Variations"<<ENDL;
return TEST_SKIPPED;
}
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,0,NULL,NO_ACCESSOR));
fTestPass = FALSE;
COMPARE(BufferedUpdate(), FALSE);
fTestPass = TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc In immediate update mode. Create two rowsets on the same table. The second rowset change a row
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Visible_Keyset_Command_Cursor::Variation_1()
{
HROW *pHRow=NULL;
HROW *pHRowSecond=NULL;
HROW *pHRowLast=NULL;
DBCOUNTITEM cRows = 0;
void *pData=NULL;
void *pDataSecond=NULL;
IRowsetInfo *pIRowsetInfo=NULL;
ICommand *pICommand=NULL;
IUnknown *pIRowset=NULL;
IRowsetChange *pIRowsetChange=NULL;
DBROWSTATUS DBRowStatus;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass=TEST_SKIPPED;
HRESULT hr = S_OK;
rgPropertyIDs[0]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
//create a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
0,NULL,ON_COMMAND_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS, UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass = FALSE;
//get the 10th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,9,1,&cRows,&pHRow),S_OK);
//get a copy of the data on 10th row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//create a new data buffer to set the data for all updatable columns
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//create another rowset object on the same command object
TESTC_(m_pIAccessor->QueryInterface(IID_IRowsetInfo, (LPVOID *)&pIRowsetInfo),S_OK);
if(!m_pIDBCreateCommand)
{
fTestPass=TRUE;
goto CLEANUP;
}
//get the ICommand pointer
TESTC_(pIRowsetInfo->GetSpecification(IID_ICommand,(IUnknown **)&pICommand),S_OK);
//exeute the same command object
TESTC_(pICommand->Execute(NULL,IID_IRowset,NULL,NULL,&pIRowset),S_OK);
//set data on the first rowset
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
//allocat memory of pDataSecond
if(!(pDataSecond=PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//retrieve the 10th row handle on the second rowset
TESTC_(((IRowset*)pIRowset)->GetNextRows(NULL,9,1,&cRows, &pHRowSecond),S_OK);
//get data on the second rowset. Share the same accessor on the command
if(SUCCEEDED(m_hr=(((IRowset*)pIRowset)->GetData(*pHRowSecond,m_hAccessor,pDataSecond))))
{
//the second rowset should see the change
if(CompareBuffer(pDataSecond, pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY))
{
fTestPass=TRUE;
goto CLEANUP;
}
}
else
{
//the GetData realized the row is deleted
if(!COMPARE(m_hr, DB_E_DELETEDROW))
goto CLEANUP;
}
TESTC_(((IRowset*)pIRowset)->ReleaseRows(1, pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,&DBRowStatus),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(((IRowset *)(pIRowset))->ReleaseRows(1,pHRowSecond,NULL,NULL,&DBRowStatus),S_OK);
PROVIDER_FREE(pHRowSecond);
if(pHRowLast && m_pIRowset)
CHECK(((IRowset *)(pIRowset))->ReleaseRows(1,pHRowLast,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowLast);
PROVIDER_FREE(pData);
PROVIDER_FREE(pDataSecond);
SAFE_RELEASE(pIRowsetInfo);
SAFE_RELEASE(pIRowsetChange);
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pICommand);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc In immediate update mode. Create two rowsets on the same table. The second rowset change a non key column.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Visible_Keyset_Command_Cursor::Variation_2()
{
HROW *pHRow=NULL;
HROW *pHRowSecond=NULL;
DBCOUNTITEM cRows = 0;
DBORDINAL cCol;
DBORDINAL *rgColNumber=NULL;
void *pData=NULL;
void *pDataSecond=NULL;
IRowsetInfo *pIRowsetInfo=NULL;
ICommand *pICommand=NULL;
IUnknown *pIRowset=NULL;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass=TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_COLLISTFROMTBL,2,rgPropertyIDs,
0,NULL,NO_ACCESSOR));
//get an array of numeric and updatable columns
GetNumericAndUpdatable(&cCol,&rgColNumber);
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass = FALSE;
//has to find such a column
if(!cCol)
goto CLEANUP;
ReleaseRowsetAndAccessor();
//create an accessor on the command object on the numeric and updatable column only
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_COLLISTFROMTBL,2,rgPropertyIDs,
0,NULL,ON_COMMAND_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,rgColNumber));
//get the 10th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,9,1,&cRows,&pHRow),S_OK);
//get a copy of the data on 10th row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//create a new data buffer to set the data for the numeric and updatablecolumn
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,1,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//create another rowset object on the same command object
TESTC_(m_pIAccessor->QueryInterface(IID_IRowsetInfo, (LPVOID *)&pIRowsetInfo),S_OK);
if(!m_pIDBCreateCommand)
{
fTestPass=TRUE;
goto CLEANUP;
}
//get the ICommand pointer
TESTC_(pIRowsetInfo->GetSpecification(IID_ICommand,(IUnknown **)&pICommand),S_OK);
//exeute the same command object
TESTC_(pICommand->Execute(NULL,IID_IRowset,NULL,NULL,&pIRowset),S_OK);
//set data on the first rowset
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
//allocat memory of pDataSecond
if(!(pDataSecond=PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//retrieve the 10th row handle on the second rowset
TESTC_(((IRowset*)pIRowset)->GetNextRows(NULL,9,1,&cRows,&pHRowSecond),S_OK);
//get data on the second rowset. Share the same accessor on the command
TESTC_(((IRowset*)pIRowset)->GetData(*pHRowSecond,m_hAccessor,pDataSecond),S_OK);
//the second rowset should see the change
if(COMPARE(CompareBuffer(pDataSecond, pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(((IRowset *)(pIRowset))->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(pData);
PROVIDER_FREE(pDataSecond);
SAFE_RELEASE(pIRowsetInfo);
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pICommand);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc In buffered update mode. Create two rowsets on the same table. The second rowset change a row
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Visible_Keyset_Command_Cursor::Variation_3()
{
HROW *pHRow=NULL;
HROW *pHRowSecond=NULL;
HROW *pHRowLast=NULL;
DBCOUNTITEM cRows = 0;
void *pData=NULL;
void *pDataSecond=NULL;
IRowsetInfo *pIRowsetInfo=NULL;
ICommand *pICommand=NULL;
IUnknown *pIRowset=NULL;
IRowsetChange *pIRowsetChange=NULL;
DBROWSTATUS DBRowStatus;
DBROWSTATUS *pDBRowStatus=NULL;
DBPROPID rgPropertyIDs[3];
BOOL fTestPass=TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
//create a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
0,NULL,ON_COMMAND_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//get the 3th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get a copy of the data on 3rd row
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//create a new data buffer to set the data for all updatable columns
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//create another rowset object on the same command object
TESTC_(m_pIAccessor->QueryInterface(IID_IRowsetInfo, (LPVOID *)&pIRowsetInfo),S_OK);
//get the ICommand pointer
TESTC_(pIRowsetInfo->GetSpecification(IID_ICommand,(IUnknown **)&pICommand),S_OK);
//exeute the same command object
TESTC_(pICommand->Execute(NULL,IID_IRowset,NULL,NULL,&pIRowset),S_OK);
//set data on the first rowset
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,&pDBRowStatus),S_OK);
//allocat memory of pDataSecond
if(!(pDataSecond=PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//for keyset driven cursor with cursor based update, the update of a new key
//value should be visible as a delete only.
//retrieve the 3rd row handle on the second rowset
TESTC_(((IRowset*)pIRowset)->GetNextRows(NULL,2,1,&cRows, &pHRowSecond),S_OK);
//get data on the second rowset. Share the same accessor on the command
if(SUCCEEDED(m_hr=((IRowset *)(pIRowset))->GetData(*pHRowSecond,m_hAccessor,pDataSecond)))
{
//the second rowset should see the change
if(CompareBuffer(pDataSecond, pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY))
{
fTestPass=TRUE;
goto CLEANUP;
}
}
else
{
//the GetData realized the row is deleted( for sql providers)
if(!COMPARE(m_hr, DB_E_DELETEDROW))
goto CLEANUP;
}
//release the row handle
TESTC_(((IRowset*)pIRowset)->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
fTestPass=TRUE;
CLEANUP:
//free the memory
PROVIDER_FREE(pDBRowStatus);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL, &DBRowStatus, NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(((IRowset *)(pIRowset))->ReleaseRows(1,pHRowSecond,NULL, &DBRowStatus, NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
if(pHRowLast && m_pIRowset)
CHECK(((IRowset *)(pIRowset))->ReleaseRows(1,pHRowLast,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowLast);
PROVIDER_FREE(pData);
PROVIDER_FREE(pDataSecond);
SAFE_RELEASE(pIRowsetInfo);
SAFE_RELEASE(pIRowsetChange);
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pICommand);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc In buffered update mode. Create two rowsets on the same table. The second rowset change a non key column.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Visible_Keyset_Command_Cursor::Variation_4()
{
return TEST_PASS;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Visible_Keyset_Command_Cursor::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Visible_Dynamic_Command_Cursor)
//*-----------------------------------------------------------------------
//| Test Case: Visible_Dynamic_Command_Cursor - Visible_Dynamic_Command_Cursor
//| Created: 04/15/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Visible_Dynamic_Command_Cursor::Init()
{
DBPROPID rgPropertyIDs[2];
BOOL fTestPass=TEST_SKIPPED;
if(!TCIRowsetChange::Init())
return FALSE;
if(!m_pIDBCreateCommand)
goto CLEANUP;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERINSERT;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_COLLISTFROMTBL,2,rgPropertyIDs,
0,NULL,NO_ACCESSOR));
fTestPass = FALSE;
COMPARE(BufferedUpdate(),FALSE);
fTestPass = TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc In immediate update mode. Create two rowsets on the same table. The second rowset change a row
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Visible_Dynamic_Command_Cursor::Variation_1()
{
HROW *pHRow=NULL;
HROW *pHRowSecond=NULL;
DBCOUNTITEM cRows = 0;
void *pData=NULL;
void *pDataSecond=NULL;
IRowsetInfo *pIRowsetInfo=NULL;
ICommand *pICommand=NULL;
IUnknown *pIRowset=NULL;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass=TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_OTHERINSERT;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
//create a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
0,NULL,ON_COMMAND_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass=FALSE;
//get the third row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//create a new data buffer to set the data for all updatable columns
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//create another rowset object on the same command object
TESTC_(m_pIAccessor->QueryInterface(IID_IRowsetInfo, (LPVOID *)&pIRowsetInfo),S_OK);
//get the ICommand pointer
TESTC_(pIRowsetInfo->GetSpecification(IID_ICommand,(IUnknown **)&pICommand),S_OK);
//exeute the same command object
TESTC_(pICommand->Execute(NULL,IID_IRowset,NULL,NULL,&pIRowset),S_OK);
//set data on the 2rd rowset
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
TESTC_(((IRowset*)m_pIRowset)->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//allocat memory of pDataSecond
if(!(pDataSecond=PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//retrieve the row handle
//restartposition
m_hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(m_hr==S_OK || m_hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
while(((IRowset*)pIRowset)->GetNextRows(NULL,0,1,&cRows, &pHRowSecond) == S_OK)
{
if(cRows == 0)
break;
//Get the data for the xth row handle
TESTC_(((IRowset*)pIRowset)->GetData(*pHRowSecond,m_hAccessor,pDataSecond),S_OK);
TESTC_(((IRowset*)pIRowset)->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
//make sure GetData should be able to see the change
//the second rowset should see the change.
if(CompareBuffer(pDataSecond, pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
//release memory
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pDataSecond, TRUE);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && pIRowset)
CHECK(((IRowset *)(pIRowset))->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
SAFE_RELEASE(pIRowsetInfo);
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pICommand);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc In buffered update mode. Create two rowsets on the same table. The second rowset change a non-key column.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Visible_Dynamic_Command_Cursor::Variation_2()
{
HROW *pHRow=NULL;
HROW *pHRowSecond=NULL;
DBCOUNTITEM cRows = 0;
DBORDINAL cCol;
DBORDINAL *rgColNumber=NULL;
void *pData=NULL;
void *pDataSecond=NULL;
IRowsetInfo *pIRowsetInfo=NULL;
ICommand *pICommand=NULL;
IUnknown *pIRowset=NULL;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass=TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_OTHERINSERT;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
// 0,NULL,NO_ACCESSOR));
0,NULL,NO_ACCESSOR,TRUE));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate)|| (!m_cBinding))
goto CLEANUP;
fTestPass=FALSE;
//get an array of numeric and updatable columns
GetNumericAndUpdatable(&cCol,&rgColNumber);
//has to find such a column
if(!cCol)
goto CLEANUP;
ReleaseRowsetAndAccessor();
//create an accessor on the command object on the numeric and updatable column only
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
0,NULL,ON_COMMAND_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, USE_COLS_TO_BIND_ARRAY,
FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,rgColNumber));
//get the 4th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows,&pHRow),S_OK);
//get a copy of the data
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//create a new data buffer to set the data for the numeric and updatable column
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,1,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//create another rowset object on the same command object
TESTC_(m_pIAccessor->QueryInterface(IID_IRowsetInfo, (LPVOID *)&pIRowsetInfo),S_OK);
//get the ICommand pointer
TESTC_(pIRowsetInfo->GetSpecification(IID_ICommand,(IUnknown **)&pICommand),S_OK);
//exeute the same command object
TESTC_(pICommand->Execute(NULL,IID_IRowset,NULL,NULL,&pIRowset),S_OK);
//set data on the first rowset
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//allocat memory of pDataSecond
if(!(pDataSecond=PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//for dynamic cursor, the update for non-key value is always visible.retrieve the 4th row handle on the second rowset
TESTC_(((IRowset*)pIRowset)->GetNextRows(NULL,3,1,&cRows,&pHRowSecond),S_OK);
//get data on the second rowset. Share the same accessor on the command
TESTC_(((IRowset*)pIRowset)->GetData(*pHRowSecond,m_hAccessor,pDataSecond),S_OK);
//the second rowset should see the change
if(COMPARE(CompareBuffer(pDataSecond, pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
fTestPass=TRUE;
CLEANUP:
if(rgColNumber)
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(pHRowSecond && pIRowset)
{
CHECK(((IRowset *)(pIRowset))->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
}
PROVIDER_FREE(pData);
PROVIDER_FREE(pDataSecond);
SAFE_RELEASE(pIRowsetInfo);
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pICommand);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Immediate update mode. A second command object deletes one row by SQL text.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Visible_Dynamic_Command_Cursor::Variation_3()
{
HROW *pHRow=NULL;
HROW *pHRowSecond=NULL;
DBCOUNTITEM cRows = 0;
void *pData=NULL;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass=TEST_SKIPPED;
IRowset *pIRowset=NULL;
IRowsetChange *pIRowsetChange=NULL;
rgPropertyIDs[0]=DBPROP_OTHERINSERT;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
0,NULL,ON_COMMAND_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass=FALSE;
//create a new data buffer to set the data for all updatable columns to 1
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//get the last row handle
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows-1,1,&cRows,&pHRow),S_OK);
//execute the command again
TESTC_(m_pICommand->Execute(NULL, IID_IRowset, NULL, NULL, (IUnknown **)&pIRowset),S_OK);
//QI for the IRowsetChange
TESTC_(pIRowset->QueryInterface(IID_IRowsetChange, (LPVOID *)&pIRowsetChange),S_OK);
//get the same row
TESTC_(pIRowset->GetNextRows(NULL,m_ulTableRows-1,1,&cRows,&pHRowSecond),S_OK);
//delete the row
TESTC_(pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRowSecond, NULL),S_OK);
//set data on the deleted row
if(CHECK(SetData(*pHRow, m_hAccessor, pData),DB_E_DELETEDROW))
fTestPass=TRUE;
CLEANUP:
//release the row handle on the second row set
if(pHRowSecond && pIRowset)
{
CHECK(((IRowset *)(pIRowset))->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
}
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pIRowsetChange);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(pData)
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Immediate update mode. A second commnd object changes one row by SQL text.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Visible_Dynamic_Command_Cursor::Variation_4()
{
HROW *pHRow=NULL;
HROW *pHRowSecond=NULL;
DBCOUNTITEM cRows = 0;
void *pData=NULL;
void *pDataSecond=NULL;
DBPROPID rgPropertyIDs[2];
IRowset *pIRowset=NULL;
IRowsetChange *pIRowsetChange=NULL;
BOOL fTestPass=TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_OTHERINSERT;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
//create a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
0,NULL,ON_COMMAND_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass=FALSE;
//create a new data buffer to set the data for all updatable columns to 1
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//create a new data buffer to set the data for all updatable columns to 1
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pDataSecond,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//get the 1st row row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get data
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//execute the command again
TESTC_(m_pICommand->Execute(NULL, IID_IRowset, NULL, NULL, (IUnknown **)&pIRowset),S_OK);
//QI for the IRowsetChange
TESTC_(pIRowset->QueryInterface(IID_IRowsetChange, (LPVOID *)&pIRowsetChange),S_OK);
//get the same row
TESTC_(pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRowSecond),S_OK);
//Update the row
TESTC_(pIRowsetChange->SetData(*pHRowSecond, m_hAccessor,pDataSecond),S_OK);
//set data on the 1st row handle. The row appear to be deleted.
if(CHECK(SetData(*pHRow, m_hAccessor, pData),DB_E_DELETEDROW))
fTestPass=TRUE;
CLEANUP:
//release the row handle on the second row set
if(pHRowSecond && pIRowset)
{
CHECK(((IRowset *)(pIRowset))->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
}
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pIRowsetChange);
if(pDataSecond)
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pDataSecond, TRUE);
//release the 1st rowset
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(pData)
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Buffered update mode. A second commnd object changes one row by SQL text.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Visible_Dynamic_Command_Cursor::Variation_5()
{
HROW *pHRow = NULL;
HROW *pUpdatedHRow = NULL;
HROW *pHRowSecond = NULL;
DBROWSTATUS *pDBRowStatus = NULL;
DBCOUNTITEM cRows = 0;
IRowset *pIRowset = NULL;
IRowsetChange *pIRowsetChange = NULL;
IRowsetUpdate *pIRowsetUpdate = NULL;
void *pData = NULL;
void *pDataSecond = NULL;
DBPROPID rgPropertyIDs[3];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr = S_OK;
DWORD cCount = 0;
rgPropertyIDs[0]=DBPROP_OTHERINSERT;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
rgPropertyIDs[2]=DBPROP_REMOVEDELETED;
//create a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,0,NULL,
ON_COMMAND_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS, UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate)|| (!m_cBinding))
goto CLEANUP;
fTestPass=FALSE;
//create a new data buffer to set the data for all updatable columns to 4
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//create a new data buffer to set the data for all updatable columns to 1
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pDataSecond,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//get the 2nd row row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//get data
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//execute the command again
TESTC_(m_pICommand->Execute(NULL, IID_IRowset, NULL, NULL, (IUnknown **)&pIRowset),S_OK);
//QI for the IRowsetChange
TESTC_(pIRowset->QueryInterface(IID_IRowsetChange, (LPVOID *)&pIRowsetChange),S_OK);
//QI for the IRowsetUpdate
TESTC_(pIRowset->QueryInterface(IID_IRowsetUpdate, (LPVOID *)&pIRowsetUpdate),S_OK);
//get the same row
TESTC_(pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRowSecond),S_OK);
//Update the row
TESTC_(pIRowsetChange->SetData(*pHRowSecond, m_hAccessor,pDataSecond),S_OK);
//get data
TESTC_(pIRowset->GetData(*pHRowSecond, m_hAccessor, m_pData),S_OK);
//push update to back end //some provider's can choose to delete/insert instead of update
TESTC_(pIRowsetUpdate->Update(NULL,1,pHRowSecond,NULL,NULL,NULL),S_OK);
//Update the row in the cache
TESTC_(SetData(*pHRow, m_hAccessor,pDataSecond),S_OK);
//push update tp back end, row is moved on back endso this should fail
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,&cRows,&pUpdatedHRow,&pDBRowStatus),DB_E_ERRORSOCCURRED);
PROVIDER_FREE(pDBRowStatus);
PROVIDER_FREE(pUpdatedHRow);
//try again
//set data on the 1st row handle, just cache so it should be ok
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
//udpate should fail
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,&cRows,&pUpdatedHRow,&pDBRowStatus),DB_E_ERRORSOCCURRED);
//the test will not expect for the status because this is a dynamic curosr
//so the row is moved to the end of the row set
if(COMPARE(*pDBRowStatus, DBROWSTATUS_E_DELETED))
fTestPass=TRUE;
//get data
hr=pIRowset->GetData(*pHRowSecond, m_hAccessor, m_pData);
if (S_OK!=hr)
{
if (DB_S_ERRORSOCCURRED==hr)
{
//loop through columns
for (
cCount=0;
cCount < m_cBinding;
cCount++
)
{
// switch (*((BYTE *)dwAddrGet+(m_rgBinding[cCount]).obStatus))
switch (STATUS_BINDING(m_rgBinding[cCount],pData))
{
case DBSTATUS_S_OK:
case DBSTATUS_E_UNAVAILABLE:
break;
case DBSTATUS_S_ISNULL:
case DBSTATUS_S_TRUNCATED:
case DBSTATUS_E_BADACCESSOR:
case DBSTATUS_E_CANTCONVERTVALUE:
case DBSTATUS_E_CANTCREATE:
case DBSTATUS_E_DATAOVERFLOW:
case DBSTATUS_E_SIGNMISMATCH:
case DBSTATUS_E_PERMISSIONDENIED:
case DBSTATUS_E_INTEGRITYVIOLATION:
case DBSTATUS_E_SCHEMAVIOLATION:
case DBSTATUS_E_BADSTATUS:
case DBSTATUS_S_DEFAULT:
//some error on some column :)
default:
goto CLEANUP;
}
}
}
else
{
goto CLEANUP;
}
}
CLEANUP:
//release the row handle on the second row set
if(pHRowSecond && pIRowset)
CHECK(((IRowset *)(pIRowset))->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pIRowsetChange);
SAFE_RELEASE(pIRowsetUpdate);
if(pDataSecond)
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pDataSecond, TRUE);
//release the row handle on the 1st row set
PROVIDER_FREE(pDBRowStatus);
//there is pending change
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pUpdatedHRow);
if(pData)
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc DBPROP_CHANGEINSERTEDROWS-TRUE.A second commnd object change a row by SQL text.It tries to change same row again-succeeds.
// It then tries to change the same row again. if DBPROP_CHANGEINSERTEDROWS is
// VARIANT_TRUE the second change will work.
// @rdesc TEST_PASS or TEST_FAIL
//
int Visible_Dynamic_Command_Cursor::Variation_6()
{
HROW *pHRow=NULL;
DBCOUNTITEM cRows = 0;
void *pData=NULL;
void *pDataSecond=NULL;
DBPROPID rgPropertyIDs[4];
BOOL fTestPass=TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_CHANGEINSERTEDROWS;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_OWNINSERT;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgPropertyIDs,
0,NULL,ON_COMMAND_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass=FALSE;
//create a new data buffer to set the data for all updatable columns to 1
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//create a new data buffer to set the data for all updatable columns to 1
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pDataSecond,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//get the 1st row row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get data
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//release the row
// CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
// PROVIDER_FREE(pHRow);
//Now Insert the row
TESTC_(m_pIRowsetChange->InsertRow(NULL, m_hAccessor,pData, pHRow),S_OK)
//set data on the 1st row handle.
// TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
//set data on the 1st row handle.
if(CHECK(SetData(*pHRow, m_hAccessor, pDataSecond),S_OK))
{
fTestPass=TRUE;
}
CLEANUP:
if(pDataSecond)
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pDataSecond, TRUE);
//release the 1st rowset
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(pData)
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc DBPROP_CHANGEINSERTEDROWS-FALSE.A second commnd object change a row by SQL text.It tries to change same row again-fails.
// It then tries to change the same row again. if DBPROP_CHANGEINSERTEDROWS is
// VARIANT_FALSE the second change won't work, the row will not
// be found when it is changed for the second time.
// @rdesc TEST_PASS or TEST_FAIL
//
int Visible_Dynamic_Command_Cursor::Variation_7()
{
HROW *pHRow=NULL;
DBCOUNTITEM cRows = 0;
void *pData=NULL;
void *pDataSecond=NULL;
DBPROPID rgPropertyIDs[3];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass=TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OWNINSERT;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
rgUnPropertyIDs[0]=DBPROP_CHANGEINSERTEDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
1,rgUnPropertyIDs,ON_COMMAND_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate) || (!m_cBinding))
goto CLEANUP;
fTestPass=FALSE;
//create a new data buffer to set the data for all updatable columns to 1
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//create a new data buffer to set the data for all updatable columns to 1
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pDataSecond,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//get the 1st row row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get data
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//Now Insert the row
TESTC_(m_pIRowsetChange->InsertRow(NULL, m_hAccessor,pData, pHRow),S_OK)
//set data on the 1st row handle.
if(CHECK(SetData(*pHRow, m_hAccessor, pDataSecond),DB_E_NEWLYINSERTED))
{
fTestPass=TRUE;
}
CLEANUP:
if(pDataSecond)
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pDataSecond, TRUE);
//release the 1st rowset
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(pData)
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Visible_Dynamic_Command_Cursor::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Bookmark_Forward)
//*-----------------------------------------------------------------------
//| Test Case: Bookmark_Forward - Bookmark_Forward
//| Created: 04/15/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Bookmark_Forward::Init()
{
DBPROPID rgPropertyIDs[2];
BOOL fTestPass=TEST_SKIPPED;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
if(!TCIRowsetChange::Init())
return FALSE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetLocate;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,0,NULL,NO_ACCESSOR));
COMPARE(BufferedUpdate(),FALSE);
fTestPass=TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc immediate update mode, call SetData on the key value on the first row handle retrieved by IRowsetLocate::GetRowsAt
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Forward::Variation_1()
{
DBBOOKMARK DBBookmark=DBBMK_FIRST;
BYTE *pBookmark=(BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
HROW *pHRowFirst=NULL;
HROW *pHRowSecond=NULL;
void *pData=NULL;
DBPROPID rgPropertyIDs[4];
BOOL fTestPass=TEST_SKIPPED;
HRESULT hr;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
rgPropertyIDs[3]=DBPROP_IRowsetIdentity;
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,4,rgPropertyIDs,
2,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//get the first row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRowFirst),S_OK);
//move the cursor away
TESTC_(m_pIRowset->GetNextRows(NULL,10,0,&cRows,&pHRowSecond),S_OK);
//no row should be retrieved
if(!COMPARE(cRows, 0) || !COMPARE(pHRowSecond, NULL))
goto CLEANUP;
//get the first row handle again by DBBMK_FIRST
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRowSecond),S_OK);
//the two row handles have to be the same
//Compare rows, the two row handles should have the same value
if (GetProperty(DBPROP_LITERALIDENTITY, DBPROPSET_ROWSET, g_pIDBInitialize))
{
COMPARE((DWORD)(*pHRowFirst), (DWORD)(*pHRowSecond));
}
else
{
if (!fnIsSameRow(m_pIRowset,pHRowFirst,pHRowSecond))
goto CLEANUP;
}
//set new data to the first row.make data for the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,(BYTE **)&pData,
g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRowSecond, m_hAccessor,pData),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRowFirst,NULL,NULL,NULL),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
//not going to use pHRowSecond again
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(pHRowFirst);
//restart position. The query will be re-executed for forward only cursor
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the row handles
//while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRowSecond)) || hr == DB_S_ENDOFROWSET )
//{
// if( cRows ==0)
// break;
// //Get the data for the 10th row handle
// TESTC_(GetData(*pHRowSecond,m_hAccessor,m_pData),S_OK);
// TESTC_(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
// PROVIDER_FREE(pHRowSecond);
// //make sure GetData should be able to see the change
// if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
// {
// fTestPass=TRUE;
// break;
// }
//}
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
if(pHRowFirst && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowFirst,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowFirst);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc buffered udpate mode, call SetData one the whole row on a middle row handle retrieved by IRowsetLocate::GetRowsByBookmark.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Forward::Variation_2()
{
BOOL fTestPass = TEST_SKIPPED;
HROW HRow = NULL;
HACCESSOR hAccessorBookmark = NULL;
DBBKMARK cbBookmark = 0;
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber = NULL;
DBPROPID rgPropertyIDs[3];
void *pData = NULL;
BYTE *pBookmark = NULL;
HRESULT hr = S_OK;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
//create an accessor on the bookmark column
cCol=0;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
2,g_rgPropertyIDs, ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,&cCol));
//get the bookmark for the 20th row in the rowset
if(!GetBookmark(1,&cbBookmark,&pBookmark))
goto CLEANUP;
//release the accessor on the rowset
ReleaseAccessorOnRowset();
//get an array of numeric and updatable columns
GetNumericAndUpdatable(&cCol,&rgColNumber);
//has to find such a column
if(!cCol)
goto CLEANUP;
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//create an accessor on the command object on the numeric and updatable column only
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,rgColNumber))
//create a new data buffer to set the data for the numeric and updatable
//column
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,1,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//get the ith row handle by its bookmark
TESTC_(m_pIRowsetLocate->GetRowsByBookmark(NULL,1,&cbBookmark,(const BYTE **)(&pBookmark),&HRow,NULL),S_OK);
//set data
TESTC_(SetData(HRow,m_hAccessor,pData),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&HRow,NULL,NULL,NULL),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,&HRow,NULL,NULL,NULL),S_OK);
//restart position
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the 20th row handle by its bookmark
TESTC_(m_pIRowsetLocate->GetRowsByBookmark(NULL,1,&cbBookmark,(const BYTE **)&pBookmark,&HRow,NULL),S_OK);
//get data
TESTC_(GetData(HRow, m_hAccessor, m_pData),S_OK);
//the data has to be same as what was set
//if(COMPARE(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
PROVIDER_FREE(pBookmark);
PROVIDER_FREE(pData);
if(HRow)
CHECK(m_pIRowset->ReleaseRows(1,&HRow,NULL,NULL,NULL),S_OK);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc delete last row then make sure BMK_LAST sees the new last row, RD=true,BMS=true
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Forward::Variation_3()
{
DBBOOKMARK DBBookmark = DBBMK_LAST;
BYTE *pBookmark = (BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond= NULL;
DBPROPID rgPropertyIDs[6];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_REMOVEDELETED;
rgPropertyIDs[5]=DBPROP_BOOKMARKSKIPPED;
rgUnPropertyIDs[0]=DBPROP_OTHERUPDATEDELETE;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,6,rgPropertyIDs,
1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by DBBMK_LAST
//row should be the new last row
hr=m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,1,pBookmark,0,1,&cRows,&pHRowSecond);
//this should always be S_OK. REMOVEDELETED is TRUE so a new last row should be fetched.
//anything else is an error.
//here is some code to help debug if the hr is not S_OK
if (S_OK!=hr)
{
goto CLEANUP;
}
//double check that the deleted row and the row brought back from GetRowsAt are different
hr=m_pIRowsetIdentity->IsSameRow(*pHRow,*pHRowSecond);
if (S_OK==hr)
{
//these are the same, fail the variation, GerRowsAt should have returned
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc delete last row then make sure BMK_LAST sees the new last row. RD=false, BMS=true
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Forward::Variation_4()
{
DBBOOKMARK DBBookmark = DBBMK_LAST;
BYTE *pBookmark = (BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond=NULL;
DBPROPID rgPropertyIDs[5];
DBPROPID rgUnPropertyIDs[2];
BOOL fTestPass=TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_BOOKMARKSKIPPED;
rgUnPropertyIDs[0]=DBPROP_REMOVEDELETED;
rgUnPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,5,rgPropertyIDs,
2,rgUnPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position. The query will be re-executed for forward only cursor
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by DBBMK_LAST
//row should be the deleted row but just marked deleted
hr=m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,1,pBookmark,0,1,&cRows,&pHRowSecond);
//this should always be S_OK(REMOVEDELETED is FALSE). anything else is an error.
//here is some code to help debug if the hr is not DB_S_ENDOFROWSET
if (S_OK!=hr)
{
//if GetRowsAt returned a row handle try to do some debugging
if (pHRowSecond)
{
//double check that the deleted row and the bookmarked row are the same
hr=m_pIRowsetIdentity->IsSameRow(*pHRow,*pHRowSecond);
if (S_OK==hr)
{
//these are the same, fail the variation, GerRowsAt should have returned
goto CLEANUP;
}
else
{
//this should never happen, this is also an error
goto CLEANUP;
}
}
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc delete last row then make sure BMK_LAST sees the new last row. RD=true,BMS=false
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Forward::Variation_5()
{
DBBOOKMARK DBBookmark = DBBMK_LAST;
BYTE *pBookmark = (BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond=NULL;
DBPROPID rgPropertyIDs[5];
DBPROPID rgUnPropertyIDs[2];
BOOL fTestPass=TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_REMOVEDELETED;
rgUnPropertyIDs[0]=DBPROP_BOOKMARKSKIPPED;
rgUnPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,5,rgPropertyIDs,
2,rgUnPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position. The query will be re-executed for forward only cursor
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by DBBMK_LAST
//row should be the deleted row (REMOVEDELETED=TRUE)
//new last row of the rowset
hr=m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,1,pBookmark,0,1,&cRows,&pHRowSecond);
//this should always be S_OK. REMOVEDELETED is TRUE so a new last row should be fetched.
//anything else is an error.
//here is some code to help debug if the hr is not S_OK
if (S_OK!=hr)
{
goto CLEANUP;
}
//double check that the deleted row and the row brought back from GetRowsAt are different
hr=m_pIRowsetIdentity->IsSameRow(*pHRow,*pHRowSecond);
if (S_OK==hr)
{
//these are the same, fail the variation, GerRowsAt should have returned
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc delete last row then make sure BMK_LAST sees the new last row. RD=false, BMS=false
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Forward::Variation_6()
{
DBBOOKMARK DBBookmark = DBBMK_LAST;
BYTE *pBookmark = (BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond=NULL;
DBPROPID rgPropertyIDs[4];
DBPROPID rgUnPropertyIDs[3];
BOOL fTestPass=TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgUnPropertyIDs[0]=DBPROP_REMOVEDELETED;
rgUnPropertyIDs[1]=DBPROP_BOOKMARKSKIPPED;
rgUnPropertyIDs[2]=DBPROP_OTHERUPDATEDELETE;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,4,rgPropertyIDs,
3,rgUnPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position. The query will be re-executed for forward only cursor
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by DBBMK_LAST
//row should be the deleted row but REMOVEDELETED is FALSE so its just marked deleted
hr=m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,1,pBookmark,0,1,&cRows,&pHRowSecond);
//this should always be S_OK eventhough BOOKMARKSSKIPPED is false cause REMOVEDELETED is FALSE.
//anything else is an error.
//here is some code to help debug if the hr is not DB_S_ENDOFROWSET
if (S_OK!=hr)
{
//if GetRowsAt returned a row handle try to do some debugging
if (pHRowSecond)
{
//double check that the deleted row and the bookmarked row are the same
hr=m_pIRowsetIdentity->IsSameRow(*pHRow,*pHRowSecond);
if (S_OK==hr)
{
//these are the same, fail the variation, GerRowsAt should have returned
goto CLEANUP;
}
else
{
//this should never happen, this is also an error
goto CLEANUP;
}
}
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc delete last row then make sure bookmark sees the new last row, RD=true,BMS=true
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Forward::Variation_7()
{
BYTE *pBookmark = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond= NULL;
DBPROPID rgPropertyIDs[6];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
DBORDINAL cCol = 0;
DBBKMARK cbBookmark = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_REMOVEDELETED;
rgPropertyIDs[5]=DBPROP_BOOKMARKSKIPPED;
rgUnPropertyIDs[0]=DBPROP_OTHERUPDATEDELETE;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//create an accessor on the bookmark column
cCol=0;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,6,rgPropertyIDs,
1,rgUnPropertyIDs, ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,&cCol));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//get the bookmark for the last row in the rowset
if(!GetBookmark(cCountRows,&cbBookmark,&pBookmark))
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the last row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by its bookmark
//row should end of rowset
hr=m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,cbBookmark,(pBookmark),0,1,&cRows,&pHRowSecond);
//this should always be DB_S_ENDOFROWSET. REMOVEDELETED is TRUE so the row with the bookmark is gonzo.
//try to get the next row
//anything else is an error.
//here is some code to help debug if the hr is not S_OK
if (DB_S_ENDOFROWSET!=hr)
{
goto CLEANUP;
}
if (pHRowSecond)
{
//double check that the deleted row and the row brought back from GetRowsAt are different
hr=m_pIRowsetIdentity->IsSameRow(*pHRow,*pHRowSecond);
if (S_OK==hr)
{
//these are the same, fail the variation, GerRowsAt should have returned
goto CLEANUP;
}
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(pBookmark);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc delete last row then make sure bookmark sees the new last row, RD=true,BMS=false
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Forward::Variation_8()
{
BYTE *pBookmark = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond= NULL;
DBPROPID rgPropertyIDs[4];
DBPROPID rgUnPropertyIDs[2];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
DBORDINAL cCol = 0;
DBBKMARK cbBookmark = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
rgPropertyIDs[3]=DBPROP_REMOVEDELETED;
rgUnPropertyIDs[1]=DBPROP_BOOKMARKSKIPPED;
rgUnPropertyIDs[0]=DBPROP_OTHERUPDATEDELETE;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//create an accessor on the bookmark column
cCol=0;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgPropertyIDs,
2,rgUnPropertyIDs, ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,&cCol));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//get the bookmark for the last row in the rowset
if(!GetBookmark(cCountRows,&cbBookmark,&pBookmark))
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the last row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by its bookmark
//row should end of rowset
//this should always be DB_E_BADBOOKMARK. BOOKMARKSSKIPPED is FALSE
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,cbBookmark,(pBookmark),0,1,&cRows,&pHRowSecond),DB_E_BADBOOKMARK);
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(pBookmark);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc delete last row of 1 row table and try to get BMK_LAST. RD=true,BMS=true
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Forward::Variation_9()
{
DBBOOKMARK DBBookmark = DBBMK_LAST;
BYTE *pBookmark = (BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond= NULL;
DBPROPID rgPropertyIDs[5];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
rgPropertyIDs[3]=DBPROP_REMOVEDELETED;
rgPropertyIDs[4]=DBPROP_BOOKMARKSKIPPED;
rgUnPropertyIDs[0]=DBPROP_OTHERUPDATEDELETE;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//set the table to one row table
SetTable(g_p1RowTable,DELETETABLE_NO);
//if an ini file is being used then delete and set to one row table
if(GetModInfo()->GetFileName())
{
//delete all rows in the table.
if(g_p1RowTable->DeleteRows(ALLROWS) == S_OK)
{
// RePopulate table
if(g_p1RowTable->Insert(1, PRIMARY) != S_OK)
{
return FALSE;
}
}
}
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,5,rgPropertyIDs,
1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle (should be handle to the only row)
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//there should only be one rwo in this table
if (cCountRows!=1)
{
goto CLEANUP;
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the only row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by DBBMK_LAST
//no rows, has to be DB_E_ENDOFROWSET
hr=m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,1,pBookmark,0,1,&cRows,&pHRowSecond);
//this should always be S_OK. REMOVEDELETED is TRUE so a new last row should be fetched.
//anything else is an error.
//here is some code to help debug if the hr is not S_OK
if (DB_S_ENDOFROWSET!=hr)
{
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
//make this a one row table again
g_p1RowTable->Insert(1, PRIMARY);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc delete last row of 1 row table and try to get bookmark. RD=true,BMS=true
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Forward::Variation_10()
{
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond= NULL;
DBPROPID rgPropertyIDs[5];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
BYTE *pBookmark = NULL;
ULONG cCol = 0;
DBCOUNTITEM cbBookmark = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
rgPropertyIDs[3]=DBPROP_REMOVEDELETED;
rgPropertyIDs[4]=DBPROP_BOOKMARKSKIPPED;
rgUnPropertyIDs[0]=DBPROP_OTHERUPDATEDELETE;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//set the table to one row table
SetTable(g_p1RowTable,DELETETABLE_NO);
//if an ini file is being used then delete and set to one row table
if(GetModInfo()->GetFileName())
{
//delete all rows in the table.
if(g_p1RowTable->DeleteRows(ALLROWS) == S_OK)
{
// RePopulate table
if(g_p1RowTable->Insert(1, PRIMARY) != S_OK)
{
return FALSE;
}
}
}
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,5,rgPropertyIDs,
1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle (should be handle to the only row)
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//there should only be one rwo in this table
if (cCountRows!=1)
{
goto CLEANUP;
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//get the bookmark for the last row in the rowset
if(!GetBookmark(cCountRows,&cbBookmark,&pBookmark))
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the only row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by its bookmark
//row should end of rowset
hr=m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,cbBookmark,(pBookmark),0,1,&cRows,&pHRowSecond);
//this should always be S_OK. REMOVEDELETED is TRUE so a new last row should be fetched.
//anything else is an error.
//here is some code to help debug if the hr is not S_OK
if (DB_S_ENDOFROWSET!=hr)
{
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
//make this a one row table again
g_p1RowTable->Insert(1, PRIMARY);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(pBookmark);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Bookmark_Forward::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Bookmark_Static)
//*-----------------------------------------------------------------------
//| Test Case: Bookmark_Static - Bookmark_Static
//| Created: 04/15/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Bookmark_Static::Init()
{
DBPROPID rgPropertyIDs[3];
BOOL fTestPass=TEST_SKIPPED;
if(!TCIRowsetChange::Init())
return FALSE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_CANSCROLLBACKWARDS;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
g_cPropertyIDs,g_rgPropertyIDs,NO_ACCESSOR));
COMPARE(BufferedUpdate(),FALSE);
fTestPass=TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc immediate update mode, call SetData on the key value on the first row handle retrieved by IRowsetLocate::GetRowsAt
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Static::Variation_1()
{
DBBOOKMARK DBBookmark=DBBMK_FIRST;
BYTE *pBookmark=(BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
HROW *pHRowFirst=NULL;
HROW *pHRowSecond=NULL;
void *pData=NULL;
void *pDataSecond=NULL;
DBPROPID rgPropertyIDs[5];
BOOL fTestPass=TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_CANSCROLLBACKWARDS;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_IRowsetIdentity;
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,5,rgPropertyIDs,
g_cPropertyIDs,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass=FALSE;
//get the first row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRowFirst),S_OK);
//move the cursor away
TESTC_(m_pIRowset->GetNextRows(NULL,10,0,&cRows,&pHRowSecond),S_OK);
//no row should be retrieved
if(!COMPARE(cRows, 0) || !COMPARE(pHRowSecond, NULL))
goto CLEANUP;
//get the first row handle again by DBBMK_FIRST
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRowSecond),S_OK);
//the two row handles have to be the same
//the two row handles have to be the same
//Compare rows, the two row handles should have the same value
if (GetProperty(DBPROP_LITERALIDENTITY, DBPROPSET_ROWSET, g_pIDBInitialize))
{
COMPARE((DWORD)(*pHRowFirst), (DWORD)(*pHRowSecond));
}
else
{
if (!fnIsSameRow(m_pIRowset,pHRowFirst,pHRowSecond))
goto CLEANUP;
}
//get a copy of the old data
TESTC_(GetData(*pHRowFirst, m_hAccessor, m_pData),S_OK);
//set new data to the first row.make data for the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRowSecond, m_hAccessor,pData),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRowFirst,NULL,NULL,NULL),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
//not going to use pHRowSecond again
PROVIDER_FREE(pHRowSecond);
//for static cursor, no change should be seen get the first row handle again by DBBMK_FIRST
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRowFirst),S_OK);
//allocate memory for GetData
pDataSecond=PROVIDER_ALLOC(m_cRowSize);
if(!pDataSecond)
PROVIDER_FREE(pDataSecond);
//get data
TESTC_(GetData(*pHRowFirst,m_hAccessor,pDataSecond),S_OK);
//the change is not seen
if(COMPARE(CompareBuffer(pDataSecond,m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
fTestPass=TRUE;
CLEANUP:
if(pData)
ReleaseInputBindingsMemory(1,m_rgBinding,(BYTE *)pData,TRUE);
PROVIDER_FREE(pDataSecond);
if(pHRowFirst && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowFirst,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowFirst);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc buffered udpate mode, call SetData one the whole row on a middle row handle retrieved by IRowsetLocate::GetRowsByBookmark.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Static::Variation_2()
{
BOOL fTestPass = TEST_SKIPPED;
HROW HRow = NULL;
HROW HRowSecond = NULL;
HACCESSOR hAccessorBookmark = NULL;
DBBKMARK cbBookmark = 0;
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber = NULL;
DBPROPID rgPropertyIDs[4];
void *pData = NULL;
BYTE *pBookmark = NULL;
HRESULT hr = S_OK;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
rgPropertyIDs[3]=DBPROP_CANSCROLLBACKWARDS;
//create an accessor on the bookmark column
cCol=0;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgPropertyIDs,
g_cPropertyIDs,g_rgPropertyIDs, ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,&cCol));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate) || (!m_pIRowsetUpdate)|| (!m_cBinding))
goto CLEANUP;
fTestPass=FALSE;
//get the bookmark for the 20th row in the rowset
if(!GetBookmark(10,&cbBookmark,&pBookmark))
goto CLEANUP;
//release the accessor on the rowset
ReleaseAccessorOnRowset();
//get an array of numeric and updatable columns
GetNumericAndUpdatable(&cCol,&rgColNumber);
//has to find such a column
if(!cCol)
goto CLEANUP;
//create an accessor on the command object on the numeric and updatable column only
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,rgColNumber))
//create a new data buffer to set the data for the numeric and updatable column
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,1,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//get the 20th row handle by its bookmark
TESTC_(m_pIRowsetLocate->GetRowsByBookmark(NULL,1,&cbBookmark,(const BYTE **)(&pBookmark),&HRow,NULL),S_OK);
//set data
TESTC_(SetData(HRow,m_hAccessor,pData),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&HRow,NULL,NULL,NULL),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,&HRow,NULL,NULL,NULL),S_OK);
HRow=NULL;
//restart position
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
goto CLEANUP;
//get the 20th row handle by its bookmark
TESTC_(m_pIRowsetLocate->GetRowsByBookmark(NULL,1,&cbBookmark,(const BYTE **)&pBookmark,&HRowSecond,NULL),S_OK);
//get data
TESTC_(GetData(HRowSecond, m_hAccessor, m_pData),S_OK);
//the data has to be same as what was before
if(COMPARE(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),FALSE))
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
PROVIDER_FREE(pData);
if(HRow)
CHECK(m_pIRowset->ReleaseRows(1,&HRow,NULL,NULL,NULL),S_OK);
if(HRowSecond)
CHECK(m_pIRowset->ReleaseRows(1,&HRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pBookmark);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Bookmark_Static::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Bookmark_Keyset)
//*-----------------------------------------------------------------------
//| Test Case: Bookmark_Keyset - Bookmark_Keyset
//| Created: 04/15/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE6
//
BOOL Bookmark_Keyset::Init()
{
DBPROPID rgPropertyIDs[3];
BOOL fTestPass=TEST_SKIPPED;
if(!TCIRowsetChange::Init())
return FALSE;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
//TESTC_PROVIDER(g_rgDBPrpt[IDX_IRowsetLocate].fSupported &&
// g_rgDBPrpt[IDX_OtherUpdateDelete].fSupported);
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
0,NULL,NO_ACCESSOR));
fTestPass=FALSE;
COMPARE(BufferedUpdate(),FALSE);
fTestPass=TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc immediate update mode, call SetData on the key value on the first row handle retrieved by IRowsetLocate::GetRowsAt
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Keyset::Variation_1()
{
DBBOOKMARK DBBookmark=DBBMK_FIRST;
BYTE *pBookmark=(BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
HROW *pHRowFirst=NULL;
HROW *pHRowSecond=NULL;
void *pData=NULL;
DBPROPID rgPropertyIDs[5];
BOOL fTestPass=TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_IRowsetIdentity;
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,5,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass=FALSE;
//get the first row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRowFirst),S_OK);
//move the cursor away
TESTC_(m_pIRowset->GetNextRows(NULL,10,0,&cRows,&pHRowSecond),S_OK);
//no row should be retrieved
if(!COMPARE(cRows, 0) || !COMPARE(pHRowSecond, NULL))
goto CLEANUP;
//get the first row handle again by DBBMK_FIRST
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,
&pHRowSecond),S_OK);
//the two row handles have to be the same
if (GetProperty(DBPROP_LITERALIDENTITY, DBPROPSET_ROWSET, g_pIDBInitialize))
{
COMPARE((DWORD)(*pHRowFirst), (DWORD)(*pHRowSecond));
}
else
{
if (!fnIsSameRow(m_pIRowset,pHRowFirst,pHRowSecond))
goto CLEANUP;
}
//set new data to the first row.make data for the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRowSecond, m_hAccessor,pData),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRowFirst,NULL,NULL,NULL),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
//not going to use pHRowSecond again
PROVIDER_FREE(pHRowSecond);
//for keyset driven cursor on cursor based update, we should be able
//to see the change. The change should be either at the last row or
//in place
//get the first row handle again by DBBMK_FIRST
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,
&pHRowFirst),S_OK);
//get data
m_hr=GetData(*pHRowFirst,m_hAccessor,m_pData);
if(m_hr!=ResultFromScode(DB_E_DELETEDROW))
{
//the data should be the same as what was set
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY))
{
fTestPass=TRUE;
goto CLEANUP;
}
}
//release
TESTC_(m_pIRowset->ReleaseRows(1,pHRowFirst,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowFirst);
pHRowFirst=NULL;
//get the last row
DBBookmark=DBBMK_LAST;
//get the last row
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,
&cRows, &pHRowFirst),S_OK);
//get data
TESTC_(GetData(*pHRowFirst,m_hAccessor,m_pData),S_OK);
//the data should be the same as what was set
if(COMPARE(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
{
fTestPass = TRUE;
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
if(pHRowFirst && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowFirst,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowFirst);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc buffered udpate mode, call SetData one the whole row on a middle row handle retrieved by IRowsetLocate::GetRowsByBookmark.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Keyset::Variation_2()
{
BOOL fTestPass=TEST_SKIPPED;
HROW HRow=NULL;
HACCESSOR hAccessorBookmark=NULL;
DBBKMARK cbBookmark=0;
DBORDINAL cCol;
DBORDINAL *rgColNumber=NULL;
DBPROPID rgPropertyIDs[3];
void *pData=NULL;
BYTE *pBookmark=NULL;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
rgPropertyIDs[2]=DBPROP_OTHERUPDATEDELETE;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
0,NULL,NO_ACCESSOR));
//create an accessor on the bookmark column
cCol=0;
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,&cCol))
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate) || (!m_pIRowsetUpdate))
goto CLEANUP;
fTestPass=FALSE;
//get the bookmark for the 20th row in the rowset
if(!GetBookmark(10,&cbBookmark,&pBookmark))
goto CLEANUP;
//release the accessor on the rowset
ReleaseAccessorOnRowset();
//get an array of numeric and updatable columns
GetNumericAndUpdatable(&cCol,&rgColNumber);
//has to find such a column
if(!cCol)
goto CLEANUP;
//create an accessor on the command object on the numeric and updatable column only
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,cCol,rgColNumber))
//create a new data buffer to set the data for the numeric and updatable
//column
TESTC_(FillInputBindings(m_pTable,
DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//get the 20th row handle by its bookmark
TESTC_(m_pIRowsetLocate->GetRowsByBookmark(NULL,1,&cbBookmark,
(const BYTE **)(&pBookmark),&HRow,NULL),S_OK);
//set data
TESTC_(SetData(HRow,m_hAccessor,pData),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&HRow,NULL,NULL,NULL),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,&HRow,NULL,NULL,NULL),S_OK);
//for keyset driven cursor on a querybased update, the change to the non-key value should be visible.
//get the 20th row handle by its bookmark
TESTC_(m_pIRowsetLocate->GetRowsByBookmark(NULL,1,&cbBookmark,(const BYTE **)&pBookmark,&HRow,NULL),S_OK);
//get data
TESTC_(GetData(HRow, m_hAccessor, m_pData),S_OK);
//the data has to be same as what was set
if(COMPARE(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
PROVIDER_FREE(pData);
PROVIDER_FREE(pBookmark);
if(HRow)
CHECK(m_pIRowset->ReleaseRows(1, &HRow,NULL,NULL,NULL),S_OK);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Immediate update mode. No row revisited.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Keyset::Variation_3()
{
DBBOOKMARK DBBookmark=DBBMK_LAST;
BYTE *pBookmark=(BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
HROW *pHRow=NULL;
HROW *pHRowSecond=NULL;
void *pData=NULL;
DBPROPID rgPropertyIDs[5];
IRowsetIdentity *pIRowsetIdentity=NULL;
BOOL fTestPass=TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_IRowsetIdentity;
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,5,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass=FALSE;
//identity is level 0 so it is required
if (!m_pIRowsetIdentity)
goto CLEANUP;
//QI For IRowsetIdentity pointer
TESTC_(m_pIRowsetChange->QueryInterface(IID_IRowsetIdentity,
(LPVOID *)&pIRowsetIdentity),S_OK);
//get the first row handle again by DBBMK_LAST
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRow),S_OK);
//set new data to the first row.
//make data for the last row
TESTC_(FillInputBindings(m_pTable,
DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow, m_hAccessor,pData),S_OK);
//get the row handle again by DBBMK_LAST
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,
&pHRowSecond),S_OK);
//get data
TESTC_(GetData(*pHRowSecond,m_hAccessor,m_pData),S_OK);
//the data should be the same as what was set
if(!COMPARE(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
goto CLEANUP;
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(pHRowSecond && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
}
SAFE_RELEASE(pIRowsetIdentity);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Buffered update mode. No row revisited.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Keyset::Variation_4()
{
BOOL fTestPass = TEST_SKIPPED;
HROW HRow = NULL;
HACCESSOR hAccessorBookmark = NULL;
DBBKMARK cbBookmark = 0;
DBORDINAL cCol = 0;
DBORDINAL *rgColNumber = NULL;
DBPROPID rgPropertyIDs[3];
void *pData = NULL;
BYTE *pBookmark = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetLocate;
rgPropertyIDs[2]=DBPROP_OTHERUPDATEDELETE;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
0,NULL,NO_ACCESSOR));
//create an accessor on the bookmark column
cCol=0;
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,&cCol))
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass=FALSE;
//get the bookmark for the 15th row in the rowset
if(!GetBookmark(13,&cbBookmark,&pBookmark))
goto CLEANUP;
//get the 15th row handle by its bookmark
TESTC_(m_pIRowsetLocate->GetRowsByBookmark(NULL,1,&cbBookmark,
(const BYTE **)(&pBookmark),&HRow,NULL),S_OK);
//release the accessor on the rowset
ReleaseAccessorOnRowset();
//get an array of numeric and updatable columns
GetNumericAndUpdatable(&cCol,&rgColNumber);
//has to find such a column
if(!cCol)
{
fTestPass = TRUE;
goto CLEANUP;
}
//create an accessor on the command object on the numeric and updatable column only
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,cCol,rgColNumber))
//create a new data buffer to set the data for the numeric and updatable
//column
TESTC_(FillInputBindings(m_pTable,
DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data
TESTC_(SetData(HRow,m_hAccessor,pData),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,&HRow,NULL,NULL,NULL),S_OK);
//for keyset driven cursor on a querybased update, the change
//to the non-key value should be visible.
//get the 15th row handle by its bookmark
TESTC_(m_pIRowsetLocate->GetRowsByBookmark(NULL,1,&cbBookmark,
(const BYTE **)&pBookmark,&HRow,NULL),S_OK);
//get data
TESTC_(GetData(HRow, m_hAccessor, m_pData),S_OK);
//the data has to be same as what was set
if(COMPARE(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
PROVIDER_FREE(pData);
if(HRow)
{
CHECK(m_pIRowset->ReleaseRows(1,&HRow,NULL,NULL,NULL),S_OK);
}
if(pBookmark)
PROVIDER_FREE(pBookmark);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc delete last row then make sure BMK_LAST sees the new last row. RD=true,BMS=true
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Keyset::Variation_5()
{
DBBOOKMARK DBBookmark = DBBMK_LAST;
BYTE *pBookmark = (BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond= NULL;
DBPROPID rgPropertyIDs[7];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_REMOVEDELETED;
rgPropertyIDs[5]=DBPROP_BOOKMARKSKIPPED;
rgPropertyIDs[6]=DBPROP_OTHERUPDATEDELETE;
rgUnPropertyIDs[0]=DBPROP_OTHERINSERT;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,7,rgPropertyIDs,
1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by DBBMK_LAST
//row should be the new last row
hr=m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,1,pBookmark,0,1,&cRows,&pHRowSecond);
//this should always be S_OK. REMOVEDELETED is TRUE so a new last row should be fetched.
//anything else is an error.
//here is some code to help debug if the hr is not S_OK
if (S_OK!=hr)
{
goto CLEANUP;
}
//double check that the deleted row and the row brought back from GetRowsAt are different
hr=m_pIRowsetIdentity->IsSameRow(*pHRow,*pHRowSecond);
if (S_OK==hr)
{
//these are the same, fail the variation, GerRowsAt should have returned
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc delete last row then make sure BMK_LAST sees the new last row. RD=true,BMS=false
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Keyset::Variation_6()
{
DBBOOKMARK DBBookmark = DBBMK_LAST;
BYTE *pBookmark = (BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond=NULL;
DBPROPID rgPropertyIDs[6];
DBPROPID rgUnPropertyIDs[2];
BOOL fTestPass=TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_REMOVEDELETED;
rgPropertyIDs[5]=DBPROP_OTHERUPDATEDELETE;
rgUnPropertyIDs[0]=DBPROP_BOOKMARKSKIPPED;
rgUnPropertyIDs[1]=DBPROP_OTHERINSERT;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,6,rgPropertyIDs,
2,rgUnPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position. The query will be re-executed for forward only cursor
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//so restart position. The query will be re-executed for forward only cursor
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position. The query will be re-executed for forward only cursor
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by DBBMK_LAST
//row should be the deleted row (REMOVEDELETED=TRUE) so get the new last row
//new last row of the rowset
hr=m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,1,pBookmark,0,1,&cRows,&pHRowSecond);
//this should always be S_OK. REMOVEDELETED is TRUE so a new last row should be fetched.
//anything else is an error.
//here is some code to help debug if the hr is not S_OK
if (S_OK!=hr)
{
goto CLEANUP;
}
//double check that the deleted row and the row brought back from GetRowsAt are different
hr=m_pIRowsetIdentity->IsSameRow(*pHRow,*pHRowSecond);
if (S_OK==hr)
{
//these are the same, fail the variation, GerRowsAt should have returned
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc delete last row then make sure bookmark sees the new last row, RD=true,BMS=true
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Keyset::Variation_7()
{
BYTE *pBookmark = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond= NULL;
DBPROPID rgPropertyIDs[7];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
DBORDINAL cCol = 0;
DBBKMARK cbBookmark = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_REMOVEDELETED;
rgPropertyIDs[5]=DBPROP_BOOKMARKSKIPPED;
rgPropertyIDs[6]=DBPROP_OTHERUPDATEDELETE;
rgUnPropertyIDs[0]=DBPROP_OTHERINSERT;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//create an accessor on the bookmark column
cCol=0;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,7,rgPropertyIDs,
1,rgUnPropertyIDs, ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,&cCol));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate))
goto CLEANUP;
fTestPass = FALSE;
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//get the bookmark for the last row in the rowset
if(!GetBookmark(cCountRows,&cbBookmark,&pBookmark))
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the last row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by its bookmark
//row should end of rowset
hr=m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,cbBookmark,(pBookmark),0,1,&cRows,&pHRowSecond);
//this should always be DB_S_ENDOFROWSET. REMOVEDELETED is TRUE so the row with the bookmark is gonzo.
//try to get the next row
//anything else is an error.
//here is some code to help debug if the hr is not S_OK
if (DB_S_ENDOFROWSET!=hr)
{
goto CLEANUP;
}
if (pHRowSecond)
{
//double check that the deleted row and the row brought back from GetRowsAt are different
hr=m_pIRowsetIdentity->IsSameRow(*pHRow,*pHRowSecond);
if (S_OK==hr)
{
//these are the same, fail the variation, GerRowsAt should have returned
goto CLEANUP;
}
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(pBookmark);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc delete last row then make sure bookmark sees the new last row, RD=true,BMS=false
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Keyset::Variation_8()
{
BYTE *pBookmark = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond= NULL;
DBPROPID rgPropertyIDs[6];
DBPROPID rgUnPropertyIDs[2];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
DBORDINAL cCol = 0;
DBBKMARK cbBookmark = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_REMOVEDELETED;
rgPropertyIDs[5]=DBPROP_OTHERUPDATEDELETE;
rgUnPropertyIDs[1]=DBPROP_BOOKMARKSKIPPED;
rgUnPropertyIDs[0]=DBPROP_OTHERINSERT;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//create an accessor on the bookmark column
cCol=0;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,6,rgPropertyIDs,
2,rgUnPropertyIDs, ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,&cCol));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate))
goto CLEANUP;
fTestPass = FALSE;
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//get the bookmark for the last row in the rowset
if(!GetBookmark(cCountRows,&cbBookmark,&pBookmark))
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the last row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by its bookmark
//row should end of rowset
//this should always be DB_E_BADBOOKMARK. BOOKMARKSSKIPPED is FALSE
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,cbBookmark,(pBookmark),0,1,&cRows,&pHRowSecond),DB_E_BADBOOKMARK);
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(pBookmark);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc delete last row of 1 row table and try to get BMK_LAST. RD=true,BMS=true
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Keyset::Variation_9()
{
DBBOOKMARK DBBookmark = DBBMK_LAST;
BYTE *pBookmark = (BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond= NULL;
DBPROPID rgPropertyIDs[6];
DBPROPID rgUnPropertyIDs[2];
BOOL fTestPass=TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_REMOVEDELETED;
rgPropertyIDs[5]=DBPROP_OTHERUPDATEDELETE;
rgUnPropertyIDs[0]=DBPROP_BOOKMARKSKIPPED;
rgUnPropertyIDs[1]=DBPROP_OTHERINSERT;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//set the table to one row table
SetTable(g_p1RowTable,DELETETABLE_NO);
//if an ini file is being used then delete and set to one row table
if(GetModInfo()->GetFileName())
{
//delete all rows in the table.
if(g_p1RowTable->DeleteRows(ALLROWS) == S_OK)
{
// RePopulate table
if(g_p1RowTable->Insert(1, PRIMARY) != S_OK)
{
return FALSE;
}
}
}
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,6,rgPropertyIDs,
2,rgUnPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle (should be handle to the only row)
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//there should only be one rwo in this table
if (cCountRows!=1)
{
goto CLEANUP;
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the only row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by DBBMK_LAST
//no rows, has to be DB_E_ENDOFROWSET
hr=m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,1,pBookmark,0,1,&cRows,&pHRowSecond);
//this should always be S_OK. REMOVEDELETED is TRUE so a new last row should be fetched.
//anything else is an error.
//here is some code to help debug if the hr is not S_OK
if (DB_S_ENDOFROWSET!=hr)
{
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
//make this a one row table again
g_p1RowTable->Insert(1, PRIMARY);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc delete last row of 1 row table and try to get bookmark. RD=true,BMS=true
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Keyset::Variation_10()
{
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond= NULL;
DBPROPID rgPropertyIDs[6];
DBPROPID rgUnPropertyIDs[2];
BOOL fTestPass=TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
BYTE *pBookmark = NULL;
DBORDINAL cCol = 0;
DBBKMARK cbBookmark = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_REMOVEDELETED;
rgPropertyIDs[5]=DBPROP_OTHERUPDATEDELETE;
rgUnPropertyIDs[0]=DBPROP_BOOKMARKSKIPPED;
rgUnPropertyIDs[1]=DBPROP_OTHERINSERT;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//set the table to one row table
SetTable(g_p1RowTable,DELETETABLE_NO);
//if an ini file is being used then delete and set to one row table
if(GetModInfo()->GetFileName())
{
//delete all rows in the table.
if(g_p1RowTable->DeleteRows(ALLROWS) == S_OK)
{
// RePopulate table
if(g_p1RowTable->Insert(1, PRIMARY) != S_OK)
{
return FALSE;
}
}
}
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,6,rgPropertyIDs,
2,rgUnPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle (should be handle to the only row)
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//there should only be one rwo in this table
if (cCountRows!=1)
{
goto CLEANUP;
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//get the bookmark for the last row in the rowset
if(!GetBookmark(cCountRows,&cbBookmark,&pBookmark))
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the only row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by its bookmark
//row should end of rowset
//this should always be DB_E_BADBOOKMARK. BOOKMARKSSKIPPED is FALSE
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,cbBookmark,(pBookmark),0,1,&cRows,&pHRowSecond),DB_E_BADBOOKMARK);
fTestPass=TRUE;
CLEANUP:
//make this a one row table again
g_p1RowTable->Insert(1, PRIMARY);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(pBookmark);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Bookmark_Keyset::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// {{ TCW_TC_PROTOTYPE(Bookmark_Dynamic)
//*-----------------------------------------------------------------------
//| Test Case: Bookmark_Dynamic - Bookmark_Dynamic
//| Created: 04/15/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Bookmark_Dynamic::Init()
{
DBPROPID rgPropertyIDs[3];
BOOL fTestPass=TEST_SKIPPED;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
if(!TCIRowsetChange::Init())
return FALSE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERINSERT;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
0,NULL,NO_ACCESSOR));
fTestPass=FALSE;
COMPARE(BufferedUpdate(),FALSE);
fTestPass=TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc immediate update mode, call SetData on the key value on the first row handle retrieved by IRowsetLocate::GetRowsAt
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Dynamic::Variation_1()
{
DBBOOKMARK DBBookmark=DBBMK_FIRST;
BYTE *pBookmark=(BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
HROW *pHRowFirst=NULL;
HROW *pHRowSecond=NULL;
void *pData=NULL;
DBPROPID rgPropertyIDs[5];
BOOL fTestPass=TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_OTHERINSERT;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_IRowsetIdentity;
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,5,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//get the first row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRowFirst),S_OK);
//move the cursor away
TESTC_(m_pIRowset->GetNextRows(NULL,10,0,&cRows,&pHRowSecond),S_OK);
//no row should be retrieved
if(!COMPARE(cRows, 0) || !COMPARE(pHRowSecond, NULL))
{
goto CLEANUP;
}
//get the first row handle again by DBBMK_FIRST
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRowSecond),S_OK);
//the two row handles have to be the same
//Compare rows, the two row handles should have the same value
if (GetProperty(DBPROP_LITERALIDENTITY, DBPROPSET_ROWSET, g_pIDBInitialize))
{
COMPARE((DWORD)(*pHRowFirst), (DWORD)(*pHRowSecond));
}
else
{
if (!fnIsSameRow(m_pIRowset,pHRowFirst,pHRowSecond))
{
goto CLEANUP;
}
}
//set new data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRowSecond, m_hAccessor,pData),S_OK);
//release the row handles
TESTC_(m_pIRowset->ReleaseRows(1,pHRowFirst,NULL,NULL,NULL),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
//not going to use pHRowSecond again
PROVIDER_FREE(pHRowSecond);
//retriev
DBBookmark=DBBMK_FIRST;
//get the first row handle again by DBBMK_FIRST
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRowFirst),S_OK);
//get data
TESTC_(GetData(*pHRowFirst,m_hAccessor,m_pData),S_OK);
//the data should be the same as what was set
if(COMPARE(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
{
fTestPass=TRUE;
}
CLEANUP:
PROVIDER_FREE(pData);
if(pHRowFirst && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRowFirst,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRowFirst);
if(pHRowSecond && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc buffered udpate mode, call SetData one the whole row on a middle row handle retrieved by IRowsetLocate::GetRowsByBookmark.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Dynamic::Variation_2()
{
BOOL fTestPass=TEST_SKIPPED;
HROW HRow=NULL;
HACCESSOR hAccessorBookmark=NULL;
DBBKMARK cbBookmark=0;
DBCOUNTITEM cCol;
DBORDINAL *rgColNumber=NULL;
DBPROPID rgPropertyIDs[3];
void *pData=NULL;
BYTE *pBookmark=NULL;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
rgPropertyIDs[2]=DBPROP_OTHERINSERT;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
0,NULL,NO_ACCESSOR));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate) || (!m_pIRowsetUpdate))
goto CLEANUP;
fTestPass=FALSE;
//create an accessor on the bookmark column
cCol=0;
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,&cCol))
//get the bookmark for the 20th row in the rowset
if(!GetBookmark(2,&cbBookmark,&pBookmark))
goto CLEANUP;
//release the accessor on the rowset
ReleaseAccessorOnRowset();
//get an array of numeric and updatable columns
GetNumericAndUpdatable(&cCol,&rgColNumber);
//has to find such a column
if(!cCol)
goto CLEANUP;
//create an accessor on the command object on the numeric and updatable column only
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,rgColNumber))
//create a new data buffer to set the data for the numeric and updatable
//column
TESTC_(FillInputBindings(m_pTable,
DBACCESSOR_ROWDATA,1,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//get the 20th row handle by its bookmark
TESTC_(m_pIRowsetLocate->GetRowsByBookmark(NULL,1,&cbBookmark,
(const BYTE **)(&pBookmark),&HRow,NULL),S_OK);
//set data
TESTC_(SetData(HRow,m_hAccessor,pData),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&HRow,NULL,NULL,NULL),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,&HRow,NULL,NULL,NULL),S_OK);
//get the 20th row handle by its bookmark
TESTC_(m_pIRowsetLocate->GetRowsByBookmark(NULL,1,&cbBookmark,(const BYTE **)&pBookmark,&HRow,NULL),S_OK);
//get data
TESTC_(GetData(HRow, m_hAccessor, m_pData),S_OK);
//the data has to be same as what was set
if(COMPARE(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
PROVIDER_FREE(pData);
PROVIDER_FREE(pBookmark);
if(HRow)
CHECK(m_pIRowset->ReleaseRows(1,&HRow,NULL,NULL,NULL),S_OK);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc delete last row then make sure BMK_LAST sees the new last row. RD=true,BMS=true
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Dynamic::Variation_3()
{
DBBOOKMARK DBBookmark = DBBMK_LAST;
BYTE *pBookmark = (BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond= NULL;
DBPROPID rgPropertyIDs[8];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_REMOVEDELETED;
rgPropertyIDs[5]=DBPROP_BOOKMARKSKIPPED;
rgPropertyIDs[6]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[7]=DBPROP_OTHERINSERT;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,8,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by DBBMK_LAST
//row should be the new last row
hr=m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,1,pBookmark,0,1,&cRows,&pHRowSecond);
//this should always be S_OK. REMOVEDELETED is TRUE so a new last row should be fetched.
//anything else is an error.
//here is some code to help debug if the hr is not S_OK
if (S_OK!=hr)
{
goto CLEANUP;
}
//double check that the deleted row and the row brought back from GetRowsAt are different
hr=m_pIRowsetIdentity->IsSameRow(*pHRow,*pHRowSecond);
if (S_OK==hr)
{
//these are the same, fail the variation, GerRowsAt should have returned
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc delete last row then make sure BMK_LAST sees the new last row. RD=true,BMS=false
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Dynamic::Variation_4()
{
DBBOOKMARK DBBookmark = DBBMK_LAST;
BYTE *pBookmark = (BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond=NULL;
DBPROPID rgPropertyIDs[7];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass=TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_REMOVEDELETED;
rgPropertyIDs[5]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[6]=DBPROP_OTHERINSERT;
rgUnPropertyIDs[0]=DBPROP_BOOKMARKSKIPPED;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,7,rgPropertyIDs,
1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate) || (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position. The query will be re-executed for forward only cursor
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//so restart position. The query will be re-executed for forward only cursor
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position. The query will be re-executed for forward only cursor
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by DBBMK_LAST
//row should be the deleted row (REMOVEDELETED=TRUE) so get the new last row
//new last row of the rowset
hr=m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,1,pBookmark,0,1,&cRows,&pHRowSecond);
//this should always be S_OK. REMOVEDELETED is TRUE so a new last row should be fetched.
//anything else is an error.
//here is some code to help debug if the hr is not S_OK
if (S_OK!=hr)
{
goto CLEANUP;
}
//double check that the deleted row and the row brought back from GetRowsAt are different
hr=m_pIRowsetIdentity->IsSameRow(*pHRow,*pHRowSecond);
if (S_OK==hr)
{
//these are the same, fail the variation, GerRowsAt should have returned
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc delete last row then make sure bookmark sees the new last row, RD=true,BMS=true
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Dynamic::Variation_5()
{
BYTE *pBookmark = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond= NULL;
DBPROPID rgPropertyIDs[8];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
DBCOUNTITEM cCol = 0;
DBBKMARK cbBookmark = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_REMOVEDELETED;
rgPropertyIDs[5]=DBPROP_BOOKMARKSKIPPED;
rgPropertyIDs[6]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[7]=DBPROP_OTHERINSERT;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//create an accessor on the bookmark column
cCol=0;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,8,rgPropertyIDs,
0,NULL, ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,&cCol));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate) || (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//get the bookmark for the last row in the rowset
if(!GetBookmark(cCountRows,&cbBookmark,&pBookmark))
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the last row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by its bookmark
//row should end of rowset
hr=m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,cbBookmark,(pBookmark),0,1,&cRows,&pHRowSecond);
//this should always be DB_S_ENDOFROWSET. REMOVEDELETED is TRUE so the row with the bookmark is gonzo.
//try to get the next row
//anything else is an error.
//here is some code to help debug if the hr is not S_OK
if (DB_S_ENDOFROWSET!=hr)
{
goto CLEANUP;
}
if (pHRowSecond)
{
//double check that the deleted row and the row brought back from GetRowsAt are different
hr=m_pIRowsetIdentity->IsSameRow(*pHRow,*pHRowSecond);
if (S_OK==hr)
{
//these are the same, fail the variation, GerRowsAt should have returned
goto CLEANUP;
}
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(pBookmark);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc delete last row then make sure bookmark sees the new last row, RD=true,BMS=false
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Dynamic::Variation_6()
{
BYTE *pBookmark = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond= NULL;
DBPROPID rgPropertyIDs[7];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
DBCOUNTITEM cCol = 0;
DBBKMARK cbBookmark = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_REMOVEDELETED;
rgPropertyIDs[5]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[6]=DBPROP_OTHERINSERT;
rgUnPropertyIDs[0]=DBPROP_BOOKMARKSKIPPED;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//create an accessor on the bookmark column
cCol=0;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,7,rgPropertyIDs,
1,rgUnPropertyIDs, ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,&cCol));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//get the bookmark for the last row in the rowset
if(!GetBookmark(cCountRows,&cbBookmark,&pBookmark))
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the last row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by its bookmark
//row should end of rowset
//this should always be DB_E_BADBOOKMARK. BOOKMARKSSKIPPED is FALSE
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,cbBookmark,(pBookmark),0,1,&cRows,&pHRowSecond),DB_E_BADBOOKMARK);
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(pBookmark);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc delete last row of 1 row table and try to get BMK_LAST. RD=true,BMS=true
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Dynamic::Variation_7()
{
DBBOOKMARK DBBookmark = DBBMK_LAST;
BYTE *pBookmark = (BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond= NULL;
DBPROPID rgPropertyIDs[8];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr;
ULONG cCountRows = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_REMOVEDELETED;
rgPropertyIDs[5]=DBPROP_BOOKMARKSKIPPED;
rgPropertyIDs[6]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[7]=DBPROP_OTHERINSERT;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//set the table to one row table
SetTable(g_p1RowTable,DELETETABLE_NO);
//if an ini file is being used then delete and set to one row table
if(GetModInfo()->GetFileName())
{
//delete all rows in the table.
if(g_p1RowTable->DeleteRows(ALLROWS) == S_OK)
{
// RePopulate table
if(g_p1RowTable->Insert(1, PRIMARY) != S_OK)
{
return FALSE;
}
}
}
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,8,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle (should be handle to the only row)
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//there should only be one rwo in this table
if (cCountRows!=1)
{
goto CLEANUP;
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the only row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by DBBMK_LAST
//no rows, has to be DB_E_ENDOFROWSET
hr=m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,1,pBookmark,0,1,&cRows,&pHRowSecond);
//this should always be S_OK. REMOVEDELETED is TRUE so a new last row should be fetched.
//anything else is an error.
//here is some code to help debug if the hr is not S_OK
if (DB_S_ENDOFROWSET!=hr)
{
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
//make this a one row table again
g_p1RowTable->Insert(1, PRIMARY);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc delete last row of 1 row table and try to get bookmark. RD=true,BMS=true
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Bookmark_Dynamic::Variation_8()
{
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pHRowSecond= NULL;
DBPROPID rgPropertyIDs[8];
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr;
DBROWCOUNT cCountRows = 0;
BYTE *pBookmark = NULL;
DBCOUNTITEM cCol = 0;
DBCOUNTITEM cbBookmark = 0;
rgPropertyIDs[0]=DBPROP_IRowsetLocate;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetIdentity;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_REMOVEDELETED;
rgPropertyIDs[5]=DBPROP_BOOKMARKSKIPPED;
rgPropertyIDs[6]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[7]=DBPROP_OTHERINSERT;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
//set the table to one row table
SetTable(g_p1RowTable,DELETETABLE_NO);
//if an ini file is being used then delete and set to one row table
if(GetModInfo()->GetFileName())
{
//delete all rows in the table.
if(g_p1RowTable->DeleteRows(ALLROWS) == S_OK)
{
// RePopulate table
if(g_p1RowTable->Insert(1, PRIMARY) != S_OK)
{
return FALSE;
}
}
}
//open a rowset and create an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,8,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass = FALSE;
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the last row handle (should be handle to the only row)
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)))
{
cCountRows++;
if( cRows ==0)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//there should only be one rwo in this table
if (cCountRows!=1)
{
goto CLEANUP;
}
if(DB_S_ENDOFROWSET != hr)
{
goto CLEANUP;
}
//get the bookmark for the last row in the rowset
if(!GetBookmark(cCountRows,&cbBookmark,&pBookmark))
{
goto CLEANUP;
}
//so restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//and fetch last row
TESTC_(m_pIRowset->GetNextRows(NULL,(cCountRows-1),1,&cRows, &pHRow),S_OK);
//delete the only row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position.
hr=m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the LAST row handle again by its bookmark
//row should end of rowset
hr=m_pIRowsetLocate->GetRowsAt(NULL,DB_NULL_HCHAPTER,cbBookmark,(pBookmark),0,1,&cRows,&pHRowSecond);
//this should always be S_OK. REMOVEDELETED is TRUE so a new last row should be fetched.
//anything else is an error.
//here is some code to help debug if the hr is not S_OK
if (DB_S_ENDOFROWSET!=hr)
{
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
//make this a one row table again
g_p1RowTable->Insert(1, PRIMARY);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
PROVIDER_FREE(pBookmark);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Bookmark_Dynamic::Terminate()
{
return(TCIRowsetChange::Terminate());
}//}}
//}}
//}}
// {{ TCW_TC_PROTOTYPE(OrderedBookmark_Keyset)
//*-----------------------------------------------------------------------
//| Test Case: OrderedBookmark_Keyset - OrderedBookmark_Keyset
//| Created: 04/16/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL OrderedBookmark_Keyset::Init()
{
DBPROPID rgPropertyIDs[4];
BOOL fTestPass = TEST_SKIPPED;
if(!TCIRowsetChange::Init())
return FALSE;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
rgPropertyIDs[3]=DBPROP_ORDEREDBOOKMARKS;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgPropertyIDs,0,NULL,NO_ACCESSOR));
fTestPass = FALSE;
COMPARE(BufferedUpdate(),FALSE);
fTestPass=TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc immediate update mode. Create two rowsets on the same table. One rowset changes one row.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int OrderedBookmark_Keyset::Variation_1()
{
HROW *pHRow = NULL;
HROW *pHRowSecond = NULL;
DBBOOKMARK DBBookmark = DBBMK_FIRST;
BYTE *pBookmark = (BYTE *)&DBBookmark;
DBCOUNTITEM cRows = 0;
void *pData = NULL;
void *pDataSecond = NULL;
IRowsetInfo *pIRowsetInfo = NULL;
ICommand *pICommand = NULL;
IUnknown *pIRowset = NULL;
IRowsetLocate *pIRowsetLocate = NULL;
DBPROPID rgPropertyIDs[4];
BOOL fTestPass = TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
rgPropertyIDs[3]=DBPROP_ORDEREDBOOKMARKS;
if(!m_pIDBCreateCommand)
return TEST_SKIPPED;
//create a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,4,rgPropertyIDs,
0,NULL,ON_COMMAND_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate)|| (!m_cBinding))
goto CLEANUP;
fTestPass=FALSE;
//get the 1st row handle by 1st bookmark
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRow),S_OK);
//create a new data buffer to set the data for all updatable columns
//the new data is for the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//create another rowset object on the same command object
//QI for IRowsetInfo pointer
TESTC_(m_pIAccessor->QueryInterface(IID_IRowsetInfo, (LPVOID *)&pIRowsetInfo),S_OK);
//get the ICommand pointer
TESTC_(pIRowsetInfo->GetSpecification(IID_ICommand,(IUnknown **)&pICommand),S_OK);
//exeute the same command object
TESTC_(pICommand->Execute(NULL,IID_IRowset,NULL,NULL,&pIRowset),S_OK);
//QI for IRowsetLocate pointer on the second rowset
if(!COMPARE(((IRowset *)pIRowset)->QueryInterface(IID_IRowset,(LPVOID *)&pIRowsetLocate),S_OK))
{
goto CLEANUP;
}
//set data on the first rowset
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
//allocate memory of pDataSecond
if(!(pDataSecond=PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
//retrieve the 1st row handle on the second rowset by 1st bookmark
if(SUCCEEDED(m_hr=pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRowSecond)))
{
//get data on the second rowset. Share the same accessor on the command
TESTC_(((IRowset *)(pIRowset))->GetData(*pHRowSecond,m_hAccessor,pDataSecond),S_OK);
}
else
{
//the first row is detected as deleted
COMPARE(m_hr, DB_E_DELETEDROW);
//get the last row by it bookmark
DBBookmark=DBBMK_LAST;
TESTC_(pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRowSecond),S_OK);
goto CLEANUP;
//get data on the second rowset. Share the same accessor on the command
TESTC_(((IRowset *)(pIRowset))->GetData(*pHRowSecond,m_hAccessor,pDataSecond),S_OK);
}
//the second rowset should be able to see the change
if(COMPARE(CompareBuffer(pDataSecond,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
{
fTestPass=TRUE;
}
CLEANUP:
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(pHRowSecond && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
PROVIDER_FREE(pData);
PROVIDER_FREE(pDataSecond);
SAFE_RELEASE(pIRowsetInfo);
SAFE_RELEASE(pIRowsetLocate);
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pICommand);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc buffered update mode. Create two rowsets on the same table. The second row set changed a row.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int OrderedBookmark_Keyset::Variation_2()
{
HROW *pHRow = NULL;
HROW *pHRowSecond = NULL;
DBCOUNTITEM cRows = 0;
DBBOOKMARK DBBookmark = DBBMK_FIRST;
BYTE *pBookmark = (BYTE *)&DBBookmark;
DBCOUNTITEM cCol = 0;
DBORDINAL *rgColNumber = NULL;
void *pData = NULL;
void *pDataSecond = NULL;
IRowsetInfo *pIRowsetInfo = NULL;
IRowsetLocate *pIRowsetLocate = NULL;
ICommand *pICommand = NULL;
IUnknown *pIRowset = NULL;
DBPROPID rgPropertyIDs[4];
BOOL fTestPass = TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
rgPropertyIDs[3]=DBPROP_ORDEREDBOOKMARKS;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgPropertyIDs,0,NULL,NO_ACCESSOR));
//get an array of numeric and updatable columns
GetNumericAndUpdatable(&cCol,&rgColNumber);
//has to find such a column
if(!cCol)
goto CLEANUP;
ReleaseRowsetAndAccessor();
//create an accessor on the command object on the numeric and updatable column only
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgPropertyIDs,
0,NULL,ON_COMMAND_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,rgColNumber));
if ((!m_pIRowsetChange) || (!m_pIRowsetLocate) || (!m_pIRowsetUpdate))
goto CLEANUP;
fTestPass=FALSE;
//get the 20th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,10,1,&cRows,&pHRow),S_OK);
//get the 1st row handle by 1st bookmark
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRow),S_OK);
//create a new data buffer to set the data for the numeric and updatable//column
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,1,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//create another rowset object on the same command object
TESTC_(m_pIAccessor->QueryInterface(IID_IRowsetInfo, (LPVOID *)&pIRowsetInfo),S_OK);
if(!m_pIDBCreateCommand)
return TEST_PASS;
//get the ICommand pointer
TESTC_(pIRowsetInfo->GetSpecification(IID_ICommand,(IUnknown **)&pICommand),S_OK);
//exeute the same command object
TESTC_(pICommand->Execute(NULL,IID_IRowset,NULL,NULL,
&pIRowset),S_OK);
//QI for IRowsetLocate pointer on the second rowset
if(!COMPARE(((IRowset *)pIRowset)->QueryInterface(IID_IRowset,
(LPVOID *)&pIRowsetLocate),S_OK))
goto CLEANUP;
//set data on the first rowset
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//allocat memory of pDataSecond
if(!(pDataSecond=PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//get the 1st row handle by 1st bookmark on the second rowset by its bookmark
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRowSecond),S_OK);
//get data on the second rowset. Share the same accessor on the command
TESTC_(((IRowset *)(pIRowset))->GetData(*pHRowSecond,m_hAccessor,pDataSecond),S_OK);
//the second rowset should see the change
if(COMPARE(CompareBuffer(pDataSecond, pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
fTestPass=TRUE;
CLEANUP:
if(rgColNumber)
PROVIDER_FREE(rgColNumber);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if(pHRowSecond && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
PROVIDER_FREE(pData);
PROVIDER_FREE(pDataSecond);
SAFE_RELEASE(pIRowsetInfo);
SAFE_RELEASE(pIRowsetLocate);
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pICommand);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL OrderedBookmark_Keyset::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Invalid_Keyset_Cursor_Immediate)
//*-----------------------------------------------------------------------
//| Test Case: Invalid_Keyset_Cursor_Immediate - Invalid_Keyset_Cursor_Immediate
//| Created: 04/16/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Invalid_Keyset_Cursor_Immediate::Init()
{
DBPROPID rgPropertyIDs[2];
BOOL fTestPass = TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
if(!TCIRowsetChange::Init())
return FALSE;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgPropertyIDs,0,NULL,NO_ACCESSOR));
fTestPass = TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc The accessor is DBACCESSOR_READ | DBACCCESOR_PASSBYREF. DB_E_READONLYACCESSOR or E_FAIL.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Immediate::Variation_1()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
void *pData = NULL;
DBPROPID rgPropertyIDs[3];
BOOL fGetAccessor;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
HRESULT hr = S_OK;
if (!GetProperty(DBPROP_BYREFACCESSORS, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, VARIANT_TRUE))
{
goto CLEANUP;
}
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,0,NULL,NO_ACCESSOR));
//create an accessor on the command object on updatable columns
fGetAccessor = GetAccessorOnRowset(ON_ROWSET_ACCESSOR, TRUE,
DBACCESSOR_PASSBYREF | DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND);
if (fGetAccessor==TEST_SKIPPED)
{
goto CLEANUP;
}
TESTC_PROVIDER(fGetAccessor);
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//insert should fail
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,NULL),DB_E_BADACCESSORTYPE);
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,9,1,&cRows,&pHRow),S_OK);
//set data should fail
if(CHECK(m_pIRowsetChange->SetData(*pHRow,m_hAccessor,pData),DB_E_BADACCESSORTYPE))
{
fTestPass=TRUE;
}
CLEANUP:
if(pData)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
}
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc The accessor is DBACCCESOR_PASSCOLUMNSBYREF. DB_E_READONLYACCESSOR or E_FAIL.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Immediate::Variation_2()
{
return TEST_PASS;
}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc The status flag specified in a binding structure is neither DBSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALUE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Immediate::Variation_3()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
DBORDINAL rgColNumber[2];
HROW *pHRow = NULL;
void *pData = NULL;
void *pGetData = NULL;
DBPROPID rgPropertyIDs[3];
DBSTATUS dbsSecondColStatus;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
HRESULT hr = S_OK;
rgColNumber[0]=1;
rgColNumber[1]=3;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,0,NULL,NO_ACCESSOR));
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass=FALSE;
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//create an accessor on the command object on updatable columns
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,
2,rgColNumber))
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//change the second status binding to anything other than _OK or NULL
// *(DBSTATUS *)(((DWORD)pData)+ m_rgBinding[0].obStatus)=DBSTATUS_S_TRUNCATED;
STATUS_BINDING(m_rgBinding[0],pData)=DBSTATUS_S_TRUNCATED;
// keep track of 2nd colstatus
// dbsSecondColStatus = *(DBSTATUS *)(((DWORD)pData)+ m_rgBinding[1].obStatus);
dbsSecondColStatus = STATUS_BINDING(m_rgBinding[0],pData);
//set data should fail
m_hr=SetData(*pHRow,m_hAccessor,pData);
if ( !COMPARE(m_hr == DB_E_ERRORSOCCURRED || m_hr == DB_S_ERRORSOCCURRED, TRUE) )
goto CLEANUP;
TESTC_(GetStatus(pData, &(m_rgBinding[0])),DBSTATUS_E_BADSTATUS);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if ( m_hr == DB_S_ERRORSOCCURRED )
{
if(m_cBinding > 1)
{
TESTC_(GetStatus(pData, &(m_rgBinding[1])),dbsSecondColStatus);
}
}
else
{
if(m_cBinding > 1)
{
TESTC_(GetStatus(pData, &(m_rgBinding[1])),DBSTATUS_E_UNAVAILABLE);
}
//allocate memory for getting data again
pGetData=PROVIDER_ALLOC(m_cRowSize);
if(!pGetData)
{
goto CLEANUP;
}
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, pGetData),S_OK);
//columns should not be changed
if(!COMPARE(CompareBuffer(pGetData, m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
{
goto CLEANUP;
}
}
fTestPass=TRUE;
CLEANUP:
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
PROVIDER_FREE(pGetData);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc The column number specified in the last binding structure = # of columns of the rowset+1. DB_E_COLUMNUNAVAILABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Immediate::Variation_4()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
IAccessor *pIAccessor = NULL;
HACCESSOR hAccessor = NULL;
DBORDINAL iOrdinal;
void *pData = NULL;
void *pGetData = NULL;
DBPROPID rgPropertyIDs[3];
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
0,NULL,NO_ACCESSOR));
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass=FALSE;
//create an accessor on the command object on updatable columns
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND))
//save the old column number
iOrdinal=m_rgBinding[m_cBinding-1].iOrdinal;
m_rgBinding[m_cBinding-1].iOrdinal=m_cRowsetCols+10;
//QI for IAccessor pointer on the rowset object
TESTC_(m_pIRowset->QueryInterface(IID_IAccessor, (LPVOID *)&pIAccessor),S_OK);
if(FAILED(m_hr=pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,0,&hAccessor,NULL)))
{
fTestPass=TRUE;
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//copy back the column number
m_rgBinding[m_cBinding-1].iOrdinal=iOrdinal;
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data should fail
TESTC_(m_hr=SetData(*pHRow,hAccessor,pData),DB_E_BADORDINAL);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
//allocate memory for getting data again
pGetData=PROVIDER_ALLOC(m_cRowSize);
if(!pGetData)
goto CLEANUP;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, pGetData),S_OK);
//data should not be changed
if(COMPARE(CompareBuffer(pGetData, m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
fTestPass=TRUE;
CLEANUP:
if(hAccessor)
CHECK(pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
SAFE_RELEASE(pIAccessor);
m_hAccessor=NULL;
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
PROVIDER_FREE(pGetData);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Set a duplicate column on which a unique index is created. DB_E_INTEGRITYVIOLATION.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Immediate::Variation_5()
{
BOOL fTestPass=TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow=NULL;
DBORDINAL rgColNumber[1];
void *pData=NULL;
void *pGetData=NULL;
DBPROPID rgPropertyIDs[3];
HROW *pUpdatedHRow=NULL;
DBROWSTATUS *pDBRowStatus=NULL;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
HRESULT hr = S_OK;
if(!m_pIDBCreateCommand || !m_bIndexExists)
return TEST_PASS;
rgColNumber[0]=g_pTable->GetIndexColumn();
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
0,NULL,NO_ACCESSOR));
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass=FALSE;
//create an accessor on the command object on the 1st columns
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,
1,rgColNumber))
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the 2nd row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the previous (1st) row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data (first row) should be ok
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//get a (2nd) row handle - again
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//set this time (the 2nd time) should fail
hr=SetData(*pHRow,m_hAccessor,pData);
if (DB_E_ERRORSOCCURRED==hr)
{
if(!COMPARE(GetStatus(pData,&(m_rgBinding[0])),DBSTATUS_E_INTEGRITYVIOLATION))
goto CLEANUP;
}
else if (DB_E_INTEGRITYVIOLATION!=hr)
{
odtLog << "INTEGRITYVIOLATION ERROR"<<ENDL;
goto CLEANUP;
}
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//allocate memory for getting data again
pGetData=PROVIDER_ALLOC(m_cRowSize);
if(!pGetData)
goto CLEANUP;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, pGetData),S_OK);
// data should not be changed
if(COMPARE(CompareBuffer(pGetData, m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
fTestPass=TRUE;
CLEANUP:
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
PROVIDER_FREE(pGetData);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
}
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc The accessor sets the status field of non nullable columns NULL. DB_E_SCHEMAVIOLATION. The row goes back to its original sta
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Immediate::Variation_6()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW* pHRow = NULL;
DBCOUNTITEM ulCol = 0;
DBORDINAL* rgColNumber = 0;
void* pData = NULL;
void* pGetData = NULL;
DBPROPID rgPropertyIDs[3];
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
0,NULL,NO_ACCESSOR));
//Get Not nullable and Updatable column. .
if(!GetNotNullableAndUpdatable(&ulCol, &rgColNumber))
{
odtLog<<L"There are no Updateble, not null columns, test Skipped."<<ENDL;
goto CLEANUP;
}
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass=FALSE;
//create an accessor on the command object on the nullable columns
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,
1,rgColNumber))
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set the not nullable column to NULL
// *(DBSTATUS *)(((DWORD)pData)+m_rgBinding[0].obStatus)=DBSTATUS_S_ISNULL;
*(DBSTATUS*)&STATUS_BINDING(m_rgBinding[0],pData)=DBSTATUS_S_ISNULL;
//set data should fail
TESTC_(SetData(*pHRow,m_hAccessor,pData),DB_E_ERRORSOCCURRED);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
//allocate memory for getting data again
pGetData=PROVIDER_ALLOC(m_cRowSize);
if(!pGetData)
{
goto CLEANUP;
}
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, pGetData),S_OK);
//no data should be changed
if(COMPARE(CompareBuffer(pGetData, m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
PROVIDER_FREE(pGetData);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc The length binding > cbMaxLen for a variable length column. DB_S_ERRORSOCCURRED. Truncation should occur. Check the status b
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Immediate::Variation_7()
{
BOOL fTestPass=TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow=NULL;
DBCOUNTITEM cCnt;
DBCOUNTITEM ulCol;
DBORDINAL *rgColNumber = NULL;
DBORDINAL rgColToBind[2];
void *pData=NULL;
void *pGetData=NULL;
DBPROPID rgPropertyIDs[3];
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
rgColToBind[0]=1;
rgColToBind[1]=1;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,0,NULL,NO_ACCESSOR));
//Get a variable length column. .
if(!GetVariableLengthAndUpdatable(&ulCol, &rgColNumber))
{
odtLog << "no variable length updateable columns available"<<ENDL;
fTestPass = TRUE;
goto CLEANUP;
}
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
fTestPass=FALSE;
//find a data type that is not ORed with DBTYPE_ARRAY or DBTYPE_VECTOR
for(cCnt=0; cCnt<ulCol; cCnt++)
{
if( ((m_rgInfo[rgColNumber[cCnt]-1].wType & DBTYPE_ARRAY) == 0) &&
((m_rgInfo[rgColNumber[cCnt]-1].wType & DBTYPE_VECTOR) == 0)
)
{
break;
}
}
if(cCnt==ulCol)
{
odtLog << "no variable length updateable columns that is not ORed with DBTYPE_ARRAY or DBTYPE_VECTOR available"<<ENDL;
fTestPass = TEST_SKIPPED;
goto CLEANUP;
}
//if this is a bookmarked rowset account for the first ordinal being zero
if (m_rgInfo[0].iOrdinal==1)
{
rgColNumber[cCnt]--;
}
rgColToBind[1]=m_rgInfo[rgColNumber[cCnt]].iOrdinal;
//accessor on 1st variable length and updatable column
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,
2,rgColToBind))
//restartPosition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//change the length to cbMaxLen + 1
// *(ULONG *)((DWORD)pData+m_rgBinding[1].obLength)=m_rgBinding[1].cbMaxLen+1;
LENGTH_BINDING(m_rgBinding[1],pData)=m_rgBinding[1].cbMaxLen+1;
//set data should fail
hr = SetData(*pHRow,m_hAccessor,pData);
if (DB_E_ERRORSOCCURRED==hr)
{
// if(!COMPARE(*(DBSTATUS *)((DWORD)pData+m_rgBinding[1].obStatus),DBSTATUS_E_CANTCONVERTVALUE))
if(!COMPARE(STATUS_BINDING(m_rgBinding[1],pData),DBSTATUS_E_CANTCONVERTVALUE))
{
goto CLEANUP;
}
//check the status for the 1st column
// if(!COMPARE(*(DBSTATUS *)((DWORD)pData+m_rgBinding[0].obStatus),DBSTATUS_E_UNAVAILABLE))
if(!COMPARE(STATUS_BINDING(m_rgBinding[0],pData),DBSTATUS_E_UNAVAILABLE))
{
goto CLEANUP;
}
}
else
{
if (DB_S_ERRORSOCCURRED==hr)
{
// if(!COMPARE(*(DBSTATUS *)((DWORD)pData+m_rgBinding[1].obStatus),DBSTATUS_E_CANTCONVERTVALUE))
if(!COMPARE(*(DBSTATUS*)&STATUS_BINDING(m_rgBinding[1],pData),DBSTATUS_E_CANTCONVERTVALUE))
{
goto CLEANUP;
}
//check the staus for the 1st column
// if(!COMPARE(*(DBSTATUS *)((DWORD)pData+m_rgBinding[0].obStatus),DBSTATUS_S_OK))
if(!COMPARE(STATUS_BINDING(m_rgBinding[0],pData),DBSTATUS_S_OK))
{
goto CLEANUP;
}
}
else
{
goto CLEANUP;
}
}
//release the row handle
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
//allocate memory for getting data again
pGetData=PROVIDER_ALLOC(m_cRowSize);
if(!pGetData)
{
goto CLEANUP;
}
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//Make sure no row is inserted
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows,1,&cRows,&pHRow),DB_S_ENDOFROWSET);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
PROVIDER_FREE(pGetData);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseAccessorOnRowset();
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc The accessor only has length binding. E_FAIL.(See testing issue #2
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Immediate::Variation_8()
{
BOOL fTestPass=TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
ULONG cCount=0;
HROW *pHRow=NULL;
void *pData=NULL;
DBPROPID rgPropertyIDs[3];
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
0,NULL,NO_ACCESSOR));
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass=FALSE;
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//acceesor with only length binding
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, TRUE,DBACCESSOR_ROWDATA,
DBPART_LENGTH,UPDATEABLE_COLS_BOUND))
//get some data to insert
pData=PROVIDER_ALLOC(m_cRowSize);
for(cCount=0; cCount<m_cBinding; cCount++)
// *(ULONG *)((DWORD)pData+m_rgBinding[cCount].obLength)=2;
// *(ULONG *)((DWORD)pData+m_rgBinding[cCount].obLength)=2;
//set data should fail
if(CHECK(SetData(*pHRow,m_hAccessor,pData),DB_E_ERRORSOCCURRED))
{
//can't check status, it wasn't bound
fTestPass=TRUE;
}
CLEANUP:
PROVIDER_FREE(pData);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseAccessorOnRowset();
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc The accessor only has status and length binding. Some the columns are not set to NULL.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Immediate::Variation_9()
{
BOOL fTestPass=TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
ULONG cCount=0;
HROW *pHRow=NULL;
void *pData=NULL;
DBPROPID rgPropertyIDs[3];
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,0,NULL,NO_ACCESSOR));
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass=FALSE;
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//acceesor with only length binding
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, TRUE,DBACCESSOR_ROWDATA,
DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND))
//get some data to insert
pData=PROVIDER_ALLOC(m_cRowSize);
for(cCount=0; cCount<m_cBinding; cCount++)
{
// *(ULONG *)((DWORD)pData+m_rgBinding[cCount].obLength)=2;
// *(DBSTATUS *)((DWORD)pData+m_rgBinding[cCount].obStatus)=DBSTATUS_S_OK;
LENGTH_BINDING(m_rgBinding[cCount],pData)=2;
STATUS_BINDING(m_rgBinding[cCount],pData)=DBSTATUS_S_OK;
}
//set data should fail
TESTC_(SetData(*pHRow,m_hAccessor,pData),DB_E_ERRORSOCCURRED);
for(cCount=0; cCount<m_cBinding; cCount++)
{
if(!COMPARE(GetStatus(pData, &(m_rgBinding[cCount])),DBSTATUS_E_UNAVAILABLE))
{
goto CLEANUP;
}
}
//release the row handle
PROVIDER_FREE(pData);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
ReleaseAccessorOnRowset();
//get accessor on the rowset for length binding only
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,
DBACCESSOR_ROWDATA,DBPART_LENGTH,UPDATEABLE_COLS_BOUND))
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get some data to insert
pData=PROVIDER_ALLOC(m_cRowSize);
for(cCount=0; cCount<m_cBinding; cCount++)
{
// *(ULONG *)((DWORD)pData+m_rgBinding[cCount].obLength)=2;
LENGTH_BINDING(m_rgBinding[cCount],pData)=2;
}
//set data should fail
if(CHECK(SetData(*pHRow,m_hAccessor,pData),DB_E_ERRORSOCCURRED))
{
//can't chceck status, onlylength is bound here
fTestPass=TRUE;
}
CLEANUP:
PROVIDER_FREE(pData);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc Set an auto increment column. DB_SEC_E_PERMISSIONDENIED
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Immediate::Variation_10()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
DBCOUNTITEM cNotUpdateCol = 0;
DBCOUNTITEM *rgNotUpdateColNumber = NULL;
DBCOUNTITEM cCol = 0;
DBORDINAL *rgColNumber = NULL;
ULONG cCount = 0;
ULONG cBinding = 0;
void *pData = NULL;
void *pGetData = NULL;
DBPROPID rgPropertyIDs[3];
DBCOUNTITEM i = 0;
DBCOUNTITEM j = 0;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_IRowsetLocate;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
0,NULL,NO_ACCESSOR));
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass=FALSE;
//Get Non Updatable column. If all columns are updatable, exit.
GetNotUpdatable(&cNotUpdateCol,&rgNotUpdateColNumber);
if(cNotUpdateCol==0)
{
fTestPass=TEST_SKIPPED;
goto CLEANUP;
}
//get an array of columns that exclude the 1st column
if(!GetAllButFirst(&cCol, &rgColNumber))
{
goto CLEANUP;
}
//create an accessor on the rowset object on the all the columns
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF,
DBTYPE_EMPTY, cCol, rgColNumber))
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//fill input bindings will set the staus of read-only cols to DBSTATUS_S_IGNORE
//change it back to S_OK so we try to bind to the read-only columns
for (i=0;i<cCol;i++)
{
for (j=0;j<cNotUpdateCol;j++)
{
if (m_rgBinding[i].iOrdinal==rgNotUpdateColNumber[j])
{
// *(ULONG *)((DWORD)pData+m_rgBinding[i].obStatus)=DBSTATUS_S_OK;
STATUS_BINDING(m_rgBinding[i],pData)=DBSTATUS_S_OK;
}
}
}
//set data should fail
hr = SetData(*pHRow,m_hAccessor,pData);
if ( !COMPARE(hr == DB_S_ERRORSOCCURRED || hr == DB_E_ERRORSOCCURRED, TRUE ) )
{
goto CLEANUP;
}
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if ( hr == DB_E_ERRORSOCCURRED )
{
//allocate memory for getting data again
pGetData=PROVIDER_ALLOC(m_cRowSize);
if(!pGetData)
{
goto CLEANUP;
}
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, pGetData),S_OK);
//no data should be changed
if(COMPARE(CompareBuffer(pGetData, m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
{
fTestPass=TRUE;
}
}
else
{
// check status of each not updateable column
for (i=0;i<cCol;i++)
{
for (j=0;j<cNotUpdateCol;j++)
{
if (m_rgBinding[i].iOrdinal==rgNotUpdateColNumber[j])
{
// if (!COMPARE(*(DBSTATUS *)((DWORD)pData+m_rgBinding[i].obStatus), DBSTATUS_E_PERMISSIONDENIED))
if (!COMPARE(STATUS_BINDING(m_rgBinding[i],pData), DBSTATUS_E_PERMISSIONDENIED))
{
goto CLEANUP;
}
}
}
}
}
fTestPass=TEST_PASS;
CLEANUP:
CoTaskMemFree(pData); pData = NULL; //PROVIDER_FREE(pData);
PROVIDER_FREE(pGetData);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(rgColNumber);
PROVIDER_FREE(rgNotUpdateColNumber);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc Setting a bookmark column DBSTATUS_E_?
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Immediate::Variation_11()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
ULONG cCount = 0;
HROW *pHRow = NULL;
DBCOUNTITEM cNotUpdateCol = 0;
DBCOUNTITEM *rgNotUpdateColNumber = NULL;
DBCOUNTITEM cCol = 0;
DBORDINAL rgColNumber[1];
void *pData = NULL;
void *pGetData = NULL;
DBPROPID rgPropertyIDs[4];
DBPROPID rgUnPropertyIDs[1];
DWORD dwStatus = DBSTATUS_S_OK;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetLocate;
rgPropertyIDs[2]=DBPROP_BOOKMARKS;
rgPropertyIDs[3]=DBPROP_OTHERUPDATEDELETE;
rgUnPropertyIDs[0]=DBPROP_COLUMNRESTRICT;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgPropertyIDs,1,rgUnPropertyIDs,NO_ACCESSOR));
//Get Non Updatable column. If all columns are updatable, exit.
GetNotUpdatable(&cNotUpdateCol,&rgNotUpdateColNumber);
if(cNotUpdateCol==0)
goto CLEANUP;
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass=FALSE;
//set array for the bookmark col
rgColNumber[0]=0;
cCol=1;
//create an accessor on the rowset object on the all the columns
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF,
DBTYPE_EMPTY, cCol, rgColNumber))
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//make new data to set
if(!(pData=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
memset(pData,0,(size_t)m_cRowSize);
// *(ULONG *)((DWORD)pData+m_rgBinding[0].obStatus) = DBSTATUS_S_OK;
// *(ULONG *)((DWORD)pData+m_rgBinding[0].obValue) = 2525;
// *(ULONG *)((DWORD)pData+m_rgBinding[0].obLength) = 4;
*(DBBKMARK*)&VALUE_BINDING(m_rgBinding[0], pData)=2525;
STATUS_BINDING(m_rgBinding[0],pData)=DBSTATUS_S_OK;
LENGTH_BINDING(m_rgBinding[0],pData)=4;
//set data should fail
if(FAILED(m_hr=SetData(*pHRow,m_hAccessor,pData)))
{
// dwStatus=*(DBSTATUS *)((DWORD)pData+m_rgBinding[0].obStatus);
dwStatus=STATUS_BINDING(m_rgBinding[0],pData);
if (COMPARE(m_hr == DB_E_ERRORSOCCURRED || m_hr == DB_S_ERRORSOCCURRED, TRUE))
{
//not sure what the error status should be but i'll use INTEGRITYVIOLATION for the time being
if(!COMPARE(dwStatus,DBSTATUS_E_PERMISSIONDENIED))
{
goto CLEANUP;
}
}
}
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
fTestPass=TRUE;
CLEANUP:
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(rgNotUpdateColNumber);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc asking for no REMOVEDELETED on dynamic cursor
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Immediate::Variation_12()
{
BOOL fTestPass =TEST_PASS;
DBPROPID rgPropertyIDs[2];
DBPROPID rgUnPropertyIDs[1];
DWORD dwStatus =DBSTATUS_S_OK;
rgPropertyIDs[0]=DBPROP_OTHERINSERT;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgUnPropertyIDs[0]=DBPROP_REMOVEDELETED;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,1,rgUnPropertyIDs,NO_ACCESSOR));
//DBPROP_OTHERINSERT gets a dynamic cursor
//DBPROP_REMOVEDELETED must be TRUE if there is a dynamic cursor
//so if we have a rowset with the props requested there is an error
fTestPass = TEST_FAIL;
CLEANUP:
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Invalid_Keyset_Cursor_Immediate::Terminate()
{
ReleaseRowsetAndAccessor();
return(TCIRowsetChange::Terminate());
} // }}
// }}
// {{ TCW_TC_PROTOTYPE(Invalid_Keyset_Cursor_Buffered)
//*-----------------------------------------------------------------------
//| Test Case: Invalid_Keyset_Cursor_Buffered - Invalid_Keyset_Cursor_Buffered
//| Created: 04/16/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Invalid_Keyset_Cursor_Buffered::Init()
{
DBPROPID rgPropertyIDs[2];
BOOL fTestPass = TEST_SKIPPED;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
if(!TCIRowsetChange::Init())
return FALSE;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,NO_ACCESSOR));
fTestPass = TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc The Accessor is read-only accessor. DB_E_READONLYACCESSOR or E_FAIL.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Buffered::Variation_1()
{
BOOL fTestPass=TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow=NULL;
void *pData=NULL;
DBPROPID rgPropertyIDs[3];
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_BYREFACCESSORS;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
0,NULL,NO_ACCESSOR));
fTestPass=FALSE;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create an accessor on the command object on updatable columns
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_PASSBYREF | DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//insert should fail
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,NULL),DB_E_BADACCESSORTYPE);
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,9,1,&cRows,&pHRow),S_OK);
//set data should fail
if(CHECK(m_pIRowsetChange->SetData(*pHRow,m_hAccessor,pData),DB_E_BADACCESSORTYPE))
fTestPass=TRUE;
CLEANUP:
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc The accessor is DBACCESSOR_READ | DBACCCESOR_PASSCOLUMNSBYREF. DB_E_READONLYACCESSOR or E_FAIL.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Buffered::Variation_2()
{
return TEST_PASS;
}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Set an auto increment column. DB_SEC_E_PERMISSIONDENIED
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Buffered::Variation_3()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
ULONG cCount = 0;
HROW *pHRow = NULL;
HROW *pUpdatedHRow = NULL;
DBROWSTATUS *pDBRowStatus = NULL;
DBCOUNTITEM cNotUpdateCol = 0 ;
DBCOUNTITEM *rgNotUpdateColNumber = NULL;
DBCOUNTITEM cCol = 0;
DBORDINAL *rgColNumber = NULL;
void *pData = NULL;
void *pGetData = NULL;
DBPROPID rgPropertyIDs[2];
DBCOUNTITEM i = 0;
DBCOUNTITEM j = 0;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
0,NULL,NO_ACCESSOR));
//Get Non Updatable column. If all columns are updatable, exit.
GetNotUpdatable(&cNotUpdateCol,&rgNotUpdateColNumber);
if(cNotUpdateCol==0)
{
goto CLEANUP;
}
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate))
{
goto CLEANUP;
}
fTestPass=FALSE;
//get an array of columns that exclude the 1st column
if(!GetAllButFirst(&cCol, &rgColNumber))
{
goto CLEANUP;
}
//create an accessor on the rowset object on the all the columns
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF,
DBTYPE_EMPTY, cCol, rgColNumber))
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//fill input bindings will set the staus of read-only cols to DBSTATUS_S_IGNORE
//change it back to S_OK so we try to bind to the read-only columns
for (i=0;i<cCol;i++)
{
for (j=0;j<cNotUpdateCol;j++)
{
if (m_rgBinding[i].iOrdinal==rgNotUpdateColNumber[j])
{
// *(ULONG *)((DWORD)pData+m_rgBinding[i].obStatus)=DBSTATUS_S_OK;
STATUS_BINDING(m_rgBinding[i],pData)=DBSTATUS_S_OK;
}
}
}
//set data should fail
if(FAILED(m_hr=SetData(*pHRow,m_hAccessor,pData)))
{
if ( !COMPARE(m_hr == DB_S_ERRORSOCCURRED || m_hr == DB_E_ERRORSOCCURRED, TRUE ) )
{
goto CLEANUP;
}
}
else
{
//update should fail
hr=m_pIRowsetUpdate->Update(NULL,1,pHRow,&cRows,&pUpdatedHRow,&pDBRowStatus);
if ( !COMPARE(hr == DB_E_ERRORSOCCURRED || hr == DB_S_ERRORSOCCURRED, TRUE) )
{
if(!COMPARE(*pDBRowStatus,DBROWSTATUS_E_INTEGRITYVIOLATION))
goto CLEANUP;
}
}
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if ( m_hr == DB_E_ERRORSOCCURRED )
{
//allocate memory for getting data again
pGetData=PROVIDER_ALLOC(m_cRowSize);
if(!pGetData)
{
goto CLEANUP;
}
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, pGetData),S_OK);
//no data should be changed
if(COMPARE(CompareBuffer(pGetData, m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
{
fTestPass=TRUE;
}
}
else
{
// check status of each not updateable column
for (i=0;i<cCol;i++)
{
for (j=0;j<cNotUpdateCol;j++)
{
if (m_rgBinding[i].iOrdinal==rgNotUpdateColNumber[j])
{
// if (!COMPARE(*(DBSTATUS *)((DWORD)pData+m_rgBinding[i].obStatus), DBSTATUS_E_PERMISSIONDENIED))
if (!COMPARE(STATUS_BINDING(m_rgBinding[i],pData), DBSTATUS_E_PERMISSIONDENIED))
{
goto CLEANUP;
}
}
}
}
}
fTestPass=TEST_PASS;
CLEANUP:
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
PROVIDER_FREE(pUpdatedHRow);
PROVIDER_FREE(pDBRowStatus);
PROVIDER_FREE(pGetData);
PROVIDER_FREE(pUpdatedHRow);
PROVIDER_FREE(pDBRowStatus);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(rgColNumber);
PROVIDER_FREE(rgNotUpdateColNumber);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc The status flag specified in a binding structure is MAX(DWORD)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Buffered::Variation_4()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW* pHRow = NULL;
void* pData = NULL;
DBPROPID rgPropertyIDs[2];
ULONG cCount = 0;
HRESULT hr = S_OK;
DBCOUNTITEM ulIndex = 0;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,NO_ACCESSOR));
if (!m_pIRowsetChange||!m_pIRowsetUpdate)
goto CLEANUP;
fTestPass=FALSE;
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//create an accessor on the rowset object on updatable columns
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND))
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//change the first status binding to anything other than _OK or NULL
// *(ULONG *)(((DWORD)pData)+ m_rgBinding[3].obStatus)=MAX_ULONG;
STATUS_BINDING(m_rgBinding[3],pData)=MAX_ULONG;
//set data should fail
hr = SetData(*pHRow,m_hAccessor,pData);
for (cCount=0;cCount<m_cBinding;cCount++)
{
if (DB_E_ERRORSOCCURRED==hr)
{
// if( *(DBSTATUS *)((DWORD)pData+m_rgBinding[1].obStatus)!=DBSTATUS_E_CANTCONVERTVALUE &&
// *(DBSTATUS *)((DWORD)pData+m_rgBinding[0].obStatus)!=DBSTATUS_E_UNAVAILABLE )
if ( DBSTATUS_E_CANTCONVERTVALUE != STATUS_BINDING(m_rgBinding[1],pData) &&
DBSTATUS_E_UNAVAILABLE != STATUS_BINDING(m_rgBinding[0],pData))
{
goto CLEANUP;
}
}
else
{
if (DB_S_ERRORSOCCURRED==hr)
{
// if( *(DBSTATUS *)((DWORD)pData+m_rgBinding[1].obStatus)!=DBSTATUS_E_CANTCONVERTVALUE &&
// *(DBSTATUS *)((DWORD)pData+m_rgBinding[0].obStatus)!=DBSTATUS_S_OK )
if ( DBSTATUS_E_CANTCONVERTVALUE != STATUS_BINDING(m_rgBinding[1],pData) &&
DBSTATUS_S_OK != STATUS_BINDING(m_rgBinding[0],pData))
{
goto CLEANUP;
}
}
else
{
goto CLEANUP;
}
}
}
if(!COMPARE(GetStatus(pData,&(m_rgBinding[3])),DBSTATUS_E_BADSTATUS))
{
goto CLEANUP;
}
//if some columns were set expect a status of OK for all but the bad status column
if (DB_S_ERRORSOCCURRED==hr)
{
//the status for the rest
for(ulIndex=m_cBinding; ulIndex>0; ulIndex--)
{
if(ulIndex==4)
{
continue;
}
if(!COMPARE(GetStatus(pData,&(m_rgBinding[ulIndex-1])),DBSTATUS_S_OK))
{
goto CLEANUP;
}
}
}
//if no columns were set expect a status of UNAVAILABLE for all but the bad status column
if (DB_E_ERRORSOCCURRED==hr)
{
//the status for the rest
for(ulIndex=m_cBinding; ulIndex>0; ulIndex--)
{
if(ulIndex==4)
{
continue;
}
if(!COMPARE(GetStatus(pData,&(m_rgBinding[ulIndex-1])),DBSTATUS_E_UNAVAILABLE))
{
goto CLEANUP;
}
}
}
fTestPass=TRUE;
CLEANUP:
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Change the primary key of two rows to be the same. DB_E_INTEGRITYVIOLATION.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Buffered::Variation_5()
{
BOOL fTestPass=TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
DBORDINAL rgColNumber[2];
HROW *pHRow=NULL;
HROW *pUpdatedHRow=NULL;
DBROWSTATUS *pDBRowStatus=NULL;
void *pData=NULL;
void *pGetData=NULL;
DBPROPID rgPropertyIDs[2];
DBPROPID rgPropertyIDsOff[1];
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDsOff[0]=DBPROP_REMOVEDELETED;
HRESULT hr = S_OK;
if(!m_pIDBCreateCommand || !m_bIndexExists)
{
return TEST_PASS;
}
rgColNumber[0]=g_pTable->GetIndexColumn();
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,1,rgPropertyIDsOff,NO_ACCESSOR))
//create an accessor on the rowset object on 1st column twice
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,
1,rgColNumber))
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate))
{
goto CLEANUP;
}
fTestPass=FALSE;
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get handle to 2nd row
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get the previous (1st) row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data (first row) should be ok
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,&cRows,&pUpdatedHRow,&pDBRowStatus),S_OK);
PROVIDER_FREE(pUpdatedHRow);
PROVIDER_FREE(pDBRowStatus);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//get a (2nd) row handle - again
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//set this time (the 2nd time) should pass
TESTC_(SetData(*pHRow,m_hAccessor,pData),S_OK);
//update should fail when data is actually pushed to the back end
hr=m_pIRowsetUpdate->Update(NULL,1,pHRow,&cRows,&pUpdatedHRow,&pDBRowStatus);
if (DB_E_ERRORSOCCURRED==hr)
{
if(!COMPARE(*pDBRowStatus,DBROWSTATUS_E_INTEGRITYVIOLATION))
{
goto CLEANUP;
}
}
else if (DB_E_INTEGRITYVIOLATION!=hr)
{
odtLog << "INTEGRITYVIOLATION ERROR"<<ENDL;
goto CLEANUP;
}
PROVIDER_FREE(pUpdatedHRow);
PROVIDER_FREE(pDBRowStatus);
//restart position
TESTC_(m_pIRowset->RestartPosition(NULL),DB_E_ROWSNOTRELEASED);
//update failed so there are still pending changes. undo them so test can RestartPosition
TESTC_(m_pIRowsetUpdate->Undo(NULL,1,pHRow,&cRows,&pUpdatedHRow,&pDBRowStatus),S_OK);
//release the row handle so test can RestartPosition
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//allocate memory for getting data again
pGetData=PROVIDER_ALLOC(m_cRowSize);
if(!pGetData)
goto CLEANUP;
//get a row handle
m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow);
GetData(*pHRow, m_hAccessor, pGetData);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, pGetData),S_OK);
//the 1st column should not be changed
if(COMPARE(CompareBuffer(pGetData, m_pData,1,&(m_rgBinding[0]),m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
fTestPass=TRUE;
CLEANUP:
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
PROVIDER_FREE(pGetData);
PROVIDER_FREE(pUpdatedHRow);
PROVIDER_FREE(pDBRowStatus);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc The accessor sets the status field of non nullable columns NULL. DB_E_SCHEMAVIOLATION. The row goes back to its original sta
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Buffered::Variation_6()
{
BOOL fTestPass=TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pUpdatedRow = NULL;
DBROWSTATUS *pDBRowStatus = NULL;
DBCOUNTITEM ulCol = 0;
DBORDINAL *rgColNumber = NULL;
ULONG cCount = 0;
void *pData = NULL;
void *pGetData = NULL;
DBPROPID rgPropertyIDs[2];
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
0,NULL,NO_ACCESSOR))
//Get Not nullable and Updatable column. .
if(!GetNotNullableAndUpdatable(&ulCol, &rgColNumber))
goto CLEANUP;
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate))
goto CLEANUP;
fTestPass=FALSE;
//accessor on not nullable and updatable column
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,
1,rgColNumber))
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, SECONDARY),S_OK);
//set the not nullable column to NULL
// *(DBSTATUS *)(((DWORD)pData)+m_rgBinding[0].obStatus)=DBSTATUS_S_ISNULL;
STATUS_BINDING(m_rgBinding[0],pData)=DBSTATUS_S_ISNULL;
//set data should fail
if(FAILED(m_hr=SetData(*pHRow,m_hAccessor,pData)))
{
COMPARE(m_hr, DB_E_ERRORSOCCURRED);
if(!COMPARE(GetStatus(pData,&(m_rgBinding[0])),DBSTATUS_E_INTEGRITYVIOLATION))
goto CLEANUP;
}
else
{
//update should fail
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,&cRows,&pUpdatedRow,&pDBRowStatus),DB_E_ERRORSOCCURRED);
if(!COMPARE(*pDBRowStatus,DBROWSTATUS_E_INTEGRITYVIOLATION))
{
goto CLEANUP;
}
COMPARE(*pDBRowStatus,DBROWSTATUS_S_PENDINGCHANGES);
}
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//undo all the updates
TESTC_(m_pIRowsetUpdate->Undo(NULL,0,NULL,NULL,NULL,NULL),S_OK);
//allocate memory for getting data again
pGetData=PROVIDER_ALLOC(m_cRowSize);
if(!pGetData)
goto CLEANUP;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//get data on the row handle
TESTC_(GetData(*pHRow, m_hAccessor, pGetData),S_OK);
//no data should be changed
if(COMPARE(CompareBuffer(pGetData, m_pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),TRUE))
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
PROVIDER_FREE(pGetData);
PROVIDER_FREE(pUpdatedRow);
PROVIDER_FREE(pDBRowStatus);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc The length binding > cbMaxLen for a variable length column. DB_S_ERRORSOCCURRED. Truncation should occur. Check the status b
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Buffered::Variation_7()
{
BOOL fTestPass=TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow=NULL;
DBCOUNTITEM cCnt;
DBCOUNTITEM ulCol;
DBORDINAL *rgColNumber = NULL;
void *pData=NULL;
DBPROPID rgPropertyIDs[2];
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
HRESULT hr = S_OK;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
0,NULL,NO_ACCESSOR))
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate))
goto CLEANUP;
fTestPass=FALSE;
//Get a variable length column. .
if(!GetVariableLengthAndUpdatable(&ulCol, &rgColNumber,FALSE))
if(!GetVariableLengthAndUpdatable(&ulCol, &rgColNumber))
{
odtLog << "no variable length updateable columns available"<<ENDL;
fTestPass = TRUE;
goto CLEANUP;
}
//find a data type that is not ORed with DBTYPE_ARRAY or DBTYPE_VECTOR
for(cCnt=0; cCnt<ulCol; cCnt++)
{
if(((m_rgInfo[rgColNumber[cCnt]-1].wType & DBTYPE_ARRAY) == 0) &&
((m_rgInfo[rgColNumber[cCnt]-1].wType & DBTYPE_VECTOR) == 0)
)
break;
}
if(cCnt==ulCol)
{
odtLog << "no variable length updateable columns that is not ORed with DBTYPE_ARRAY or DBTYPE_VECTOR available"<<ENDL;
fTestPass = TRUE;
goto CLEANUP;
}
//accessor on 1st variable length and updatable column
TESTC_PROVIDER( GetAccessorOnRowset( ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,
1,((&rgColNumber[cCnt]))
))
//restartPosition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,4,1,&cRows,&pHRow),S_OK);
//make new data to set
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//change the length to cbMaxLen + 1
// *(ULONG *)((DWORD)pData+m_rgBinding[0].obLength)=m_rgBinding[0].cbMaxLen+1;
LENGTH_BINDING(m_rgBinding[0],pData)=m_rgBinding[0].cbMaxLen+1;
//set data should fail
if((m_hr=SetData(*pHRow,m_hAccessor,pData))==DB_E_ERRORSOCCURRED)
{
// if(!COMPARE(*(DBSTATUS *)((DWORD)pData+m_rgBinding[0].obStatus), DBSTATUS_E_CANTCONVERTVALUE))
if(!COMPARE(STATUS_BINDING(m_rgBinding[0],pData), DBSTATUS_E_CANTCONVERTVALUE))
{
goto CLEANUP;
}
}
else
{
//has to be successful code
COMPARE(m_hr, ResultFromScode(S_OK));
//update should fail
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),DB_E_ERRORSOCCURRED);
}
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc The accessor only has status binding for DBSTATUS_S_OK.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Buffered::Variation_8()
{
BOOL fTestPass=TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
ULONG cCount;
HROW *pHRow=NULL;
void *pData=NULL;
DBPROPID rgPropertyIDs[2];
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
//create a rowset without an accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,NO_ACCESSOR))
if (!m_pIRowsetChange||!m_pIRowsetUpdate)
goto CLEANUP;
fTestPass=FALSE;
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
//accessor with only status binding
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_STATUS,UPDATEABLE_COLS_BOUND))
//get some data to insert
pData=PROVIDER_ALLOC(m_cRowSize);
for(cCount=0; cCount<m_cBinding; cCount++)
{
// *(DBSTATUS *)((DWORD)pData+m_rgBinding[cCount].obStatus)=DBSTATUS_S_OK;
STATUS_BINDING(m_rgBinding[cCount],pData)=DBSTATUS_S_OK;
}
//set data should fail
TESTC_(SetData(*pHRow,m_hAccessor,pData),DB_E_ERRORSOCCURRED);
for(cCount=0; cCount<m_cBinding; cCount++)
{
if(!COMPARE(GetStatus(pData, &(m_rgBinding[cCount])),DBSTATUS_E_UNAVAILABLE))
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc The accessor is not a row accessor. DB_E_BADACCESSORTYPE.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Buffered::Variation_9()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
DBPROPID rgPropertyIDs[2];
void *pData = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,0,NULL,ON_COMMAND_ACCESSOR,FALSE,
DBACCESSOR_ROWDATA,DBPART_LENGTH|DBPART_STATUS|DBPART_VALUE,
UPDATEABLE_COLS_BOUND,FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,
0,NULL,NO_COLS_OWNED_BY_PROV,DBPARAMIO_INPUT))
//create data to set to the first row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//release the accessor
ReleaseRowsetAndAccessor();
if (!m_pIRowsetChange||!m_pIRowsetUpdate)
{
goto CLEANUP;
}
//now make a param accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,ON_COMMAND_ACCESSOR,FALSE,
DBACCESSOR_PARAMETERDATA,DBPART_LENGTH|DBPART_STATUS|DBPART_VALUE,
UPDATEABLE_COLS_BOUND,FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,
0,NULL,NO_COLS_OWNED_BY_PROV,DBPARAMIO_INPUT))
fTestPass=FALSE;
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//set data should fail
if(CHECK(m_pIRowsetChange->SetData(*pHRow,m_hAccessor,pData),DB_E_BADACCESSORTYPE))
fTestPass=TRUE;
CLEANUP:
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
}
//release the accessor
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc REMOVEDELTED FALSE LITERALINDETITY TRUE in buffered mode.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Buffered::Variation_10()
{
DBPROPID rgPropertyIDs[6];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
HROW *pHRow = NULL;
HROW *pHRowb = NULL;
DBCOUNTITEM cRows = 0;
HRESULT hr = S_OK;
HROW *pUpdatedHRow = NULL;
DBROWSTATUS *pDBRowStatus = NULL;
void *pData = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
rgPropertyIDs[2]=DBPROP_OWNUPDATEDELETE;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_IRowsetIdentity;
rgPropertyIDs[5]=DBPROP_LITERALIDENTITY;
rgUnPropertyIDs[0]=DBPROP_REMOVEDELETED;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,6,rgPropertyIDs,1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange||!m_pIRowsetUpdate|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
if(!(pData=PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
TESTC_(GetData(*pHRow,m_hAccessor,pData),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRowb),S_OK);
//get the data for the row, return DB_E_DELETEDROW
hr=GetData(*pHRowb,m_hAccessor,m_pData);
//if GetData returned S_OK, it is legal here because reporting the row is actually a pending delete
//may be too expense for some providers
if (hr!=DB_E_DELETEDROW && hr!=S_OK)
{
goto CLEANUP;
}
//if the hole was not returned and the row was returned then make sure it returns
//the correct buffer
if (S_OK==hr)
{
if(!CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
goto CLEANUP;
}
}
//these should be the same rows, should see the hole or the deleted row
//LITERALIDENTITY TRUE, REMOVEDELETED FALSE
TESTC_(m_pIRowsetIdentity->IsSameRow(*pHRow,*pHRowb),S_OK);
//call update, transmit the delete
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//release the row handles
TESTC_(m_pIRowset->ReleaseRows(1,pHRowb,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowb);
pHRowb=NULL;
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 4th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows,&pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the next 5 row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,5,&cRows,&pHRow),S_OK);
//call update for the first 5 rows
if (
!CHECK(m_pIRowsetUpdate->Update(NULL,5,pHRow,&cRows,&pUpdatedHRow,&pDBRowStatus),DB_S_ERRORSOCCURRED)
)
{
goto CLEANUP;
}
//only the first row should be marked as deleted since this was the only row transmitted to the data source
//prior to this update, the fourth row just deleted should not cause an error
if (!
(COMPARE(pDBRowStatus[0],DBROWSTATUS_E_DELETED)) &&
(COMPARE(pDBRowStatus[3],DBROWSTATUS_S_OK))
)
{
goto CLEANUP;
}
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
hr=GetData(*pHRow,m_hAccessor,m_pData);
//if GetData returned S_OK, it is legal here because reporting the row is actually a pending delete
//may be too expense for some providers
if (hr!=DB_E_DELETEDROW && hr!=S_OK)
{
goto CLEANUP;
}
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//retrieve the 4th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
//get the data for the row, return DB_E_DELETEDROW
hr=GetData(*pHRow,m_hAccessor,m_pData);
//if GetData returned S_OK, it is legal here because reporting the row is actually a pending delete
//may be too expense for some providers
if (hr!=DB_E_DELETEDROW && hr!=S_OK)
{
goto CLEANUP;
}
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
fTestPass = TEST_PASS;
CLEANUP:
if(pData)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
}
PROVIDER_FREE(pUpdatedHRow);
PROVIDER_FREE(pDBRowStatus);
//release the row handle
if (m_pIRowset && pHRow)
{
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK)
PROVIDER_FREE(pHRow);
}
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc REMOVEDELTED FALSE LITERALINDETITY FALSE in buffered mode.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Buffered::Variation_11()
{
DBPROPID rgPropertyIDs[5];
DBPROPID rgUnPropertyIDs[2];
BOOL fTestPass = TEST_SKIPPED;
HROW *pHRow = NULL;
HROW *pHRowb = NULL;
DBCOUNTITEM cRows = 0;
HRESULT hr = S_OK;
HROW *pUpdatedHRow = NULL;
DBROWSTATUS *pDBRowStatus = NULL;
void *pData1 = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
rgPropertyIDs[2]=DBPROP_OWNUPDATEDELETE;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_IRowsetIdentity;
rgUnPropertyIDs[0]=DBPROP_REMOVEDELETED;
rgUnPropertyIDs[1]=DBPROP_LITERALIDENTITY;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,5,rgPropertyIDs,2,rgUnPropertyIDs,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange||!m_pIRowsetUpdate|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
if(!(pData1=PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
TESTC_(GetData(*pHRow,m_hAccessor,pData1),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRowb),S_OK);
//get the data for the row, return S_OK, should not see the pending change
TESTC_(GetData(*pHRowb,m_hAccessor,m_pData),S_OK);
//the deleted row should be visible here, check its buffer
if(!CompareBuffer(m_pData,pData1,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
goto CLEANUP;
}
//these should be the same rows,
//LITERALIDENTITY TRUE, REMOVEDELETED FALSE
TESTC_(m_pIRowsetIdentity->IsSameRow(*pHRow,*pHRowb),S_OK);
//call update, transmit the delete
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRowb,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowb);
pHRowb=NULL;
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 4th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows,&pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the next 5 row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,5,&cRows,&pHRow),S_OK);
//call update for the first 5 rows
if (
!CHECK(m_pIRowsetUpdate->Update(NULL,5,pHRow,&cRows,&pUpdatedHRow,&pDBRowStatus),DB_S_ERRORSOCCURRED)
)
{
goto CLEANUP;
}
//only the first row should be marked as deleted since this was the only row transmitted to the data source
//prior to this update, the fourth row just deleted should not cause an error
if (!
(COMPARE(pDBRowStatus[0],DBROWSTATUS_E_DELETED)) &&
(COMPARE(pDBRowStatus[3],DBROWSTATUS_S_OK))
)
{
goto CLEANUP;
}
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
hr=GetData(*pHRow,m_hAccessor,m_pData);
//if GetData returned S_OK, it is legal here because reporting the row is actually a pending delete
//may be too expense for some providers
if (hr!=DB_E_DELETEDROW && hr!=S_OK)
{
goto CLEANUP;
}
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//retrieve the 4th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
hr=GetData(*pHRow,m_hAccessor,m_pData);
//if GetData returned S_OK, it is legal here because reporting the row is actually a pending delete
//may be too expense for some providers
if (hr!=DB_E_DELETEDROW && hr!=S_OK)
{
goto CLEANUP;
}
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
fTestPass = TEST_PASS;
CLEANUP:
if(pData1)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData1,TRUE);
}
PROVIDER_FREE(pUpdatedHRow);
PROVIDER_FREE(pDBRowStatus);
//release the row handle
if (m_pIRowset && pHRow)
{
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK)
PROVIDER_FREE(pHRow);
}
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc REMOVEDELTED TRUE, LITERALIDENITTY TRUE in buffered mode.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Buffered::Variation_12()
{
DBPROPID rgPropertyIDs[7];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
HROW *pHRow = NULL;
HROW *pHRowb = NULL;
DBCOUNTITEM cRows = 0;
DBCOUNTITEM cUpdatedRows = 0;
DBCOUNTITEM cRowsExpected = 0;
HRESULT hr = S_OK;
HROW *pUpdatedHRow = NULL;
DBROWSTATUS *pDBRowStatus = NULL;
void *pData1 = NULL;
void *pData2 = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OWNUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
rgPropertyIDs[3]=DBPROP_REMOVEDELETED;
rgPropertyIDs[4]=DBPROP_LITERALIDENTITY;
rgPropertyIDs[5]=DBPROP_IRowsetIdentity;
rgPropertyIDs[6]=DBPROP_IRowsetUpdate;
rgUnPropertyIDs[0]=DBPROP_OTHERINSERT;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,7,rgPropertyIDs,1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if(!(pData1=PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
if(!(pData2=PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
if (!m_pIRowsetChange||!m_pIRowsetUpdate|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRowb),S_OK);
TESTC_(GetData(*pHRowb,m_hAccessor,pData1),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRowb, NULL),S_OK);
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get the data for the row, return S_OK
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//the deleted row should not be visible here, check its buffer
if(CompareBuffer(m_pData,pData1,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
goto CLEANUP;
}
//these should not be the same rows,
//LITERALIDENTITY TRUE, REMOVEDELETED TRUE
TESTC_(m_pIRowsetIdentity->IsSameRow(*pHRow,*pHRowb),S_FALSE);
//call update, transmit the delete
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//release the row handles
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
PROVIDER_FREE(pHRowb);
pHRowb=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
TESTC_(GetData(*pHRow,m_hAccessor,pData2),S_OK);
//the deleted row should not be visible here, no hole so the buffer should
//be from a new row
if(CompareBuffer(pData1,pData2,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
goto CLEANUP;
}
//release the row handles
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 4th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows,&pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the next 5 row handles, expect 5 rows to be fetched
cRowsExpected = 5;
TESTC_(m_pIRowset->GetNextRows(NULL,0,5,&cRows,&pHRow),S_OK);
//call update for the first 5 rows
if (
!CHECK(m_pIRowsetUpdate->Update(NULL,5,pHRow,&cRows,&pUpdatedHRow,&pDBRowStatus),S_OK)
)
{
//this is an error, lets do some more debugging
//no row should be marked as deleted since this was REMOVEDELETED is TRUE
for(DBCOUNTITEM i=0; i<cRows; i++)
{
//no holes from delete
COMPARE(pDBRowStatus[0],DBROWSTATUS_S_OK);
}
m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL);
PROVIDER_FREE(pHRow);
goto CLEANUP;
}
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get the data for the row, S_OK because REMOVEDELETED is TRUE
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//retrieve the 4th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows,&pHRow),S_OK);
//get the data for the row, return S_OK because REMOVEDELETED is TRUE
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
fTestPass = TEST_PASS;
CLEANUP:
if(pData1)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData1,TRUE);
}
PROVIDER_FREE(pData2);
//release the row handle
if (m_pIRowset)
{
//release the row handle
m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL,NULL);
PROVIDER_FREE(pHRow);
m_pIRowset->ReleaseRows(1,pHRowb, NULL,NULL,NULL);
PROVIDER_FREE(pHRowb);
}
PROVIDER_FREE(pUpdatedHRow);
PROVIDER_FREE(pDBRowStatus);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc REMOVEDELTED TRUE, LITERALIDENITTY FALSE in buffered mode.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Invalid_Keyset_Cursor_Buffered::Variation_13()
{
DBPROPID rgPropertyIDs[6];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
HROW *pHRow = NULL;
HROW *pHRowb = NULL;
DBCOUNTITEM cRows = 0;
HRESULT hr = S_OK;
HROW *pUpdatedHRow = NULL;
DBROWSTATUS *pDBRowStatus = NULL;
void *pData1 = NULL;
void *pData2 = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
rgPropertyIDs[2]=DBPROP_OWNUPDATEDELETE;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_REMOVEDELETED;
rgPropertyIDs[5]=DBPROP_IRowsetIdentity;
rgUnPropertyIDs[0]=DBPROP_LITERALIDENTITY;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,6,rgPropertyIDs,1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if(!(pData1=PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
if(!(pData2=PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
if (!m_pIRowsetChange||!m_pIRowsetUpdate|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRowb),S_OK);
TESTC_(GetData(*pHRowb,m_hAccessor,pData1),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRowb, NULL),S_OK);
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get the data for the row, return S_OK
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//the deleted row should be visible here, check its buffer
if(!CompareBuffer(m_pData,pData1,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
goto CLEANUP;
}
//these should be the same rows,
//LITERALIDENTITY FALSE, REMOVEDELETED TRUE
TESTC_(m_pIRowsetIdentity->IsSameRow(*pHRow,*pHRowb),S_OK);
//call update, transmit the delete
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//release the row handles
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
PROVIDER_FREE(pHRowb);
pHRowb=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
TESTC_(GetData(*pHRow,m_hAccessor,pData2),S_OK);
//the deleted row should not be visible here, no hole so the buffer should
//be from a new row
if(CompareBuffer(pData1,pData2,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
goto CLEANUP;
}
//release the row handles
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 4th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows,&pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow, NULL),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the next 5 row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,5,&cRows,&pHRow),S_OK);
//call update for the first 5 rows
if (
!CHECK(m_pIRowsetUpdate->Update(NULL,5,pHRow,&cRows,&pUpdatedHRow,&pDBRowStatus),S_OK)
)
{
//this is an error, lets do some more debugging
//no row should be marked as deleted since this was REMOVEDELETED is TRUE
COMPARE(pDBRowStatus[0],DBROWSTATUS_S_OK);//no hole from first delete, should be new row
COMPARE(pDBRowStatus[1],DBROWSTATUS_S_OK);
COMPARE(pDBRowStatus[2],DBROWSTATUS_S_OK);
COMPARE(pDBRowStatus[3],DBROWSTATUS_S_OK);
COMPARE(pDBRowStatus[4],DBROWSTATUS_S_OK);
goto CLEANUP;
}
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//restart position
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 1th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get the data for the row, S_OK because REMOVEDELETED is TRUE
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
//retrieve the 4th row handle
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows,&pHRow),S_OK);
//get the data for the row, return S_OK because REMOVEDELETED is TRUE
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
fTestPass = TEST_PASS;
CLEANUP:
if(pData1)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData1,TRUE);
}
PROVIDER_FREE(pData2);
//release the row handle
if (m_pIRowset)
{
//release the row handle
m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL,NULL),S_OK;
PROVIDER_FREE(pHRow);
m_pIRowset->ReleaseRows(1,pHRowb, NULL,NULL,NULL),S_OK;
PROVIDER_FREE(pHRowb);
}
PROVIDER_FREE(pUpdatedHRow);
PROVIDER_FREE(pDBRowStatus);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Invalid_Keyset_Cursor_Buffered::Terminate()
{
ReleaseRowsetAndAccessor();
return(TCIRowsetChange::Terminate());
} // }}
// }}
// {{ TCW_TC_PROTOTYPE(Valid_Keyset_Cursor_Immediate)
//*-----------------------------------------------------------------------
//| Test Case: Valid_Keyset_Cursor_Immediate - Valid_Keyset_Cursor_Immediate
//| Created: 04/17/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Valid_Keyset_Cursor_Immediate::Init()
{
BOOL fTestPass = TEST_SKIPPED;
m_rgPropertyIDs[0]=DBPROP_IRowsetChange;
m_rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
m_rgPropertyIDs[2]=DBPROP_IRowsetLocate;
m_cGuid=3;
if(!TCIRowsetChange::Init())
return FALSE;
fTestPass = TRUE;
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Change fixed length columns, in FORWARD order of the rowset.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Valid_Keyset_Cursor_Immediate::Variation_1()
{
DBCOUNTITEM cCol = 0;
DBORDINAL* rgColNumber=NULL;
DBCOUNTITEM cRows = 0;
HROW* pHRow=NULL;
void* pData=NULL;
BOOL fTestPass=TEST_SKIPPED;
//create a rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cGuid,m_rgPropertyIDs,0,NULL,NO_ACCESSOR));
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass = FALSE;
//get the fixed length updatable columns
if(!GetUpdatableCols(&cCol, &rgColNumber))
goto CLEANUP;
//create a write only accessor on the fixed length updatable columns
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,cCol,rgColNumber))
//create data to set to the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//set data
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
//reexcute the query
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cGuid,m_rgPropertyIDs,0,NULL,
ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,cCol,rgColNumber))
//retrieve the 12 row handle
while(m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow) == S_OK)
{
if(cRows == 0)
break;
//Get the data for the 10th row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Change the fixed length data type columns with bogus length information.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Valid_Keyset_Cursor_Immediate::Variation_2()
{
DBCOUNTITEM cCnt = 0;
DBCOUNTITEM cCol = 0;
DBORDINAL *rgColNumber = NULL;
DBCOUNTITEM cRows = 0;
HROW rghRows[1] = {NULL};
HROW* pHRow = &rghRows[0];
void *pData = NULL;
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr;
//create a rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cGuid,m_rgPropertyIDs,0,NULL,NO_ACCESSOR));
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass = FALSE;
//get the fixed length updatable columns
if(!GetFixedLengthAndUpdatable(&cCol, &rgColNumber))
goto CLEANUP;
//create a write only accessor on the fixed length updatable columns
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,cCol,rgColNumber))
//create data to set to the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//make the length information bogus
for(cCnt=0;cCnt<m_cBinding;cCnt++)
{
// *(ULONG *)(((DWORD)pData)+m_rgBinding[cCnt].obLength)=0;
LENGTH_BINDING(m_rgBinding[cCnt],pData)=0;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//set data
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
if(*pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the 10th row handle
hr = GetData(*pHRow,m_hAccessor,m_pData);
//Taking cares of SQL Providers for keyset cursor
TESTC(hr == S_OK || hr == DB_E_DELETEDROW);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
*pHRow = NULL;
//make sure CompareBuffer will not compare length information
for(cCnt=0;cCnt<m_cBinding;cCnt++)
{
m_rgBinding[cCnt].dwPart=m_rgBinding[cCnt].dwPart&(~DBPART_LENGTH);
}
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(*pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Change the variable length columns with only value binding.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Valid_Keyset_Cursor_Immediate::Variation_3()
{
DBCOUNTITEM cCol;
DBORDINAL *rgColNumber=NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow =NULL;
void *pData =NULL;
void *pSecondData=NULL;
BOOL fTestPass =TEST_SKIPPED;
HRESULT hr = S_OK;
//create a rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cGuid,m_rgPropertyIDs,
0,NULL,NO_ACCESSOR));
//get the variable length updatable columns. No bytes
if(!GetVariableLengthAndUpdatable(&cCol, &rgColNumber,TRUE,FALSE))
goto CLEANUP;
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass = FALSE;
//create a write only accessor on the variable length updatable columns
//do not include the last column
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS,
USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,/*cCol-1*/1,rgColNumber))
//create data to set to the first row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//set data
TESTC_(m_pIRowsetChange->SetData(*pHRow, m_hAccessor, pData),S_OK);
//free the memory
PROVIDER_FREE(pData);
PROVIDER_FREE(rgColNumber);
//release the accessor
ReleaseAccessorOnRowset();
//get the variable length updatable columns
if(!GetStr(&cCol, &rgColNumber))
goto CLEANUP;
//create a write only accessor on the variable length updatable columns
//do not include the last column
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS,
USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,cCol,rgColNumber))
//create data to set to the first row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//allocate memory
if(!(pSecondData=PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//set data
TESTC_(m_pIRowsetChange->SetData(*pHRow, m_hAccessor, pData),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//retrieve the 12 row handle
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the 10th row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(rgColNumber);
PROVIDER_FREE(m_pData);
PROVIDER_FREE(pSecondData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Change the whole row with status and value binding. Set some columns to NULL.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Valid_Keyset_Cursor_Immediate::Variation_4()
{
DBCOUNTITEM cCol = 0;
DBCOUNTITEM cIndex = 0;
DBORDINAL *rgColNumber = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
void *pData = NULL;
void *pSecondData = NULL;
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr = S_OK;
//create a rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cGuid,m_rgPropertyIDs,
0,NULL,NO_ACCESSOR))
//get the variable length updatable columns
if(!GetVariableLengthAndUpdatable(&cCol, &rgColNumber))
goto CLEANUP;
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass=FALSE;
//create a write only accessor on the variable length updatable columns
//do not include the last column
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,cCol-1,rgColNumber))
//create data to set to the first row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//search for the DBTYPE_STR data
for(cCol=0; cCol<m_cBinding; cCol++)
{
if(m_rgBinding[cCol].wType==DBTYPE_STR)
{
cIndex=cCol;
break;
}
}
//exit if no such column is found
if(cCol==m_cBinding)
{
fTestPass=TRUE;
goto CLEANUP;
}
//add a NULL terminator to the data buffer
// *((BYTE *)((DWORD)pData+m_rgBinding[cIndex].obValue+4))='\0';
*((size_t *)&VALUE_BINDING(m_rgBinding[0], pData))='\0';
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//allocate memory
if(!(pSecondData=PROVIDER_ALLOC(m_cRowSize)))
goto CLEANUP;
//set data
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get data
TESTC_(GetData(*pHRow, m_hAccessor,pSecondData),S_OK);
// Make sure data should be changed except for DBTYPE_BYTES
if(!memcmp (
// (void *)((DWORD)pData+m_rgBinding[cIndex].obValue),
// (void *)((DWORD)pSecondData+m_rgBinding[cIndex].obValue),
// *(ULONG *)((DWORD)pData+m_rgBinding[cIndex].obLength)
&VALUE_BINDING(m_rgBinding[cIndex], pData),
&VALUE_BINDING(m_rgBinding[cIndex], pSecondData),
LENGTH_BINDING(m_rgBinding[cIndex],pData)
)
)
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
PROVIDER_FREE(pSecondData);
PROVIDER_FREE(pData);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Change a row with DBTYPE_BYREF.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Valid_Keyset_Cursor_Immediate::Variation_5()
{
DBCOUNTITEM cRows = 0;
ULONG cCount = 0;
HROW *pHRow = NULL;
void *pData = NULL;
BOOL fTestPass = TEST_SKIPPED;
DBBINDING *rgBinding = NULL;
DBCOUNTITEM cCol = 0;
DBORDINAL *rgColNumber = NULL;
DBCOUNTITEM cRow = g_ulNextRow++;
HRESULT hr = S_OK;
//create a rowset and accessor that binds to DBTYPE_BYREF
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cGuid,m_rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR))
//GetUpdatable columns
if(!GetUpdatableCols(&cCol, &rgColNumber))
goto CLEANUP;
for(cCount=0; cCount<cCol; cCount++)
{
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_BYREF,
1,&(rgColNumber[cCount])))
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass=FALSE;
//get a row handle
if(cCount==0)
{
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
}
else
{
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK);
}
//create data to set to the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,cRow,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//restartpostion
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
goto CLEANUP;
if(pData)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData);
PROVIDER_FREE(pData);
PROVIDER_FREE(m_pData);
PROVIDER_FREE(m_rgBinding);
m_cBinding = 0;
}
}
ReleaseRowsetAndAccessor();
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cGuid,m_rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR, TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,
1,rgColNumber))
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the 10th row handle
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
// the Data should be the same as what was set
if(CompareData(m_cRowsetCols,m_rgTableColOrds,cRow,m_pData,m_cBinding,m_rgBinding,m_pTable,m_pIMalloc))
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(rgColNumber);
PROVIDER_FREE(rgBinding);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Change a row with DBTYPE_ARRAY.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Valid_Keyset_Cursor_Immediate::Variation_6()
{
return TEST_PASS;
}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Change a row with DBTYPE_VECTOR.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Valid_Keyset_Cursor_Immediate::Variation_7()
{
return TEST_PASS;
}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc Duplicate column bindings in the same accessor.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Valid_Keyset_Cursor_Immediate::Variation_8()
{
DBCOUNTITEM cCol;
DBORDINAL *rgColNumber = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
DBBYTEOFFSET obValue;
void *pData = NULL;
HACCESSOR hAccessor = NULL;
BOOL fTestPass = TEST_SKIPPED;
//create a rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cGuid,m_rgPropertyIDs,0,NULL,NO_ACCESSOR))
//get the 1st numeric and updatable columns
if(!GetNumericAndUpdatable(&cCol, &rgColNumber))
goto CLEANUP;
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass=FALSE;
//can not go on testing without more than 1 column in the table
if(cCol<2)
{
fTestPass=TRUE;
goto CLEANUP;
}
//create a write only accessor on the 1st numeric updatable column twice
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,2,rgColNumber))
//copy the binding strcture
m_rgBinding[1].iOrdinal=m_rgBinding[0].iOrdinal;
m_rgBinding[1].wType=m_rgBinding[0].wType;
m_rgBinding[1].cbMaxLen=m_rgBinding[0].cbMaxLen;
//create an accessor
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,
m_cBinding, m_rgBinding, 0, &hAccessor,NULL),S_OK);
obValue=m_rgBinding[1].obValue;
//create data to set to the last row
TESTC_(FillInputBindings(m_pTable,
DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//make the second copy of the data into the first half
//of pData buffer
TESTC_(FillInputBindings(m_pTable,
DBACCESSOR_ROWDATA,1,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//set data
TESTC_(SetData(*pHRow, hAccessor, pData),S_OK);
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
//release the accessor
if(hAccessor)
{
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
hAccessor=NULL;
}
ReleaseRowsetAndAccessor();
//reexcute the query
//create an accessor on the 1st numeric updatable column only once
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cGuid,m_rgPropertyIDs,0,NULL,
ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,1,rgColNumber))
fTestPass=FALSE;
//get the last row
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//get data
TESTC_(GetData(*pHRow, m_hAccessor,m_pData),S_OK);
// the Data should be the same as what was set for the second time
// if(COMPARE(CompareDBTypeData( (void *)((DWORD)m_pData+m_rgBinding[0].obValue),
if(COMPARE(CompareDBTypeData( (size_t *)&VALUE_BINDING(m_rgBinding[0], m_pData),
(void *)((size_t)pData+obValue),
m_rgBinding[0].wType,
0,
0,
0,
m_pIMalloc,
FALSE,
DBTYPE_EMPTY,
0),TRUE))
{
PROVIDER_FREE(pData);
fTestPass=TRUE;
}
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//release the accessor
if(hAccessor)
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Valid_Keyset_Cursor_Immediate::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// {{ TCW_TC_PROTOTYPE(Related_Delete_NewRow)
//*-----------------------------------------------------------------------
//| Test Case: Related_Delete_NewRow - Related interfaces with IRowsetDelete and IRowsetNewRow
//| Created: 04/22/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Related_Delete_NewRow::Init()
{
BOOL fTestPass = TEST_SKIPPED;
if(!TCIRowsetChange::Init())
return FALSE;
fTestPass = TRUE;
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Delete one row. Add a new row and change it. Immediate update mode.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Related_Delete_NewRow::Variation_1()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRowDelete = NULL;
HROW *pHRowNew = NULL;
void *pData = NULL;
DBPROPID rgPropertyIDs[5];
ULONG uRefCount = 0;
DBROWSTATUS DBRowStatus;
HRESULT hr;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
rgPropertyIDs[3]=DBPROP_CANFETCHBACKWARDS;
rgPropertyIDs[4]=DBPROP_IRowsetLocate;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//open a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,5,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR, TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass = TEST_FAIL;
//fillup input data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,10,1,&cRows, &pHRowDelete),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRowDelete,NULL),S_OK);
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRowDelete,&DBRowStatus),DB_E_ERRORSOCCURRED);
if(!COMPARE(DBRowStatus, DBROWSTATUS_E_DELETED))
{
goto CLEANUP;
}
//addRef on a deleted row. No ref count is added
TESTC_(m_pIRowset->AddRefRows(1,pHRowDelete,&uRefCount,&DBRowStatus),DB_E_ERRORSOCCURRED);
if(!COMPARE(DBRowStatus, DBROWSTATUS_E_DELETED))
goto CLEANUP;
//get data on a deleted row is undefined, but no crash
m_hr=GetData(*pHRowDelete, m_hAccessor, m_pData);
//try to change the deleted row
TESTC_(SetData(*pHRowDelete,m_hAccessor, pData),DB_E_DELETEDROW);
//try to retrieve a deleted row handle
TESTC_(m_pIRowset->GetNextRows(NULL, 0, -1,&cRows, &pHRowNew),S_OK);
//insert a new row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,NULL),S_OK);
//release the deleted row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRowDelete, NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDelete);
TESTC_(m_pIRowset->ReleaseRows(1,pHRowNew, NULL,NULL,NULL),S_OK);
ReleaseRowsetAndAccessor();
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//reexecute the query,
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,5,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR, TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,UPDATEABLE_COLS_BOUND))
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRowNew)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the 10th row handle
TESTC_(GetData(*pHRowNew,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRowNew,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowNew);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
//free the memory used by pData
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRowDelete && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRowDelete, NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDelete);
}
if(pHRowNew && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRowNew, NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowNew);
}
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Delete one row. Add a new row and change it. Query and buffered update mode.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Related_Delete_NewRow::Variation_2()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRowDelete = NULL;
HROW *pHRowNew = NULL;
void *pData = NULL;
DBPROPID rgPropertyIDs[5];
ULONG uRefCount1 = 0;
ULONG uRefCount2 = 0;
DBROWSTATUS DBRowStatus;
HRESULT hr;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
rgPropertyIDs[2]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_CANFETCHBACKWARDS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//open a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,5,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate)|| (!m_cBinding))
goto CLEANUP;
fTestPass=FALSE;
//fillup input data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,10,1,&cRows, &pHRowDelete),S_OK);
//addRef on a soft deleted row. Should be OK
TESTC_(m_pIRowset->AddRefRows(1,pHRowDelete,&uRefCount1,&DBRowStatus),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRowDelete,NULL),S_OK);
//addRef on a soft deleted row. Should be OK
TESTC_(m_pIRowset->AddRefRows(1,pHRowDelete,&uRefCount2,&DBRowStatus),S_OK);
if(uRefCount2 <= uRefCount1)
goto CLEANUP;
if(!COMPARE(DBRowStatus, DBROWSTATUS_S_OK))
goto CLEANUP;
//release the row twice S_OK
TESTC_(m_pIRowset->ReleaseRows(1,pHRowDelete,NULL,&uRefCount1,&DBRowStatus),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRowDelete,NULL,&uRefCount2,&DBRowStatus),S_OK);
if(1!=uRefCount2)
{
odtLog << "warning, reference count mismatch"<<ENDL;
}
if(!COMPARE(DBRowStatus, DBROWSTATUS_S_PENDINGCHANGES))
goto CLEANUP;
//try to change the deleted row
TESTC_(SetData(*pHRowDelete,m_hAccessor, pData),DB_E_DELETEDROW);
//try to read the deleted row
GetData(*pHRowDelete,m_hAccessor, m_pData);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL, 1, pHRowDelete,NULL,NULL,NULL),S_OK);
//addRef on a hard deleted row.
TESTC_(m_pIRowset->AddRefRows(1,pHRowDelete,&uRefCount1,&DBRowStatus),DB_E_ERRORSOCCURRED);
if(!COMPARE(DBRowStatus, DBROWSTATUS_E_DELETED))
goto CLEANUP;
//try to retrieve a deleted row handle
TESTC_(m_pIRowset->GetNextRows(NULL, 0, -1,&cRows, &pHRowNew),S_OK);
//insert a new row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,NULL),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),S_OK);
//release the deleted row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRowDelete, NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDelete);
TESTC_(m_pIRowset->ReleaseRows(1,pHRowNew, NULL,NULL,NULL),S_OK);
ReleaseRowsetAndAccessor();
//reexecute the query, creaete a read-only accessor
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgPropertyIDs,
0,NULL,ON_COMMAND_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,
UPDATEABLE_COLS_BOUND))
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRowNew)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the 10th row handle
TESTC_(GetData(*pHRowNew,m_hAccessor,m_pData),S_OK);
TESTC_(m_pIRowset->ReleaseRows(1,pHRowNew,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowNew);
//make sure GetData should be able to see the change
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fTestPass=TRUE;
break;
}
}
CLEANUP:
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRowDelete && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowDelete, NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDelete);
if(pHRowNew && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowNew, NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowNew);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Delete rows from a static cursor/immediate update mode
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Related_Delete_NewRow::Variation_3()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRowDelete = NULL;
DBPROPID rgPropertyIDs[2]= {NULL,NULL};
DBROWSTATUS DBRowStatus[3];
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
m_fUseCmdTmeOut = TRUE;
//open a rowset with an accessor on all updatable columns with a static cursor
TESTC_PROVIDER( GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,2,g_rgPropertyIDs,
ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//get row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,3,&cRows, &pHRowDelete),S_OK);
//delete the rows
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,cRows,pHRowDelete,DBRowStatus),S_OK);
COMPARE(DBRowStatus[0], DBROWSTATUS_S_OK);
COMPARE(DBRowStatus[1], DBROWSTATUS_S_OK);
COMPARE(DBRowStatus[2], DBROWSTATUS_S_OK);
fTestPass=TRUE;
CLEANUP:
m_fUseCmdTmeOut = FALSE;
if(pHRowDelete && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRowDelete, NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRowDelete);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Boundary checks from a static cursor
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Related_Delete_NewRow::Variation_4()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRowDelete = NULL;
HROW *pHRowNew = NULL;
void *pData = NULL;
DBPROPID rgPropertyIDs[2]={NULL,NULL};
ULONG uRefCount1 = 0;
ULONG uRefCount2 = 0;
DBROWSTATUS DBRowStatus[3];
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//open a rowset with an accessor on all updatable columns with a static cursor
TESTC_PROVIDER( GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,2,g_rgPropertyIDs,
ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//get row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,3,&cRows, &pHRowDelete),S_OK);
//delete the rows
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,NULL,DBRowStatus),E_INVALIDARG);
//no op
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,0,pHRowDelete,DBRowStatus),S_OK);
//no op
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,0,NULL,DBRowStatus),S_OK);
//delete the rows
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,2,pHRowDelete,DBRowStatus),S_OK);
//delete the rows again
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,cRows,pHRowDelete,DBRowStatus),DB_S_ERRORSOCCURRED);
COMPARE(DBRowStatus[0], DBROWSTATUS_E_DELETED);
COMPARE(DBRowStatus[1], DBROWSTATUS_E_DELETED);
COMPARE(DBRowStatus[2], DBROWSTATUS_S_OK);
fTestPass = TEST_PASS;
CLEANUP:
if(pData)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
}
if(pHRowDelete && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRowDelete, NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRowDelete);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc NEWLYINSERTED from a static cursor
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Related_Delete_NewRow::Variation_5()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW HRowNew = NULL;
void *pData = NULL;
DBPROPID rgPropertyIDs[2] = {NULL,NULL};
DBPROPID rgUnPropertyIDs[3] = {NULL,NULL,NULL};
DBROWSTATUS DBRowStatus;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
rgUnPropertyIDs[0]=DBPROP_OTHERINSERT;
rgUnPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgUnPropertyIDs[2]=DBPROP_CHANGEINSERTEDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//open a rowset with an accessor on all updatable columns with a static cursor
TESTC_PROVIDER( GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,3,rgUnPropertyIDs,
ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//fillup input data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//insert a new row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,&HRowNew),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,&HRowNew,&DBRowStatus),DB_E_ERRORSOCCURRED);
if(!COMPARE(DBRowStatus, DBROWSTATUS_E_NEWLYINSERTED))
{
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
if(pData)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
}
if(&HRowNew && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,&HRowNew, NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc key non-key cols, set 2 rows the same and delete
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Related_Delete_NewRow::Variation_6()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
void *pData = NULL;
void *pData1 = NULL;
DBPROPID rgPropertyIDs[2]= {NULL,NULL};
DBROWSTATUS DBRowStatus;
DBCOUNTITEM cCol = 0;
DBORDINAL *rgColNumber = NULL;
DBCOUNTITEM ulCol = 0;
HRESULT hr;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//open a rowset with an accessor on all updatable columns with a static cursor
//create an accessor with IRowsetChange. Buffered update mode.
//No accessor to be created.
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,2,g_rgPropertyIDs,NO_ACCESSOR));
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
//get an array of fixed length and updatable columns
if(!COMPARE(GetNonKeyNonBLOB(&cCol,&rgColNumber),TRUE))
{
goto CLEANUP;
}
fTestPass = FALSE;
//pick the third column. if there is not 3 columns use the last one
if(cCol<3)
ulCol=cCol-1;
else
ulCol=3;
//get 2 row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,2,&cRows,&pHRow),S_OK);
//create an accessor to the first numeric and updatable column.
TESTC_PROVIDER(GetAccessorOnRowset( ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,USE_COLS_TO_BIND_ARRAY,
FORWARD,NO_COLS_BY_REF,DBTYPE_EMPTY,1,&(rgColNumber[ulCol])))
//get a new data buffer to set the data a row. Set
//the data to be the same as the another row handle
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//set data. Change the row to the same as the other handle's data
TESTC_(SetData(pHRow[0],m_hAccessor,pData),S_OK);
TESTC_(SetData(pHRow[1],m_hAccessor,pData),S_OK);
//delete the row, first one only
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,&pHRow[0],&DBRowStatus),S_OK);
if(!COMPARE(DBRowStatus, DBROWSTATUS_S_OK))
{
goto CLEANUP;
}
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if (S_OK!=hr && DB_S_COMMANDREEXECUTED!=hr)
{
if (DB_E_ROWSNOTRELEASED==hr)
{
//if CANHOLDROWS is TRUE and RestartPosition returns DB_E_ROWSNOTRELEASED
//then check DBPROP_QUICKRESTART.
//if DBPROP_QUICKRESTART is FALSE (command re-executed) this could be valid
//but if DBPROP_QUICKRESTART is TRUE DB_E_ROWSNOTRELEASED should not be
//returned from RestartPosition if CANHOLDROWS is requested
if(GetProperty(DBPROP_QUICKRESTART, DBPROPSET_ROWSET, (IUnknown*)m_pIRowset))
{
goto CLEANUP;
}
else
{
//if here then DBPROP_QUICKRESTART is TRUE
fTestPass = TEST_SKIPPED;
goto CLEANUP;
}
}
}
//get 2 row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,2,&cRows,&pHRow),S_OK);
//allocate memory for GetData
if(!(pData1=PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
//get the first 2 rows
//row 1
hr=m_pIRowset->GetData(pHRow[0],m_hAccessor,pData1);
//DBPROP_REMOVEDELETEDROWS maybe false
if(DB_E_DELETEDROW==hr)
{
TESTC_(m_pIRowset->GetData(pHRow[1],m_hAccessor,pData1),S_OK);
//second row here (pData1) should match the changed data
if(!CompareBuffer(pData,pData1,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
goto CLEANUP;
}
}
//DBPROP_REMOVEDELETEDROWS maybe true
if(S_OK==hr)
{
//the deleted row was removed so the first row fetch should now be the seond changed row
if(!CompareBuffer(pData,pData1,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
goto CLEANUP;
}
TESTC_(m_pIRowset->GetData(pHRow[1],m_hAccessor,pData1),S_OK);
//second row here (pData1) should now not match the changed data
if(CompareBuffer(pData,pData1,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
goto CLEANUP;
}
}
fTestPass=TRUE;
CLEANUP:
if(pData)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
}
if(pData1)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData1,TRUE);
}
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Delete rows from a static cursor/immediate mode, delete not supported
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Related_Delete_NewRow::Variation_7()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRowDelete = NULL;
DBPROPID rgPropertyIDs[2]= {NULL,NULL};
DBROWSTATUS DBRowStatus;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_INSERT;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,
2,g_rgPropertyIDs,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//get row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,3,&cRows, &pHRowDelete),S_OK);
//delete the rows
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,cRows,pHRowDelete,&DBRowStatus),DB_E_NOTSUPPORTED);
fTestPass=TRUE;
CLEANUP:
if(pHRowDelete && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRowDelete, NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRowDelete);
PROVIDER_FREE(m_pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc delete with a row handle from an unallocated rowset
//
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Related_Delete_NewRow::Variation_8()
{
HROW HRow = 27;
DBPROPID rgPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgDBRowStatus[1];
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create an accessor on the command object on the numeric and updatable column only
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,2,g_rgPropertyIDs,
ON_COMMAND_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange || !m_cBinding))
{
goto CLEANUP;
}
fTestPass = FALSE;
//get row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,3,&cRows, &pHRow),S_OK);
//delete the row using different row handle
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,&HRow,rgDBRowStatus),DB_E_ERRORSOCCURRED);
TESTC(COMPARE(rgDBRowStatus[0], DBROWSTATUS_E_INVALID));
fTestPass = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc delete with a row handle from an allocated rowset
//
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Related_Delete_NewRow::Variation_9()
{
HROW HRow = 27;
DBPROPID rgPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgDBRowStatus[1];
rgPropertyIDs[0]=DBPROP_IRowsetChange;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create an accessor on the command object on the numeric and updatable column only
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,2,g_rgPropertyIDs,
ON_COMMAND_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange || !m_cBinding))
{
goto CLEANUP;
}
fTestPass = FALSE;
//delete the row using different row handle
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,&HRow,rgDBRowStatus),DB_E_ERRORSOCCURRED);
TESTC(COMPARE(rgDBRowStatus[0], DBROWSTATUS_E_INVALID));
fTestPass = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc insert a row update then Hard Delete the row,
// @rdesc TEST_PASS or TEST_FAIL
//
int Related_Delete_NewRow::Variation_10()
{
BOOL fTestPass = TEST_SKIPPED;
HROW HRow;
void *pData = NULL;
DBPROPID rgPropertyIDs[6];
DBROWSTATUS rgDBRowStatus[1];
DBCOUNTITEM cRows = 0;
HROW *pUpdatedHRow = NULL;
DBROWSTATUS *pRowStatus = NULL;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
rgPropertyIDs[2]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[3]=DBPROP_CANHOLDROWS;
rgPropertyIDs[4]=DBPROP_CANFETCHBACKWARDS;
rgPropertyIDs[5]=DBPROP_CHANGEINSERTEDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//open a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,6,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate)|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
//fillup input data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//insert a new row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,&HRow),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL, 1, &HRow,&cRows,&pUpdatedHRow,&pRowStatus),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,&HRow,rgDBRowStatus),S_OK);
fTestPass = TEST_PASS;
CLEANUP:
if(pData)
{
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
}
if(m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,&HRow, NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pUpdatedHRow);
PROVIDER_FREE(pRowStatus);
if (m_pData)
{
PROVIDER_FREE(m_pData);
}
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc delete the same row handle
// @rdesc TEST_PASS or TEST_FAIL
//
int Related_Delete_NewRow::Variation_11()
{
BOOL fTestPass = TEST_SKIPPED;
HROW HRow[2];
HROW *pHRow = NULL;
DBPROPID rgPropertyIDs[3];
DBROWSTATUS rgDBRowStatus[2];
DBCOUNTITEM cRows = 0;
HRESULT hr;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
rgPropertyIDs[2]=DBPROP_OTHERUPDATEDELETE;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//open a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL, 1, 1, &cRows, &pHRow),S_OK);
//make an array of the same row handle
HRow[0] = *pHRow;
HRow[1] = *pHRow;
//delete the row
hr=m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,2,HRow,rgDBRowStatus);
//S_OK could be returned here
if (S_OK==hr)
{
TESTC(COMPARE(rgDBRowStatus[0], DBROWSTATUS_S_OK));
TESTC(COMPARE(rgDBRowStatus[1], DBROWSTATUS_S_OK));
}
//or DB_S_ERRORSOCCURRED
if (DB_S_ERRORSOCCURRED==hr)
{
if (rgDBRowStatus[0]==DBROWSTATUS_S_OK)
{
TESTC(COMPARE(rgDBRowStatus[1], DBROWSTATUS_E_DELETED));
}
else
{
TESTC(COMPARE(rgDBRowStatus[0], DBROWSTATUS_E_DELETED));
TESTC(COMPARE(rgDBRowStatus[1], DBROWSTATUS_S_OK));
}
}
fTestPass = TEST_PASS;
CLEANUP:
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL,NULL),S_OK);
}
if (m_pData)
{
PROVIDER_FREE(m_pData);
}
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Related_Delete_NewRow::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Sequence)
//*-----------------------------------------------------------------------
//| Test Case: Sequence - sequence testing
//| Created: 04/22/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Sequence::Init()
{
BOOL fTestPass = TEST_SKIPPED;
if(!TCIRowsetChange::Init())
return FALSE;
fTestPass = TRUE;
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Call SetData three times on the same row in an immediately update mode. One attempt is not successful.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Sequence::Variation_1()
{
BOOL fTestPass=TEST_SKIPPED;
void *pData=NULL;
void *pBadData=NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow=NULL;
DBPROPID rgPropertyIDs[2];
HRESULT hr;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
//open a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR, TRUE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,
UPDATEABLE_COLS_BOUND))
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass=FALSE;
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL, 2, 1, &cRows, &pHRow),S_OK);
TESTC_(GetData(*pHRow, m_hAccessor, m_pData),S_OK);
//fillup input data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//fillup input data again
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pBadData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//set data
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
//set data
hr=SetData(*pHRow, m_hAccessor, pBadData);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
fTestPass = TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pBadData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pBadData,TRUE);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Call SetData on two different row handles in an immediately update mode. One attempt is not successful
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Sequence::Variation_2()
{
BOOL fTestPass=TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow=NULL;
HROW *pHRowSecond=NULL;
void *pData=NULL;
void *pDataSecond=NULL;
DBPROPID rgPropertyIDs[3];
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
//open a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR, TRUE,
DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,
UPDATEABLE_COLS_BOUND))
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass=FALSE;
//fillup input data to the last row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//fillup input data again for the second row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pDataSecond,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL, 3, 1, &cRows, &pHRow),S_OK);
//get another row handle
TESTC_(m_pIRowset->GetNextRows(NULL, 0, 1, &cRows, &pHRowSecond),S_OK);
//set data
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
//set data to the second row
TESTC_(SetData(*pHRowSecond, m_hAccessor, pDataSecond),S_OK);
//relase the 2nd row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
fTestPass=TRUE;
CLEANUP:
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pDataSecond)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pDataSecond,TRUE);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Call SetData twice on the same row in a buffered update mode. The second attempt is not successful.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Sequence::Variation_3()
{
BOOL fTestPass=TEST_SKIPPED;
void *pData=NULL;
void *pBadData=NULL;
ULONG ulStatus;
DBCOUNTITEM cRows = 0;
ULONG cBinding = 0;
HROW *pHRow=NULL;
HROW *pUpdatedHRow=NULL;
ULONG cRefCount=0;
DBROWSTATUS *pRowStatus=NULL;
DBPROPID rgPropertyIDs[3];
HRESULT hr = S_OK;
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
//open a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR,FALSE, DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,
UPDATEABLE_COLS_BOUND))
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate)|| (!m_cBinding))
goto CLEANUP;
fTestPass=FALSE;
//fillup input data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//fillup input data again
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pBadData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//change the status binding of the first column to an invalid value
// ulStatus=*(DBSTATUS *)((DWORD)pBadData+m_rgBinding[0].obStatus);
// *(DBSTATUS *)((DWORD)pBadData+m_rgBinding[0].obStatus)=DBSTATUS_E_CANTCONVERTVALUE;
ulStatus=STATUS_BINDING(m_rgBinding[0],pBadData);
STATUS_BINDING(m_rgBinding[0],pBadData)=DBSTATUS_E_CANTCONVERTVALUE;
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL, 3, 1, &cRows, &pHRow),S_OK);
//set data
TESTC_(SetData(*pHRow, m_hAccessor, pData),S_OK);
//udpate data
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//set data
hr = SetData(*pHRow, m_hAccessor, pBadData);
TESTC(COMPARE(hr == DB_E_ERRORSOCCURRED || hr == DB_S_ERRORSOCCURRED, TRUE));
if ( hr == DB_S_ERRORSOCCURRED )
{
// check status
// fTestPass = COMPARE(*(DBSTATUS *)((DWORD)pBadData+m_rgBinding[0].obStatus),DBSTATUS_E_BADSTATUS);
fTestPass = COMPARE(STATUS_BINDING(m_rgBinding[0],pBadData),DBSTATUS_E_BADSTATUS);
for (cBinding = 1; cBinding<m_cBinding; cBinding++)
{
if (
// DBSTATUS_S_OK != *(DBSTATUS *)((DWORD)pBadData+m_rgBinding[cBinding].obStatus) &&
// DBSTATUS_S_ISNULL != *(DBSTATUS *)((DWORD)pBadData+m_rgBinding[cBinding].obStatus)
DBSTATUS_S_OK != STATUS_BINDING(m_rgBinding[cBinding],pBadData) &&
DBSTATUS_S_ISNULL != STATUS_BINDING(m_rgBinding[cBinding],pBadData)
)
{
fTestPass = FALSE;
}
}
}
//udpate data
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow, &cRows,&pUpdatedHRow,&pRowStatus),S_OK);
//release the row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRow, NULL, &cRefCount, NULL),S_OK);
PROVIDER_FREE(pHRow);
pHRow=NULL;
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pUpdatedHRow);
PROVIDER_FREE(pRowStatus);
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pBadData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pBadData,TRUE);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc In buffered update mode, retrieve 50 row handles, call IRowsetChange on each row handle, then call IRowstUpdate::Update
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Sequence::Variation_4()
{
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cCnt = g_ulNextRow++;
DBCOUNTITEM cCol = 0;
DBORDINAL *rgColNumber = NULL;
void *pData = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow=NULL;
DBCOUNTITEM cUpdatedRows = 0;
DBCOUNTITEM cMaxPendingRows = 0;
HROW *pUpdatedHRow = NULL;
DBROWSTATUS *rgDBRowStatus = NULL;
DBPROPID rgPropertyIDs[2];
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
//open a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,
0,NULL,NO_ACCESSOR))
TESTC(GetProperty(DBPROP_MAXPENDINGROWS, DBPROPSET_ROWSET, m_pIRowset, &cMaxPendingRows));
//get variable length updated columns
if(!GetVariableLengthAndUpdatable(&cCol, &rgColNumber))
goto CLEANUP;
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate)|| (!m_cBinding))
goto CLEANUP;
fTestPass=FALSE;
//create an write only accessor on the rowset for variable length columns
TESTC_PROVIDER(GetAccessorOnRowset(ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF, DBTYPE_EMPTY,
cCol, rgColNumber))
//get data for change row
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,cCnt++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//get all row handles
TESTC_(m_pIRowset->GetNextRows(NULL, 0,m_ulTableRows,&cRows,&pHRow),S_OK);
if(!COMPARE(cRows, m_ulTableRows))
goto CLEANUP;
if ( cMaxPendingRows > m_ulTableRows )
{
//update all the row handles
for(cCnt=0; cCnt<m_ulTableRows; cCnt++)
{
//set data
TESTC_(SetData(pHRow[cCnt], m_hAccessor, pData),S_OK);
}
//call update to update the 31 rows at the same time
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,&cUpdatedRows,&pUpdatedHRow,&rgDBRowStatus),S_OK);
if(COMPARE(cUpdatedRows, m_ulTableRows))
fTestPass=TRUE;
}
else
{
for ( cCnt=0; cCnt<m_ulTableRows; cCnt++ )
{
//set data for one row
TESTC_(SetData(pHRow[cCnt], m_hAccessor, pData),S_OK);
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&(pHRow[cCnt]),&cUpdatedRows,&pUpdatedHRow,&rgDBRowStatus),S_OK);
TESTC(COMPARE(cUpdatedRows, 1));
TESTC(COMPARE(pHRow[cCnt], pUpdatedHRow[0]));
TESTC(COMPARE(rgDBRowStatus[0], DBROWSTATUS_S_OK));
PROVIDER_FREE(pUpdatedHRow);
PROVIDER_FREE(rgDBRowStatus);
}
fTestPass = TRUE;
}
CLEANUP:
PROVIDER_FREE(rgColNumber);
PROVIDER_FREE(rgDBRowStatus);
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(cRows, pHRow, NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pUpdatedHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Sequence::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Transaction)
//*-----------------------------------------------------------------------
//| Test Case: Transaction - Testing IRowsetChange within a transaction
//| Created: 04/23/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Transaction::Init()
{
ULONG ulUpdValue = 0;
m_DBPropSet.rgProperties=NULL;
if(!CTransaction::Init())
return TEST_SKIPPED;
m_DBPropSet.guidPropertySet=DBPROPSET_ROWSET;
m_DBPropSet.cProperties=3;
m_DBPropSet.rgProperties=(DBPROP *)PROVIDER_ALLOC(6*sizeof(DBPROP));
if(!m_DBPropSet.rgProperties)
return FALSE;
//IID_IRowsetChange
m_DBPropSet.rgProperties[0].dwPropertyID=DBPROP_IRowsetChange;
m_DBPropSet.rgProperties[0].dwOptions=DBPROPOPTIONS_REQUIRED;
m_DBPropSet.rgProperties[0].vValue.vt=VT_BOOL;
m_DBPropSet.rgProperties[0].colid = DB_NULLID;
V_BOOL(&m_DBPropSet.rgProperties[0].vValue)=VARIANT_TRUE;
//DBPROP_UPDATEABILITY
m_DBPropSet.rgProperties[1].dwPropertyID=DBPROP_UPDATABILITY;
m_DBPropSet.rgProperties[1].dwOptions=DBPROPOPTIONS_REQUIRED;
m_DBPropSet.rgProperties[1].vValue.vt=VT_I4;
m_DBPropSet.rgProperties[1].colid = DB_NULLID;
V_I4(&m_DBPropSet.rgProperties[1].vValue)=DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//DBPROP_CANHOLDROWS
m_DBPropSet.rgProperties[2].dwPropertyID=DBPROP_CANHOLDROWS;
m_DBPropSet.rgProperties[2].dwOptions=DBPROPOPTIONS_REQUIRED;
m_DBPropSet.rgProperties[2].vValue.vt=VT_BOOL;
m_DBPropSet.rgProperties[2].colid = DB_NULLID;
V_BOOL(&m_DBPropSet.rgProperties[2].vValue)=VARIANT_TRUE;
if(SupportedProperty(DBPROP_IRowsetChange,DBPROPSET_ROWSET,g_pIDBCreateSession))
{
//register interface to be tested
if(!RegisterInterface(ROWSET_INTERFACE, IID_IRowsetChange, 1, &m_DBPropSet))
{
//all of these props are not supported
return TEST_SKIPPED;
}
}
return TRUE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Commit with fRetaining=TRUE. Cursor based.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Transaction::Variation_1()
{
BOOL fTestPass=TEST_SKIPPED;
HACCESSOR hAccessor=NULL;
IAccessor *pIAccessor=NULL;
void *pSetData=NULL;
void *pSetSecondData=NULL;
DBLENGTH cRowSize=0;
DBCOUNTITEM cBinding=0;
DBBINDING *rgBinding=NULL;
IRowsetChange *pIRowsetChange=NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow=NULL;
if(!SupportedProperty(DBPROP_IRowsetChange,DBPROPSET_ROWSET,g_pIDBCreateSession))
{
odtLog<<L"IRowsetChange not supported, test Skipped."<<ENDL;
goto CLEANUP;
}
TESTC_PROVIDER(StartTransaction(SELECT_ALLFROMTBL, (IUnknown **)&pIRowsetChange,1,&m_DBPropSet));
fTestPass=FALSE;
//create an accessor on the rowset object so that it can be shared
TESTC_(GetAccessorAndBindings(
m_pIRowset,
DBACCESSOR_ROWDATA,
&hAccessor,
&rgBinding,
&cBinding,
&cRowSize,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_NONINDEX_COLS_BOUND
),S_OK);
//get a row
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows, &pHRow),S_OK);
//Get data to set
TESTC_(FillInputBindings(m_pCTable,DBACCESSOR_ROWDATA,cBinding,rgBinding,
(BYTE **)&pSetData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//Get a second buffer to set
TESTC_(FillInputBindings(m_pCTable,DBACCESSOR_ROWDATA,cBinding,rgBinding,
(BYTE **)&pSetSecondData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//set data
TESTC_(pIRowsetChange->SetData(*pHRow, hAccessor,pSetData),S_OK);
//commit the transaction with fRetaining==TRUE
if(!GetCommit(TRUE))
{
goto CLEANUP;
}
if(!m_fCommitPreserve)
{
if(CHECK(pIRowsetChange->SetData(*pHRow, hAccessor, pSetSecondData),E_UNEXPECTED))
{
fTestPass=TRUE;
goto CLEANUP;
}
}
//test the rowset should be fully functional
TESTC_(pIRowsetChange->SetData(*pHRow, hAccessor, pSetSecondData),S_OK);
//commit the transaction with fRetaining==TRUE
if(!GetCommit(TRUE))
goto CLEANUP;
//releaset the accessor
TESTC_(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
fTestPass = TRUE;
hAccessor=NULL;
PROVIDER_FREE(rgBinding);
CLEANUP:
//release the accessor on the second rowset
if(hAccessor)
{
if(CHECK(pIRowsetChange->QueryInterface(IID_IAccessor,
(LPVOID *)&pIAccessor),S_OK))
{
CHECK(pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
SAFE_RELEASE(pIAccessor);
}
}
//release SetData buffers
if(pSetData)
ReleaseInputBindingsMemory(cBinding, rgBinding, (BYTE *)pSetData, TRUE);
if(pSetSecondData)
ReleaseInputBindingsMemory(cBinding, rgBinding, (BYTE *)pSetSecondData, TRUE);
//release the binding structure
PROVIDER_FREE(rgBinding);
//release the row handle on the 1st rowset
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1, pHRow, NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
SAFE_RELEASE(pIRowsetChange);
//clean up
CleanUpTransaction(S_OK);
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Commit with fRetaining=FALSE. Query based.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Transaction::Variation_2()
{
BOOL fTestPass=TEST_SKIPPED;
HACCESSOR hAccessor=NULL;
IAccessor *pIAccessor=NULL;
void *pSetData=NULL;
DBLENGTH cRowSize=0;
DBCOUNTITEM cBinding=0;
DBBINDING *rgBinding=NULL;
IRowsetChange *pIRowsetChange=NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow=NULL;
if(!SupportedProperty(DBPROP_IRowsetChange,DBPROPSET_ROWSET,g_pIDBCreateSession))
{
odtLog<<L"IRowsetChange not supported, test Skipped."<<ENDL;
goto CLEANUP;
}
//start a transaction. Create a rowset with IRowsetChange pointer.
TESTC_PROVIDER(StartTransaction(SELECT_ALLFROMTBL, (IUnknown **)&pIRowsetChange,1,&m_DBPropSet));
fTestPass=FALSE;
//get a row
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows, &pHRow),S_OK);
//create an accessor on the rowset object so that it can be shared
TESTC_(GetAccessorAndBindings(m_pIRowset,DBACCESSOR_ROWDATA,
&hAccessor, &rgBinding,&cBinding,&cRowSize,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_NONINDEX_COLS_BOUND),S_OK);
//Get data to set
TESTC_(FillInputBindings(m_pCTable,DBACCESSOR_ROWDATA,cBinding,rgBinding,
(BYTE **)&pSetData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//set data
TESTC_(pIRowsetChange->SetData(*pHRow, hAccessor,pSetData),S_OK);
//commit the transaction with fRetaining==FALSE
if(!GetCommit(FALSE))
goto CLEANUP;
if(!m_fCommitPreserve)
{
//test zombie
if(CHECK(pIRowsetChange->SetData(*pHRow, hAccessor, pSetData),E_UNEXPECTED))
fTestPass=TRUE;
goto CLEANUP;
}
//test the rowset should be fully functional
TESTC_(pIRowsetChange->SetData(*pHRow, hAccessor, pSetData), S_OK);
//release the accessor
TESTC_(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
fTestPass = TRUE;
hAccessor=NULL;
PROVIDER_FREE(rgBinding);
CLEANUP:
//release the accessor on the second rowset
if(hAccessor)
{
if(CHECK(pIRowsetChange->QueryInterface(IID_IAccessor,
(LPVOID *)&pIAccessor),S_OK))
{
CHECK(pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
SAFE_RELEASE(pIAccessor);
}
}
//release SetData buffers
if(pSetData)
ReleaseInputBindingsMemory(cBinding, rgBinding, (BYTE *)pSetData, TRUE);
//release the binding structure
PROVIDER_FREE(rgBinding);
//release the row handle on the 1st rowset
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1, pHRow, NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
SAFE_RELEASE(pIRowsetChange);
//clean up
CleanUpTransaction(XACT_E_NOTRANSACTION);
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Abort with fRetaining=TRUE. Query based.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Transaction::Variation_3()
{
BOOL fTestPass = TEST_SKIPPED;
BOOL fFound = FALSE;
HACCESSOR hAccessor = NULL;
IAccessor *pIAccessor = NULL;
void *pSetData = NULL;
DBLENGTH cRowSize = 0;
void *pGetOriginalData = NULL;
void *pData = NULL;
DBCOUNTITEM cBinding = 0;
DBBINDING *rgBinding = NULL;
IRowsetChange *pIRowsetChange = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HRESULT hr = S_OK;
IMalloc *pIMalloc;
CoGetMalloc(MEMCTX_TASK, &pIMalloc);
if(!SupportedProperty(DBPROP_IRowsetChange,DBPROPSET_ROWSET,g_pIDBCreateSession))
{
odtLog<<L"IRowsetChange not supported, test Skipped."<<ENDL;
goto CLEANUP;
}
//start a transaction. Create a rowset with IRowsetChange pointer.
TESTC_PROVIDER(StartTransaction(SELECT_ORDERBYNUMERIC, (IUnknown **)&pIRowsetChange,1,&m_DBPropSet));
fTestPass=FALSE;
//get a row
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows, &pHRow),S_OK);
//create an accessor on the command object so that it can be shared
TESTC_(GetAccessorAndBindings(m_pIRowset,DBACCESSOR_ROWDATA,&hAccessor, &rgBinding,&cBinding,&cRowSize,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_NONINDEX_COLS_BOUND),S_OK);
//allocate memory for GetData
if(!(pGetOriginalData=PROVIDER_ALLOC(cRowSize)))
goto CLEANUP;
TESTC_(m_pIRowset->GetData(*pHRow, hAccessor,pGetOriginalData),S_OK);
//Get data to set
TESTC_(FillInputBindings(m_pCTable,DBACCESSOR_ROWDATA,cBinding,rgBinding,
(BYTE **)&pSetData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//set data
// TESTC_(pIRowsetChange->SetData(*pHRow, hAccessor,pSetData),S_OK);
pIRowsetChange->SetData(*pHRow, hAccessor,pSetData);
//Abort the transaction with fRetaining==TRUE
if(!GetAbort(TRUE))
goto CLEANUP;
if(!m_fAbortPreserve)
{
//test zombie
if(CHECK(pIRowsetChange->SetData(*pHRow, hAccessor, pSetData),E_UNEXPECTED))
fTestPass=TRUE;
goto CLEANUP;
}
//release the row handle on the 1st rowset
if(pHRow && m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(1, pHRow, NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
//get the data from the row
//allocate memory for GetData
if(!(pData=PROVIDER_ALLOC(cRowSize)))
goto CLEANUP;
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
{
if( cRows ==0)
break;
//Get the data for the ith row handle
TESTC_(m_pIRowset->GetData(*pHRow,hAccessor,pData),S_OK);
//make sure GetData should NOT be able to see the change
//ABORT was called!
if(CompareBuffer(pData,pSetData,cBinding,rgBinding,pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
{
fFound=TRUE;
break;
}
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
}
if (fFound)
{
goto CLEANUP;
}
//free the memory used by m_pData
ReleaseInputBindingsMemory(cBinding,rgBinding,(BYTE *)pData);
//test the rowset should be fully functional
//restartposition
hr = m_pIRowset->RestartPosition(NULL);
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
{
goto CLEANUP;
}
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows, &pHRow),S_OK);
TESTC_(pIRowsetChange->SetData(*pHRow, hAccessor, pSetData),S_OK);
//Abort the transaction with fRetaining==TRUE
if(!GetAbort(TRUE))
goto CLEANUP;
//release the accessor
TESTC_(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
fTestPass = TRUE;
CLEANUP:
//release the accessor on the second rowset
if(hAccessor)
{
if(CHECK(pIRowsetChange->QueryInterface(IID_IAccessor,
(LPVOID *)&pIAccessor),S_OK))
{
CHECK(pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
SAFE_RELEASE(pIAccessor);
}
}
//release SetData buffers
if(pSetData)
ReleaseInputBindingsMemory(cBinding, rgBinding, (BYTE *)pSetData, TRUE);
if(pGetOriginalData)
ReleaseInputBindingsMemory(cBinding, rgBinding, (BYTE *)pGetOriginalData, TRUE);
SAFE_RELEASE(pIMalloc);
//release the binding structure
PROVIDER_FREE(rgBinding);
//release the row handle on the 1st rowset
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1, pHRow, NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
SAFE_RELEASE(pIRowsetChange);
//clean up
CleanUpTransaction(S_OK);
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Abort with fRetaining=FALSE. Cursor based.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Transaction::Variation_4()
{
BOOL fTestPass = TEST_SKIPPED;
HACCESSOR hAccessor = NULL;
IAccessor *pIAccessor = NULL;
void *pSetData = NULL;
DBLENGTH cRowSize = 0;
void *pGetData = NULL;
DBCOUNTITEM cBinding = 0;
DBBINDING *rgBinding = NULL;
IRowsetChange *pIRowsetChange = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW *pSecondHRow = NULL;
IUnknown *pRowset = NULL;
if(!SupportedProperty(DBPROP_IRowsetChange,DBPROPSET_ROWSET,g_pIDBCreateSession))
{
odtLog<<L"IRowsetChange not supported, test Skipped."<<ENDL;
goto CLEANUP;
}
//start a transaction. Create a rowset with IRowsetChange pointer.
TESTC_PROVIDER(StartTransaction(SELECT_ORDERBYNUMERIC, (IUnknown **)&pIRowsetChange,1,&m_DBPropSet));
fTestPass=FALSE;
//get a row
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow),S_OK);
//create an accessor on the command object so that it can be shared
TESTC_(GetAccessorAndBindings(m_pIRowset,DBACCESSOR_ROWDATA,&hAccessor,&rgBinding,&cBinding,&cRowSize,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_NONINDEX_COLS_BOUND),S_OK);
//Get data to set
TESTC_(FillInputBindings(m_pCTable,DBACCESSOR_ROWDATA,cBinding,rgBinding,
(BYTE **)&pSetData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//set data
TESTC_(pIRowsetChange->SetData(*pHRow, hAccessor,pSetData),S_OK);
//Abort the transaction with fRetaining==FALSE
if(!GetAbort(FALSE))
goto CLEANUP;
if(!m_fAbortPreserve)
{
//test zombie
if(CHECK(pIRowsetChange->SetData(*pHRow, hAccessor, pSetData),E_UNEXPECTED))
fTestPass=TRUE;
goto CLEANUP;
}
//test the rowset should be fully functional
TESTC_(pIRowsetChange->SetData(*pHRow, hAccessor, pSetData),S_OK);
//releaset the accessor
TESTC_(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
fTestPass = TRUE;
hAccessor=NULL;
PROVIDER_FREE(rgBinding);
CLEANUP:
//release GetData buffers
PROVIDER_FREE(pGetData);
//release the accessor on the second rowset
if(hAccessor)
{
//QI for IAccessor. The accessor could be on the 1st rowset
if(pRowset)
{
if(CHECK(pRowset->QueryInterface(IID_IAccessor,
(LPVOID *)&pIAccessor),S_OK))
{
CHECK(pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
SAFE_RELEASE(pIAccessor);
}
}
else
if(CHECK(pIRowsetChange->QueryInterface(IID_IAccessor,
(LPVOID *)&pIAccessor),S_OK))
{
CHECK(pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
SAFE_RELEASE(pIAccessor);
}
}
//release the row handles generated for the second time
if(pSecondHRow)
CHECK(((IRowset *)pRowset)->ReleaseRows(1, pSecondHRow, NULL,NULL, NULL),S_OK);
PROVIDER_FREE(pSecondHRow);
SAFE_RELEASE(pRowset);
//release SetData buffers
if(pSetData)
ReleaseInputBindingsMemory(cBinding, rgBinding, (BYTE *)pSetData, TRUE);
//release the binding structure
PROVIDER_FREE(rgBinding);
//release the row handle on the 1st rowset
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1, pHRow, NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
SAFE_RELEASE(pIRowsetChange);
//clean up
CleanUpTransaction(XACT_E_NOTRANSACTION);
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Transaction::Terminate()
{
if(m_DBPropSet.rgProperties)
PROVIDER_FREE(m_DBPropSet.rgProperties);
return(CTransaction::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(ExtendedErrors)
//*-----------------------------------------------------------------------
//| Test Case: ExtendedErrors - Extended Errors
//| Created: 07/26/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL ExtendedErrors::Init()
{
if(!TCIRowsetChange::Init())
return FALSE;
return TRUE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Valid DeleteRows calls with previous error object existing.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int ExtendedErrors::Variation_1()
{
BOOL fTestPass=TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRowDelete=NULL;
DBPROPID rgPropertyIDs[3];
HRESULT hr;
//For each method of the interface, first create an error object on
//the current thread, try get a success from the IRowsetChange method.
//We then check extended errors to verify the right extended error behavior.
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
rgPropertyIDs[2]=DBPROP_OTHERUPDATEDELETE;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//open a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass = FALSE;
//get a row handle
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows, &pHRowDelete),S_OK);
//create an error object
m_pExtError->CauseError();
//delete the row
if(CHECK(hr=m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRowDelete,NULL),S_OK))
//Do extended check following DeleteRows
fTestPass = XCHECK(m_pIRowsetChange, IID_IRowsetChange, hr);
else
goto CLEANUP;
//release the deleted row handle
TESTC_(m_pIRowset->ReleaseRows(1,pHRowDelete, NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDelete);
CLEANUP:
if(pHRowDelete && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowDelete, NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowDelete);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Invalid DeleteRows calls with previous error object existing
//
// @rdesc TEST_PASS or TEST_FAIL
//
int ExtendedErrors::Variation_2()
{
BOOL fTestPass=TEST_SKIPPED;
DBPROPID rgPropertyIDs[3];
HRESULT hr;
//For each method of the interface, first create an error object on
//the current thread, try get a failure from the IRowsetIdentity method.
//We then check extended errors to verify the right extended error behavior.
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//open a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass = FALSE;
//create an error object
m_pExtError->CauseError();
//delete the row
if(CHECK(hr=m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,NULL,NULL),E_INVALIDARG))
//Do extended check following DeleteRows
fTestPass = XCHECK(m_pIRowsetChange, IID_IRowsetChange, hr);
else
goto CLEANUP;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Invalid DeleteRows calls with no previous error object existing
//
// @rdesc TEST_PASS or TEST_FAIL
//
int ExtendedErrors::Variation_3()
{
BOOL fTestPass=TEST_SKIPPED;
DBPROPID rgPropertyIDs[3];
HRESULT hr;
//For each method of the interface, with no error object on
//the current thread, try get a failure from the IRowsetChange method.
//We then check extended errors to verify the right extended error behavior.
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//open a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass = FALSE;
//delete the row
if(CHECK(hr=m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,NULL,NULL),E_INVALIDARG))
//Do extended check following DeleteRows
fTestPass = XCHECK(m_pIRowsetChange, IID_IRowsetChange, hr);
else
goto CLEANUP;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Valid SetData calls with previous error object existing.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int ExtendedErrors::Variation_4()
{
HROW hRow[1];
HROW *pHRow = hRow;
DBCOUNTITEM cRowsObtained = 0;
HACCESSOR hAccessor;
DBPROPID rgPropertyIDs[1];
HRESULT hr;
BOOL fPass = TEST_SKIPPED;
//For each method of the interface, first create an error object on
//the current thread, try get a success from the IRowsetChange method.
//We then check extended errors to verify the right extended error behavior.
rgPropertyIDs[0]=DBPROP_IRowsetUpdate;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR));
if (!m_pIRowsetChange)
goto CLEANUP;
fPass = FALSE;
//create an NULL accessor
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,
0,NULL,0,&hAccessor,NULL),S_OK);
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRowsObtained, &pHRow),S_OK);
COMPARE(cRowsObtained, 1);
//create an error object
//m_pExtError->CauseError();
if(CHECK(hr=SetData(hRow[0],hAccessor,NULL),S_OK))
//Do extended check following SetData
fPass = XCHECK(m_pIRowsetChange, IID_IRowsetChange, hr);
CHECK(m_pIRowset->ReleaseRows(1,hRow,NULL,NULL,NULL),S_OK);
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
CLEANUP:
ReleaseRowsetAndAccessor();
return fPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Invalid SetData calls with previous error object existing
//
// @rdesc TEST_PASS or TEST_FAIL
//
int ExtendedErrors::Variation_5()
{
HROW hRow[1];
HROW *pHRow = hRow;
DBCOUNTITEM cRowsObtained = 0;
HACCESSOR hAccessor;
BOOL fPass = TEST_SKIPPED;
DBPROPID rgPropertyIDs[1];
HRESULT hr;
//For each method of the interface, first create an error object on
//the current thread, try get a failure from the IRowsetChange method.
//We then check extended errors to verify the right extended error behavior.
rgPropertyIDs[0]=DBPROP_IRowsetChange;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR));
if (!m_pIRowsetChange)
goto CLEANUP;
fPass = FALSE;
//create an NULL accessor
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,
0,NULL,0,&hAccessor,NULL),S_OK);
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRowsObtained, &pHRow),S_OK);
COMPARE(cRowsObtained, 1);
//create an error object
m_pExtError->CauseError();
//use NULL hRow
if(CHECK(hr=m_pIRowsetChange->SetData(DB_NULL_HROW,hAccessor,m_pData),
DB_E_BADROWHANDLE))
//Do extended check following SetData
fPass = XCHECK(m_pIRowsetChange, IID_IRowsetChange, hr);
else
goto CLEANUP;
CHECK(m_pIRowset->ReleaseRows(1,hRow,NULL,NULL,NULL),S_OK);
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
CLEANUP:
ReleaseRowsetAndAccessor();
return fPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Invalid SetData calls with no previous error object existing
//
// @rdesc TEST_PASS or TEST_FAIL
//
int ExtendedErrors::Variation_6()
{
HROW hRow[1];
HROW *pHRow = hRow;
DBCOUNTITEM cRowsObtained = 0;
HACCESSOR hAccessor;
HRESULT hr;
BOOL fPass = TEST_SKIPPED;
DBPROPID rgPropertyIDs[1];
//For each method of the interface, first create an error object on
//the current thread, try get a failure from the IRowsetChange method.
//We then check extended errors to verify the right extended error behavior.
rgPropertyIDs[0]=DBPROP_IRowsetChange;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//create a rowset and an accessor on the rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR))
if (!m_pIRowsetChange)
goto CLEANUP;
fPass = FALSE;
//create an NULL accessor
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,&hAccessor,NULL),S_OK);
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRowsObtained, &pHRow),S_OK);
COMPARE(cRowsObtained, 1);
//use NULL hAccessor
if(CHECK(hr=SetData(hRow[0],DB_NULL_HACCESSOR,m_pData),DB_E_BADACCESSORHANDLE))
//Do extended check following SetData
fPass = XCHECK(m_pIRowsetChange, IID_IRowsetChange, hr);
else
goto CLEANUP;
CHECK(m_pIRowset->ReleaseRows(1,hRow,NULL,NULL,NULL),S_OK);
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
CLEANUP:
ReleaseRowsetAndAccessor();
return fPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Valid InsertRow calls with previous error object existing.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int ExtendedErrors::Variation_7()
{
BOOL fTestPass=TEST_SKIPPED;
void *pData=NULL;
DBPROPID rgPropertyIDs[3];
HRESULT hr;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
//For each method of the interface, with no error object on
//the current thread, try get a failure from the IRowsetChange method.
//We then check extended errors to verify the right extended error behavior.
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//open a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,3,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass = FALSE;
//fillup input data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//create an error object
m_pExtError->CauseError();
//insert a new row
if(CHECK(hr=m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,NULL),S_OK))
//Do extended check following InsertRow
fTestPass = XCHECK(m_pIRowsetChange, IID_IRowsetChange, hr);
else
goto CLEANUP;
CLEANUP:
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc Invalid InsertRow calls with previous error object existing
//
// @rdesc TEST_PASS or TEST_FAIL
//
int ExtendedErrors::Variation_8()
{
BOOL fTestPass=TEST_SKIPPED;
DBPROPID rgPropertyIDs[3];
HRESULT hr;
//For each method of the interface, with no error object on
//the current thread, try get a failure from the IRowsetChange method.
//We then check extended errors to verify the right extended error behavior.
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//open a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,3,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass = FALSE;
//create an error object
m_pExtError->CauseError();
//insert a new row
if(CHECK(hr=m_pIRowsetChange->InsertRow(NULL,m_hAccessor,NULL,NULL),E_INVALIDARG))
//Do extended check following InsertRow
fTestPass = XCHECK(m_pIRowsetChange, IID_IRowsetChange, hr);
else
goto CLEANUP;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc Invalid InsertRow calls with no previous error object existing
//
// @rdesc TEST_PASS or TEST_FAIL
//
int ExtendedErrors::Variation_9()
{
BOOL fTestPass=TRUE;
void *pData=NULL;
DBPROPID rgPropertyIDs[4];
HRESULT hr;
//For each method of the interface, with no error object on
//the current thread, try get a failure from the IRowsetChange method.
//We then check extended errors to verify the right extended error behavior.
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_OTHERUPDATEDELETE;
rgPropertyIDs[2]=DBPROP_CANHOLDROWS;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
//open a rowset with an accessor on all updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,3,rgPropertyIDs,
0,NULL,ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE | DBPART_LENGTH |DBPART_STATUS,UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
goto CLEANUP;
fTestPass = FALSE;
//fillup input data
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
//insert a new row
if(CHECK(hr=m_pIRowsetChange->InsertRow(NULL,DB_NULL_HACCESSOR,pData,NULL),DB_E_BADACCESSORHANDLE))
//Do extended check following InsertRow
fTestPass = XCHECK(m_pIRowsetChange, IID_IRowsetChange, hr);
else
goto CLEANUP;
CLEANUP:
if(pData)
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE *)pData,TRUE);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL ExtendedErrors::Terminate()
{
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(ProviderOwnedMem)
//*-----------------------------------------------------------------------
//| Test Case: ProviderOwnedMem - Use ProviderOwned Memory for SetData
//| Created: 07/31/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL ProviderOwnedMem::Init()
{
BOOL fTestPass = TEST_SKIPPED;
// {{ TCW_INIT_BASECLASS_CHECK
if(!TCIRowsetChange::Init())
// }}
return FALSE;
fTestPass = TRUE;
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc ProdiverOwnedMem for SetData. Keyset_Query_Buffered
//
// @rdesc TEST_PASS or TEST_FAIL
//
int ProviderOwnedMem::Variation_1()
{
DBCOUNTITEM cCol = 0;
DBORDINAL *rgColNumber = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRowFirst = NULL;
HROW *pHRowSecond = NULL;
DBPROPID rgDBProp[4];
void *pData = NULL;
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr = S_OK;
//Init
rgDBProp[0]=DBPROP_IRowsetChange;
rgDBProp[1]=DBPROP_OTHERUPDATEDELETE;
rgDBProp[2]=DBPROP_CANHOLDROWS;
rgDBProp[3]=DBPROP_IRowsetLocate;
//create a rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,4,rgDBProp,0,NULL,NO_ACCESSOR));
//get the variable length updatable columns
if(!GetVariableLengthAndUpdatable(&cCol, &rgColNumber))
goto CLEANUP;
if (!m_pIRowsetChange)
goto CLEANUP;
fTestPass = FALSE;
//create a write only accessor on the variable length updatable columns
//do not include the first column. Use Provider owned memory.
fTestPass = GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE, DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD,NO_COLS_BY_REF,
DBTYPE_BYREF,cCol,rgColNumber,ALL_COLS_OWNED_BY_PROV);
//DB_E_ERRORSOCCURRED is temperarily acceptable for providers that don't support provider
//owned memory. a new prop to determine if a provider supports this is on its way
if (TEST_SKIPPED == fTestPass)
goto CLEANUP;
if (TRUE!=fTestPass)
goto CLEANUP;
//get a first row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRowFirst),S_OK);
//get a second row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRowSecond),S_OK);
//get data for the original values of variable length data types
TESTC_(GetData(*pHRowFirst, m_hAccessor,m_pData),S_OK);
//set data to the second row handle
TESTC_(SetData(*pHRowSecond, m_hAccessor, m_pData),S_OK);
//release the row handles
TESTC_(m_pIRowset->ReleaseRows(1,pHRowFirst,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowFirst);
TESTC_(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgColNumber);
if(pHRowFirst && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowFirst,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowFirst);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc ProdiverOwnedMem for SetData. Keyset_Cursor_Imm
//
// @rdesc TEST_PASS or TEST_FAIL
//
int ProviderOwnedMem::Variation_2()
{
DBCOUNTITEM cCol = 0;
DBORDINAL *rgColNumber = NULL;
DBCOUNTITEM cRows = 0;
HROW *pHRowFirst = NULL;
HROW *pHRowSecond = NULL;
DBPROPID rgDBProp[3];
void *pData = NULL;
BOOL fTestPass = TEST_SKIPPED;
HRESULT hr = S_OK;
//Init
rgDBProp[0]=DBPROP_IRowsetUpdate;
rgDBProp[1]=DBPROP_OTHERUPDATEDELETE;
rgDBProp[2]=DBPROP_CANHOLDROWS;
//create a rowset
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,3,rgDBProp,0,NULL,NO_ACCESSOR));
//get the variable length updatable columns
if(!GetVariableLengthAndUpdatable(&cCol, &rgColNumber))
goto CLEANUP;
if ((!m_pIRowsetChange) || (!m_pIRowsetUpdate))
goto CLEANUP;
fTestPass = FALSE;
//create a write only accessor on the variable length updatable columns
//do not include the first column. Use Provider owned memory.
fTestPass= GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE, DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
USE_COLS_TO_BIND_ARRAY,FORWARD,NO_COLS_BY_REF,
DBTYPE_BYREF,cCol,rgColNumber,ALL_COLS_OWNED_BY_PROV);
//DB_E_ERRORSOCCURRED is temperarily acceptable for providers that don't support provider
//owned memory. a new prop to determine if a provider supports this is on its way
if (TEST_SKIPPED == fTestPass)
goto CLEANUP;
if (TRUE!=fTestPass)
goto CLEANUP;
//get a first row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRowFirst),S_OK);
//get a second row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRowSecond),S_OK);
//get data for the original values of variable length data types
TESTC_(GetData(*pHRowFirst, m_hAccessor,m_pData),S_OK);
//set data to the second row handle
TESTC_(SetData(*pHRowSecond, m_hAccessor, m_pData),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRowSecond,NULL,NULL,NULL),S_OK);
//release the row handles
TESTC_(m_pIRowset->ReleaseRows(1,pHRowFirst,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowFirst);
fTestPass = TRUE;
CLEANUP:
PROVIDER_FREE(pData);
PROVIDER_FREE(rgColNumber);
if(pHRowFirst && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowFirst,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowFirst);
if(pHRowSecond && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRowSecond,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRowSecond);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL ProviderOwnedMem::Terminate()
{
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCIRowsetChange::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(SetDefault)
//*-----------------------------------------------------------------------
//| Test Case: SetDefault - Default value in data setting operations
//| Created: 6/8/98
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc Builds a list of info about the default property of the columns
//
//*-----------------------------------------------------------------------
BOOL SetDefault::GetDefaultColumns()
{
CRowset Rowset;
BOOL fRes = FALSE;
ULONG i = 0;
const ULONG cRes = 4;
VARIANT rgRes[cRes];
CCol col;
HROW hRow;
DBBINDING *pColNameBinding = NULL;
DBBINDING *pColGUIDBinding = NULL;
DBBINDING *pColPROPIDBinding = NULL;
DBBINDING *pOrdinalPosBinding = NULL;
DBBINDING *pHasDefaultBinding = NULL;
DBBINDING *pDefaultBinding = NULL;
DBBINDING *pIsNullableBinding = NULL;
DBID ColID;
DBCOUNTITEM nCol = 0;
ULONG cCol = 0;
DBORDINAL cNumColonTable = m_pTable->CountColumnsOnTable();
// init the retrictions for COLUMNS Schema Rowset
for (i=0; i<cRes; i++)
{
VariantInit(&rgRes[i]);
}
// set the table name restriction
rgRes[2].vt = DBTYPE_BSTR;
V_BSTR(&rgRes[2]) = SysAllocString(m_pTable->GetTableName());
// alloc mem for the output parameters and initialize
SAFE_ALLOC(m_rgbDefault, BOOL, cNumColonTable);
memset(m_rgbDefault, 0, (size_t)(sizeof(BOOL)*cNumColonTable));
// set restrictions and create rowset, accessor and bindings (do not bind bookmark)
Rowset.SetRestrictions(cRes, rgRes);
TESTC_PROVIDER(Rowset.CreateRowset(SELECT_DBSCHEMA_COLUMNS, IID_IRowset, m_pTable, DBACCESSOR_ROWDATA,
DBPART_ALL, ALL_COLS_EXCEPTBOOKMARK) == S_OK);
// map various bindings
pColNameBinding = &Rowset.m_rgBinding[3];
pColGUIDBinding = &Rowset.m_rgBinding[4];
pColPROPIDBinding = &Rowset.m_rgBinding[5];
pOrdinalPosBinding = &Rowset.m_rgBinding[6];
pHasDefaultBinding = &Rowset.m_rgBinding[7];
pDefaultBinding = &Rowset.m_rgBinding[8];
pIsNullableBinding = &Rowset.m_rgBinding[10];
// iterate the columns
while (Rowset.GetNextRows(&hRow) == S_OK)
{
// get data for this column
TESTC_PROVIDER(Rowset.GetRowData(hRow, &Rowset.m_pData) == S_OK);
//check binding status for info required
TESTC( DBSTATUS_S_OK == STATUS_BINDING(*pColNameBinding, Rowset.m_pData)
|| DBSTATUS_S_OK == STATUS_BINDING(*pColGUIDBinding, Rowset.m_pData)
|| DBSTATUS_S_OK == STATUS_BINDING(*pColPROPIDBinding, Rowset.m_pData)
|| DBSTATUS_S_OK == STATUS_BINDING(*pOrdinalPosBinding, Rowset.m_pData));
TESTC(DBSTATUS_S_OK == STATUS_BINDING(*pHasDefaultBinding, Rowset.m_pData));
// identify the column (using the ordinal position, name, guid or propid)
if (DBSTATUS_S_OK == STATUS_BINDING(*pOrdinalPosBinding, Rowset.m_pData))
{
// using the ordinal position
nCol = *(unsigned int*)((BYTE*)Rowset.m_pData + pOrdinalPosBinding->obValue);
}
else
{
if (DBSTATUS_S_OK == STATUS_BINDING(*pColNameBinding, Rowset.m_pData))
{
// identify the column through its name
ColID.eKind = DBKIND_NAME;
ColID.uName.pwszName = (WCHAR*)((BYTE*)Rowset.m_pData + pColNameBinding->obValue);
}
else
if (DBSTATUS_S_OK == STATUS_BINDING(*pColGUIDBinding, Rowset.m_pData))
{
// get the column based on guid
ColID.eKind = DBKIND_GUID;
ColID.uGuid.guid = *(GUID*)((BYTE*)Rowset.m_pData+pColGUIDBinding->obValue);
}
else
{
// get the propid of the column
ColID.eKind = DBKIND_PROPID;
ColID.uName.ulPropid = *(PROPID*)((BYTE*)Rowset.m_pData+pColPROPIDBinding->obValue);
}
// retrieve column info from the table and get column number (ordinal position)
m_pTable->GetColInfo(&ColID, col);
nCol = col.GetColNum();
}
col = m_pTable->GetColInfoForUpdate(nCol);
// go and check that the column has a default value
if (VARIANT_TRUE == *(VARIANT_BOOL*)((BYTE*)Rowset.m_pData+pHasDefaultBinding->obValue))
{
m_rgbDefault[nCol-1] = TRUE;
if (DBSTATUS_S_OK == STATUS_BINDING(*pDefaultBinding, Rowset.m_pData))
{
VARIANT vDefault;
// get column default
col.SetHasDefault(TRUE);
vDefault.vt = VT_BSTR;
V_BSTR(&vDefault) = SysAllocString((WCHAR*)((BYTE*)Rowset.m_pData+pDefaultBinding->obValue));
col.SetDefaultValue(vDefault);
VariantClear(&vDefault);
}
else
if (DBSTATUS_S_ISNULL == STATUS_BINDING(*pDefaultBinding, Rowset.m_pData))
{
col.SetNullable(TRUE);
}
}
// check if the column is nullable
if ( col.GetNullable()
|| ( DBSTATUS_S_OK == STATUS_BINDING(*pIsNullableBinding, Rowset.m_pData)
&& VARIANT_TRUE == *(VARIANT_BOOL*)((BYTE*)Rowset.m_pData+pIsNullableBinding->obValue)))
{
col.SetNullable(TRUE);
m_rgbDefault[nCol-1] = TRUE;
}
}
fRes = TRUE;
CLEANUP:
// clean restriction array
for (i=0; i<cRes; i++)
{
VariantClear(&rgRes[i]);
}
return fRes;
} // SetDefault::GetDefaultColumns
//*-----------------------------------------------------------------------
// @mfunc mask the m_fHasDefault field of columns in m_pTable
//
void SetDefault::MaskDefColumns(BOOL fMask)
{
ULONG iCol = 0;
DBORDINAL cCol = g_pTable->CountColumnsOnTable();
CCol col;
for (iCol=0; iCol < cCol; iCol++)
{
col = g_pTable->GetColInfoForUpdate(iCol+1);
if (m_rgbDefault[iCol] && fMask)
g_pTable->SetHasDefaultValue(col, fMask);
else
g_pTable->SetHasDefaultValue(col, FALSE);
}
return;
} //SetDefault::MaskDefColumns
//*-----------------------------------------------------------------------
// @mfunc SetDefault::PrepareForSetData
// Creates a rowset and accessors, fills the input bindings and
// set the proper status of the given column
//
// @rdesc TEST_FAIL on failure or TEST_PASS on success. TEST_SKIPPED when prop not supported
//
BOOL SetDefault::PrepareForSetData(
DBORDINAL cSelectedColumn, // [in] the ordinal of the selected column (1 based)
DBSTATUS Status, // [in] the status value for the selected column
DBCOUNTITEM lRowsOffset, // [in] row number for data creation
BYTE **ppData // [out] data buffer
)
{
BOOL fTestPass = TEST_SKIPPED;
ULONG cBinding = 0;
// properties asked for the rowset related to bindings
DBPROPID rgPropertyIDs[] = {DBPROP_IRowsetChange};
TESTC(NULL != ppData);
*ppData = NULL;
//create an accessor on the command object on a updatable column only
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,NUMELEM(rgPropertyIDs),rgPropertyIDs,0,NULL,
ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND,
FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,0,NULL));
TESTC(0 < m_cBinding);
fTestPass = TEST_FAIL;
//get a new data buffer to set the data
TESTC_(FillInputBindings( m_pTable,
DBACCESSOR_ROWDATA,
m_cBinding,
m_rgBinding,
ppData,
lRowsOffset, // row number for data creation
m_cRowsetCols,
m_rgTableColOrds,
PRIMARY),S_OK);
// set status in bindings
for (cBinding = 0; cBinding < m_cBinding; cBinding++)
{
if (m_rgBinding[cBinding].iOrdinal == cSelectedColumn)
{
*(ULONG *)(*ppData+m_rgBinding[cBinding].obStatus) = Status;
break;
}
}
fTestPass = TEST_PASS;
CLEANUP:
return fTestPass;
} // SetDefault::PrepareForSetData
//*-----------------------------------------------------------------------
// @mfunc SetData, check it, get data, check it
//
// @rdesc TRUE or FALSE
//
BOOL SetDefault::SetAndCheckDefault(
BYTE *pData, // [in] buffer for IRowsetChange::SetData
HRESULT hrSetDataExpected, // [in] expected hr for IRowsetChange::SetData
BOOL fValidate /*= TRUE*/, // [in] validation flag
HRESULT *hrSetData /*= NULL*/ // [out] actual result of IRowsetChange::SetData
)
{
BOOL fRes = TRUE;
HRESULT hr;
HRESULT hrGetData;
// buffer for row data
BYTE *pDataCC = NULL;
BYTE *pDataOne = NULL; // for comparison
HROW *pHRow = NULL;
DBCOUNTITEM cRows = 0;
ULONG lRowsOffset = 0;
ULONG ulStatus;
ULONG ulStatusCC;
ULONG ulStatusGet;
void *pDefault = NULL;
USHORT cb = 0;
ULONG size;
ULONG cBinding = 0;
CCol col;
DBORDINAL cOrdinalPos = 0;
DBORDINAL nCols = m_pTable->CountColumnsOnTable();
WCHAR *pwszMakeData = NULL;
// make sure pData is not null
if (NULL == pData)
{
odtLog << "ERROR: pData is NULL"<<ENDL;
fRes = FALSE;
goto CLEANUP;
}
// carbon copy of original pData in pDataCC
SAFE_ALLOC(pDataCC, BYTE, m_cRowSize);
memcpy(pDataCC, pData, (size_t)m_cRowSize);
//get the row handle
if (!CHECK(m_pIRowset->GetNextRows(NULL,lRowsOffset,1,&cRows,&pHRow),S_OK))
{
fRes = FALSE;
}
// set data
hr = SetData(*pHRow,m_hAccessor,pData);
// check hr
if (NULL != hrSetData)
{
*hrSetData = hr;
}
if (S_OK!=hr)
{
if (fValidate)
{
//skip this check if test violates an integrity violation
for (cBinding=0;cBinding<m_cBinding;cBinding++)
{
if ( DB_E_INTEGRITYVIOLATION == hr ||
( DB_E_ERRORSOCCURRED == hr &&
DBSTATUS_E_INTEGRITYVIOLATION == *(ULONG *)(pData+m_rgBinding[cBinding].obStatus)
)
)
{
goto CLEANUP;
}
}
//some provider can't set a default value
//if they return can't and DB_E_ERRORSOCCURRED make sure they
//set the status to DBSTATUS_E_BADSTATUS where it was asked to be DBSTATUS_S_DEFAULT
if (DB_E_ERRORSOCCURRED!=hr)
{
odtLog << "Error in IRowsetChange::SetData return value"<<ENDL;
fRes = FALSE;
COMPARE(1,0);
goto CLEANUP;
}
else
{
for (cBinding=0;cBinding<m_cBinding;cBinding++)
{
if (DBSTATUS_E_BADSTATUS!= *(ULONG *)(pData+m_rgBinding[cBinding].obStatus) &&
DBSTATUS_S_DEFAULT == *(ULONG *)(pDataCC+m_rgBinding[cBinding].obStatus))
{
odtLog << "Error in IRowsetChange::SetData return value"<<ENDL;
COMPARE(1,0);
fRes = FALSE;
goto CLEANUP;
}
if (DBSTATUS_E_BADSTATUS== *(ULONG *)(pData+m_rgBinding[cBinding].obStatus) &&
DBSTATUS_S_DEFAULT == *(ULONG *)(pDataCC+m_rgBinding[cBinding].obStatus))
{
odtLog << "Warning in IRowsetChange:Provider does not support DBSTATUS_S_DEFAULT"<<ENDL;
goto CLEANUP;
}
// goto CLEANUP;
}
}
}
goto CLEANUP;
}
//get the data from the row
SAFE_ALLOC(pDataOne, BYTE, m_cRowSize);
memset(pDataOne, 0, (size_t)m_cRowSize);
// get the same row
hrGetData = GetData(*pHRow,m_hAccessor,pDataOne);
// general check for data
if (!COMPARE(CompareBuffer(pDataOne, pDataCC, m_cBinding, m_rgBinding, m_pIMalloc, TRUE, FALSE, COMPARE_ONLY, TRUE), TRUE))
{
fRes = FALSE;
}
m_pTable->SetIndexColumn(1);
// for the column with the ordinal cCount
// the provider can return either a status of OK, NULL or UNAVAILABLE
// for the column marked as DEFAULT going in
// the provider detected a default value for the column => DBSTATUS_S_OK or DBSTATUS_S_ISNULL
for (cBinding = 0; cBinding < m_cBinding; cBinding++)
{
// get ordinal of the column
cOrdinalPos = m_rgBinding[cBinding].iOrdinal;
col = m_pTable->GetColInfoForUpdate(cOrdinalPos);
// make sure it is in range
if (!COMPARE(cOrdinalPos <= nCols, TRUE))
fRes = FALSE;
// get status
ulStatus = *(ULONG*)(pData+m_rgBinding[cBinding].obStatus);
ulStatusCC = *(ULONG*)(pDataCC+m_rgBinding[cBinding].obStatus);
ulStatusGet = *(ULONG*)(pDataOne+m_rgBinding[cBinding].obStatus);
// get data size
size = *(ULONG*)(pDataOne+m_rgBinding[cBinding].obLength);
// if column status was DBSTATUS_S_DEFAULT...
if (DBSTATUS_S_DEFAULT == ulStatusCC)
{
// check success in setting data
if (DBSTATUS_S_DEFAULT != ulStatus &&
DBSTATUS_E_BADSTATUS != ulStatus)
{
odtLog << "ERROR: Bad return status for column " << col.GetColName() << " in SetData"<<ENDL;
fRes = FALSE;
}
if (col.GetHasDefault())
{
// status for getting data
switch (ulStatusGet)
{
case DBSTATUS_S_OK:
m_pTable->MakeData(pwszMakeData,m_cSeed,cOrdinalPos,PRIMARY);
pDefault = WSTR2DBTYPE(pwszMakeData, m_rgBinding[cBinding].wType, &cb);
if (!CompareDBTypeData( pDefault,
(void*)(pDataOne+m_rgBinding[cBinding].obValue),
m_rgBinding[cBinding].wType,
(USHORT)size,
(BYTE)col.GetPrecision(),
(BYTE)col.GetScale(),
m_pIMalloc,
FALSE,
DBTYPE_EMPTY,
size))
//if (!COMPARE(memcmp(pDefault, (void*)(pDataOne+m_rgBinding[cBinding].obValue), size), 0))
{
odtLog << L"ERROR comparing the returned value for column " << cOrdinalPos << L" (default)"<<ENDL;
fRes = FALSE;
}
break;
case DBSTATUS_E_UNAVAILABLE:
break;
default:
odtLog << "ERROR in IRowset::GetData for column " << col.GetColName() <<ENDL;
fRes = FALSE;
break;
}
}
else
{
// the default value is null
// status for getting data
switch (ulStatusGet)
{
case DBSTATUS_S_OK:
// the column was not recognized as default
// still it could be a default column
// do not return error in this case
break;
case DBSTATUS_S_ISNULL:
if (!col.GetNullable() || col.GetHasDefault())
{
fRes = FALSE;
}
break;
case DBSTATUS_E_UNAVAILABLE:
break;
default:
odtLog << "ERROR in IRowset::GetData for column " << col.GetColName() <<ENDL;
fRes = FALSE;
break;
}
}
SAFE_FREE(pDefault);
}
}
CLEANUP:
SAFE_FREE(pDefault);
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
SAFE_FREE(pHRow);
SAFE_FREE(pDataCC);
SAFE_FREE(pDataOne);
return fRes;
} //SetDefault::SetAndCheckDefault
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL SetDefault::Init()
{
BOOL fRes = TEST_SKIPPED;
ULONG nCol = 0;
DBCOLUMNDESC *pColumnDesc = NULL;
ULONG cColumnDesc = 1;
HRESULT hr;
ULONG nDefault = 0;
ITableDefinition *pITableDefinition = NULL;
DBCOUNTITEM cSeed = g_ulNextRow++;
DBORDINAL cColsOnTable = 0;
DBPROPID rgPropertyIDs[1];
rgPropertyIDs[0]=DBPROP_IRowsetChange;
//set the number of rows each table will have in each variation
m_nRows = 12;
m_pCustomTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
m_rgbDefault = NULL;
// {{ TCW_INIT_BASECLASS_CHECK
// }}
if(TCIRowsetChange::Init())
{
//first check if IRowsetChange is supported
//create a rowset and an accessor on the rowset
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR,TRUE));
if (!m_pIRowsetChange)
{
goto CLEANUP;
}
fRes = TEST_FAIL;
// check if there is any way to create a customized table
if( !VerifyInterface(m_pIOpenRowset, IID_ITableDefinition, SESSION_INTERFACE, (IUnknown**)&pITableDefinition)
&& ( !g_pTable->GetCommandSupOnCTable() ||
!g_pTable->GetSQLSupport()
))
{
// there is no way to build customized table, use the existing one
m_fCustomTables = FALSE;
GetDefaultColumns();
}
else
{
// use customized table
m_fCustomTables = TRUE;
// set custom CTable
SetTable(m_pCustomTable, DELETETABLE_NO);
//get the number of columns on the table
cColsOnTable = g_pTable->CountColumnsOnTable();
// alloc space for bool table
SAFE_ALLOC(m_rgbDefault, BOOL, cColsOnTable);
// initialize the array to FALSE
memset(m_rgbDefault, 0, (size_t)(sizeof(BOOL)*cColsOnTable));
for (nCol = 0; nCol < cColsOnTable; nCol++)
{
SAFE_ALLOC(pColumnDesc, DBCOLUMNDESC, 1);
// get column info for nCol'th column from the global table
CCol& rCol = g_pTable->GetColInfoForUpdate(nCol+1);
//sets the default in the CCol list for a column
if (g_pTable->SetDefaultValue(rCol, cSeed))
{
// build the column description (set pColumnDesc from the global table created in ExtraLib)
g_pTable->BuildColumnDesc(pColumnDesc, rCol);
// set column desc as current column desc for the table
m_pCustomTable->SetColumnDesc(pColumnDesc, 1);
m_pCustomTable->SetBuildColumnDesc(FALSE); // use the pcolumnDesc
//if the table can be created with this default for this type then it
//is a valid default
if (S_OK == (hr = m_pCustomTable->CreateTable(0, 0)))
{
m_rgbDefault[rCol.GetColNum()-1] = TRUE;
}
else
{
g_pTable->SetHasDefaultValue(rCol, FALSE);
}
m_pCustomTable->DropTable();
// release column desc
m_pCustomTable->SetColumnDesc(NULL, 0);
ReleaseColumnDesc(pColumnDesc, 1);
pColumnDesc = NULL;
}
else
SAFE_FREE(pColumnDesc);
}
}
fRes = TEST_PASS;
}
CLEANUP:
ReleaseRowsetAndAccessor();
SAFE_RELEASE(pITableDefinition);
m_pCustomTable->SetColumnDesc(NULL, 0);
return fRes;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Set default values on all default columns
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetDefault::Variation_1()
{
BOOL fTestRes = TEST_SKIPPED;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
DBORDINAL cOrdinalPos = 0;
ULONG cBinding = 0;
CCol col;
// buffer for row data
BYTE *pData = NULL;
ULONG nDefault = 0;
MaskDefColumns(TRUE);
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
if (m_fCustomTables)
{
// create a table with maximum number of default values
g_pTable->BuildColumnDescs(&rgColumnDesc);
m_pCustomTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table with as many default columns as possible
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
}
// create rowset and accessor and fill input bindings
// zero in the first param means ignore the first 2 params
TESTC_SetData(PrepareForSetData(0, DBSTATUS_S_DEFAULT, g_ulNextRow++, &pData));
fTestRes = TEST_FAIL;
// bind status to DBSTATUS_S_DEFAULT for all the updateable and default columns
for (cBinding = 0; cBinding < m_cBinding; cBinding++)
{
// get column number and retrieve column
cOrdinalPos = m_rgBinding[cBinding].iOrdinal;
col = m_pTable->GetColInfoForUpdate(cOrdinalPos);
// if column has a default value set status in bindings
// nullable columns are considered as well, according to SQL92
if (col.GetHasDefault() || col.GetNullable())
{
*(ULONG *)(pData+m_rgBinding[cBinding].obStatus) = DBSTATUS_S_DEFAULT;
nDefault++;
}
}
if (0 == nDefault)
{
fTestRes = TEST_SKIPPED;
odtLog << "Skip variation: No default columns were found"<<ENDL;
goto CLEANUP;
}
TESTC(SetAndCheckDefault(pData, S_OK));
fTestRes = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->SetColumnDesc(NULL, 0);
m_pCustomTable->DropTable();
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
// release buffers
SAFE_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Set default value on a default column; set many columns, one is asked default
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetDefault::Variation_2()
{
BOOL fTestRes = TEST_SKIPPED;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
CCol col;
// buffer for row data
BYTE *pData = NULL;
DBORDINAL cSelectedColumn = 0;
ULONG ulColAttr;
MaskDefColumns(TRUE);
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
if (m_fCustomTables)
{
// build the custom table
g_pTable->BuildColumnDescs(&rgColumnDesc);
m_pCustomTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table with as many default columns as possible
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
}
// get a default column
ulColAttr = COL_COND_DEFAULT;
if (!m_pTable->GetColWithAttr(1, &ulColAttr, &cSelectedColumn))
{
// there is no explicit default, get a nullable column
ulColAttr = COL_COND_NULL;
if (!m_pTable->GetColWithAttr(1, &ulColAttr, &cSelectedColumn))
{
fTestRes = TEST_SKIPPED;
odtLog << "No default column was detected"<<ENDL;
goto CLEANUP;
}
}
//create an accessor on the command object on a updatable column only
// create rowset and accessor and fill input bindings
TESTC_SetData(PrepareForSetData(cSelectedColumn, DBSTATUS_S_DEFAULT, g_ulNextRow++, &pData));
TESTC(SetAndCheckDefault(pData, S_OK));
fTestRes = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->SetColumnDesc(NULL, 0);
m_pCustomTable->DropTable();
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
// release buffers
SAFE_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Set default value on a not nullable default column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetDefault::Variation_3()
{
BOOL fTestRes = TEST_SKIPPED;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
CCol col;
// buffer for row data
BYTE *pData = NULL;
DBORDINAL cSelectedColumn = 0;
ULONG rgColAttr[] = {COL_COND_DEFAULT, COL_COND_NOTNULL};
ULONG cColAttr = m_fCustomTables? 1: 2;
BOOL fOldNullable;
BOOL fPropNULLSet = FALSE;
WORD i = 0;
MaskDefColumns(TRUE);
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
// get a default not nullable column
if (!g_pTable->GetColWithAttr(cColAttr, rgColAttr, &cSelectedColumn))
{
fTestRes = TEST_SKIPPED;
odtLog << "could not find a default nullable column"<<ENDL;
goto CLEANUP;
}
col = g_pTable->GetColInfoForUpdate(cSelectedColumn);
if (m_fCustomTables)
{
fOldNullable = col.GetNullable();
col.SetNullable(FALSE);
// restore previous nullable status of the column
g_pTable->BuildColumnDescs(&rgColumnDesc);
col.SetNullable(fOldNullable);
//loop through already set column property values
for (i=0;i<rgColumnDesc[col.GetColNum()-1].rgPropertySets->cProperties;i++)
{
//if DBPROPSET_COLUMN is set, change the value to FALSE instead of adding another DBPROPSET_COLUMN
//to the prop set because that won't work!
if (rgColumnDesc[col.GetColNum()-1].rgPropertySets->rgProperties[i].dwPropertyID==DBPROP_COL_NULLABLE)
{
rgColumnDesc[col.GetColNum()-1].rgPropertySets->rgProperties[i].vValue.boolVal=VARIANT_FALSE;
fPropNULLSet = TRUE;
}
}
//make sure DBPROP_COL_NULLABLE is set (to VARIANT_FALSE)
if (!fPropNULLSet)
{
SetProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN,
&rgColumnDesc[col.GetColNum()-1].cPropertySets,
&rgColumnDesc[col.GetColNum()-1].rgPropertySets,
VT_BOOL, (ULONG_PTR) VARIANT_FALSE, DBPROPOPTIONS_REQUIRED, DB_NULLID);
}
m_pCustomTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table with as many default columns as possible
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
// retrieve column
col = m_pTable->GetColInfoForUpdate(cSelectedColumn);
// set status in bindings
TESTC(col.GetHasDefault());
TESTC(!col.GetNullable());
}
// create rowset and accessor and fill input bindings
TESTC_SetData(PrepareForSetData(cSelectedColumn, DBSTATUS_S_DEFAULT, g_ulNextRow++, &pData));
fTestRes = TEST_FAIL;
TESTC(SetAndCheckDefault(pData, S_OK));
fTestRes = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->SetColumnDesc(NULL, 0);
m_pCustomTable->DropTable();
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
// release buffers
SAFE_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Set default value on a nullable default column (def == NULL)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetDefault::Variation_4()
{
BOOL fTestRes = TEST_SKIPPED;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
CCol col;
// buffer for row data
BYTE *pData = NULL;
DBORDINAL cSelectedColumn = 0;
ULONG rgColAttr[] = {COL_COND_UPDATEABLE, COL_COND_NOTDEFAULT, COL_COND_NULL};
ULONG cColAttr = 3;
BOOL fPropNULLSet = FALSE;
WORD i;
// reset all the columns to their non default value
MaskDefColumns(FALSE);
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
// get an implicit default (nullable) column (def == null)
if (!g_pTable->GetColWithAttr(cColAttr, rgColAttr, &cSelectedColumn))
{
fTestRes = TEST_SKIPPED;
odtLog << "could not find an updateable column"<<ENDL;
goto CLEANUP;
}
col = g_pTable->GetColInfoForUpdate(cSelectedColumn);
if (m_fCustomTables)
{
g_pTable->BuildColumnDescs(&rgColumnDesc);
//loop through already set column property values
for (i=0;i<rgColumnDesc[col.GetColNum()-1].rgPropertySets->cProperties;i++)
{
//if DBPROPSET_COLUMN is set, change the value to TRUE instead of adding another DBPROPSET_COLUMN
//to the prop set because that won't work!
if (rgColumnDesc[col.GetColNum()-1].rgPropertySets->rgProperties[i].dwPropertyID==DBPROP_COL_NULLABLE)
{
rgColumnDesc[col.GetColNum()-1].rgPropertySets->rgProperties[i].vValue.boolVal=VARIANT_TRUE;
fPropNULLSet = TRUE;
}
}
//make sure DBPROP_COL_NULLABLE is set (to VARIANT_TRUE)
if (!fPropNULLSet)
{
SetProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN,
&rgColumnDesc[col.GetColNum()-1].cPropertySets,
&rgColumnDesc[col.GetColNum()-1].rgPropertySets,
VT_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED, DB_NULLID);
}
m_pCustomTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table with as many default columns as possible
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
col = m_pTable->GetColInfoForUpdate(cSelectedColumn);
TESTC(col.GetNullable());
TESTC(!col.GetHasDefault());
}
//create an accessor on the command object on a updatable column only
// create rowset and accessor and fill input bindings
TESTC_SetData(PrepareForSetData(cSelectedColumn, DBSTATUS_S_DEFAULT, g_ulNextRow++, &pData));
fTestRes = TEST_FAIL;
TESTC(SetAndCheckDefault(pData, S_OK));
fTestRes = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->SetColumnDesc(NULL, 0);
m_pCustomTable->DropTable();
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
// release buffers
SAFE_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Set default value on a nullable default column (def != NULL)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetDefault::Variation_5()
{
BOOL fTestRes = TEST_SKIPPED;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
CCol col;
// buffer for row data
BYTE *pData = NULL;
DBORDINAL cSelectedColumn = 0;
BOOL fPropNULLSet = FALSE;
WORD i;
// get a default, nullable column (def != NULL)
ULONG rgColAttr[] = {COL_COND_DEFAULT, COL_COND_UPDATEABLE, COL_COND_NULL};
ULONG cColAttr = 3;
// reset all the columns to their non default value
MaskDefColumns(TRUE);
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
// get a default nullable column (default != null)
if (!g_pTable->GetColWithAttr(cColAttr, rgColAttr, &cSelectedColumn))
{
fTestRes = TEST_SKIPPED;
odtLog << "could not identify column with specified attributes"<<ENDL;
goto CLEANUP;
}
// prezerve info about that column
col = g_pTable->GetColInfoForUpdate(cSelectedColumn);
if (m_fCustomTables)
{
g_pTable->BuildColumnDescs(&rgColumnDesc);
//loop through already set column property values
for (i=0;i<rgColumnDesc[col.GetColNum()-1].rgPropertySets->cProperties;i++)
{
//if DBPROPSET_COLUMN is set, change the value to TRUE instead of adding another DBPROPSET_COLUMN
//to the prop set because that won't work!
if (rgColumnDesc[col.GetColNum()-1].rgPropertySets->rgProperties[i].dwPropertyID==DBPROP_COL_NULLABLE)
{
rgColumnDesc[col.GetColNum()-1].rgPropertySets->rgProperties[i].vValue.boolVal=VARIANT_TRUE;
fPropNULLSet = TRUE;
}
}
//make sure DBPROP_COL_NULLABLE is set (to VARIANT_TRUE)
if (!fPropNULLSet)
{
SetProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN,
&rgColumnDesc[col.GetColNum()-1].cPropertySets,
&rgColumnDesc[col.GetColNum()-1].rgPropertySets,
VT_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED, DB_NULLID);
}
m_pCustomTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table with as many default columns as possible
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
col = m_pTable->GetColInfoForUpdate(cSelectedColumn);
// set status in bindings
TESTC(col.GetHasDefault());
TESTC(col.GetNullable());
}
//create an accessor on the command object on a updatable column only
// create rowset and accessor and fill input bindings
TESTC_SetData(PrepareForSetData(cSelectedColumn, DBSTATUS_S_DEFAULT, g_ulNextRow++, &pData));
fTestRes = TEST_FAIL;
TESTC(SetAndCheckDefault(pData, S_OK));
fTestRes = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->SetColumnDesc(NULL, 0);
m_pCustomTable->DropTable();
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
// release buffers
SAFE_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Set default value on a not default column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetDefault::Variation_6()
{
BOOL fTestRes = TEST_SKIPPED;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
CCol col;
// buffer for row data
BYTE *pData = NULL;
DBORDINAL cSelectedColumn = 0;
HRESULT hr;
BOOL fOldNullable;
BOOL fPropNULLSet = FALSE;
WORD i;
MaskDefColumns(FALSE);
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
if (m_fCustomTables)
{
//get a updateable column (not def)
//this is because a custom table won't have non default or non null cols so this would
//be skipped if
if (!g_pTable->GetColWithAttr(COL_COND_UPDATEABLE, &cSelectedColumn))
{
fTestRes = TEST_SKIPPED;
goto CLEANUP;
}
col = g_pTable->GetColInfoForUpdate(cSelectedColumn);
// make the column not default and not nullable
col.SetHasDefault(FALSE);
fOldNullable = col.GetNullable();
col.SetNullable(FALSE);
// restore previous nullable status of the column
g_pTable->BuildColumnDescs(&rgColumnDesc);
col.SetNullable(fOldNullable);
//loop through already set column property values
for (i=0;i<rgColumnDesc[col.GetColNum()-1].rgPropertySets->cProperties;i++)
{
//if DBPROPSET_COLUMN is set, change the value to FALSE instead of adding another DBPROPSET_COLUMN
//to the prop set because that won't work!
if (rgColumnDesc[col.GetColNum()-1].rgPropertySets->rgProperties[i].dwPropertyID==DBPROP_COL_NULLABLE)
{
rgColumnDesc[col.GetColNum()-1].rgPropertySets->rgProperties[i].vValue.boolVal=VARIANT_FALSE;
fPropNULLSet = TRUE;
}
//if DBPROP_COL_DEFAULT is set then free all properties and reset the NULL (which is all this variation needs)
//this variation does not want a default sodo not set one with through the column properites
if (rgColumnDesc[col.GetColNum()-1].rgPropertySets->rgProperties[i].dwPropertyID==DBPROP_COL_DEFAULT)
{
//no default property should be set here and all the test needs is NULL so free'em up and
//set NULL to FALSE
FreeProperties(&rgColumnDesc[col.GetColNum()-1].cPropertySets,&rgColumnDesc[col.GetColNum()-1].rgPropertySets);
fPropNULLSet = FALSE;
break;
}
}
//make sure DBPROP_COL_NULLABLE is set (to VARIANT_FALSE)
if (!fPropNULLSet)
{
SetProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN,
&rgColumnDesc[col.GetColNum()-1].cPropertySets,
&rgColumnDesc[col.GetColNum()-1].rgPropertySets,
VT_BOOL, (ULONG_PTR) VARIANT_FALSE, DBPROPOPTIONS_REQUIRED, DB_NULLID);
}
m_pCustomTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table with as many default columns as possible
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
}
else
{
ULONG rgColAttr[] = {COL_COND_UPDATEABLE, COL_COND_NOTDEFAULT, COL_COND_NOTNULL};
// get an updateable column (not def)
if (!g_pTable->GetColWithAttr(NUMELEM(rgColAttr), rgColAttr, &cSelectedColumn))
{
fTestRes = TEST_SKIPPED;
goto CLEANUP;
}
col = g_pTable->GetColInfoForUpdate(cSelectedColumn);
}
//create an accessor on the command object on a updatable column only
// create rowset and accessor and fill input bindings
TESTC_SetData(PrepareForSetData(cSelectedColumn, DBSTATUS_S_DEFAULT, g_ulNextRow++, &pData));
fTestRes = TEST_FAIL;
TESTC(SetAndCheckDefault(pData, DB_E_ERRORSOCCURRED, TRUE, &hr));
TESTC(DB_E_ERRORSOCCURRED == hr || DB_E_INTEGRITYVIOLATION == hr);
if (DB_E_ERRORSOCCURRED == hr)
{
TESTC ( DBSTATUS_E_INTEGRITYVIOLATION == *(ULONG*)(pData+m_rgBinding[0].obStatus) ||
DBSTATUS_E_BADSTATUS == *(ULONG*)(pData+m_rgBinding[0].obStatus)
);
}
fTestRes = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->SetColumnDesc(NULL, 0);
m_pCustomTable->DropTable();
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
// release buffers
SAFE_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Set default value on a unique default value
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetDefault::Variation_7()
{
BOOL fTestRes = TEST_SKIPPED;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
CCol col;
// buffer for row data
BYTE *pData = NULL;
DBORDINAL cSelectedColumn = 0;
HRESULT hr;
ULONG rgColAttr[] = {COL_COND_DEFAULT, COL_COND_UNIQUE};
ULONG cColAttr = m_fCustomTables? 1: 2;
BOOL fOldNullable;
BOOL fPropNULLSet = FALSE;
WORD i;
if (!SettableProperty(DBPROP_COL_UNIQUE, DBPROPSET_COLUMN))
{
fTestRes = TEST_SKIPPED;
goto CLEANUP;
}
// reset all the columns to their non default value
MaskDefColumns(TRUE);
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
// get a default column
if (!g_pTable->GetColWithAttr(cColAttr, rgColAttr, &cSelectedColumn))
{
// try again, this time looking for a nullable column
rgColAttr[0] = COL_COND_NULL;
if (m_fCustomTables || !g_pTable->GetColWithAttr(cColAttr, rgColAttr, &cSelectedColumn))
{
fTestRes = TEST_SKIPPED;
goto CLEANUP;
}
}
col = g_pTable->GetColInfoForUpdate(cSelectedColumn);
if (m_fCustomTables)
{
// make the column default and non nullable
fOldNullable = col.GetNullable();
col.SetNullable(FALSE);
col.SetUnique(TRUE);
// restore previous nullable status of the column
g_pTable->BuildColumnDescs(&rgColumnDesc);
col.SetNullable(fOldNullable);
//loop through already set column property values
for (i=0;i<rgColumnDesc[col.GetColNum()-1].rgPropertySets->cProperties;i++)
{
//if DBPROPSET_COLUMN is set, change the value to FALSE instead of adding another DBPROPSET_COLUMN
//to the prop set because that won't work!
if (rgColumnDesc[col.GetColNum()-1].rgPropertySets->rgProperties[i].dwPropertyID==DBPROP_COL_NULLABLE)
{
rgColumnDesc[col.GetColNum()-1].rgPropertySets->rgProperties[i].vValue.boolVal=VARIANT_FALSE;
fPropNULLSet = TRUE;
}
}
//make sure DBPROP_COL_NULLABLE is set (to VARIANT_FALSE)
if (!fPropNULLSet)
{
SetProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN,
&rgColumnDesc[col.GetColNum()-1].cPropertySets,
&rgColumnDesc[col.GetColNum()-1].rgPropertySets,
VT_BOOL, (ULONG_PTR) VARIANT_FALSE, DBPROPOPTIONS_REQUIRED, DB_NULLID);
}
m_pCustomTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table with as many default columns as possible
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
// retrieve the column and make sure is has a default value
col = m_pTable->GetColInfoForUpdate(cSelectedColumn);
// set status in bindings
TESTC(col.GetHasDefault());
}
//create an accessor on the command object on a updatable column only
// create rowset and accessor and fill input bindings
TESTC_SetData(PrepareForSetData(cSelectedColumn, DBSTATUS_S_DEFAULT, g_ulNextRow++, &pData));
fTestRes = TEST_FAIL;
TESTC(SetAndCheckDefault(pData, S_OK));
SetAndCheckDefault(pData, S_OK, TRUE, &hr);
TESTC(DB_E_INTEGRITYVIOLATION == hr || DB_E_ERRORSOCCURRED == hr);
if (DB_E_ERRORSOCCURRED == hr)
{
TESTC ( DBSTATUS_E_INTEGRITYVIOLATION == *(ULONG*)(pData+m_rgBinding[0].obStatus) ||
DBSTATUS_E_BADSTATUS == *(ULONG*)(pData+m_rgBinding[0].obStatus)
);
}
fTestRes = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->SetColumnDesc(NULL, 0);
m_pCustomTable->DropTable();
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
// release buffers
SAFE_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL SetDefault::Terminate()
{
// TO DO: Add your own code here
// {{ TCW_TERM_BASECLASS_CHECK2
SAFE_FREE(m_rgbDefault);
delete m_pCustomTable;
return(TCIRowsetChange::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(SetIgnore)
//*-----------------------------------------------------------------------
//| Test Case: SetIgnore - Ignore data in SetData
//| Created: 6/18/98
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL SetIgnore::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
return SetDefault::Init();
// }}
}
//*-----------------------------------------------------------------------
// @mfunc SetData, check it, get data, check it
//
// @rdesc TRUE or FALSE
//
BOOL SetIgnore::SetAndCheckDefault(
BYTE *pData, // [in] buffer for IRowsetChange::SetData
HRESULT hrSetDataExpected, // [in] expected hr for IRowsetChange::SetData
BOOL fValidate, /*= TRUE*/ // [in] validation flag
HRESULT *hrSetData, /*= NULL*/ // [out] actual result of IRowsetChange::SetData
BOOL fCheck /*= TRUE*/ // [in] whether to do a check a GetData
)
{
BOOL fRes = TRUE;
HRESULT hr;
HRESULT hrGetData;
// buffer for row data
BYTE *pDataCC = NULL;
BYTE *pDataOne = NULL; // for comparison
BYTE *pDataZero = NULL; // initial values
HROW *pHRow = NULL;
DBCOUNTITEM cRows = 0;
ULONG lRowsOffset = 0;
ULONG ulStatus;
ULONG ulStatusCC;
ULONG ulStatusGet;
ULONG ulStatusGetZero;
ULONG size = 0;
ULONG cBinding = 0;
CCol col;
DBORDINAL cOrdinalPos = 0;
DBORDINAL nCols = m_pTable->CountColumnsOnTable();
// make sure pData is not null
if (NULL == pData)
{
odtLog << "ERROR: pData is NULL"<<ENDL;
fRes = FALSE;
goto CLEANUP;
}
// carbon copy of original pData in pDataCC
SAFE_ALLOC(pDataCC, BYTE, m_cRowSize);
memcpy(pDataCC, pData, (size_t)m_cRowSize);
SAFE_ALLOC(pDataZero, BYTE, m_cRowSize);
memset(pDataZero, 0, (size_t)m_cRowSize);
//get the row handle
if (!CHECK(m_pIRowset->GetNextRows(NULL,lRowsOffset,1,&cRows,&pHRow),S_OK))
fRes = FALSE;
// get data in pDataZero
TESTC_(hr = GetData(*pHRow,m_hAccessor,pDataZero), S_OK);
// set data from pData
hr = SetData(*pHRow,m_hAccessor,pData);
// check hr
if (NULL != hrSetData)
{
*hrSetData = hr;
}
if (fValidate && !CHECK(hr, hrSetDataExpected))
{
odtLog << "Error in IRowsetChange::SetData return value"<<ENDL;
fRes = FALSE;
}
if (!fCheck)
{
goto CLEANUP;
}
//get the data from the row
SAFE_ALLOC(pDataOne, BYTE, m_cRowSize);
memset(pDataOne, 0, (size_t)m_cRowSize);
// get the same row data in pDataOne
hrGetData = GetData(*pHRow,m_hAccessor,pDataOne);
// general check for data (data got - pDataOne, against data set - pData
if (!COMPARE(CompareBuffer(pDataOne, pData, m_cBinding, m_rgBinding, m_pIMalloc, TRUE,FALSE,COMPARE_ONLY), TRUE))
{
fRes = FALSE;
}
// for the column with the ordinal cCount
// the provider can return either a status of OK, NULL or UNAVAILABLE
// for the column marked as DEFAULT going in
// the provider detected a default value for the column => DBSTATUS_S_OK or DBSTATUS_S_ISNULL
for (cBinding = 0; cBinding < m_cBinding; cBinding++)
{
// get ordinal of the column
cOrdinalPos = m_rgBinding[cBinding].iOrdinal;
col = m_pTable->GetColInfoForUpdate(cOrdinalPos);
// make sure it is in range
if (!COMPARE(cOrdinalPos <= nCols, TRUE))
fRes = FALSE;
// get statuses
ulStatus = *(ULONG*)(pData+m_rgBinding[cBinding].obStatus);
ulStatusCC = *(ULONG*)(pDataCC+m_rgBinding[cBinding].obStatus);
ulStatusGet = *(ULONG*)(pDataOne+m_rgBinding[cBinding].obStatus);
ulStatusGetZero = *(ULONG*)(pDataZero+m_rgBinding[cBinding].obStatus);
// get data size
size = *(ULONG*)(pDataOne+m_rgBinding[cBinding].obLength);
// if column status was DBSTATUS_S_DEFAULT...
if (DBSTATUS_S_IGNORE == ulStatusCC)
{
// check success in setting data
if (S_OK == hr && !COMPARE(DBSTATUS_S_IGNORE, ulStatus))
{
odtLog << "ERROR: Bad return status for column " << col.GetColName() << " in SetData"<<ENDL;
fRes = FALSE;
}
// status for getting data
switch (ulStatusGet)
{
case DBSTATUS_S_OK:
// both get statuses should be DBSTATUS_S_OK and values should be the same
if (!COMPARE(DBSTATUS_S_OK, ulStatusGetZero))
{
odtLog << "ERROR: mismatch in getting statuses"<<ENDL;
fRes = FALSE;
}
else if (!CompareDBTypeData( (void*)(pDataZero+m_rgBinding[cBinding].obValue),
(void*)(pDataOne+m_rgBinding[cBinding].obValue),
m_rgBinding[cBinding].wType,
(USHORT)size,
(BYTE)col.GetPrecision(),
(BYTE)col.GetScale(),
m_pIMalloc,
FALSE,
DBTYPE_EMPTY,
*(ULONG*)(pDataZero+m_rgBinding[cBinding].obLength)))
{
odtLog << L"ERROR comparing the returned value for column " << cOrdinalPos << L" (ignore)"<<ENDL;
fRes = FALSE;
}
break;
case DBSTATUS_S_ISNULL:
if (!col.GetNullable() || !COMPARE(ulStatusGetZero, DBSTATUS_S_ISNULL))
{
odtLog << "ERROR: mismatch for get statuses: DBSTATUS_S_ISNULL"<<ENDL;
fRes = FALSE;
}
break;
case DBSTATUS_E_UNAVAILABLE:
break;
default:
odtLog << "ERROR in IRowset::GetData for column " << col.GetColName() <<ENDL;
fRes = FALSE;
break;
}
}
}
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
SAFE_FREE(pHRow);
SAFE_FREE(pDataCC);
SAFE_FREE(pDataOne);
SAFE_FREE(pDataZero);
return fRes;
} //SetIgnore::SetAndCheckDefault
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Set ignore values on all updateable columns
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetIgnore::Variation_1()
{
BOOL fTestRes = TEST_SKIPPED;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
DBORDINAL cOrdinalPos = 0;
DBCOUNTITEM cBinding = 0;
CCol col;
// buffer for row data
BYTE *pData = NULL;
MaskDefColumns(TRUE);
if (m_fCustomTables)
{
// create a table with maximum number of default values
g_pTable->BuildColumnDescs(&rgColumnDesc);
m_pCustomTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table with as many default columns as possible
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
}
//create an accessor on the command object on a updatable column only
// create rowset and accessor and fill input bindings
TESTC_SetData(PrepareForSetData(0, DBSTATUS_S_IGNORE, g_ulNextRow++, &pData));
fTestRes = TEST_FAIL;
// bind status to DBSTATUS_S_IGNORE for all the updateable and default columns
for (cBinding = 0; cBinding < m_cBinding; cBinding++)
{
// get column number and retrieve column
cOrdinalPos = m_rgBinding[cBinding].iOrdinal;
col = m_pTable->GetColInfoForUpdate(cOrdinalPos);
*(ULONG *)(pData+m_rgBinding[cBinding].obStatus) = DBSTATUS_S_IGNORE;
}
TESTC(SetAndCheckDefault(pData, S_OK));
fTestRes = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->SetColumnDesc(NULL, 0);
m_pCustomTable->DropTable();
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
// release buffers
SAFE_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Set ignore value on a column; set many columns, one is asked ignored
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetIgnore::Variation_2()
{
BOOL fTestRes = TEST_SKIPPED;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
CCol col;
// buffer for row data
BYTE *pData = NULL;
ULONG cSelectedColumn = 0;
DBCOUNTITEM cBinding;
MaskDefColumns(TRUE);
if (m_fCustomTables)
{
// build the custom table
g_pTable->BuildColumnDescs(&rgColumnDesc);
m_pCustomTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table with as many default columns as possible
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
}
//create an accessor on the command object on a updatable column only
// create rowset and accessor and fill input bindings
TESTC_SetData(PrepareForSetData(cSelectedColumn, DBSTATUS_S_IGNORE, g_ulNextRow++, &pData));
fTestRes = TEST_FAIL;
cBinding = m_cBinding / 2;
// ask for column default
*(ULONG*)(pData+m_rgBinding[cBinding].obStatus) = DBSTATUS_S_IGNORE;
TESTC(SetAndCheckDefault(pData, S_OK));
fTestRes = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->SetColumnDesc(NULL, 0);
m_pCustomTable->DropTable();
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
// release buffers
SAFE_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Set ignore value on a not nullable default column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetIgnore::Variation_3()
{
BOOL fTestRes = TEST_SKIPPED;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
CCol col;
// buffer for row data
BYTE *pData = NULL;
DBORDINAL cSelectedColumn = 0;
ULONG rgColAttr[] = {COL_COND_DEFAULT, COL_COND_NOTNULL};
ULONG cColAttr = m_fCustomTables? 1: 2;
BOOL fOldNullable;
MaskDefColumns(TRUE);
// get a default not nullable column
if (!g_pTable->GetColWithAttr(cColAttr, rgColAttr, &cSelectedColumn))
{
fTestRes = TEST_SKIPPED;
odtLog << "could not find a default nullable column"<<ENDL;
goto CLEANUP;
}
col = g_pTable->GetColInfoForUpdate(cSelectedColumn);
if (m_fCustomTables)
{
fOldNullable = col.GetNullable();
col.SetNullable(FALSE);
// restore previous nullable status of the column
g_pTable->BuildColumnDescs(&rgColumnDesc);
col.SetNullable(fOldNullable);
SetProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN,
&rgColumnDesc[col.GetColNum()-1].cPropertySets,
&rgColumnDesc[col.GetColNum()-1].rgPropertySets,
VT_BOOL, (ULONG_PTR) VARIANT_FALSE, DBPROPOPTIONS_REQUIRED, DB_NULLID);
m_pCustomTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table with as many default columns as possible
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
// retrieve column
col = m_pTable->GetColInfoForUpdate(cSelectedColumn);
// set status in bindings
TESTC(col.GetHasDefault());
TESTC(!col.GetNullable());
}
//create an accessor on the command object on a updatable column only
// create rowset and accessor and fill input bindings
TESTC_SetData(PrepareForSetData(cSelectedColumn, DBSTATUS_S_IGNORE, g_ulNextRow++, &pData));
fTestRes = TEST_FAIL;
TESTC(SetAndCheckDefault(pData, S_OK));
fTestRes = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->SetColumnDesc(NULL, 0);
m_pCustomTable->DropTable();
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
// release buffers
SAFE_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Set ignore value on a nullable default column (def == NULL)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetIgnore::Variation_4()
{
BOOL fTestRes = TEST_SKIPPED;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
CCol col;
// buffer for row data
BYTE *pData = NULL;
DBORDINAL cSelectedColumn = 0;
ULONG rgColAttr[] = {COL_COND_UPDATEABLE, COL_COND_NOTDEFAULT, COL_COND_NULL};
ULONG cColAttr = 3;
// reset all the columns to their non default value
MaskDefColumns(FALSE);
// set an implicit default (nullable) column (def == null)
if (!g_pTable->GetColWithAttr(cColAttr, rgColAttr, &cSelectedColumn))
{
fTestRes = TEST_SKIPPED;
odtLog << "could not find an updateable column"<<ENDL;
goto CLEANUP;
}
col = g_pTable->GetColInfoForUpdate(cSelectedColumn);
if (m_fCustomTables)
{
g_pTable->BuildColumnDescs(&rgColumnDesc);
SetProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN,
&rgColumnDesc[col.GetColNum()-1].cPropertySets,
&rgColumnDesc[col.GetColNum()-1].rgPropertySets,
VT_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED, DB_NULLID);
m_pCustomTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table with as many default columns as possible
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
col = m_pTable->GetColInfoForUpdate(cSelectedColumn);
TESTC(col.GetNullable());
TESTC(!col.GetHasDefault());
}
//create an accessor on the command object on a updatable column only
// create rowset and accessor and fill input bindings
TESTC_SetData(PrepareForSetData(cSelectedColumn, DBSTATUS_S_IGNORE, g_ulNextRow++, &pData));
fTestRes = TEST_FAIL;
TESTC(SetAndCheckDefault(pData, S_OK));
fTestRes = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->SetColumnDesc(NULL, 0);
m_pCustomTable->DropTable();
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
// release buffers
SAFE_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Set ignore value on a nullable default column (def != NULL)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetIgnore::Variation_5()
{
BOOL fTestRes = TEST_SKIPPED;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
CCol col;
// buffer for row data
BYTE *pData = NULL;
DBORDINAL cSelectedColumn = 0;
// get a default, nullable column (def != NULL)
ULONG rgColAttr[] = {COL_COND_DEFAULT, COL_COND_UPDATEABLE, COL_COND_NULL};
ULONG cColAttr = 3;
// reset all the columns to their non default value
MaskDefColumns(TRUE);
// get a default nullable column (default != null)
if (!g_pTable->GetColWithAttr(cColAttr, rgColAttr, &cSelectedColumn))
{
fTestRes = TEST_SKIPPED;
odtLog << "could not identify column with specified attributes"<<ENDL;
goto CLEANUP;
}
// reset all the columns to their non default value
MaskDefColumns(FALSE);
// prezerve info about that column
col = g_pTable->GetColInfoForUpdate(cSelectedColumn);
if (m_fCustomTables)
{
g_pTable->BuildColumnDescs(&rgColumnDesc);
SetProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN,
&rgColumnDesc[col.GetColNum()-1].cPropertySets,
&rgColumnDesc[col.GetColNum()-1].rgPropertySets,
VT_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED, DB_NULLID);
m_pCustomTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table with as many default columns as possible
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
col = m_pTable->GetColInfoForUpdate(cSelectedColumn);
// set status in bindings
TESTC(col.GetHasDefault());
TESTC(col.GetNullable());
}
//create an accessor on the command object on a updatable column only
// create rowset and accessor and fill input bindings
TESTC_SetData(PrepareForSetData(cSelectedColumn, DBSTATUS_S_IGNORE, g_ulNextRow++, &pData));
fTestRes = TEST_FAIL;
TESTC(SetAndCheckDefault(pData, S_OK));
fTestRes = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->SetColumnDesc(NULL, 0);
m_pCustomTable->DropTable();
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
// release buffers
SAFE_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Set ignore value on a not default column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetIgnore::Variation_6()
{
BOOL fTestRes = TEST_SKIPPED;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
CCol col;
// buffer for row data
BYTE *pData = NULL;
DBORDINAL cSelectedColumn = 0;
BOOL fOldNullable;
MaskDefColumns(FALSE);
if (m_fCustomTables)
{
// set a updateable column (not def)
if (!g_pTable->GetColWithAttr(COL_COND_UPDATEABLE, &cSelectedColumn))
{
fTestRes = TEST_SKIPPED;
goto CLEANUP;
}
col = g_pTable->GetColInfoForUpdate(cSelectedColumn);
// make the column not default and not nullable
col.SetHasDefault(FALSE);
fOldNullable = col.GetNullable();
col.SetNullable(FALSE);
// restore previous nullable status of the column
g_pTable->BuildColumnDescs(&rgColumnDesc);
col.SetNullable(fOldNullable);
SetProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN,
&rgColumnDesc[col.GetColNum()-1].cPropertySets,
&rgColumnDesc[col.GetColNum()-1].rgPropertySets,
VT_BOOL, (ULONG_PTR) VARIANT_FALSE, DBPROPOPTIONS_REQUIRED, DB_NULLID);
m_pCustomTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table with as many default columns as possible
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
}
else
{
ULONG rgColAttr[] = {COL_COND_UPDATEABLE, COL_COND_NOTDEFAULT, COL_COND_NOTNULL};
// get an updateable column (not def)
if (!g_pTable->GetColWithAttr(NUMELEM(rgColAttr), rgColAttr, &cSelectedColumn))
{
fTestRes = TEST_SKIPPED;
goto CLEANUP;
}
col = g_pTable->GetColInfoForUpdate(cSelectedColumn);
}
//create an accessor on the command object on a updatable column only
// create rowset and accessor and fill input bindings
TESTC_SetData(PrepareForSetData(cSelectedColumn, DBSTATUS_S_IGNORE, g_ulNextRow++, &pData));
fTestRes = TEST_FAIL;
TESTC(SetAndCheckDefault(pData, S_OK));
fTestRes = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->SetColumnDesc(NULL, 0);
m_pCustomTable->DropTable();
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
// release buffers
SAFE_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Bind a single column and set status to DBSTATUS_S_IGNORE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetIgnore::Variation_7()
{
BOOL fTestRes = TEST_SKIPPED;
// properties asked for the rowset related to bindings
DBPROPID rgPropertyIDs[2];
// buffer for row data
BYTE *pData = NULL;
DBCOUNTITEM cSelectedColumn = 0;
rgPropertyIDs[0]=DBPROP_CANHOLDROWS;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
if (m_fCustomTables)
{
// set a updateable column (not def)
// create a table with as many default columns as possible
m_pCustomTable->SetBuildColumnDesc(TRUE); // create ColList again
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
}
if (!m_pTable->GetColWithAttr(COL_COND_UPDATEABLE, &cSelectedColumn))
{
fTestRes = TEST_SKIPPED;
goto CLEANUP;
}
//create an accessor on the command object on a updatable column only
fTestRes = TEST_SKIPPED;
//create an accessor on the command object on the numeric and updatable column only
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,NUMELEM(rgPropertyIDs),rgPropertyIDs,0,NULL,
ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, USE_COLS_TO_BIND_ARRAY,
FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,&cSelectedColumn));
fTestRes = TEST_FAIL;
TESTC(1 == m_cBinding);
//get a new data buffer to set the data
TESTC_(FillInputBindings( m_pTable,
DBACCESSOR_ROWDATA,
m_cBinding,
m_rgBinding,
&pData,
g_ulNextRow++, // row number for data creation
m_cRowsetCols,
m_rgTableColOrds,
PRIMARY),S_OK);
// set status in bindings
*(ULONG *)(pData+m_rgBinding[0].obStatus) = DBSTATUS_S_IGNORE;
TESTC(SetAndCheckDefault(pData, S_OK));
fTestRes = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->DropTable();
// release buffers
SAFE_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc Bind all updateable cols, set status to DBSTATUS_S_IGNORE for half of them
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetIgnore::Variation_8()
{
BOOL fTestRes = TEST_SKIPPED;
// buffer for row data
BYTE *pData = NULL;
ULONG cBinding;
CCol col;
if (m_fCustomTables)
{
// create a table with as many default columns as possible
m_pCustomTable->SetBuildColumnDesc(TRUE); // create ColList again
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
}
//create an accessor on the command object on a updatable column only
// create rowset and accessor and fill input bindings
TESTC_SetData(PrepareForSetData(0, DBSTATUS_S_IGNORE, g_ulNextRow++, &pData));
fTestRes = TEST_FAIL;
// set status in bindings
for (cBinding = 0; cBinding < m_cBinding; cBinding++)
{
col = m_pTable->GetColInfoForUpdate(m_rgBinding[cBinding].iOrdinal);
if ( cBinding % 2
&& (col.GetHasDefault() || col.GetNullable()))
{
*(ULONG *)(pData+m_rgBinding[cBinding].obStatus) = DBSTATUS_S_IGNORE;
break;
}
}
TESTC(SetAndCheckDefault(pData, S_OK));
fTestRes = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->DropTable();
// release buffers
SAFE_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc Bind a single read only column and set status to DBSTATUS_S_IGNORE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetIgnore::Variation_9()
{
BOOL fTestRes = TEST_SKIPPED; // properties asked for the rowset related to bindings
DBPROPID rgPropertyIDs[] = {DBPROP_IRowsetChange};
BYTE *pData = NULL; // buffer for row data
DBORDINAL cSelectedColumn = 0;
HRESULT hrOut = S_OK;
if (m_fCustomTables)
{
// set a updateable column (not def)
// create a table with as many default columns as possible
m_pCustomTable->SetBuildColumnDesc(TRUE); // create ColList again
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
}
if (!m_pTable->GetColWithAttr(COL_COND_NOTUPDATEABLE, &cSelectedColumn))
{
fTestRes = TEST_SKIPPED;
goto CLEANUP;
}
//create an accessor on the command object on a updatable column only
fTestRes = TEST_SKIPPED;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,NUMELEM(rgPropertyIDs),rgPropertyIDs,0,NULL,
ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, USE_COLS_TO_BIND_ARRAY,
FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,1,&cSelectedColumn));
fTestRes = TEST_FAIL;
TESTC(1 == m_cBinding);
//get a new data buffer to set the data
TESTC_(FillInputBindings( m_pTable,
DBACCESSOR_ROWDATA,
m_cBinding,
m_rgBinding,
&pData,
g_ulNextRow++, // row number for data creation
m_cRowsetCols,
m_rgTableColOrds,
PRIMARY),S_OK);
// set status in bindings
*(DBSTATUS *)(pData+m_rgBinding[0].obStatus) = DBSTATUS_S_IGNORE;
//since the read only column has a status of IGNORE it should not cause an error
//expect here either S_OK if all other columns are nullable or
//DB_E_INTEGRITYVIOLATION in case another column in the row that is not bound is not nullable
TESTC(SetAndCheckDefault(pData, S_OK,TRUE, &hrOut, TRUE));
if (DB_E_INTEGRITYVIOLATION==hrOut || S_OK==hrOut)
{
fTestRes = TEST_PASS;
}
if (DB_E_ERRORSOCCURRED==hrOut)
{
if (*(ULONG *)(pData+m_rgBinding[0].obStatus)==DBSTATUS_E_INTEGRITYVIOLATION)
{
fTestRes = TEST_PASS;
}
}
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->DropTable();
// release buffers
SAFE_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc SetData()/SetData(IGNORE)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int SetIgnore::Variation_10()
{
BOOL fTestRes = TEST_SKIPPED;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
DBORDINAL cOrdinalPos = 0;
ULONG cBinding = 0;
CCol col;
// buffer for row data
BYTE *pDataIn = NULL;
BYTE *pDataCopy = NULL;
BYTE *pDataReIn = NULL;
ULONG nDefault = 0;
HROW *pHRow = NULL;
DBCOUNTITEM cRows = 0;
MaskDefColumns(TRUE);
if (m_fCustomTables)
{
// create a table with maximum number of default values
g_pTable->BuildColumnDescs(&rgColumnDesc);
m_pCustomTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table with as many default columns as possible
TESTC_(m_pCustomTable->CreateTable(m_nRows, 1), S_OK);
}
//create an accessor on the command object on a updatable column only
// create rowset and accessor and fill input bindings
TESTC_SetData(PrepareForSetData(0, DBSTATUS_S_OK, g_ulNextRow++, &pDataIn));
fTestRes = TEST_FAIL;
//get the row handle
if (!CHECK(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK))
{
goto CLEANUP;
}
// get data in pDataIn
TESTC_(GetData(*pHRow,m_hAccessor,pDataIn), S_OK);
//make a copy of the buffer and allocate a third
SAFE_ALLOC(pDataCopy, BYTE, m_cRowSize);
memcpy(pDataCopy, pDataIn,(size_t)m_cRowSize);
SAFE_ALLOC(pDataReIn, BYTE, m_cRowSize);
memset(pDataReIn, 0, (size_t)m_cRowSize);
// SetData with what was just read in by GetData
TESTC_(SetData(*pHRow,m_hAccessor,pDataIn),S_OK);
// bind status to DBSTATUS_S_IGNORE for all the updateable and default columns
for (cBinding = 0; cBinding < m_cBinding; cBinding++)
{
// get column number and retrieve column
cOrdinalPos = m_rgBinding[cBinding].iOrdinal;
col = m_pTable->GetColInfoForUpdate(cOrdinalPos);
*(ULONG *)(pDataIn+m_rgBinding[cBinding].obStatus) = DBSTATUS_S_IGNORE;
}
//SetData again with IGNORE
TESTC_(SetData(*pHRow,m_hAccessor,pDataIn),S_OK);
//GetData in pDataReIn
TESTC_(GetData(*pHRow,m_hAccessor,pDataReIn), S_OK);
//compare the buffers
if (!COMPARE(CompareBuffer(pDataCopy, pDataReIn, m_cBinding, m_rgBinding, m_pIMalloc, TRUE, FALSE, COMPARE_ONLY, TRUE), TRUE))
{
goto CLEANUP;
}
fTestRes = TEST_PASS;
CLEANUP:
ReleaseRowsetAndAccessor();
m_pCustomTable->SetColumnDesc(NULL, 0);
m_pCustomTable->DropTable();
// release buffers
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
SAFE_FREE(pHRow);
SAFE_FREE(pDataIn);
SAFE_FREE(pDataCopy);
SAFE_FREE(pDataReIn);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL SetIgnore::Terminate()
{
// TO DO: Add your own code here
// {{ TCW_TERM_BASECLASS_CHECK2
return(SetDefault::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(DeleteRows)
//*-----------------------------------------------------------------------
//| Test Case: DeleteRows - Testing DeleteRows
//| Created: 06/24/98
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL DeleteRows::Init()
{
DBPROPID rgPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
if(!TCIRowsetChange::Init())
{
return FALSE;
}
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_COLLISTFROMTBL,1,rgPropertyIDs,0,NULL,NO_ACCESSOR));
fTestPass=TRUE;
CLEANUP:
ReleaseRowsetAndAccessor();
return fTestPass;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc delete array of handles that point to one row.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_1()
{
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HROW rgHRow[4];
DBPROPID rgPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgRowStatus[4];
HRESULT hr = S_OK;
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE;
//muck up the DBROWSTATUS
memset(rgRowStatus,1,sizeof(DBROWSTATUS)*(4));
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0] = DBPROP_IRowsetChange;
g_fMAXPENDINGROWS = TRUE;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//retrieve row handles
TESTC_(m_pIRowset->GetNextRows(NULL,0,2,&cRows,&pHRow),S_OK);
//build an array of the same HROW plus a different HROW
rgHRow[0] = pHRow[0];
rgHRow[1] = pHRow[0];
rgHRow[2] = pHRow[1];
rgHRow[3] = pHRow[0];
//delete the rows
hr=m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,4,rgHRow,rgRowStatus);
//all other row status are undefined
if (S_OK==hr)
{
COMPARE(rgRowStatus[0], DBROWSTATUS_S_OK);
COMPARE(rgRowStatus[1], DBROWSTATUS_S_OK);
COMPARE(rgRowStatus[2], DBROWSTATUS_S_OK);
COMPARE(rgRowStatus[3], DBROWSTATUS_S_OK);
}
else
{
COMPARE(rgRowStatus[0], DBROWSTATUS_S_OK);
COMPARE(rgRowStatus[1], DBROWSTATUS_E_DELETED);
COMPARE(rgRowStatus[2], DBROWSTATUS_S_OK);
COMPARE(rgRowStatus[3], DBROWSTATUS_E_DELETED);
}
fTestPass=TRUE;
CLEANUP:
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
g_fMAXPENDINGROWS = FALSE;
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc DB_S_ERRORSOCCURRED status check all rows, DBROWSTATUS_S_MULTIPLECHANGES.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_2()
{
//add code here :)
return TEST_PASS;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc DB_S_ERRORSOCCURRED status check all rows, DBROWSTATUS_E_INVALID.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_3()
{
const ULONG culNumProps = 2;
BOOL fTestPass = TEST_SKIPPED;
DBCOUNTITEM cRows = 0;
HROW *pHRow = NULL;
HRESULT hr = S_OK;
IRowset *pIRowset1 = NULL;
IRowset *pIRowset2 = NULL;
IRowsetChange *pIRowsetChange1 = NULL;
IRowsetChange *pIRowsetChange2 = NULL;
DBPROPSET rgDBPropSet[1];
ULONG cDBPropSet = 1;
DBROWSTATUS rgRowStatus[1];
//init DBPropSet[0]
rgDBPropSet[0].rgProperties = NULL;
rgDBPropSet[0].cProperties = culNumProps;
rgDBPropSet[0].guidPropertySet= DBPROPSET_ROWSET;
//muck up the DBROWSTATUS
memset(rgRowStatus,1,sizeof(DBROWSTATUS)*(1));
//allocate
rgDBPropSet[0].rgProperties=(DBPROP *)PROVIDER_ALLOC(sizeof(DBPROP) * (culNumProps));
memset(rgDBPropSet[0].rgProperties,0,sizeof(DBPROP)*(culNumProps));
if(!rgDBPropSet[0].rgProperties)
{
goto CLEANUP;
}
//set props
rgDBPropSet[0].rgProperties[0].dwPropertyID=DBPROP_IRowsetChange;
rgDBPropSet[0].rgProperties[0].dwOptions=DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[0].vValue.vt=VT_BOOL;
rgDBPropSet[0].rgProperties[0].colid = DB_NULLID;
rgDBPropSet[0].rgProperties[0].vValue.lVal=VARIANT_TRUE;
rgDBPropSet[0].rgProperties[1].dwPropertyID=DBPROP_UPDATABILITY;
rgDBPropSet[0].rgProperties[1].dwOptions=DBPROPOPTIONS_REQUIRED;
rgDBPropSet[0].rgProperties[1].vValue.vt=VT_I4;
rgDBPropSet[0].rgProperties[0].colid = DB_NULLID;
rgDBPropSet[0].rgProperties[1].vValue.lVal=DBPROPVAL_UP_DELETE | DBPROPVAL_UP_CHANGE | DBPROPVAL_UP_INSERT;
//Get Rowset1
//call IOpenRowset to return a Rowset
hr=m_pTable->CreateRowset (
USE_OPENROWSET,
IID_IRowset,
1,
rgDBPropSet,
(IUnknown**)&pIRowset1,
NULL,
NULL,
NULL);
//Get Rowset2
//call IOpenRowset to return a Rowset
hr=m_pTable->CreateRowset (
USE_OPENROWSET,
IID_IRowset,
1,
rgDBPropSet,
(IUnknown**)&pIRowset2,
NULL,
NULL,
NULL);
//get the IRowsetChange pointer 1
TESTC_(pIRowset1->QueryInterface(IID_IRowsetChange, (LPVOID *)&pIRowsetChange1),S_OK);
//get the IRowsetChange pointer 2
TESTC_(pIRowset2->QueryInterface(IID_IRowsetChange, (LPVOID *)&pIRowsetChange2),S_OK);
fTestPass=FALSE;
//retrieve row handle
TESTC_(pIRowset1->GetNextRows(NULL,0,2,&cRows,&pHRow),S_OK);
//delete a row from this rowset
TESTC_(pIRowsetChange1->DeleteRows(DB_NULL_HCHAPTER,1,&pHRow[0],rgRowStatus),S_OK);
COMPARE(rgRowStatus[0], DBROWSTATUS_S_OK);
//delete a row from the other rowset
//as long as this doesn't GPF it is ok
hr=pIRowsetChange2->DeleteRows(DB_NULL_HCHAPTER,1,&pHRow[1],rgRowStatus);
if(DB_E_ERRORSOCCURRED==hr)
{
COMPARE(rgRowStatus[0], DBROWSTATUS_E_INVALID);
}
if(S_OK==hr)
{
COMPARE(rgRowStatus[0], DBROWSTATUS_S_OK);
}
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(rgDBPropSet[0].rgProperties);
CHECK(pIRowset1->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//release IRowset pointer
SAFE_RELEASE(pIRowset1);
SAFE_RELEASE(pIRowsetChange1);
SAFE_RELEASE(pIRowset2);
SAFE_RELEASE(pIRowsetChange2);
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc use rows with immediate deletes in other methods
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_4()
{
BYTE *pData = NULL;
DBCOUNTITEM cRows = 0;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgRowStatus[1];
DBROWSTATUS *prgRowStatus = NULL;
HROW *pHRow = NULL;
HRESULT hr = S_OK;
//muck up the DBROWSTATUS
memset(rgRowStatus,1,sizeof(DBROWSTATUS)*(1));
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_CHANGE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0] = DBPROP_IRowsetChange;
rgPropertyIDs[1] = DBPROP_IRowsetIdentity;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//retrieve row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow,rgRowStatus),S_OK);
COMPARE(rgRowStatus[0], DBROWSTATUS_S_OK);
//try to use HRowX
//Set/Get
TESTC_(SetData(*pHRow,m_hAccessor,pData),DB_E_DELETEDROW);
//get the data
TESTC_(GetData(*pHRow, m_hAccessor, pData),DB_E_DELETEDROW);
//compare the handles
TESTC_(m_pIRowsetIdentity->IsSameRow(*pHRow,*pHRow),DB_E_DELETEDROW);
fTestPass=TRUE;
CLEANUP:
if(m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(prgRowStatus);
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc DB_S_ERRORSOCCURRED status check all rows, DBROWSTATUS_E_MAXPENDCHANGESEXCEEDED.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_5()
{
DBCOUNTITEM cRows = 0;
DBCOUNTITEM i = 0;
HROW *pHRow = NULL;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgRowStatus[4];
HRESULT hr = S_OK;
ULONG cPropSets = 0;
DBPROPSET *rgPropSets = NULL;
//muck up the DBROWSTATUS
memset(rgRowStatus,1,sizeof(DBROWSTATUS)*(4));
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
// Initialize UPDATABILITY flag for class
g_lMaxPendRows = 2;
rgPropertyIDs[0]=DBPROP_IRowsetChange;
rgPropertyIDs[1]=DBPROP_IRowsetUpdate;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_pIRowsetUpdate || (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
//retrieve 1 more row handle than MAXPENDINGROWS
TESTC_(m_pIRowset->GetNextRows(NULL,0,(g_lMaxPendRows+1),&cRows,&pHRow),S_OK);
//delete the rows
hr=m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,(g_lMaxPendRows+1),pHRow,rgRowStatus);
if (S_OK==hr)
{
//if DeleteRows returns S_OK is has to be because g_lMaxPendRows is zero or no limit
for (i=0;i<(g_lMaxPendRows+1);i++)
{
COMPARE(rgRowStatus[i], DBROWSTATUS_S_OK);
}
COMPARE(g_lMaxPendRows,0);
fTestPass=TRUE;
goto CLEANUP;
}
if (DB_S_ERRORSOCCURRED==hr)
{
for (i=0;i<g_lMaxPendRows;i++)
{
COMPARE(rgRowStatus[i], DBROWSTATUS_S_OK);
}
COMPARE(rgRowStatus[g_lMaxPendRows], DBROWSTATUS_E_MAXPENDCHANGESEXCEEDED);
fTestPass=TRUE;
}
CLEANUP:
if(m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
g_lMaxPendRows=-1;
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc DB_S_ERRORSOCCURRED status check all rows, DBROWSTATUS_E_NEWLYINSERTED.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_6()
{
BYTE *pData = NULL;
DBPROPID rgPropertyIDs[1];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgRowStatus[1];
HROW HRowX = NULL;
//muck up the DBROWSTATUS
memset(rgRowStatus,1,sizeof(DBROWSTATUS)*(1));
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE;
rgPropertyIDs[0] = DBPROP_IRowsetChange;
rgUnPropertyIDs[0] = DBPROP_CHANGEINSERTEDROWS;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//insert a new row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,&HRowX),S_OK);
//delete the rows
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,&HRowX,rgRowStatus),DB_E_ERRORSOCCURRED);
COMPARE(rgRowStatus[0], DBROWSTATUS_E_NEWLYINSERTED);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc DeleteRows from a zombie.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_7()
{
ITransactionLocal *pITransactionLocal = NULL;
DBPROPID rgPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgRowStatus[1];
DBPROPID rgUnPropertyIDs[1];
HROW *pHRow = NULL;
DBCOUNTITEM cRows = 0;
ULONG ulTransactionLevel = 0;
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0] = DBPROP_IRowsetChange;
rgUnPropertyIDs[0] = DBPROP_COMMITPRESERVE;
//Get ITransactionLocal on test session
if(!VerifyInterface(m_pIOpenRowset, IID_ITransactionLocal, SESSION_INTERFACE, (IUnknown **)&pITransactionLocal))
{
odtLog << L"ITransactionLocal not supported."<<ENDL;
return TEST_SKIPPED;
}
TESTC_(pITransactionLocal->StartTransaction(ISOLATIONLEVEL_READCOMMITTED,0, NULL, &ulTransactionLevel),S_OK);
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgPropertyIDs,1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=TEST_FAIL;
//retrieve row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//commit the session
if(XACT_E_NOTSUPPORTED==pITransactionLocal->Commit(FALSE, XACTTC_ASYNC_PHASEONE, 0))
{
if(XACT_E_NOTSUPPORTED==pITransactionLocal->Commit(FALSE, XACTTC_SYNC_PHASEONE, 0))
{
if(XACT_E_NOTSUPPORTED==pITransactionLocal->Commit(FALSE, XACTTC_SYNC_PHASETWO, 0))
{
if(XACT_E_NOTSUPPORTED==pITransactionLocal->Commit(FALSE, XACTTC_SYNC, 0))
{
if(XACT_E_NOTSUPPORTED==pITransactionLocal->Commit(FALSE, 0, 0))
{
//commit retaining not supported
odtLog << L"Non-Retaining Commit not supported, returning TEST_PASS."<<ENDL;
fTestPass = TEST_SKIPPED;
goto CLEANUP;
}
}
}
}
}
//delete the rows
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow,rgRowStatus),E_UNEXPECTED);
fTestPass=TEST_PASS;
CLEANUP:
if(m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
SAFE_RELEASE(pITransactionLocal);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc DB_S_ERRORSOCCURRED status check all rows, not DBROWSTATUS_E_PENDINGINSERT.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_8()
{
BYTE *pData = NULL;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgRowStatus[1];
HROW HRowX = NULL;
DBPROPID rgUnPropertyIDs[1];
//muck up the DBROWSTATUS
memset(rgRowStatus,1,sizeof(DBROWSTATUS)*(1));
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0] = DBPROP_IRowsetChange;
rgPropertyIDs[1] = DBPROP_IRowsetUpdate;
//DBROWSTATUS_E_PENDINGINSERT is not a valid return from DeleteRows
//even with DBPROP_RETURNPENDINGINSERTS set to FALSE
rgUnPropertyIDs[0] = DBPROP_RETURNPENDINGINSERTS;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_pIRowsetUpdate|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//insert a new row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,&HRowX),S_OK);
//delete the rows
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,&HRowX,rgRowStatus),S_OK);
COMPARE(rgRowStatus[0], DBROWSTATUS_S_OK);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc use pending deletes by using them in other methods
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_9()
{
BYTE *pDataV = NULL;
BYTE *pData = NULL;
DBCOUNTITEM cRows = 0;
DBPROPID rgPropertyIDs[3];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgRowStatus[1];
DBROWSTATUS *prgRowStatus = NULL;
HROW *pHRow = NULL;
DBCOUNTITEM cRowsResynched = 0;
HROW *rghRowsResynched = NULL;
IRowsetResynch *pIRowsetResynch = NULL;
//muck up the DBROWSTATUS
memset(rgRowStatus,1,sizeof(DBROWSTATUS)*(1));
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_CHANGE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0] = DBPROP_IRowsetChange;
rgPropertyIDs[1] = DBPROP_IRowsetUpdate;
rgPropertyIDs[2] = DBPROP_IRowsetResynch;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_pIRowsetUpdate|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//retrieve row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow,rgRowStatus),S_OK);
COMPARE(rgRowStatus[0], DBROWSTATUS_S_OK);
if(!VerifyInterface(m_pIRowsetChange, IID_IRowsetResynch, ROWSET_INTERFACE, (IUnknown**)&pIRowsetResynch))
{
goto CLEANUP;
}
TESTC_(pIRowsetResynch->ResynchRows(0, pHRow, &cRowsResynched, &rghRowsResynched, &prgRowStatus),S_OK);
COMPARE(prgRowStatus[0], DBROWSTATUS_S_OK);
if(!(pDataV=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
TESTC_(pIRowsetResynch->GetVisibleData(*pHRow, m_hAccessor,pDataV), S_OK);
fTestPass=TRUE;
CLEANUP:
if(m_pIRowset) {
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
PROVIDER_FREE(rghRowsResynched);
SAFE_RELEASE(pIRowsetResynch);
PROVIDER_FREE(prgRowStatus);
PROVIDER_FREE(pData);
PROVIDER_FREE(pDataV);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc use pending deletes by using them in other methods
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_10()
{
BYTE *pData = NULL;
DBCOUNTITEM cRows = 0;
DBPROPID rgPropertyIDs[3];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgRowStatus[1];
DBROWSTATUS *prgRowStatus = NULL;
HROW *pHRow = NULL;
DBCOUNTITEM cPendingRows = 0;
HROW *rgPendingRows = NULL;
DBPENDINGSTATUS rgPendingStatus[1];
DBPENDINGSTATUS *prgPendingStatus = NULL;
HRESULT hr = S_OK;
//muck up the DBROWSTATUS
memset(rgRowStatus,1,sizeof(DBROWSTATUS)*(1));
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_CHANGE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0] = DBPROP_IRowsetChange;
rgPropertyIDs[1] = DBPROP_IRowsetUpdate;
rgPropertyIDs[2] = DBPROP_IRowsetIdentity;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_pIRowsetUpdate|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//retrieve row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,cRows,pHRow,rgRowStatus),S_OK);
COMPARE(rgRowStatus[0], DBROWSTATUS_S_OK);
TESTC_(SetData(*pHRow,m_hAccessor,pData),DB_E_DELETEDROW);
//get the data
hr=GetData(*pHRow, m_hAccessor, pData);
//if GetData returned S_OK, it is legal here because reporting the row is actually a pending delete
//may be too expense for some providers
if (hr!=DB_E_DELETEDROW && hr!=S_OK)
{
goto CLEANUP;
}
//the following methods should support a row handle to a pending insert
TESTC_(m_pIRowsetUpdate->GetRowStatus(NULL,1,pHRow,rgPendingStatus),S_OK);
COMPARE(rgPendingStatus[0], DBPENDINGSTATUS_DELETED);
TESTC_(m_pIRowsetUpdate->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,&rgPendingRows,&prgPendingStatus),S_OK);
TESTC_(m_pIRowsetIdentity->IsSameRow(*pHRow,rgPendingRows[0]),S_OK);
COMPARE(prgPendingStatus[0], DBPENDINGSTATUS_DELETED);
TESTC_(m_pIRowsetUpdate->Undo(NULL,1,pHRow,NULL,NULL,&prgRowStatus),S_OK);
COMPARE(prgRowStatus[0], DBROWSTATUS_S_OK);
TESTC_(m_pIRowsetUpdate->GetOriginalData(*pHRow,m_hAccessor,pData),S_OK);
fTestPass=TRUE;
CLEANUP:
if(m_pIRowset) {
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
CHECK(m_pIRowset->ReleaseRows(cPendingRows,rgPendingRows,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
PROVIDER_FREE(rgPendingRows);
PROVIDER_FREE(prgRowStatus);
PROVIDER_FREE(prgPendingStatus);
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc delete pending insert, Change
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_11()
{
BYTE *pData = NULL;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgRowStatus[1];
HROW HRowX = NULL;
HRESULT hr = S_OK;
//muck up the DBROWSTATUS
memset(rgRowStatus,1,sizeof(DBROWSTATUS)*(1));
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE;
rgPropertyIDs[0] = DBPROP_IRowsetChange;
rgPropertyIDs[1] = DBPROP_IRowsetUpdate;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_pIRowsetUpdate || (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//insert a new row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,&HRowX),S_OK);
//delete the rows
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,&HRowX,rgRowStatus),S_OK);
COMPARE(rgRowStatus[0], DBROWSTATUS_S_OK);
//try to use HRowX
//set data
TESTC_(SetData(HRowX,m_hAccessor,pData),DB_E_DELETEDROW);
//get the data
hr=GetData(HRowX, m_hAccessor, pData);
//if GetData returned S_OK, it is legal here because reporting the row is actually a pending delete
//may be too expense for some providers
if (hr!=DB_E_DELETEDROW && hr!=S_OK)
{
goto CLEANUP;
}
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc delete pending insert, Update
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_12()
{
BYTE *pData = NULL;
DBPROPID rgPropertyIDs[2];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgRowStatus[1];
DBROWSTATUS *prgRowStatus = NULL;
HROW HRowX = NULL;
DBCOUNTITEM cPendingRows = 0;
HROW *rgPendingRows = NULL;
DBPENDINGSTATUS rgPendingStatus[1];
DBPENDINGSTATUS *prgPendingStatus = NULL;
//muck up the DBROWSTATUS
memset(rgRowStatus,1,sizeof(DBROWSTATUS)*(1));
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0] = DBPROP_IRowsetChange;
rgPropertyIDs[1] = DBPROP_IRowsetUpdate;
//create an accessor to bind updatable columns
TESTC_PROVIDER(
(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_pIRowsetUpdate|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//insert a new row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,&HRowX),S_OK);
//delete the rows
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,&HRowX,rgRowStatus),S_OK);
COMPARE(rgRowStatus[0], DBROWSTATUS_S_OK);
//try to use HRowX
//it should fail in everything except ReleaseRows
TESTC_(m_pIRowsetUpdate->GetOriginalData(HRowX,m_hAccessor,pData),DB_E_DELETEDROW);
TESTC_(m_pIRowsetUpdate->GetRowStatus(NULL,1,&HRowX,rgPendingStatus),DB_E_ERRORSOCCURRED);
COMPARE(rgPendingStatus[0], DBPENDINGSTATUS_INVALIDROW);
TESTC_(m_pIRowsetUpdate->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,&rgPendingRows,&prgPendingStatus),S_FALSE);
TESTC_(m_pIRowsetUpdate->Undo(NULL,1,&HRowX,NULL,NULL,&prgRowStatus),DB_E_ERRORSOCCURRED);
COMPARE(prgRowStatus[0], DBROWSTATUS_E_DELETED);
fTestPass=TRUE;
CLEANUP:
if(m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(cPendingRows,rgPendingRows,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(rgPendingRows);
PROVIDER_FREE(prgRowStatus);
PROVIDER_FREE(prgPendingStatus);
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc delete pending insert, Resync
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_13()
{
BYTE *pData = NULL;
BYTE *pDataV = NULL;
DBPROPID rgPropertyIDs[3];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgRowStatus[1];
DBROWSTATUS *prgRowStatus = NULL;
HROW HRowX = NULL;
DBCOUNTITEM cRowsResynched = 0;
HROW *rghRowsResynched = NULL;
IRowsetResynch *pIRowsetResynch = NULL;
//muck up the DBROWSTATUS
memset(rgRowStatus,1,sizeof(DBROWSTATUS)*(1));
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0] = DBPROP_IRowsetChange;
rgPropertyIDs[1] = DBPROP_IRowsetUpdate;
rgPropertyIDs[2] = DBPROP_IRowsetResynch;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_pIRowsetUpdate|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//insert a new row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,&HRowX),S_OK);
//delete the rows
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,&HRowX,rgRowStatus),S_OK);
COMPARE(rgRowStatus[0], DBROWSTATUS_S_OK);
//try to use HRowX
//it should fail in everything except ReleaseRows
//set data
//Resyncs
if(!VerifyInterface(m_pIRowsetChange, IID_IRowsetResynch, ROWSET_INTERFACE, (IUnknown**)&pIRowsetResynch))
{
goto CLEANUP;
}
TESTC_(pIRowsetResynch->ResynchRows(1, &HRowX, &cRowsResynched, &rghRowsResynched, &prgRowStatus),DB_E_ERRORSOCCURRED);
COMPARE(prgRowStatus[0], DBROWSTATUS_E_DELETED);
if(!(pDataV=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
TESTC_(pIRowsetResynch->GetVisibleData(HRowX, m_hAccessor,pDataV), DB_E_DELETEDROW);
fTestPass=TRUE;
CLEANUP:
if(m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(cRowsResynched,rghRowsResynched,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(rghRowsResynched);
SAFE_RELEASE(pIRowsetResynch);
PROVIDER_FREE(prgRowStatus);
PROVIDER_FREE(pData);
PROVIDER_FREE(pDataV);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(14)
//*-----------------------------------------------------------------------
// @mfunc check for pending delete, LITERALIDENTITY - FALSE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_14()
{
DBPROPID rgPropertyIDs[4];
DBPROPID rgUnPropertyIDs[1];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgRowStatus[1];
HRESULT hr = S_OK;
HROW *pHRow = NULL;
DBCOUNTITEM cRows = 0;
//muck up the DBROWSTATUS
memset(rgRowStatus,1,sizeof(DBROWSTATUS)*(1));
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0] = DBPROP_IRowsetChange;
rgPropertyIDs[1] = DBPROP_IRowsetUpdate;
rgPropertyIDs[2] = DBPROP_REMOVEDELETED;
rgPropertyIDs[3] = DBPROP_CANHOLDROWS;
rgUnPropertyIDs[0] = DBPROP_LITERALIDENTITY;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgPropertyIDs,1,rgUnPropertyIDs,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_pIRowsetUpdate|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
//retrieve row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow,rgRowStatus),S_OK);
COMPARE(rgRowStatus[0], DBROWSTATUS_S_OK);
//release the row handle
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//restart position.
hr = m_pIRowset->RestartPosition(NULL);
CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE);
//retrieve row handle again
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//should be deleted row and here, eventhough DBPROP_REMOVEDELETED is variant_true
//literidentity if variant_false so pending deleted rows are returned
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),DB_E_DELETEDROW);
CLEANUP:
if(m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(15)
//*-----------------------------------------------------------------------
// @mfunc check for pending delete, LITERALIDENTITY - TRUE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_15()
{
DBPROPID rgPropertyIDs[5];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgRowStatus[1];
HRESULT hr = S_OK;
HROW *pHRow = NULL;
DBCOUNTITEM cRows = 0;
BYTE *pData = NULL;
//muck up the DBROWSTATUS
memset(rgRowStatus,1,sizeof(DBROWSTATUS)*(1));
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0] = DBPROP_IRowsetChange;
rgPropertyIDs[1] = DBPROP_IRowsetUpdate;
rgPropertyIDs[2] = DBPROP_REMOVEDELETED;
rgPropertyIDs[3] = DBPROP_LITERALIDENTITY;
rgPropertyIDs[4] = DBPROP_CANHOLDROWS;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,5,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_pIRowsetUpdate|| (!m_cBinding))
{
goto CLEANUP;
}
fTestPass=FALSE;
if(!(pData=(BYTE*)PROVIDER_ALLOC(m_cRowSize)))
{
goto CLEANUP;
}
//retrieve row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
TESTC_(GetData(*pHRow,m_hAccessor,pData),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow,rgRowStatus),S_OK);
COMPARE(rgRowStatus[0], DBROWSTATUS_S_OK);
//release the row handle
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
//restart position.
hr = m_pIRowset->RestartPosition(NULL);
CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE);
//retrieve row handle again
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//DBPROP_REMOVEDELETED is VARIANT_TRUE
TESTC_(GetData(*pHRow,m_hAccessor,m_pData),S_OK);
//these should be different rows
if(COMPARE(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY),FALSE))
{
fTestPass=TRUE;
}
CLEANUP:
if(m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
PROVIDER_FREE(pData);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc Deleted handle, no status
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_16()
{
DBCOUNTITEM cRows = 0;
DBPROPID rgPropertyIDs[2] = {NULL,NULL};
BOOL fTestPass = TEST_SKIPPED;
HROW *pHRow = NULL;
BYTE *pData = NULL;
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0] = DBPROP_IRowsetChange;
rgPropertyIDs[1] = DBPROP_CANHOLDROWS;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//retrieve row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow,NULL),S_OK);
//delete the row again but do not use a status
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow,NULL),DB_E_ERRORSOCCURRED);
fTestPass=TRUE;
CLEANUP:
if(m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(17)
//*-----------------------------------------------------------------------
// @mfunc Invlaid handle, no status
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_17()
{
DBCOUNTITEM cRows = 0;
DBPROPID rgPropertyIDs[2] = {NULL,NULL};
BOOL fTestPass = TEST_SKIPPED;
HROW rgHRow[1];
HROW *pHRow = NULL;
BYTE *pData = NULL;
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE;
// Check to see if supported
if( m_ulpProvUpdFlags && (m_ulpProvUpdFlags & m_ulpUpdFlags) )
m_ulpUpdFlags = m_ulpProvUpdFlags;
rgPropertyIDs[0] = DBPROP_IRowsetChange;
rgPropertyIDs[1] = DBPROP_CANHOLDROWS;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//retrieve row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
rgHRow[0] = *pHRow+11;
//delete the row with an invlaid handle but do not use a status
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,&rgHRow[0],NULL),DB_E_ERRORSOCCURRED);
fTestPass=TRUE;
CLEANUP:
if(m_pIRowset)
{
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
}
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(18)
//*-----------------------------------------------------------------------
// @mfunc DB_S_OK when deleting an inserted/trasmitted row from a pending rowset
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_18()
{
BYTE *pData = NULL;
DBPROPID rgPropertyIDs[3];
BOOL fTestPass = TEST_SKIPPED;
DBROWSTATUS rgRowStatus[1];
HROW HRowX = NULL;
DBROWSTATUS *rgDBRowStatus = NULL;
//muck up the DBROWSTATUS
memset(rgRowStatus,1,sizeof(DBROWSTATUS)*(1));
// Initialize UPDATABILITY flag for class
m_ulpUpdFlags = DBPROPVAL_UP_DELETE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE;
rgPropertyIDs[0] = DBPROP_IRowsetChange;
rgPropertyIDs[1] = DBPROP_CHANGEINSERTEDROWS;
rgPropertyIDs[2] = DBPROP_IRowsetUpdate;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR,FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds, PRIMARY),S_OK);
//insert a new row
TESTC_(m_pIRowsetChange->InsertRow(NULL,m_hAccessor,pData,&HRowX),S_OK);
//call update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&HRowX,NULL,NULL,&rgDBRowStatus),S_OK);
COMPARE(rgDBRowStatus[0], DBROWSTATUS_S_OK);
//delete the rows
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,&HRowX,rgRowStatus),S_OK);
COMPARE(rgRowStatus[0], DBSTATUS_S_OK);
fTestPass=TRUE;
CLEANUP:
PROVIDER_FREE(pData);
PROVIDER_FREE(rgDBRowStatus);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc delete/update/reposition cursor
//
// @rdesc TEST_PASS or TEST_FAIL
//
int DeleteRows::Variation_19()
{
DBCOUNTITEM cRows = 0;
BYTE *pData = NULL;
HROW *pHRow = NULL;
DBPROPID rgPropertyIDs[3];
BOOL fTestPass = TEST_SKIPPED;
ULONG cProperty = 0;
HRESULT hr;
//allocation memory
pHRow = (HROW*)PROVIDER_ALLOC(sizeof(HROW));
rgPropertyIDs[0]=DBPROP_IRowset;
rgPropertyIDs[1]=DBPROP_IRowsetChange;
rgPropertyIDs[2]=DBPROP_IRowsetUpdate;
// Initialize
m_ulpUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
//create an accessor to bind updatable columns
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgPropertyIDs,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
UPDATEABLE_COLS_BOUND));
if (!m_pIRowsetChange || !m_cBinding)
{
goto CLEANUP;
}
fTestPass=FALSE;
//retrieve the ith row handle
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//release my main row
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
//retrieve the ith row handle again
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
//delete the row
TESTC_(m_pIRowsetChange->DeleteRows(DB_NULL_HCHAPTER,1,pHRow,NULL),S_OK);
//update
TESTC_(m_pIRowsetUpdate->Update(NULL,1,pHRow,NULL,NULL,NULL),S_OK);
//release my main row
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
//retrieve the ith row handle
TESTC_(hr=m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
fTestPass=TRUE;
CLEANUP:
if(pHRow && m_pIRowset)
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
PROVIDER_FREE(pHRow);
ReleaseRowsetAndAccessor();
return fTestPass;
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL DeleteRows::Terminate()
{
return(TCIRowsetChange::Terminate());
} // }}
// }}