17464 lines
487 KiB
C++
17464 lines
487 KiB
C++
//--------------------------------------------------------------------
|
|
// Microsoft OLE DB Test
|
|
//
|
|
// Copyright 1995-2000 Microsoft Corporation.
|
|
//
|
|
// @doc
|
|
//
|
|
// @module irownew.CPP | The test module for IRowsetNewRow.
|
|
//
|
|
|
|
#include "modstandard.hpp"
|
|
#include "irownew.h"
|
|
#include "extralib.h"
|
|
|
|
|
|
#undef TESTC_PROVIDER
|
|
#define TESTC_PROVIDER(hr) { TESTB = TEST_PASS; if(hr==S_FALSE) { TOUTPUT(L"NotSupported by Provider, skipping Variation"); fTestPass = TEST_SKIPPED; goto CLEANUP; } }
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Module Values
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// {{ TCW_MODULE_GLOBALS
|
|
DECLARE_MODULE_CLSID = { 0x2d8c4a62, 0x336d, 0x11d1, { 0xae, 0xde, 0x0, 0xc0, 0x4f, 0xd7, 0x6, 0x80 } };
|
|
DECLARE_MODULE_NAME("IRowsetNewRow");
|
|
DECLARE_MODULE_OWNER("Microsoft");
|
|
DECLARE_MODULE_DESCRIP("The test module for IRowsetNewRow");
|
|
DECLARE_MODULE_VERSION(839384934);
|
|
// TCW_WizardVersion(2)
|
|
// TCW_Automation(True)
|
|
// }} TCW_MODULE_GLOBALS_END
|
|
// }}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Globals
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
//DBPROPID g_rgDBPropID[2]={DBPROP_OTHERINSERT, DBPROP_OTHERUPDATEDELETE};
|
|
//DBCOUNTITEM g_ulRowCount;
|
|
DBPROPID g_rgDBPropID[3]={ DBPROP_OTHERINSERT, DBPROP_OTHERUPDATEDELETE,DBPROP_OWNUPDATEDELETE};
|
|
DBCOUNTITEM g_ulRowCount;
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// @func Module level initialization routine
|
|
//
|
|
// Return the status value indicated by the binding structure
|
|
//--------------------------------------------------------------------
|
|
DBSTATUS GetStatus(void *pData, DBBINDING *pBinding)
|
|
{
|
|
BYTE *pbAddr;
|
|
|
|
pbAddr=(BYTE *)pData;
|
|
return(*(DBSTATUS *)(pbAddr+(pBinding->obStatus)));
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// @func Module level initialization routiner
|
|
//
|
|
// @rdesc Success or Failure
|
|
// @flag TRUE | Successful initialization
|
|
// @flag FALSE | Initialization problems
|
|
//
|
|
BOOL ModuleInit(CThisTestModule *pThisTestModule)
|
|
{
|
|
BOOL fPass = CommonModuleInit(pThisTestModule, IID_IRowsetChange, 15);
|
|
|
|
if (TEST_PASS == fPass)
|
|
{
|
|
g_ulRowCount = g_pTable->GetRowsOnCTable();
|
|
}
|
|
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
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
//
|
|
// TCIRowsetNewRow: the base class for the rest of test cases in this
|
|
// test module.
|
|
//
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
class TCIRowsetNewRow : 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;
|
|
|
|
IRowsetIdentity *m_pIRowsetIdentity;
|
|
|
|
//@cmember: interface pointer for IRowset
|
|
IRowset *m_pIRowset;
|
|
|
|
//@cmember: accessory handle
|
|
HACCESSOR m_hAccessor;
|
|
|
|
//@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: the location of accessor handle
|
|
EACCESSORLOCATION m_eAccessorLocation;
|
|
|
|
//@cmember
|
|
DBCOUNTITEM m_ulTableRows;
|
|
|
|
//@cmember
|
|
BOOL m_bIndexExists;
|
|
|
|
//@cmember: The Updatability Flags for DBPROP_UPDATABILITY
|
|
ULONG m_ulUpdFlags;
|
|
|
|
//@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
|
|
HRESULT 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,
|
|
DBORDINAL cColsToBind = 0,
|
|
DBORDINAL *rgColsToBind = NULL,
|
|
ECOLS_MEM_PROV_OWNED eColsMemProvOwned = NO_COLS_OWNED_BY_PROV,
|
|
DBPARAMIO eParamIO = DBPARAMIO_NOTPARAM
|
|
);
|
|
|
|
|
|
//@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 = UPDATEABLE_COLS_BOUND,
|
|
ECOLUMNORDER eBindingOrder = FORWARD,
|
|
ECOLS_BY_REF eColsByRef = NO_COLS_BY_REF,
|
|
DBTYPE dbTypeModifier = DBTYPE_EMPTY,
|
|
DBORDINAL cColsToBind = 0,
|
|
DBORDINAL *rgColsToBind = NULL,
|
|
DBPARAMIO eParamIO = DBPARAMIO_NOTPARAM//@paramopt [IN] Parameter type to specify for eParmIO
|
|
);
|
|
|
|
//@mfun: Get the bookmark for the row
|
|
BOOL GetBookmark
|
|
(
|
|
ULONG ulRow,
|
|
DBBKMARK *pcbBookmark,
|
|
BYTE **ppBookmark
|
|
);
|
|
|
|
HRESULT GetBookmarkByRow
|
|
(
|
|
HROW hRow,
|
|
DBBKMARK *pcbBookmark,
|
|
BYTE **ppBookmark
|
|
);
|
|
|
|
//@mfunc: Get cursor type of the rowset
|
|
ECURSOR GetCursorType();
|
|
|
|
//@mfunc: Return TRUE if the deleted rows are removed
|
|
BOOL RemoveDeleted();
|
|
|
|
//@mfunc: Return TRUE if the ROWRESTICT is TRUE.
|
|
BOOL RowStrict();
|
|
|
|
//@mfunc: Return TRUE if the property is VARIANT_TRUE.
|
|
BOOL GetProp(DBPROPID DBPropID);
|
|
|
|
//@mfunc: Return TRUE if the property is set with dwPropVal.
|
|
BOOL CheckProp(DWORD dwPropVal);
|
|
|
|
//@mfun: Return TRUE if we are on buffered update mode
|
|
BOOL BufferedUpdate();
|
|
|
|
//@mfun: Return TRUE if strong identity
|
|
BOOL StrongIdentity();
|
|
|
|
BOOL GetUpdatableCols(DBORDINAL *pcbCol,
|
|
DBORDINAL **prgColNum);
|
|
|
|
|
|
//@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 Fixed Length and Updatable column
|
|
BOOL GetFixedLengthAndUpdatable(DBORDINAL *pcbCol,
|
|
DBORDINAL **prgColNum);
|
|
|
|
//@mfunc: Get the Variable Length and Updatable column
|
|
BOOL GetVariableLengthAndUpdatable(DBORDINAL *pcbCol,
|
|
DBORDINAL **prgColNum);
|
|
|
|
//@mfunc: Get not updatable column
|
|
DBORDINAL GetNotUpdatable();
|
|
|
|
//@mfunc: Get first updatable column
|
|
DBORDINAL GetFirstUpdatable();
|
|
|
|
//@mfunc: Get long and updatable columns
|
|
DBORDINAL GetLongAndUpdatable();
|
|
|
|
//@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();
|
|
|
|
//@mfunc: Check if the row data in pRowData matches a row obtainable from pIRowset
|
|
BOOL CheckRowVisible(IRowset *pIRowset, void *pRowData, BOOL fRowVisible);
|
|
|
|
public:
|
|
//constructor
|
|
TCIRowsetNewRow(WCHAR *wstrTestCaseName);
|
|
|
|
//destructor
|
|
~TCIRowsetNewRow();
|
|
};
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc base class TCIRowsetNewRow constructor, must take testcase name
|
|
// as parameter.
|
|
//
|
|
TCIRowsetNewRow::TCIRowsetNewRow(WCHAR * wstrTestCaseName) //Takes TestCase Class name as parameter
|
|
: CRowsetObject(wstrTestCaseName)
|
|
{
|
|
|
|
m_pIRowsetChange=NULL;
|
|
m_pIRowsetUpdate=NULL;
|
|
m_pIRowsetLocate=NULL;
|
|
m_pIRowsetIdentity=NULL;
|
|
m_pIRowset=NULL;
|
|
m_hAccessor=NULL;
|
|
m_cRowSize=0;
|
|
m_cBinding=0;
|
|
m_rgBinding=NULL;
|
|
m_rgInfo=NULL;
|
|
m_pStringsBuffer=NULL;
|
|
m_pData=NULL;
|
|
m_eAccessorLocation=NO_ACCESSOR;
|
|
m_ulTableRows=0;
|
|
m_bIndexExists = FALSE;
|
|
m_ulUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc base class TCIRowsetNewRow destructor
|
|
//
|
|
TCIRowsetNewRow::~TCIRowsetNewRow()
|
|
{
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//@mfunc: Init creates a Data Source object, a DB Session object,
|
|
//and a command object and initialize corresponding interface pointers.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL TCIRowsetNewRow::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_pTable->DoesIndexExist(&m_bIndexExists);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
//@mfunc: Terminate release the data source object, DB Session object, Command object
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL TCIRowsetNewRow::Terminate()
|
|
{
|
|
//Release the existing Session
|
|
ReleaseRowsetObject(); //releases m_pIAccessor
|
|
ReleaseCommandObject(); //releases m_pICommand
|
|
ReleaseDBSession();
|
|
ReleaseDataSourceObject();
|
|
return(CRowsetObject::Terminate());
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
//@mfunc: Create a command object and set properties, execute a sql statement,
|
|
// and create a rowset object. Create an accessor on the rowset
|
|
//
|
|
//--------------------------------------------------------------------
|
|
HRESULT TCIRowsetNewRow::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
|
|
)
|
|
{
|
|
IColumnsInfo *pIColumnsInfo = NULL;
|
|
ICommandProperties *pICommandProperties = NULL;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW *pHRow = NULL;
|
|
ULONG cDBPropSet = 1;
|
|
DBPROPSET rgDBPropSet[2] = {NULL,NULL};
|
|
ULONG cProp = 0;
|
|
ULONG cNumErrors = 0;
|
|
ULONG cNumNotSupported = 0;
|
|
HRESULT hr = S_FALSE;
|
|
HRESULT hrReturn = S_FALSE;
|
|
BLOBTYPE blobType;
|
|
BOOL fTestPass = FALSE;
|
|
ULONG cPropSets = 0;
|
|
DBPROPSET *rgPropSets = NULL;
|
|
|
|
if(fBindLongColumn)
|
|
blobType=BLOB_LONG;
|
|
else
|
|
blobType=NO_BLOB_COLS;
|
|
|
|
//init DBPropSet[0]
|
|
rgDBPropSet[0].rgProperties = NULL;
|
|
rgDBPropSet[0].cProperties = 0;
|
|
rgDBPropSet[0].guidPropertySet= DBPROPSET_ROWSET;
|
|
|
|
//Set up the DB Properties struct
|
|
if(cProperties || cPropertiesUnset)
|
|
{
|
|
//Might need an extra for DBPROP_UPDATABILITY (+1)
|
|
rgDBPropSet[0].rgProperties=(DBPROP *)PROVIDER_ALLOC(sizeof(DBPROP) * (cProperties + cPropertiesUnset + 1));
|
|
if(!rgDBPropSet[0].rgProperties)
|
|
goto CLEANUP;
|
|
|
|
//Memset to zeros
|
|
memset(rgDBPropSet[0].rgProperties, 0, (sizeof(DBPROP) * (cProperties + cPropertiesUnset + 1)));
|
|
|
|
ULONG i;
|
|
//go through the loop to set every DB Property required
|
|
for(i=0; i<cProperties; i++)
|
|
{
|
|
rgDBPropSet[0].rgProperties[cProp].dwPropertyID = rgProperties[i];
|
|
rgDBPropSet[0].rgProperties[cProp].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
rgDBPropSet[0].rgProperties[cProp].colid = DB_NULLID;
|
|
rgDBPropSet[0].rgProperties[cProp].vValue.vt = VT_BOOL;
|
|
V_BOOL(&rgDBPropSet[0].rgProperties[cProp].vValue)= VARIANT_TRUE;
|
|
cProp++;
|
|
}
|
|
|
|
if ( DBPROPFLAGS_WRITE & GetPropInfoFlags(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, m_pIDBInitialize))
|
|
{
|
|
//set DBPROP_UPDATABILITY
|
|
rgDBPropSet[0].rgProperties[cProp].dwPropertyID = DBPROP_UPDATABILITY;
|
|
rgDBPropSet[0].rgProperties[cProp].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
rgDBPropSet[0].rgProperties[cProp].colid = DB_NULLID;
|
|
rgDBPropSet[0].rgProperties[cProp].vValue.vt = VT_I4;
|
|
rgDBPropSet[0].rgProperties[cProp].vValue.lVal = m_ulUpdFlags;
|
|
cProp++;
|
|
}
|
|
|
|
//go through the loop to unset every DB Property required
|
|
for(i=0; i<cPropertiesUnset; i++)
|
|
{
|
|
rgDBPropSet[0].rgProperties[cProp].dwPropertyID = rgPropertiesUnset[i];
|
|
rgDBPropSet[0].rgProperties[cProp].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
rgDBPropSet[0].rgProperties[cProp].colid = DB_NULLID;
|
|
rgDBPropSet[0].rgProperties[cProp].vValue.vt = VT_BOOL;
|
|
V_BOOL(&rgDBPropSet[0].rgProperties[cProp].vValue) = VARIANT_FALSE;
|
|
cProp++;
|
|
}
|
|
|
|
rgDBPropSet[0].cProperties = cProp;
|
|
}
|
|
|
|
|
|
//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);
|
|
}
|
|
|
|
//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;
|
|
|
|
if(!m_pIDBCreateCommand &&
|
|
(eSQLStmt==SELECT_ALLFROMTBL || eSQLStmt==SELECT_ORDERBYNUMERIC || eSQLStmt==USE_SUPPORTED_SELECT_ALLFROMTBL))
|
|
{
|
|
eSQLStmt = USE_OPENROWSET;
|
|
}
|
|
|
|
//create the rowset object May fail due to combinations of properties
|
|
hr = CreateRowsetObject(eSQLStmt,IID_IRowset,EXECUTE_IFNOERROR);
|
|
if(hr==DB_S_ERRORSOCCURRED || hr==DB_E_ERRORSOCCURRED)
|
|
{
|
|
if ( eSQLStmt != USE_OPENROWSET && hr == DB_E_ERRORSOCCURRED)
|
|
{
|
|
//GetProperties with DBPROPSET_PROPERTIESINERROR.
|
|
if ( hr == DB_E_ERRORSOCCURRED && m_pICommand )
|
|
{
|
|
//Setup input DBPROPSET_PROPERTIESINERROR
|
|
const ULONG cPropertyIDSets = 1;
|
|
DBPROPIDSET rgPropertyIDSets[cPropertyIDSets];
|
|
rgPropertyIDSets[0].guidPropertySet = DBPROPSET_PROPERTIESINERROR;
|
|
rgPropertyIDSets[0].cPropertyIDs = 0;
|
|
rgPropertyIDSets[0].rgPropertyIDs = NULL;
|
|
|
|
if ( FAILED(m_pICommand->QueryInterface(IID_ICommandProperties, (void**)&pICommandProperties)) )
|
|
goto CLEANUP;
|
|
if ( FAILED(pICommandProperties->GetProperties(cPropertyIDSets, rgPropertyIDSets, &cPropSets, &rgPropSets)) )
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
//if PIE returned no errors use the error status returned on the SetPropperties call
|
|
//PIE does not necessarily have to return error if it is being called from a layer on top of
|
|
//the provider, ie. Service Components or Remoting
|
|
if (!rgPropSets)
|
|
{
|
|
DumpPropertyErrors(m_cPropSets, m_rgPropSets, &cNumErrors, &cNumNotSupported);
|
|
}
|
|
else
|
|
{
|
|
if (rgPropSets->rgProperties)
|
|
{
|
|
DumpPropertyErrors(cPropSets, rgPropSets, &cNumErrors, &cNumNotSupported);
|
|
}
|
|
else
|
|
{
|
|
DumpPropertyErrors(m_cPropSets, m_rgPropSets, &cNumErrors, &cNumNotSupported);
|
|
}
|
|
}
|
|
|
|
if( cNumErrors || cNumNotSupported )
|
|
{
|
|
if( cNumErrors )
|
|
{
|
|
odtLog << L"Bad property validation \n";
|
|
hrReturn = E_FAIL;
|
|
}
|
|
else if( cNumNotSupported )
|
|
{
|
|
hrReturn = S_FALSE; // so rest of code sees this is a Not Supported error
|
|
odtLog << L"One or more required properties are not supported, not settable, or conflict \n";
|
|
}
|
|
|
|
odtLog << L"Rowset not created; test not run.\n\n";
|
|
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;
|
|
|
|
//if eAccessorLocation is NO_ACCESSOR, no need to create an accessor
|
|
if(eAccessorLocation==NO_ACCESSOR)
|
|
{
|
|
hrReturn=S_OK;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
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
|
|
TESTC_(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),S_OK);
|
|
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//allocate memory for the row
|
|
m_pData=PROVIDER_ALLOC(m_cRowSize);
|
|
if(!m_pData)
|
|
goto CLEANUP;
|
|
|
|
hrReturn=S_OK;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(rgDBPropSet[0].rgProperties);
|
|
SAFE_RELEASE(pIColumnsInfo);
|
|
SAFE_RELEASE(pICommandProperties);
|
|
FreeProperties(&cPropSets, &rgPropSets);
|
|
|
|
if(pHRow)
|
|
{
|
|
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);
|
|
}
|
|
|
|
return hrReturn;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//@mfunc: Create an accessor on the rowset
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL TCIRowsetNewRow::GetAccessorOnRowset
|
|
(
|
|
EACCESSORLOCATION eAccessorLocation, //where the accessor should be created
|
|
BOOL fBindLongColumn, //whether to bind the column column
|
|
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,
|
|
DBPARAMIO eParamIO //the array of column ordinals to bind
|
|
)
|
|
{
|
|
IUnknown *pIUnknown = NULL;
|
|
DBCOUNTITEM cRowsObtained;
|
|
HROW *pHRow = NULL;
|
|
DBORDINAL cCnt = 0;
|
|
BOOL fPass = FALSE;
|
|
BLOBTYPE blobType;
|
|
|
|
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;
|
|
}
|
|
|
|
//create an accessor on the rowset
|
|
TESTC_(GetAccessorAndBindings(pIUnknown,dwAccessorFlags,&m_hAccessor,
|
|
&m_rgBinding,&m_cBinding,&m_cRowSize,dwPart,eColsToBind,eBindingOrder,
|
|
eColsByRef,NULL,&cCnt,NULL,dbTypeModifier,cColsToBind,(LONG_PTR *) rgColsToBind,
|
|
NULL,NO_COLS_OWNED_BY_PROV,eParamIO,blobType),S_OK);
|
|
|
|
//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(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(cRowsObtained,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
|
|
//restart position. The rowset returns to its original state
|
|
HRESULT hr = m_pIRowset->RestartPosition(NULL);
|
|
CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE);
|
|
}
|
|
|
|
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 TCIRowsetNewRow::GetBookmark
|
|
(
|
|
ULONG ulRow,
|
|
DBBKMARK *pcbBookmark,
|
|
BYTE **ppBookmark
|
|
)
|
|
{
|
|
BOOL fPass = FALSE;
|
|
HROW hRow[1];
|
|
HROW *pHRow = hRow;
|
|
DBCOUNTITEM cCount;
|
|
|
|
//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=CHECK(GetBookmarkByRow(*pHRow, pcbBookmark, ppBookmark),S_OK);
|
|
|
|
//release the row handle
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
|
|
COMPARE(cCount, 0);
|
|
|
|
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.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
HRESULT TCIRowsetNewRow::GetBookmarkByRow
|
|
(
|
|
HROW hRow,
|
|
DBBKMARK *pcbBookmark,
|
|
BYTE **ppBookmark
|
|
)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
void *pData=NULL;
|
|
HACCESSOR hAccessor=NULL;
|
|
DBCOUNTITEM cBinding;
|
|
DBLENGTH cbRowSize;
|
|
DBBINDING *pBinding=NULL;
|
|
DBORDINAL ulColToBind=0;
|
|
|
|
//the rowset has to expose IRowset in order to have bookmark
|
|
if(!m_pIRowset)
|
|
return FALSE;
|
|
|
|
odtLog << "1 potato";
|
|
//check the input
|
|
if(!pcbBookmark || !ppBookmark)
|
|
return FALSE;
|
|
odtLog << "2 potato";
|
|
|
|
//create an accessor to binding the bookmark
|
|
QTESTC_(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, (LONG_PTR *)&ulColToBind),S_OK);
|
|
|
|
odtLog << "3 potato";
|
|
|
|
//allocate memory
|
|
if(!(pData=PROVIDER_ALLOC(cbRowSize)))
|
|
goto CLEANUP;
|
|
odtLog << "4 potato";
|
|
|
|
//get the data
|
|
QTESTC_(m_pIRowset->GetData(hRow, hAccessor, pData),S_OK);
|
|
odtLog << "5 potato";
|
|
|
|
//get the length of the bookmark
|
|
// *pcbBookmark= *((ULONG *)(dwAddr+pBinding[0].obLength));
|
|
*pcbBookmark=LENGTH_BINDING(pBinding[0], pData);
|
|
odtLog << "6 potato";
|
|
|
|
//allocate memory for bookmark
|
|
*ppBookmark=(BYTE *)PROVIDER_ALLOC(*pcbBookmark);
|
|
odtLog << "7 potato";
|
|
|
|
if(!(*ppBookmark))
|
|
goto CLEANUP;
|
|
odtLog << "8 potato";
|
|
|
|
//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);
|
|
odtLog << "9 potato";
|
|
|
|
hr = S_OK;
|
|
|
|
CLEANUP:
|
|
//release the memory
|
|
PROVIDER_FREE(pData);
|
|
PROVIDER_FREE(pBinding);
|
|
|
|
//free the accessor
|
|
if(hAccessor != DB_NULL_HACCESSOR)
|
|
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//@mfunc: Get cursor type of the rowset. Has to be called after a rowset
|
|
// generated.
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
ECURSOR TCIRowsetNewRow::GetCursorType()
|
|
{
|
|
IRowsetInfo *pIRowsetInfo=NULL;
|
|
ULONG cProperty;
|
|
DBPROPID rgDBPROPID[3];
|
|
DBPROPIDSET DBPropIDSet;
|
|
DBPROPSET *pDBPropSet=NULL;
|
|
ECURSOR eCursor=FORWARD_ONLY_CURSOR;
|
|
|
|
//initialization
|
|
rgDBPROPID[0]=DBPROP_OTHERINSERT;
|
|
rgDBPROPID[1]=DBPROP_OTHERUPDATEDELETE;
|
|
rgDBPROPID[2]=DBPROP_OWNUPDATEDELETE;
|
|
|
|
DBPropIDSet.guidPropertySet=DBPROPSET_ROWSET;
|
|
DBPropIDSet.cPropertyIDs=3;
|
|
DBPropIDSet.rgPropertyIDs=rgDBPROPID;
|
|
|
|
//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;
|
|
|
|
// this is the odbc cursor model - valid only when running against kagera
|
|
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:
|
|
if(pDBPropSet)
|
|
PROVIDER_FREE(pDBPropSet->rgProperties);
|
|
PROVIDER_FREE(pDBPropSet);
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
return eCursor;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//@mfunc: Return TRUE if the deleted rows are removed Has to be called after
|
|
// a rowset is generated.
|
|
//
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL TCIRowsetNewRow::RemoveDeleted()
|
|
{
|
|
IRowsetInfo *pIRowsetInfo=NULL;
|
|
ULONG cProperty;
|
|
DBPROPID DBPropID=DBPROP_REMOVEDELETED;
|
|
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:
|
|
if(pDBPropSet)
|
|
PROVIDER_FREE(pDBPropSet->rgProperties);
|
|
PROVIDER_FREE(pDBPropSet);
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
return fSupported;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//@mfunc: Return TRUE is strong identity
|
|
//
|
|
////--------------------------------------------------------------------
|
|
|
|
BOOL TCIRowsetNewRow::StrongIdentity()
|
|
{
|
|
IRowsetInfo *pIRowsetInfo=NULL;
|
|
ULONG cProperty;
|
|
DBPROPID DBPropID=DBPROP_STRONGIDENTITY;
|
|
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_STRONGIDENTITY
|
|
TESTC_(pIRowsetInfo->GetProperties(1,&DBPropIDSet,&cProperty,&pDBPropSet),S_OK);
|
|
|
|
if(V_BOOL(&pDBPropSet->rgProperties->vValue)==VARIANT_TRUE)
|
|
fSupported=TRUE;
|
|
|
|
CLEANUP:
|
|
if(pDBPropSet)
|
|
PROVIDER_FREE(pDBPropSet->rgProperties);
|
|
PROVIDER_FREE(pDBPropSet);
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
return fSupported;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//@mfun: Return TRUE if we are on buffered update mode
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL TCIRowsetNewRow::BufferedUpdate()
|
|
{
|
|
IRowsetInfo *pIRowsetInfo=NULL;
|
|
ULONG cProperty;
|
|
DBPROPID DBPropID=DBPROP_IRowsetUpdate;
|
|
DBPROPIDSET DBPropIDSet;
|
|
DBPROPSET *pDBPropSet=NULL;
|
|
BOOL fSupported=FALSE;
|
|
|
|
//initialize
|
|
DBPropIDSet.guidPropertySet=DBPROPSET_ROWSET;
|
|
DBPropIDSet.cPropertyIDs=1;
|
|
DBPropIDSet.rgPropertyIDs=&DBPropID;
|
|
|
|
if (!m_pIRowsetUpdate)
|
|
return FALSE;
|
|
|
|
//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:
|
|
if(pDBPropSet)
|
|
PROVIDER_FREE(pDBPropSet->rgProperties);
|
|
PROVIDER_FREE(pDBPropSet);
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
return fSupported;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//@mfun: Return TRUE if we are on buffered update mode
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL TCIRowsetNewRow::RowStrict()
|
|
{
|
|
IRowsetInfo *pIRowsetInfo=NULL;
|
|
ULONG cProperty;
|
|
DBPROPID DBPropID=DBPROP_ROWRESTRICT;
|
|
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 ROWRESTRICT
|
|
TESTC_(pIRowsetInfo->GetProperties(1,&DBPropIDSet,&cProperty,&pDBPropSet),S_OK);
|
|
|
|
if(V_BOOL(&pDBPropSet->rgProperties->vValue)==VARIANT_TRUE)
|
|
fSupported=TRUE;
|
|
|
|
CLEANUP:
|
|
if(pDBPropSet)
|
|
PROVIDER_FREE(pDBPropSet->rgProperties);
|
|
PROVIDER_FREE(pDBPropSet);
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
return fSupported;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------
|
|
//
|
|
// Get the updatable columns.
|
|
//
|
|
//
|
|
//---------------------------------------------------------------------------------
|
|
BOOL TCIRowsetNewRow::GetUpdatableCols
|
|
(
|
|
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++)
|
|
{
|
|
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: Return TRUE if the property is set with dwPropVal.
|
|
BOOL TCIRowsetNewRow::CheckProp(DWORD dwPropVal)
|
|
{
|
|
IRowsetInfo *pIRowsetInfo=NULL;
|
|
ULONG cProperty;
|
|
DBPROPIDSET DBPropIDSet;
|
|
DBPROPID DBPropID=DBPROP_UPDATABILITY;
|
|
DBPROPSET *pDBPropSet=NULL;
|
|
BOOL fSet=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 the property
|
|
TESTC_(pIRowsetInfo->GetProperties(1,&DBPropIDSet,&cProperty,&pDBPropSet),S_OK);
|
|
|
|
if((pDBPropSet->rgProperties->vValue).lVal & dwPropVal)
|
|
fSet=TRUE;
|
|
|
|
CLEANUP:
|
|
if(pDBPropSet)
|
|
PROVIDER_FREE(pDBPropSet->rgProperties);
|
|
PROVIDER_FREE(pDBPropSet);
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
return fSet;
|
|
|
|
}
|
|
|
|
BOOL TCIRowsetNewRow::GetProp(DBPROPID DBPropID)
|
|
{
|
|
IRowsetInfo *pIRowsetInfo=NULL;
|
|
ULONG cProperty;
|
|
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:
|
|
if(pDBPropSet)
|
|
PROVIDER_FREE(pDBPropSet->rgProperties);
|
|
PROVIDER_FREE(pDBPropSet);
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
return fSupported;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//@mfunc: Get the 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 TCIRowsetNewRow::GetNullableAndUpdatable(
|
|
DBORDINAL *pcbCol, //[out] the count of the rgColNum
|
|
DBORDINAL **prgColNum //[out] the col ordinals array
|
|
)
|
|
{
|
|
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++)
|
|
{
|
|
//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 TCIRowsetNewRow::GetNotNullableAndUpdatable(
|
|
DBORDINAL *pcbCol, //[out] the count of the rgColNum
|
|
DBORDINAL **prgColNum //[out] the col ordinals array
|
|
)
|
|
{
|
|
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++)
|
|
{
|
|
|
|
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;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//@mfunc: Get the Fixed Length and Updatable column
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL TCIRowsetNewRow::GetFixedLengthAndUpdatable
|
|
(
|
|
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++)
|
|
{
|
|
//have to consider either fixed length or not nullable
|
|
if((IsFixedLength(m_rgInfo[cColsCount].wType) ||
|
|
!(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;
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//@mfunc: Get the Variable Length and Updatable column
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL TCIRowsetNewRow::GetVariableLengthAndUpdatable
|
|
(
|
|
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);
|
|
|
|
|
|
//add the 1st column, for the convenience of insert a new row
|
|
*prgColNum[*pcbCol]=1;
|
|
(*pcbCol)++;
|
|
|
|
for(cColsCount=0;cColsCount<m_cRowsetCols;cColsCount++)
|
|
{
|
|
|
|
if((!IsFixedLength(m_rgInfo[cColsCount].wType) ||
|
|
!(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;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//@mfunc: Get not updatable column
|
|
//
|
|
//--------------------------------------------------------------------
|
|
DBORDINAL TCIRowsetNewRow::GetNotUpdatable()
|
|
{
|
|
|
|
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;
|
|
|
|
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)
|
|
)
|
|
return m_rgInfo[cColsCount].iOrdinal;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//@mfunc: Get first updatable column
|
|
//
|
|
//--------------------------------------------------------------------
|
|
DBORDINAL TCIRowsetNewRow::GetFirstUpdatable()
|
|
{
|
|
DBORDINAL cbCols = 0;
|
|
DBORDINAL *rgCols = NULL;
|
|
DBORDINAL ulUpdatableCol = 0;
|
|
|
|
GetUpdatableCols(&cbCols, &rgCols);
|
|
|
|
if (cbCols)
|
|
ulUpdatableCol = rgCols[0];
|
|
|
|
PROVIDER_FREE(rgCols);
|
|
|
|
return ulUpdatableCol;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//
|
|
//@mfunc: Get not updatable column
|
|
//
|
|
//--------------------------------------------------------------------
|
|
DBORDINAL TCIRowsetNewRow::GetLongAndUpdatable()
|
|
{
|
|
|
|
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;
|
|
|
|
for(cColsCount=0;cColsCount<m_cRowsetCols;cColsCount++)
|
|
{
|
|
|
|
if(( (m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITE) ||
|
|
(m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN)
|
|
)
|
|
&& (m_rgInfo[cColsCount].dwFlags & DBCOLUMNFLAGS_ISLONG)
|
|
)
|
|
return m_rgInfo[cColsCount].iOrdinal;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//@mfunc: free the memory referenced by the consumer's buffer
|
|
// The function has to be called after IRowset::GetData()
|
|
//
|
|
//--------------------------------------------------------------------
|
|
void TCIRowsetNewRow::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 TCIRowsetNewRow::ReleaseAccessorOnRowset()
|
|
{
|
|
//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_pIAccessor && m_eAccessorLocation!=ON_COMMAND_ACCESSOR)
|
|
{
|
|
CHECK(m_pIAccessor->ReleaseAccessor(m_hAccessor,NULL), S_OK);
|
|
m_hAccessor=NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//free binding structure
|
|
FreeAccessorBindings(m_cBinding, m_rgBinding);
|
|
|
|
//reset m_cRowset to 0 so that provider will allocate memory for next time
|
|
m_cRowSize = 0;
|
|
m_cBinding = 0;
|
|
m_rgBinding = NULL;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
//@mfunc: release a rowset object and accessor created on it
|
|
//
|
|
//--------------------------------------------------------------------
|
|
void TCIRowsetNewRow::ReleaseRowsetAndAccessor()
|
|
{
|
|
//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_pIAccessor && m_eAccessorLocation!=ON_COMMAND_ACCESSOR)
|
|
{
|
|
CHECK(m_pIAccessor->ReleaseAccessor(m_hAccessor,NULL), S_OK);
|
|
m_hAccessor=NULL;
|
|
}
|
|
}
|
|
|
|
//release IRowset pointer
|
|
SAFE_RELEASE(m_pIRowset);
|
|
SAFE_RELEASE(m_pIRowsetChange);
|
|
SAFE_RELEASE(m_pIRowsetUpdate);
|
|
SAFE_RELEASE(m_pIRowsetLocate);
|
|
SAFE_RELEASE(m_pIRowsetIdentity)
|
|
|
|
//free accessor handle
|
|
if(m_hAccessor)
|
|
{
|
|
//release the m_pIAccessor so that the rowset object is gone
|
|
SAFE_RELEASE(m_pIAccessor);
|
|
|
|
//if the accessor is created on the rowset object, use the IAccssor
|
|
//pointer directly to release the accessor handle
|
|
if(m_pICommand && m_eAccessorLocation==ON_COMMAND_ACCESSOR)
|
|
{
|
|
IAccessor *pIAccessor = NULL;
|
|
|
|
//QI for the accessor handle on the command object
|
|
if(CHECK(m_pICommand->QueryInterface(IID_IAccessor,
|
|
(LPVOID *)&pIAccessor),S_OK))
|
|
{
|
|
CHECK(pIAccessor->ReleaseAccessor(m_hAccessor,NULL), S_OK);
|
|
SAFE_RELEASE(pIAccessor);
|
|
}
|
|
}
|
|
|
|
m_hAccessor=NULL;
|
|
}
|
|
|
|
|
|
//free binding structure
|
|
PROVIDER_FREE(m_rgInfo);
|
|
PROVIDER_FREE(m_pStringsBuffer);
|
|
FreeAccessorBindings(m_cBinding, m_rgBinding);
|
|
|
|
//reset m_cRowset to 0 so that provider will allocate memory for next time
|
|
m_cRowSize = 0;
|
|
m_cBinding = 0;
|
|
m_rgBinding = NULL;
|
|
|
|
ReleaseRowsetObject(0);
|
|
ReleaseCommandObject(0);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
//@mfunc: Check if the row data in pRowData matches a row obtainable from pIRowset
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL TCIRowsetNewRow::CheckRowVisible(IRowset *pIRowset, void *pRowData, BOOL fRowIsVisible)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
DBCOUNTITEM cRows = 0;
|
|
HROW *pHRow = NULL;
|
|
BOOL fPass = TEST_FAIL;
|
|
BOOL fVisible = FALSE;
|
|
|
|
while (S_OK==(hr = pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || hr == DB_S_ENDOFROWSET )
|
|
{
|
|
if( cRows ==0)
|
|
break;
|
|
|
|
//Get the data for the row handle
|
|
TESTC_(pIRowset->GetData(*pHRow,m_hAccessor,m_pData),S_OK);
|
|
TESTC_(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,pRowData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY)==TRUE)
|
|
{
|
|
fVisible=TRUE;
|
|
FreeMemory();
|
|
break;
|
|
}
|
|
|
|
FreeMemory();
|
|
}
|
|
|
|
CLEANUP:
|
|
if(pHRow)
|
|
{
|
|
CHECK(pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
pHRow=NULL;
|
|
}
|
|
|
|
return (fVisible == fRowIsVisible);
|
|
}
|
|
|
|
|
|
// - - - - - - - - d- - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Test Case Section
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Rowset)
|
|
//--------------------------------------------------------------------
|
|
// @class Test read-only rowsets
|
|
//
|
|
class Rowset : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Rowset,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Request IRowsetNewRow on a read-only rowset by ICommand::Execute. DB_E_PROPERTYNOTAVAILABLE. select count(*
|
|
int Variation_1();
|
|
// @cmember Request IRowsetNewRow on a read-only rowset by ICommand::Execute. DB_E_PROPERTYNOTAVAILABLE. The query is left outer join
|
|
int Variation_2();
|
|
// @cmember Empty rowset. Should be able to insert one row.
|
|
int Variation_3();
|
|
// @cmember Insert the variable length columns without the length being bound.
|
|
int Variation_4();
|
|
// @cmember The accessor only has status binding for DBSTATUS_S_OK.
|
|
int Variation_5();
|
|
// @cmember The accessor only has status binding for DBSTATUS_S_ISNULL.
|
|
int Variation_6();
|
|
// @cmember The accessor only has status binding for DBSTATUS_S_ISNULL with not null cols
|
|
int Variation_7();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Rowset)
|
|
#define THE_CLASS Rowset
|
|
BEG_TEST_CASE(Rowset, TCIRowsetNewRow, L"Test read-only rowsets")
|
|
TEST_VARIATION(1, L"Request IRowsetNewRow on a read-only rowset by ICommand::Execute. DB_E_PROPERTYNOTAVAILABLE. select count(*")
|
|
TEST_VARIATION(2, L"Request IRowsetNewRow on a read-only rowset by ICommand::Execute. DB_E_PROPERTYNOTAVAILABLE. The query is left outer join")
|
|
TEST_VARIATION(3, L"Empty rowset. Should be able to insert one row.")
|
|
TEST_VARIATION(4, L"Insert the variable length columns without the length being bound.")
|
|
TEST_VARIATION(5, L"The accessor only has status binding for DBSTATUS_S_OK.")
|
|
TEST_VARIATION(6, L"The accessor only has status binding for DBSTATUS_S_ISNULL.")
|
|
TEST_VARIATION(7, L"The accessor only has status binding for DBSTATUS_S_ISNULL with not null cols.")
|
|
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 TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(MayWriteColumn,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember MaywriteColumn set to FALSE to all columns
|
|
int Variation_1();
|
|
// @cmember MayWriteColumn set to TRUE to all columns. Should fail.
|
|
int Variation_2();
|
|
// @cmember MayWriteColumn set to FALSE to all columns then insert. Should fail.
|
|
int Variation_3();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(MayWriteColumn)
|
|
#define THE_CLASS MayWriteColumn
|
|
BEG_TEST_CASE(MayWriteColumn, TCIRowsetNewRow, L"Test DBPROP_MAYWRITECOLUMN.")
|
|
TEST_VARIATION(1, L"MaywriteColumn set to FALSE to all columns")
|
|
TEST_VARIATION(2, L"MayWriteColumn set to TRUE to all columns. Should fail.")
|
|
TEST_VARIATION(3, L"MayWriteColumn set to FALSE to all columns then insert. Should fail.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(ComputedColumns)
|
|
//--------------------------------------------------------------------
|
|
// @class test computed columns by executing select col1, col1-col1 from table
|
|
//
|
|
class ComputedColumns : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(ComputedColumns,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Accessor binds the computed columns. DBSTATUS_E_PERMISSIONDENIED
|
|
int Variation_1();
|
|
// @cmember In immediate update mode, call InsertRow to insert a new row with a new value for the second column
|
|
int Variation_2();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(ComputedColumns)
|
|
#define THE_CLASS ComputedColumns
|
|
BEG_TEST_CASE(ComputedColumns, TCIRowsetNewRow, L"test computed columns by executing select col1, col1-col1 from table")
|
|
TEST_VARIATION(1, L"Accessor binds the computed columns. DBSTATUS_E_PERMISSIONDENIED")
|
|
TEST_VARIATION(2, L"In immediate update mode, call InsertRow to insert a new row with a new value for the second column")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Forward_Cursor_Immediate)
|
|
//--------------------------------------------------------------------
|
|
// @class Forward_Cursor_Immediate
|
|
//
|
|
class Forward_Cursor_Immediate : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Forward_Cursor_Immediate,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Move the cursor to the end of rowset. Insert a new row to the 1st row. Verify the reference count of the row handle.
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Forward_Cursor_Immediate)
|
|
#define THE_CLASS Forward_Cursor_Immediate
|
|
BEG_TEST_CASE(Forward_Cursor_Immediate, TCIRowsetNewRow, L"Forward_Cursor_Immediate")
|
|
TEST_VARIATION(1, L"Move the cursor to the end of rowset. Insert a new row to the 1st row. Verify the reference count of the row handle.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Forward_Query_Buffered)
|
|
//--------------------------------------------------------------------
|
|
// @class Forward_Query_Buffered
|
|
//
|
|
class Forward_Query_Buffered : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Forward_Query_Buffered,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Move the cursor to the begining of the rowset. Insert a new row with NULL values to the end of the rowset. Verify ref. count.
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Forward_Query_Buffered)
|
|
#define THE_CLASS Forward_Query_Buffered
|
|
BEG_TEST_CASE(Forward_Query_Buffered, TCIRowsetNewRow, L"Forward_Query_Buffered")
|
|
TEST_VARIATION(1, L"Move the cursor to the begining of the rowset. Insert a new row with NULL values to the end of the rowset. Verify ref. count.")
|
|
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 TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Static_Cursor_Buffered,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Move the cursor to the begining of the rowset. Insert a new row with NULL values to the middle of rowset. Verify ref. count.
|
|
int Variation_1();
|
|
// @cmember Soft Insert. Check visibility of data while row handle kept using GetData
|
|
int Variation_2();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Static_Cursor_Buffered)
|
|
#define THE_CLASS Static_Cursor_Buffered
|
|
BEG_TEST_CASE(Static_Cursor_Buffered, TCIRowsetNewRow, L"Static_Cursor_Buffered")
|
|
TEST_VARIATION(1, L"Move the cursor to the begining of the rowset. Insert a new row with NULL values to the middle of rowset. Verify ref. count.")
|
|
TEST_VARIATION(2, L"Soft Insert. Check visibility of data while row handle kept using GetData")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Static_Query_Immediate)
|
|
//--------------------------------------------------------------------
|
|
// @class Static_Query_Immediate
|
|
//
|
|
class Static_Query_Immediate : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Static_Query_Immediate,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Move the cursor to the end of rowset. Insert a new row to the 1st row. Verify the reference count of the row handle.
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Static_Query_Immediate)
|
|
#define THE_CLASS Static_Query_Immediate
|
|
BEG_TEST_CASE(Static_Query_Immediate, TCIRowsetNewRow, L"Static_Query_Immediate")
|
|
TEST_VARIATION(1, L"Move the cursor to the end of rowset. Insert a new row to the 1st row. Verify the reference count of the row handle.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Keyset_Cursor_Immediate)
|
|
//--------------------------------------------------------------------
|
|
// @class Keyset_Cursor_Immediate
|
|
//
|
|
class Keyset_Cursor_Immediate : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Keyset_Cursor_Immediate,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Move the cursor to the end of rowset. Insert a new row to the 1st row with NULL. Verify the ref count of the row handle.
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Keyset_Cursor_Immediate)
|
|
#define THE_CLASS Keyset_Cursor_Immediate
|
|
BEG_TEST_CASE(Keyset_Cursor_Immediate, TCIRowsetNewRow, L"Keyset_Cursor_Immediate")
|
|
TEST_VARIATION(1, L"Move the cursor to the end of rowset. Insert a new row to the 1st row with NULL. Verify the ref count of the row handle.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Keyset_Cursor_Buffer)
|
|
//--------------------------------------------------------------------
|
|
// @class Keyset_Cursor_Buffer
|
|
//
|
|
class Keyset_Cursor_Buffer : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Keyset_Cursor_Buffer,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Move the cursor to the begining of the rowset. Insert a new row to the end of rowset. Verify ref. count.
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Keyset_Cursor_Buffer)
|
|
#define THE_CLASS Keyset_Cursor_Buffer
|
|
BEG_TEST_CASE(Keyset_Cursor_Buffer, TCIRowsetNewRow, L"Keyset_Cursor_Buffer")
|
|
TEST_VARIATION(1, L"Move the cursor to the begining of the rowset. Insert a new row to the end of rowset. Verify ref. count.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Dynamic_Cursor_Immediate)
|
|
//--------------------------------------------------------------------
|
|
// @class Dynamic_Cursor_Immediate
|
|
//
|
|
class Dynamic_Cursor_Immediate : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Dynamic_Cursor_Immediate,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Move the cursor to the end of rowset. Insert a new row wiht NULL to 1st row. Verify the reference count of the row handle.
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Dynamic_Cursor_Immediate)
|
|
#define THE_CLASS Dynamic_Cursor_Immediate
|
|
BEG_TEST_CASE(Dynamic_Cursor_Immediate, TCIRowsetNewRow, L"Dynamic_Cursor_Immediate")
|
|
TEST_VARIATION(1, L"Move the cursor to the end of rowset. Insert a new row wiht NULL to 1st row. Verify the reference count of the row handle.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Dynamic_Query_Buffered)
|
|
//--------------------------------------------------------------------
|
|
// @class Dynamic_Query_Buffered
|
|
//
|
|
class Dynamic_Query_Buffered : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Dynamic_Query_Buffered,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Move the cursor to the begining of the rowset. Insert a new row to the middle of the rowset. Verify ref. count.
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Dynamic_Query_Buffered)
|
|
#define THE_CLASS Dynamic_Query_Buffered
|
|
BEG_TEST_CASE(Dynamic_Query_Buffered, TCIRowsetNewRow, L"Dynamic_Query_Buffered")
|
|
TEST_VARIATION(1, L"Move the cursor to the begining of the rowset. Insert a new row to the middle of the rowset. Verify ref. count.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Visible_Static_Command_Immediate)
|
|
//--------------------------------------------------------------------
|
|
// @class Visible_Static_Command_Immediate
|
|
//
|
|
class Visible_Static_Command_Immediate : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Visible_Static_Command_Immediate,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Create two rowsets on the same table. One rowset insert one row to the end of the rowset. The other rowset should not see.
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Visible_Static_Command_Immediate)
|
|
#define THE_CLASS Visible_Static_Command_Immediate
|
|
BEG_TEST_CASE(Visible_Static_Command_Immediate, TCIRowsetNewRow, L"Visible_Static_Command_Immediate")
|
|
TEST_VARIATION(1, L"Create two rowsets on the same table. One rowset insert one row to the end of the rowset. The other rowset should not see.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Visible_Keyset_Command_Buffered)
|
|
//--------------------------------------------------------------------
|
|
// @class Visible_Keyset_Command_Buffered
|
|
//
|
|
class Visible_Keyset_Command_Buffered : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Visible_Keyset_Command_Buffered,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Create two rowsets on the same table. One rowset insert one row to the end of the rowset. The other rowset should not see.
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Visible_Keyset_Command_Buffered)
|
|
#define THE_CLASS Visible_Keyset_Command_Buffered
|
|
BEG_TEST_CASE(Visible_Keyset_Command_Buffered, TCIRowsetNewRow, L"Visible_Keyset_Command_Buffered")
|
|
TEST_VARIATION(1, L"Create two rowsets on the same table. One rowset insert one row to the end of the rowset. The other rowset should not see.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Visible_Dynamic_Command_Buffered)
|
|
//--------------------------------------------------------------------
|
|
// @class Visible_Dynamic_Command_Buffered
|
|
//
|
|
class Visible_Dynamic_Command_Buffered : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Visible_Dynamic_Command_Buffered,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Create two rowsets on the same table. One rowset insert one row to the end of the rowset. The other rowset should see insert.
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Visible_Dynamic_Command_Buffered)
|
|
#define THE_CLASS Visible_Dynamic_Command_Buffered
|
|
BEG_TEST_CASE(Visible_Dynamic_Command_Buffered, TCIRowsetNewRow, L"Visible_Dynamic_Command_Buffered")
|
|
TEST_VARIATION(1, L"Create two rowsets on the same table. One rowset insert one row to the end of the rowset. The other rowset should see insert.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Visible_Dynamic_Query_Immediate)
|
|
//--------------------------------------------------------------------
|
|
// @class Visible_Dynamic_Query_Immediate
|
|
//
|
|
class Visible_Dynamic_Query_Immediate : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Visible_Dynamic_Query_Immediate,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Create two rowsets on the same table. One rowset insert one row to the end of the rowset. The other rowset should see insert.
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Visible_Dynamic_Query_Immediate)
|
|
#define THE_CLASS Visible_Dynamic_Query_Immediate
|
|
BEG_TEST_CASE(Visible_Dynamic_Query_Immediate, TCIRowsetNewRow, L"Visible_Dynamic_Query_Immediate")
|
|
TEST_VARIATION(1, L"Create two rowsets on the same table. One rowset insert one row to the end of the rowset. The other rowset should see insert.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(BMK_Forward_Query_Immediate)
|
|
//--------------------------------------------------------------------
|
|
// @class BMK_Forward_Query_Immediate
|
|
//
|
|
class BMK_Forward_Query_Immediate : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(BMK_Forward_Query_Immediate,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember call InsertRow insert the first row. Verify IRowsetLocate::GetRowsAt with DBBMK_FIRST.
|
|
int Variation_1();
|
|
// @cmember InsertRow Data to insert a last row. Verify by IRowsetLocate::GetRowsByBookmark
|
|
int Variation_2();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(BMK_Forward_Query_Immediate)
|
|
#define THE_CLASS BMK_Forward_Query_Immediate
|
|
BEG_TEST_CASE(BMK_Forward_Query_Immediate, TCIRowsetNewRow, L"BMK_Forward_Query_Immediate")
|
|
TEST_VARIATION(1, L"call InsertRow insert the first row. Verify IRowsetLocate::GetRowsAt with DBBMK_FIRST.")
|
|
TEST_VARIATION(2, L"InsertRow Data to insert a last row. Verify by IRowsetLocate::GetRowsByBookmark")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(BMK_Static_Query_Buffered)
|
|
//--------------------------------------------------------------------
|
|
// @class BMK_Static_Query_Buffered
|
|
//
|
|
class BMK_Static_Query_Buffered : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(BMK_Static_Query_Buffered,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember call InsertRow insert the last row. Verify IRowsetLocate::GetRowsAt with DBBMK_LAST.
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(BMK_Static_Query_Buffered)
|
|
#define THE_CLASS BMK_Static_Query_Buffered
|
|
BEG_TEST_CASE(BMK_Static_Query_Buffered, TCIRowsetNewRow, L"BMK_Static_Query_Buffered")
|
|
TEST_VARIATION(1, L"call InsertRow insert the last row. Verify IRowsetLocate::GetRowsAt with DBBMK_LAST.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(BMK_keyset_Cursor_Immediate)
|
|
//--------------------------------------------------------------------
|
|
// @class BMK_keyset_Cursor_Immediate
|
|
//
|
|
class BMK_keyset_Cursor_Immediate : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(BMK_keyset_Cursor_Immediate,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Try to set data to the bookmark column. DB_E_ACCESSVIOLATION
|
|
int Variation_1();
|
|
// @cmember call InsertRow insert the last row. Verify IRowsetLocate::GetRowsAt with DBBMK_LAST.
|
|
int Variation_2();
|
|
// @cmember InsertRow Data to insert a middle row. Verify by IRowsetLocate::GetRowsByBookmark
|
|
int Variation_3();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(BMK_keyset_Cursor_Immediate)
|
|
#define THE_CLASS BMK_keyset_Cursor_Immediate
|
|
BEG_TEST_CASE(BMK_keyset_Cursor_Immediate, TCIRowsetNewRow, L"BMK_keyset_Cursor_Immediate")
|
|
TEST_VARIATION(1, L"Try to set data to the bookmark column. DB_E_ACCESSVIOLATION")
|
|
TEST_VARIATION(2, L"call InsertRow insert the last row. Verify IRowsetLocate::GetRowsAt with DBBMK_LAST.")
|
|
TEST_VARIATION(3, L"InsertRow Data to insert a middle row. Verify by IRowsetLocate::GetRowsByBookmark")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(BMK_Dynamic_Cursor_Buffered)
|
|
//--------------------------------------------------------------------
|
|
// @class BMK_Dynamic_Cursor_Buffered
|
|
//
|
|
class BMK_Dynamic_Cursor_Buffered : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(BMK_Dynamic_Cursor_Buffered,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember call InsertRow insert the first row. Verify IRowsetLocate::GetRowsAt with DBBMK_FIRST.
|
|
int Variation_1();
|
|
// @cmember InsertRow Data to insert a last row. Verify by IRowsetLocate::GetRowsByBookmark
|
|
int Variation_2();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(BMK_Dynamic_Cursor_Buffered)
|
|
#define THE_CLASS BMK_Dynamic_Cursor_Buffered
|
|
BEG_TEST_CASE(BMK_Dynamic_Cursor_Buffered, TCIRowsetNewRow, L"BMK_Dynamic_Cursor_Buffered")
|
|
TEST_VARIATION(1, L"call InsertRow insert the first row. Verify IRowsetLocate::GetRowsAt with DBBMK_FIRST.")
|
|
TEST_VARIATION(2, L"InsertRow Data to insert a last row. Verify by IRowsetLocate::GetRowsByBookmark")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(boundary_keyset_immediate)
|
|
//--------------------------------------------------------------------
|
|
// @class boundary_keyset_immediate
|
|
//
|
|
class boundary_keyset_immediate : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(boundary_keyset_immediate,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember hAccessor is NULL accessor and phRow is valid
|
|
int Variation_1();
|
|
// @cmember hAccessor is NULL accessor and phRow is NULL.
|
|
int Variation_2();
|
|
// @cmember hAccessor is valid accessor and phRow is valid. pData is NULL. E_INVALIDARG
|
|
int Variation_3();
|
|
// @cmember test DB_E_ROWSNOTRELEASED.
|
|
int Variation_4();
|
|
// @cmember hChapter ignored
|
|
int Variation_5();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(boundary_keyset_immediate)
|
|
#define THE_CLASS boundary_keyset_immediate
|
|
BEG_TEST_CASE(boundary_keyset_immediate, TCIRowsetNewRow, L"boundary_keyset_immediate")
|
|
TEST_VARIATION(1, L"hAccessor is NULL accessor and phRow is valid")
|
|
TEST_VARIATION(2, L"hAccessor is NULL accessor and phRow is NULL.")
|
|
TEST_VARIATION(3, L"hAccessor is valid accessor and phRow is valid. pData is NULL. E_INVALIDARG")
|
|
TEST_VARIATION(4, L"test DB_E_ROWSNOTRELEASED.")
|
|
TEST_VARIATION(5, L"hChapter ignored")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(boundary_keyset_buffered)
|
|
//--------------------------------------------------------------------
|
|
// @class boundary_keyset_buffered
|
|
//
|
|
class boundary_keyset_buffered : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(boundary_keyset_buffered,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember hAccessor is NULL accessor and phRow is valid.
|
|
int Variation_1();
|
|
// @cmember hAccessor is NULL accessor and phRow is NULL.
|
|
int Variation_2();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(boundary_keyset_buffered)
|
|
#define THE_CLASS boundary_keyset_buffered
|
|
BEG_TEST_CASE(boundary_keyset_buffered, TCIRowsetNewRow, L"boundary_keyset_buffered")
|
|
TEST_VARIATION(1, L"hAccessor is NULL accessor and phRow is valid.")
|
|
TEST_VARIATION(2, L"hAccessor is NULL accessor and phRow is NULL.")
|
|
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 TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
DBORDINAL m_cColNumber;
|
|
DBORDINAL m_cColUpdatable;
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Invalid_Keyset_Cursor_Immediate,TCIRowsetNewRow);
|
|
// }} 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_ROWDATA. DB_E_READONLYACCESSOR.
|
|
int Variation_1();
|
|
// @cmember Try to set an auto increment column.
|
|
int Variation_2();
|
|
// @cmember The column number specified in the last binding structure = # of columns of the rowset+1. DB_E_COLUMNUNAVAILABLE.
|
|
int Variation_3();
|
|
// @cmember The accessor sets the status field of non nullable columns NULL. DB_E_SCHENMAVIOLATION.
|
|
int Variation_4();
|
|
// @cmember The accessor only has status binding for DBSTATUS_S_OK.
|
|
int Variation_5();
|
|
// @cmember Set a duplicate column on which a unique index is created. DB_E_INTEGRITYVIOLATION. No data is changed.
|
|
int Variation_6();
|
|
// @cmember The accessor is a parameter accessor. DB_E_BADACCESSORTYPE.
|
|
int Variation_7();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Invalid_Keyset_Cursor_Immediate)
|
|
#define THE_CLASS Invalid_Keyset_Cursor_Immediate
|
|
BEG_TEST_CASE(Invalid_Keyset_Cursor_Immediate, TCIRowsetNewRow, L"Invalid_Keyset_Cursor_Immediate")
|
|
TEST_VARIATION(1, L"The accessor is DBACCESSOR_READ | DBACCCESOR_ROWDATA. DB_E_READONLYACCESSOR.")
|
|
TEST_VARIATION(2, L"Try to set an auto increment column.")
|
|
TEST_VARIATION(3, L"The column number specified in the last binding structure = # of columns of the rowset+1. DB_E_COLUMNUNAVAILABLE.")
|
|
TEST_VARIATION(4, L"The accessor sets the status field of non nullable columns NULL. DB_E_SCHENMAVIOLATION.")
|
|
TEST_VARIATION(5, L"The accessor only has status binding for DBSTATUS_S_OK.")
|
|
TEST_VARIATION(6, L"Set a duplicate column on which a unique index is created. DB_E_INTEGRITYVIOLATION. No data is changed.")
|
|
TEST_VARIATION(7, L"The accessor is a parameter accessor. DB_E_BADACCESSORTYPE.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Invalid_Keyset_Query_Immediate)
|
|
//--------------------------------------------------------------------
|
|
// @class Invalid_Keyset_Query_Immediate
|
|
//
|
|
class Invalid_Keyset_Query_Immediate : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Invalid_Keyset_Query_Immediate,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember The accessor is DBACCCESOR_PASSCOLUMNSBYREF. DB_E_READONLYACCESSOR
|
|
int Variation_1();
|
|
// @cmember The status flag specified in a binding structure is neither DBSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALU
|
|
int Variation_2();
|
|
// @cmember The accessor only has length binding. E_FAIL
|
|
int Variation_3();
|
|
// @cmember The iOrdinal is out of range.
|
|
int Variation_4();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Invalid_Keyset_Query_Immediate)
|
|
#define THE_CLASS Invalid_Keyset_Query_Immediate
|
|
BEG_TEST_CASE(Invalid_Keyset_Query_Immediate, TCIRowsetNewRow, L"Invalid_Keyset_Query_Immediate")
|
|
TEST_VARIATION(1, L"The accessor is DBACCCESOR_PASSCOLUMNSBYREF. DB_E_READONLYACCESSOR")
|
|
TEST_VARIATION(2, L"The status flag specified in a binding structure is neither DBSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALU")
|
|
TEST_VARIATION(3, L"The accessor only has length binding. E_FAIL")
|
|
TEST_VARIATION(4, L"The iOrdinal is out of range.")
|
|
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 TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
DBPROPID m_rgDBPROPID[3];
|
|
ULONG m_cDBPROPID;
|
|
BOOL m_fCanConvertFromArray;
|
|
BOOL m_fCanConvertFromVector;
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Valid_Keyset_Cursor_Immediate,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Insert the variable length columns, in forward order of the rowset. Value & length binding only.
|
|
int Variation_1();
|
|
// @cmember Insert the fixed length columns with only value binding.
|
|
int Variation_2();
|
|
// @cmember DBTYPE_BYREF binding for all columns.
|
|
int Variation_3();
|
|
// @cmember DBTYPE_ARRAY binding for all columns.
|
|
int Variation_4();
|
|
// @cmember DBTYPE_VECTOR binding for all columns.
|
|
int Variation_5();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Valid_Keyset_Cursor_Immediate)
|
|
#define THE_CLASS Valid_Keyset_Cursor_Immediate
|
|
BEG_TEST_CASE(Valid_Keyset_Cursor_Immediate, TCIRowsetNewRow, L"Valid_Keyset_Cursor_Immediate")
|
|
TEST_VARIATION(1, L"Insert the variable length columns, in forward order of the rowset. Value & length binding only.")
|
|
TEST_VARIATION(2, L"Insert the fixed length columns with only value binding.")
|
|
TEST_VARIATION(3, L"DBTYPE_BYREF binding for all columns.")
|
|
TEST_VARIATION(4, L"DBTYPE_ARRAY binding for all columns.")
|
|
TEST_VARIATION(5, L"DBTYPE_VECTOR binding for all columns.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Valid_Keyset_Query_Buffered)
|
|
//--------------------------------------------------------------------
|
|
// @class Valid_Keyset_Query_Buffered
|
|
//
|
|
class Valid_Keyset_Query_Buffered : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
|
|
DBPROPID m_rgDBPROPID[5];
|
|
ULONG m_cDBPROPID;
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Valid_Keyset_Query_Buffered,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Insert the fixed length data type columns with bogus length information.
|
|
int Variation_1();
|
|
// @cmember Insert the whole row with status only. Set everything to NULL
|
|
int Variation_2();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Valid_Keyset_Query_Buffered)
|
|
#define THE_CLASS Valid_Keyset_Query_Buffered
|
|
BEG_TEST_CASE(Valid_Keyset_Query_Buffered, TCIRowsetNewRow, L"Valid_Keyset_Query_Buffered")
|
|
TEST_VARIATION(1, L"Insert the fixed length data type columns with bogus length information.")
|
|
TEST_VARIATION(2, L"Insert the whole row with status only. Set everything to NULL")
|
|
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 TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Sequence,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Set DBPROP_CanHoldRows. Set 3 rows in a row
|
|
int Variation_1();
|
|
// @cmember Unset DBPROP_CanHoldrows. Insert 2 rows. DB_E_ROWSNOTRELEASED.
|
|
int Variation_2();
|
|
// @cmember Buffered mode. Unset DBPROP_CanHoldRows. Insert 2 rows.
|
|
int Variation_3();
|
|
// @cmember Insert 50 rows. Update.
|
|
int Variation_4();
|
|
// @cmember Buffered mode,DBPROP_CanHoldRows FALSE,Insert row/release it,insert/get another
|
|
int Variation_5();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Sequence)
|
|
#define THE_CLASS Sequence
|
|
BEG_TEST_CASE(Sequence, TCIRowsetNewRow, L"sequence testing")
|
|
TEST_VARIATION(1, L"Set DBPROP_CanHoldRows. Set 3 rows in a row")
|
|
TEST_VARIATION(2, L"Unset DBPROP_CanHoldrows. Insert 2 rows. DB_E_ROWSNOTRELEASED.")
|
|
TEST_VARIATION(3, L"Buffered mode. Unset DBPROP_CanHoldRows. Insert 2 rows.")
|
|
TEST_VARIATION(4, L"Insert 50 rows. Update.")
|
|
TEST_VARIATION(5, L"Buffered mode,DBPROP_CanHoldRows FALSE,Insert row/release it,insert/get another")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Related_IRowsetDelete)
|
|
//--------------------------------------------------------------------
|
|
// @class test Related_IRowsetDelete wiht IRowsetNewRow
|
|
//
|
|
class Related_IRowsetDelete : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Related_IRowsetDelete,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember In immediately update mode, insert two rows, delete one, the insert another row
|
|
int Variation_1();
|
|
// @cmember In immediate update mode, insert one row, change it and delete it.
|
|
int Variation_2();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Related_IRowsetDelete)
|
|
#define THE_CLASS Related_IRowsetDelete
|
|
BEG_TEST_CASE(Related_IRowsetDelete, TCIRowsetNewRow, L"test Related_IRowsetDelete wiht IRowsetNewRow")
|
|
TEST_VARIATION(1, L"In immediately update mode, insert two rows, delete one, the insert another row")
|
|
TEST_VARIATION(2, L"In immediate update mode, insert one row, change it and delete it.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Related_IRowsetChange)
|
|
//--------------------------------------------------------------------
|
|
// @class test IRowsetChange and IRowsetNewRow
|
|
//
|
|
class Related_IRowsetChange : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Related_IRowsetChange,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Ichange the primary key of one row, insert a row with the original primary key. S_OK. Insert another row with the new primary
|
|
int Variation_1();
|
|
// @cmember In immediate update mode, inser two rows, change one of the row. Verify.
|
|
int Variation_2();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Related_IRowsetChange)
|
|
#define THE_CLASS Related_IRowsetChange
|
|
BEG_TEST_CASE(Related_IRowsetChange, TCIRowsetNewRow, L"test IRowsetChange and IRowsetNewRow")
|
|
TEST_VARIATION(1, L"Ichange the primary key of one row, insert a row with the original primary key. S_OK. Insert another row with the new primary")
|
|
TEST_VARIATION(2, L"In immediate update mode, inser two rows, change one of the row. Verify.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Transaction)
|
|
//--------------------------------------------------------------------
|
|
// @class testing zombie state
|
|
//
|
|
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. Query based
|
|
int Variation_1();
|
|
// @cmember Commit with fRetaining=FALSE. Cursor based
|
|
int Variation_2();
|
|
// @cmember Abort with fRetaining=TRUE. Cursor based.
|
|
int Variation_3();
|
|
// @cmember Abort with fRetaining=FALSE. Query based
|
|
int Variation_4();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(Transaction)
|
|
#define THE_CLASS Transaction
|
|
BEG_TEST_CASE(Transaction, CTransaction, L"testing zombie state")
|
|
TEST_VARIATION(1, L"Commit with fRetaining=TRUE. Query based")
|
|
TEST_VARIATION(2, L"Commit with fRetaining=FALSE. Cursor based")
|
|
TEST_VARIATION(3, L"Abort with fRetaining=TRUE. Cursor based.")
|
|
TEST_VARIATION(4, L"Abort with fRetaining=FALSE. Query based")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(EmptyTable)
|
|
//--------------------------------------------------------------------
|
|
// @class insert a new row into an empty table
|
|
//
|
|
class EmptyTable : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(EmptyTable,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Insert a new row into an empty table
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(EmptyTable)
|
|
#define THE_CLASS EmptyTable
|
|
BEG_TEST_CASE(EmptyTable, TCIRowsetNewRow, L"insert a new row into an empty table")
|
|
TEST_VARIATION(1, L"Insert a new row into an empty table")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(AppendOnly)
|
|
//--------------------------------------------------------------------
|
|
// @class test DBPROP_APPENDONLY
|
|
//
|
|
class AppendOnly : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(AppendOnly,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember check props with APPENDONLY
|
|
int Variation_1();
|
|
// @cmember AppendOnly conflict with DBPROP_CANSCROLLBACKWARDS, and OTHERINSERT.
|
|
int Variation_2();
|
|
// @cmember the rowset is empty.
|
|
int Variation_3();
|
|
// @cmember REFRESH/RESYNC, should not bring back old rows.
|
|
int Variation_4();
|
|
// @cmember RestartPosition/Get fetches only newlyinserted rows.
|
|
int Variation_5();
|
|
// @cmember Change newly inserted row..
|
|
int Variation_6();
|
|
// @cmember update pending,RestartPosition/Get fetches only newlyinserted rows.
|
|
int Variation_7();
|
|
// @cmember update pending,REFRESH/RESYNC, should not bring back old rows.
|
|
int Variation_8();
|
|
// @cmember update pending,Commit.
|
|
int Variation_9();
|
|
// @cmember update pending,Abort.
|
|
int Variation_10();
|
|
// @cmember Commit.
|
|
int Variation_11();
|
|
// @cmember Abort.
|
|
int Variation_12();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(AppendOnly)
|
|
#define THE_CLASS AppendOnly
|
|
BEG_TEST_CASE(AppendOnly, TCIRowsetNewRow, L"test DBPROP_APPENDONLY")
|
|
TEST_VARIATION(1, L"check props with APPENDONLY")
|
|
TEST_VARIATION(2, L"AppendOnly conflict with DBPROP_CANSCROLLBACKWARDS, and OTHERINSERT.")
|
|
TEST_VARIATION(3, L"the rowset is empty.")
|
|
TEST_VARIATION(4, L"REFRESH/RESYNC, should not bring back old rows.")
|
|
TEST_VARIATION(5, L"RestartPosition/Get fetches only newlyinserted rows.")
|
|
TEST_VARIATION(6, L"Change newly inserted row..")
|
|
TEST_VARIATION(7, L"update pending,RestartPosition/Get fetches only newlyinserted rows.")
|
|
TEST_VARIATION(8, L"update pending,REFRESH/RESYNC, should not bring back old rows.")
|
|
TEST_VARIATION(9, L"update pending,Commit.")
|
|
TEST_VARIATION(10, L"update pending,Abort.")
|
|
TEST_VARIATION(11, L"Commit.")
|
|
TEST_VARIATION(12, L"Abort.")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(BMK_Static_Buffered_OwnInsert)
|
|
//*-----------------------------------------------------------------------
|
|
// @class Test static cursors capable of seeing their own inserts
|
|
//
|
|
class BMK_Static_Buffered_OwnInsert : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(BMK_Static_Buffered_OwnInsert,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Test visibility of newly inserted row
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(BMK_Static_Buffered_OwnInsert)
|
|
#define THE_CLASS BMK_Static_Buffered_OwnInsert
|
|
BEG_TEST_CASE(BMK_Static_Buffered_OwnInsert, TCIRowsetNewRow, L"Test static cursors capable of seeing their own inserts")
|
|
TEST_VARIATION(1, L"Test visibility of newly inserted row")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Buffered_ReturnPendingInsert)
|
|
//*-----------------------------------------------------------------------
|
|
// @class Check ReturnPendingInsert property
|
|
//
|
|
class Buffered_ReturnPendingInsert : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Buffered_ReturnPendingInsert,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Soft Insert, check visibility
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(Buffered_ReturnPendingInsert)
|
|
#define THE_CLASS Buffered_ReturnPendingInsert
|
|
BEG_TEST_CASE(Buffered_ReturnPendingInsert, TCIRowsetNewRow, L"Check ReturnPendingInsert property")
|
|
TEST_VARIATION(1, L"Soft Insert, check visibility")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Immediate_ServerDataOnInsert)
|
|
//*-----------------------------------------------------------------------
|
|
// @class Test retrieval of bookmarks on newly inserted rows
|
|
//
|
|
class Immediate_ServerDataOnInsert : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Immediate_ServerDataOnInsert,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Test visibility of bookmark
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(Immediate_ServerDataOnInsert)
|
|
#define THE_CLASS Immediate_ServerDataOnInsert
|
|
BEG_TEST_CASE(Immediate_ServerDataOnInsert, TCIRowsetNewRow, L"Test retrieval of bookmarks on newly inserted rows")
|
|
TEST_VARIATION(1, L"Test visibility of bookmark")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Buffered_ServerDataOnInsert)
|
|
//*-----------------------------------------------------------------------
|
|
// @class Test retrieval of bookmarks on newly inserted rows
|
|
//
|
|
class Buffered_ServerDataOnInsert : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Buffered_ServerDataOnInsert,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Test visibility of bookmark
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(Buffered_ServerDataOnInsert)
|
|
#define THE_CLASS Buffered_ServerDataOnInsert
|
|
BEG_TEST_CASE(Buffered_ServerDataOnInsert, TCIRowsetNewRow, L"Test retrieval of bookmarks on newly inserted rows")
|
|
TEST_VARIATION(1, L"Test visibility of bookmark")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Immediate_ChangeInsertedRow)
|
|
//*-----------------------------------------------------------------------
|
|
// @class Test DBPROP_CHANGEINSERTEDROW
|
|
//
|
|
class Immediate_ChangeInsertedRow : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Immediate_ChangeInsertedRow,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Explicitly request ChangeInsertedRows
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(Immediate_ChangeInsertedRow)
|
|
#define THE_CLASS Immediate_ChangeInsertedRow
|
|
BEG_TEST_CASE(Immediate_ChangeInsertedRow, TCIRowsetNewRow, L"Test DBPROP_CHANGEINSERTEDROW")
|
|
TEST_VARIATION(1, L"Explicitly request ChangeInsertedRows")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(Buffered_ChangeInsertedRow)
|
|
//*-----------------------------------------------------------------------
|
|
// @class Test DBPROP_CHANGEINSERTEDROW in buffered mode
|
|
//
|
|
class Buffered_ChangeInsertedRow : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(Buffered_ChangeInsertedRow,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Explicitly request ChangeInsertedRows in buffered mode
|
|
int Variation_1();
|
|
// @cmember Delete a newly inserted row
|
|
int Variation_2();
|
|
// @cmember SetData on newly inserted followed by Delete
|
|
int Variation_3();
|
|
// @cmember Multiple SetData on newly inserted
|
|
int Variation_4();
|
|
// @cmember Multilpe newly Inserted and interleaved SetData and Delete ops
|
|
int Variation_5();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(Buffered_ChangeInsertedRow)
|
|
#define THE_CLASS Buffered_ChangeInsertedRow
|
|
BEG_TEST_CASE(Buffered_ChangeInsertedRow, TCIRowsetNewRow, L"Test DBPROP_CHANGEINSERTEDROW in buffered mode")
|
|
TEST_VARIATION(1, L"Explicitly request ChangeInsertedRows in buffered mode")
|
|
TEST_VARIATION(2, L"Delete a newly inserted row")
|
|
TEST_VARIATION(3, L"SetData on newly inserted followed by Delete")
|
|
TEST_VARIATION(4, L"Multiple SetData on newly inserted")
|
|
TEST_VARIATION(5, L"Multilpe newly Inserted and interleaved SetData and Delete ops")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(InsertDefault)
|
|
//*-----------------------------------------------------------------------
|
|
// @class InsertRow using DBSTATUS_S_DEFAULT
|
|
//
|
|
class InsertDefault : public TCIRowsetNewRow {
|
|
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
|
|
DBCOUNTITEM 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
|
|
HRESULT PrepareForInsert(
|
|
DBORDINAL cSelectedColumn, // [in] the ordinal of the selected column (1 based)
|
|
DBSTATUS Status, // [in] the status value for the selected column
|
|
LONG lRowsOffset, // [in] row number for data creation
|
|
BYTE **ppData, // [out] data buffer
|
|
ULONG cPropsToUse=1
|
|
);
|
|
|
|
// @cmember SetData, check it, get data, check it
|
|
virtual BOOL InsertAndCheckDefault(
|
|
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(InsertDefault,TCIRowsetNewRow);
|
|
// }} 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();
|
|
// @cmember Set default values on all default columns
|
|
int Variation_8();
|
|
// @cmember Set default value on a default column; set columns, one is asked default (SDI)
|
|
int Variation_9();
|
|
// @cmember Set default value on a not nullable default column (SDI)
|
|
int Variation_10();
|
|
// @cmember Set default value on a nullable default column (def == NULL)(SDI)
|
|
int Variation_11();
|
|
// @cmember Set default value on a nullable default column (def != NULL)(SDI)
|
|
int Variation_12();
|
|
// @cmember Set default value on a not default column (SDI)
|
|
int Variation_13();
|
|
// @cmember Set default value on a unique default value (SDI)
|
|
int Variation_14();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(InsertDefault)
|
|
#define THE_CLASS InsertDefault
|
|
BEG_TEST_CASE(InsertDefault, TCIRowsetNewRow, L"InsertRow using DBSTATUS_S_DEFAULT")
|
|
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")
|
|
TEST_VARIATION(8, L"Set default values on all default columns")
|
|
TEST_VARIATION(9, L"Set default value on a default column; set columns, one is asked default(SDI)")
|
|
TEST_VARIATION(10, L"Set default value on a not nullable default column(SDI)")
|
|
TEST_VARIATION(11, L"Set default value on a nullable default column (def == NULL)(SDI)")
|
|
TEST_VARIATION(12, L"Set default value on a nullable default column (def != NULL)(SDI)")
|
|
TEST_VARIATION(13, L"Set default value on a not default column(SDI)")
|
|
TEST_VARIATION(14, L"Set default value on a unique default value(SDI)")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(InsertIgnore)
|
|
//*-----------------------------------------------------------------------
|
|
// @class InsertRow using DBSTATUS_S_IGNORE
|
|
//
|
|
class InsertIgnore : public InsertDefault {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
protected:
|
|
// @cmember InsertRowset, check it, get data, check it
|
|
BOOL InsertAndCheckIgnore(
|
|
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(InsertIgnore,InsertDefault);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Insert ignore values on all updateable columns
|
|
int Variation_1();
|
|
// @cmember Insert ignore value on a column; set many columns, one is asked ignored
|
|
int Variation_2();
|
|
// @cmember Insert ignore value on a not nullable default column
|
|
int Variation_3();
|
|
// @cmember Insert ignore value on a nullable default column (def == NULL)
|
|
int Variation_4();
|
|
// @cmember Insert ignore value on a nullable default column (def != NULL)
|
|
int Variation_5();
|
|
// @cmember Insert ignore value on a not default column
|
|
int Variation_6();
|
|
// @cmember Set status to DBSTATUS_S_IGNORE on a non updateable column
|
|
int Variation_7();
|
|
// @cmember Insert all updateable cols, set status to DBSTATUS_S_IGNORE for half of them
|
|
int Variation_8();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(InsertIgnore)
|
|
#define THE_CLASS InsertIgnore
|
|
BEG_TEST_CASE(InsertIgnore, InsertDefault, L"InsertRow using DBSTATUS_S_IGNORE")
|
|
TEST_VARIATION(1, L"Insert ignore values on all updateable columns")
|
|
TEST_VARIATION(2, L"Insert ignore value on a column; set many columns, one is asked ignored")
|
|
TEST_VARIATION(3, L"Insert ignore value on a not nullable default column")
|
|
TEST_VARIATION(4, L"Insert ignore value on a nullable default column (def == NULL)")
|
|
TEST_VARIATION(5, L"Insert ignore value on a nullable default column (def != NULL)")
|
|
TEST_VARIATION(6, L"Insert ignore value on a not default column")
|
|
TEST_VARIATION(7, L"Set status to DBSTATUS_S_IGNORE on a non updateable column")
|
|
TEST_VARIATION(8, L"Insert all updateable cols, set status to DBSTATUS_S_IGNORE for half of them")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(ErrorCases)
|
|
//*-----------------------------------------------------------------------
|
|
// @class ErrorCases
|
|
//
|
|
class ErrorCases : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(ErrorCases,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember DB_E_CANTCONVERTVALUE
|
|
int Variation_1();
|
|
// @cmember DB_E_DATAOVERFLOW
|
|
int Variation_2();
|
|
// @cmember DB_E_MAXPENDCHANGESEXCEEDED
|
|
int Variation_3();
|
|
// @cmember DB_E_ROWLIMITEDEXCEEDED
|
|
int Variation_4();
|
|
// @cmember DB_E_NOTSUPPORTED
|
|
int Variation_5();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(Buffered_ChangeInsertedRow)
|
|
#define THE_CLASS ErrorCases
|
|
BEG_TEST_CASE(ErrorCases, TCIRowsetNewRow, L"Test error cases")
|
|
TEST_VARIATION(1, L"DB_E_CANTCONVERTVALUE")
|
|
TEST_VARIATION(2, L"DB_E_DATAOVERFLOW")
|
|
TEST_VARIATION(3, L"DB_E_MAXPENDCHANGESEXCEEDED")
|
|
TEST_VARIATION(4, L"DB_E_ROWLIMITEDEXCEEDED")
|
|
TEST_VARIATION(5, L"DB_E_NOTSUPPORTED")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(ErrorCases)
|
|
//*-----------------------------------------------------------------------
|
|
// @class ErrorCases
|
|
//
|
|
class ServerDataOnInsertII : public TCIRowsetNewRow {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(ServerDataOnInsertII,TCIRowsetNewRow);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Fetch computed column
|
|
int Variation_1();
|
|
// @cmember Fetch default value
|
|
int Variation_2();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(Buffered_ChangeInsertedRow)
|
|
#define THE_CLASS ServerDataOnInsertII
|
|
BEG_TEST_CASE(ServerDataOnInsertII, TCIRowsetNewRow, L"ServerDataOnInsertII")
|
|
TEST_VARIATION(1, L"Fetch computed column")
|
|
TEST_VARIATION(2, L"Fetch default value")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
// }} END_DECLARE_TEST_CASES()
|
|
|
|
// {{ TCW_TESTMODULE(ThisModule)
|
|
TEST_MODULE(41, ThisModule, gwszModuleDescrip)
|
|
TEST_CASE(1, Rowset)
|
|
TEST_CASE(2, MayWriteColumn)
|
|
TEST_CASE(3, ComputedColumns)
|
|
TEST_CASE(4, Forward_Cursor_Immediate)
|
|
TEST_CASE(5, Forward_Query_Buffered)
|
|
TEST_CASE(6, Static_Cursor_Buffered)
|
|
TEST_CASE(7, Static_Query_Immediate)
|
|
TEST_CASE(8, Keyset_Cursor_Immediate)
|
|
TEST_CASE(9, Keyset_Cursor_Buffer)
|
|
TEST_CASE(10, Dynamic_Cursor_Immediate)
|
|
TEST_CASE(11, Dynamic_Query_Buffered)
|
|
TEST_CASE(12, Visible_Static_Command_Immediate)
|
|
TEST_CASE(13, Visible_Keyset_Command_Buffered)
|
|
TEST_CASE(14, Visible_Dynamic_Command_Buffered)
|
|
TEST_CASE(15, Visible_Dynamic_Query_Immediate)
|
|
TEST_CASE(16, BMK_Forward_Query_Immediate)
|
|
TEST_CASE(17, BMK_Static_Query_Buffered)
|
|
TEST_CASE(18, BMK_keyset_Cursor_Immediate)
|
|
TEST_CASE(19, BMK_Dynamic_Cursor_Buffered)
|
|
TEST_CASE(20, boundary_keyset_immediate)
|
|
TEST_CASE(21, boundary_keyset_buffered)
|
|
TEST_CASE(22, Invalid_Keyset_Cursor_Immediate)
|
|
TEST_CASE(23, Invalid_Keyset_Query_Immediate)
|
|
TEST_CASE(24, Valid_Keyset_Cursor_Immediate)
|
|
TEST_CASE(25, Valid_Keyset_Query_Buffered)
|
|
TEST_CASE(26, Sequence)
|
|
TEST_CASE(27, Related_IRowsetDelete)
|
|
TEST_CASE(28, Related_IRowsetChange)
|
|
TEST_CASE(29, Transaction)
|
|
TEST_CASE(30, EmptyTable)
|
|
TEST_CASE(31, AppendOnly)
|
|
TEST_CASE(32, BMK_Static_Buffered_OwnInsert)
|
|
TEST_CASE(33, Buffered_ReturnPendingInsert)
|
|
TEST_CASE(34, Immediate_ServerDataOnInsert)
|
|
TEST_CASE(35, Buffered_ServerDataOnInsert)
|
|
TEST_CASE(36, Immediate_ChangeInsertedRow)
|
|
TEST_CASE(37, Buffered_ChangeInsertedRow)
|
|
TEST_CASE(38, InsertDefault)
|
|
TEST_CASE(39, InsertIgnore)
|
|
TEST_CASE(40, ErrorCases)
|
|
TEST_CASE(41, ServerDataOnInsertII)
|
|
END_TEST_MODULE()
|
|
// }} TCW_TESTMODULE_END
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Rowset)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Rowset - Test read-only rowsets
|
|
//| Created: 05/06/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Rowset::Init()
|
|
{
|
|
if(TCIRowsetNewRow::Init())
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Request IRowsetNewRow on a read-only rowset by ICommand::Execute. DB_E_PROPERTYNOTAVAILABLE. select count(*
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Rowset::Variation_1()
|
|
{
|
|
BOOL fTestPass=FALSE;
|
|
|
|
//open a rowset, asking for IRowsetChange interface pointer
|
|
TESTC_(g_pTable->CreateRowset(SELECT_ALLFROMTBL, IID_IRowsetChange,0,NULL,
|
|
(IUnknown**)&m_pIRowset,0, NULL),S_OK);
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(m_pIRowset);
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Request IRowsetNewRow on a read-only rowset by ICommand::Execute. DB_E_PROPERTYNOTAVAILABLE. The query is left outer join
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Rowset::Variation_2()
|
|
{
|
|
BOOL fTestPass=FALSE;
|
|
|
|
if(m_pIDBCreateCommand)
|
|
{
|
|
//open a rowset, asking for IRowsetChange interface pointer
|
|
m_hr = g_pTable->CreateRowset(SELECT_COUNT, IID_IRowsetChange,0,NULL, (IUnknown**)&m_pIRowset,
|
|
0, NULL);
|
|
TESTC(m_hr == S_OK || m_hr == DB_E_ERRORSOCCURRED);
|
|
}
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(m_pIRowset);
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Empty rowset. Should be able to insert one row.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Rowset::Variation_3()
|
|
{
|
|
DBPROPID rgDBPROPID[3];
|
|
DBCOUNTITEM cRows = 0;
|
|
HROW hRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
void *pData = NULL;
|
|
BOOL fTestPass = TRUE;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_CANHOLDROWS;
|
|
rgDBPROPID[2]=DBPROP_IRowsetLocate;
|
|
|
|
//create a forward-only rowset with query based updates
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,3,rgDBPROPID,0,NULL,ON_ROWSET_ACCESSOR,
|
|
FALSE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
|
|
UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass = FALSE;
|
|
//fill up buffer to make for the 5th row
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
|
|
//InsertRow should succeed
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),S_OK);
|
|
|
|
//get data should succeed
|
|
TESTC_(m_pIRowset->GetData(hRow, m_hAccessor, m_pData),S_OK);
|
|
|
|
//compare data should be successful
|
|
if(!CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE))
|
|
goto CLEANUP;
|
|
|
|
//get new rows should be successful
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
|
|
//check the reference count of the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
|
|
//release the row handle
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow,NULL,NULL,NULL),S_OK);
|
|
|
|
PROVIDER_FREE(pHRow);
|
|
ReleaseRowsetAndAccessor();
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Insert the variable length columns without the length being bound. should be ok
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Rowset::Variation_4()
|
|
{
|
|
HROW hRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
void *pData = NULL;
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
DBORDINAL *rgColsToBind = NULL;
|
|
DBORDINAL cColsNumber = 0;
|
|
ULONG cCount = 0;
|
|
DBPROPID rgDBPROPID[2];
|
|
HRESULT hr;
|
|
|
|
|
|
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();
|
|
fTestPass = TEST_FAIL;
|
|
|
|
//value and status binding only
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgDBPROPID,
|
|
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, cColsNumber, rgColsToBind))
|
|
goto CLEANUP;
|
|
|
|
//make data for insert
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert should be successful, variable length cols can use the NULL terminated string
|
|
//they do not need the length
|
|
hr = m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow);
|
|
|
|
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;
|
|
}
|
|
//hRow should not be NULL
|
|
if(!hRow)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//check the row is inserted
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
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_(m_pIRowset->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;
|
|
//delete this row. it probably inserts null values into key columns which will be tried in later variations
|
|
//multiple attemptes to insert NULL values into key columns will result in integrity violations
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,pHRow,NULL),S_OK);
|
|
TESTC_(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)m_pData);
|
|
break;
|
|
}
|
|
|
|
TESTC_(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)m_pData);
|
|
}
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
PROVIDER_FREE(rgColsToBind);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
PROVIDER_FREE(pHRow);
|
|
ReleaseRowsetAndAccessor();
|
|
return fTestPass;
|
|
}
|
|
//}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc The accessor only has status binding for DBSTATUS_S_OK.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Rowset::Variation_5()
|
|
{
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
ULONG cCount;
|
|
HROW hRow = NULL;
|
|
void *pData = NULL;
|
|
DBPROPID rgPropertyIDs[2];
|
|
DBORDINAL cCol = 0;
|
|
DBORDINAL *rgColNumber = NULL;
|
|
|
|
rgPropertyIDs[0]=DBPROP_IRowsetChange;
|
|
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
|
|
|
|
// Initialize
|
|
m_ulUpdFlags = 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)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
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;
|
|
FreeAccessorBindings(m_cBinding, m_rgBinding);
|
|
PROVIDER_FREE(m_pData);
|
|
|
|
//Create a new accessor that binds only the not nullable updatable cols
|
|
if(!GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_STATUS, USE_COLS_TO_BIND_ARRAY,FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,cCol,rgColNumber))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//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;
|
|
}
|
|
|
|
//InsertRow should fail
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),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);
|
|
PROVIDER_FREE(rgColNumber);
|
|
|
|
if(m_pIRowset && hRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow,NULL,NULL,NULL),S_OK);
|
|
}
|
|
|
|
//release the accessor
|
|
ReleaseRowsetAndAccessor();
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(6)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc The accessor only has status binding for DBSTATUS_S_ISNULL.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Rowset::Variation_6()
|
|
{
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
ULONG cCount = 0;
|
|
ULONG cCountII = 0;
|
|
HROW hRow = NULL;
|
|
void *pData = NULL;
|
|
void *pDataCpy = NULL;
|
|
DBBINDING* rgBindings = NULL;
|
|
DBPROPID rgPropertyIDs[2];
|
|
DBORDINAL cCol = 0;
|
|
DBORDINAL *rgColNumber = NULL;
|
|
HACCESSOR hAccessor;
|
|
|
|
rgPropertyIDs[0]=DBPROP_IRowsetChange;
|
|
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
|
|
|
|
// Initialize
|
|
m_ulUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
|
|
|
|
//create a rowset to get the rgBindings built
|
|
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)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//get an array of nullable and updatable columns
|
|
GetNullableAndUpdatable(&cCol,&rgColNumber);
|
|
//has to find such a column
|
|
if(!cCol)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//
|
|
//make data for the row
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
fTestPass=FALSE;
|
|
|
|
// Duplicate the pData
|
|
pDataCpy = PROVIDER_ALLOC(m_cRowSize);
|
|
TESTC(pDataCpy != NULL);
|
|
memcpy(pDataCpy, pData, (size_t)m_cRowSize);
|
|
|
|
rgBindings = (DBBINDING*) PROVIDER_ALLOC(m_cBinding * sizeof(DBBINDING));
|
|
TESTC(rgBindings != NULL);
|
|
memcpy(rgBindings, m_rgBinding, (size_t)(m_cBinding * sizeof(DBBINDING)));
|
|
|
|
//set all the nullable and updatable bindings in rbBinding to only have the dwPart set to DBPART_STATUS
|
|
for (cCount=0;cCount<cCol;cCount++)
|
|
{
|
|
for (cCountII=0;cCountII<m_cBinding;cCountII++)
|
|
{
|
|
if (m_rgBinding[cCountII].iOrdinal==rgColNumber[cCount])
|
|
{
|
|
m_rgBinding[cCountII].dwPart=DBPART_STATUS;
|
|
// *(DBSTATUS *)((DWORD)pData+m_rgBinding[cCountII].obStatus)=DBSTATUS_S_ISNULL;
|
|
STATUS_BINDING(m_rgBinding[cCountII],pData)=DBSTATUS_S_ISNULL;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
//create a new accessor with the new bindings
|
|
TESTC_(m_pIAccessor->CreateAccessor( DBACCESSOR_ROWDATA,
|
|
m_cBinding,
|
|
m_rgBinding,
|
|
m_cRowSize,
|
|
&hAccessor,
|
|
NULL),S_OK);
|
|
|
|
//InsertRow should pass
|
|
//it shouldn't matter that the buffer has the length and value fields filled, the accessor says for nullable
|
|
//cols their status is NULL so the provider shouldn't even look at the length or value for these fields
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,hAccessor,pData,&hRow),S_OK);
|
|
|
|
//set all the nullable and updatable bindings in rbBinding to only have the dwPart set to DBPART_STATUS
|
|
for (cCount=0;cCount<cCol;cCount++)
|
|
{
|
|
for (cCountII=0;cCountII<m_cBinding;cCountII++)
|
|
{
|
|
if (m_rgBinding[cCountII].iOrdinal==rgColNumber[cCount])
|
|
{
|
|
if(!COMPARE(GetStatus(pData, &(m_rgBinding[cCountII])),DBSTATUS_S_ISNULL))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
fTestPass=TRUE;
|
|
CLEANUP:
|
|
|
|
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL), S_OK);
|
|
|
|
PROVIDER_FREE(rgColNumber);
|
|
|
|
if( m_pIRowset && hRow )
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow,NULL,NULL,NULL),S_OK);
|
|
|
|
//release the accessor
|
|
PROVIDER_FREE(pData);
|
|
ReleaseInputBindingsMemory(m_cBinding, rgBindings, (BYTE *)pDataCpy, TRUE);
|
|
PROVIDER_FREE(rgBindings);
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(7)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc The accessor only has status binding for DBSTATUS_S_ISNULL with not null cols
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Rowset::Variation_7()
|
|
{
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
ULONG cCount = 0;
|
|
ULONG cCountII = 0;
|
|
HROW hRow = NULL;
|
|
void *pData = NULL;
|
|
void *pDataCpy = NULL;
|
|
DBBINDING* rgBindings = NULL;
|
|
DBPROPID rgPropertyIDs[2];
|
|
DBORDINAL cCol = 0;
|
|
DBORDINAL *rgColNumber = NULL;
|
|
HACCESSOR hAccessor = NULL;
|
|
|
|
rgPropertyIDs[0]=DBPROP_IRowsetChange;
|
|
rgPropertyIDs[1]=DBPROP_CANHOLDROWS;
|
|
|
|
// Initialize
|
|
m_ulUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
|
|
|
|
//create a rowset to get the rgBindings built
|
|
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)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//get an array of nullable and updatable columns
|
|
GetNotNullableAndUpdatable(&cCol,&rgColNumber);
|
|
//has to find such a column
|
|
if(!cCol)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//reexecute the command with just cols we want
|
|
if(!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))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//make data for the row
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
fTestPass=FALSE;
|
|
|
|
//set all the nullable and updatable bindings in rbBinding to only have the dwPart set to DBPART_STATUS
|
|
// for (cCount=0;cCount<cCol;cCount++)
|
|
// {
|
|
for (cCountII=0;cCountII<m_cBinding;cCountII++)
|
|
{
|
|
// if (m_rgBinding[cCountII].iOrdinal==rgColNumber[cCount])
|
|
// {
|
|
m_rgBinding[cCountII].dwPart=DBPART_STATUS;
|
|
// *(DBSTATUS *)((DWORD)pData+m_rgBinding[cCountII].obStatus)=DBSTATUS_S_ISNULL;
|
|
STATUS_BINDING(m_rgBinding[cCountII],pData)=DBSTATUS_S_ISNULL;
|
|
continue;
|
|
// }
|
|
}
|
|
// }
|
|
|
|
//create a new accessor with the new bindings
|
|
// TESTC_(m_pIAccessor->CreateAccessor( DBACCESSOR_ROWDATA,
|
|
// m_cBinding,
|
|
// m_rgBinding,
|
|
// m_cRowSize,
|
|
// &hAccessor,
|
|
// NULL),S_OK);
|
|
|
|
//InsertRow should fail with some sort of integrity violation
|
|
TEST2C_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),DB_E_INTEGRITYVIOLATION,DB_E_ERRORSOCCURRED);
|
|
|
|
fTestPass=TRUE;
|
|
CLEANUP:
|
|
if (hAccessor)
|
|
{
|
|
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL), S_OK);
|
|
}
|
|
PROVIDER_FREE(rgColNumber);
|
|
|
|
if( m_pIRowset && hRow )
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow,NULL,NULL,NULL),S_OK);
|
|
|
|
//release the accessor
|
|
PROVIDER_FREE(pData);
|
|
ReleaseInputBindingsMemory(m_cBinding, rgBindings, (BYTE *)pDataCpy, TRUE);
|
|
PROVIDER_FREE(rgBindings);
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Rowset::Terminate()
|
|
{
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(MayWriteColumn)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: MayWriteColumn - Test DBPROP_MAYWRITECOLUMN.
|
|
//| Created: 05/06/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL MayWriteColumn::Init()
|
|
{
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
if (!SettableProperty(DBPROP_MAYWRITECOLUMN, DBPROPSET_ROWSET))
|
|
return TEST_SKIPPED;
|
|
|
|
if (!(GetPropInfoFlags(DBPROP_MAYWRITECOLUMN, DBPROPSET_ROWSET) & DBPROPFLAGS_COLUMNOK))
|
|
return TEST_SKIPPED;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc MaywriteColumn set to FALSE to all columns
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int MayWriteColumn::Variation_1()
|
|
{
|
|
DBPROPID rgDBPROPID[2];
|
|
BOOL fTestPass=TRUE;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_MAYWRITECOLUMN;
|
|
|
|
//open a rowset, specifying all the columns not to be settable
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,1,rgDBPROPID,
|
|
1,&(rgDBPROPID[1]),NO_ACCESSOR));
|
|
|
|
//get accessor, binds to all updatable columns
|
|
if(!GetAccessorOnRowset(ON_ROWSET_ACCESSOR, TRUE, DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND))
|
|
goto CLEANUP;
|
|
|
|
fTestPass = FALSE;
|
|
//the # of columns should be 0
|
|
if(COMPARE(m_cBinding, 0))
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
ReleaseRowsetAndAccessor();
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc MayWriteColumn set to TRUE to all columns. Should fail.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int MayWriteColumn::Variation_2()
|
|
{
|
|
DBPROPID rgDBPROPID[2];
|
|
BOOL fTestPass=TRUE;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_MAYWRITECOLUMN;
|
|
|
|
fTestPass = FALSE;
|
|
|
|
//open a rowset, specifying all the columns to be settable. Should fail
|
|
if (COMPARE(GetRowsetAndAccessor(SELECT_ALLFROMTBL,2,rgDBPROPID, 0, NULL,NO_ACCESSOR),E_FAIL))
|
|
{
|
|
fTestPass=TRUE;
|
|
}
|
|
ReleaseRowsetAndAccessor();
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc MayWriteColumn set to FALSE to all columns then insert. Should fail.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int MayWriteColumn::Variation_3()
|
|
{
|
|
HROW hNewRow = NULL;
|
|
void *pData = NULL;
|
|
DBPROPID rgDBPROPID[1];
|
|
DBPROPID rgNotDBPROPID[1];
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_MAYWRITECOLUMN;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgDBPROPID,1,rgNotDBPROPID,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
fTestPass = FALSE;
|
|
|
|
//make data for the 1st row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
//insert the new row, MAYWRITECOLUMN is VARIANT_FALSE
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hNewRow),DB_E_ERRORSOCCURRED);
|
|
|
|
fTestPass=TRUE;
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
|
|
if(hNewRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
}
|
|
ReleaseRowsetAndAccessor();
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL MayWriteColumn::Terminate()
|
|
{
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(ComputedColumns)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: ComputedColumns - test computed columns by executing select col1, col1-col1 from table
|
|
//| Created: 05/06/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL ComputedColumns::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[3];
|
|
BOOL fTestPass=FALSE;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_CANFETCHBACKWARDS;
|
|
rgDBPROPID[2]=DBPROP_CANHOLDROWS;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor with IRowsetNewRow. Immediately update mode.
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_COMPUTEDCOLLIST,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA, DBPART_VALUE|DBPART_STATUS));
|
|
|
|
fTestPass = TRUE;
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Accessor binds the computed columns. DBSTATUS_E_PERMISSIONDENIED
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int ComputedColumns::Variation_1()
|
|
{
|
|
ULONG i = 0;
|
|
DBORDINAL cCol = 0;
|
|
DBCOUNTITEM cRows = 0;
|
|
DBORDINAL cColumns = 0;
|
|
HROW *pHRow = NULL;
|
|
HROW hNewRow = NULL;
|
|
HACCESSOR hAccessor = NULL;
|
|
BOOL fTestPass = TRUE;
|
|
HRESULT hr = E_FAIL;
|
|
IColumnsInfo *pIColumnsInfo = NULL;
|
|
DBCOLUMNINFO *rgColInfo = NULL;
|
|
WCHAR *pStringsBuffer = NULL;
|
|
BOOL fWriteUnknown;
|
|
|
|
if(!m_pIDBCreateCommand)
|
|
goto CLEANUP;
|
|
|
|
fTestPass=FALSE;
|
|
//get the first row handler
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
|
|
//get ordinal of the last column(the computed column)
|
|
cCol = m_rgBinding[m_cBinding-1].iOrdinal;
|
|
|
|
COMPC(VerifyInterface(m_pIRowset, IID_IColumnsInfo, ROWSET_INTERFACE, (IUnknown **)&pIColumnsInfo), TRUE);
|
|
TESTC_(pIColumnsInfo->GetColumnInfo(&cColumns, &rgColInfo, &pStringsBuffer),S_OK);
|
|
|
|
// Check that the computed column is not reported as writable
|
|
COMPC(rgColInfo[i].dwFlags & DBCOLUMNFLAGS_WRITE, FALSE);
|
|
|
|
// Some providers may not be able to detect that computed columns are read-only;
|
|
fWriteUnknown = (rgColInfo[i].dwFlags & DBCOLUMNFLAGS_WRITEUNKNOWN);
|
|
|
|
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,1,&(m_rgBinding[m_cBinding-1]),0,&hAccessor,NULL),S_OK);
|
|
|
|
//get data
|
|
TESTC_(m_pIRowset->GetData(*pHRow,hAccessor,m_pData),S_OK);
|
|
|
|
hr = m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,hAccessor,m_pData,&hNewRow);
|
|
|
|
if (!fWriteUnknown)
|
|
{
|
|
// The provider reported that the computed column was read-only
|
|
// In this case, the provider must return DB_E_ERRORSOCCURRED
|
|
// and set the appropriate status in the SetData buffer
|
|
TESTC_(hr,DB_E_ERRORSOCCURRED);
|
|
|
|
//PERMISSIONDENIED should only be returned if ROWRESTRICT is on
|
|
if(GetProperty(DBPROP_COLUMNRESTRICT, DBPROPSET_ROWSET, m_pIRowset, VARIANT_TRUE))
|
|
{
|
|
TESTC(GetStatus(m_pData, &(m_rgBinding[m_cBinding-1])) == DBSTATUS_E_PERMISSIONDENIED);
|
|
}
|
|
else
|
|
{
|
|
TESTC(GetStatus(m_pData, &(m_rgBinding[m_cBinding-1])) == DBSTATUS_E_UNAVAILABLE);
|
|
}
|
|
fTestPass = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// The provider was unable to determine whether the column was read-only
|
|
// Expect any failed HRESULT
|
|
if(COMPARE(FAILED(hr),TRUE))
|
|
{
|
|
fTestPass = TRUE;
|
|
}
|
|
}
|
|
|
|
//no row handle should be retrieved
|
|
COMPARE(hNewRow, NULL);
|
|
CLEANUP:
|
|
//release the accessor
|
|
if(hAccessor)
|
|
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
//release the row handle
|
|
if(hNewRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
PROVIDER_FREE(rgColInfo);
|
|
PROVIDER_FREE(pStringsBuffer);
|
|
SAFE_RELEASE(pIColumnsInfo);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc In immediate update mode, call InsertRow to insert a new row with a new value for the second column
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int ComputedColumns::Variation_2()
|
|
{
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
DBPROPID rgDBPROPID[5];
|
|
void *pData = NULL;
|
|
void *pVisibleData = NULL;
|
|
HROW hNewRow = NULL;
|
|
IRowsetResynch *pIRowsetResynch= NULL;
|
|
ULONG cCount = 0;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetResynch;
|
|
rgDBPROPID[2]=DBPROP_CANHOLDROWS;
|
|
rgDBPROPID[3]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[4]=DBPROP_OWNINSERT;
|
|
|
|
//this variation wants its own rowset, make sure the one created in the init is gone
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_COMPUTEDCOLLIST,5,rgDBPROPID,0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
if (!m_pIRowsetChange||!m_pIRowsetUpdate)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass = TEST_FAIL;
|
|
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&m_pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,m_pData,&hNewRow),S_OK);
|
|
|
|
//update to inserted row to back end
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
if(!(pVisibleData=PROVIDER_ALLOC(m_cRowSize)))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//Try to get visible data on the row
|
|
//should bring back computed column
|
|
if(!VerifyInterface(m_pIRowset, IID_IRowsetResynch,ROWSET_INTERFACE,(IUnknown **)&pIRowsetResynch))
|
|
goto CLEANUP;
|
|
|
|
//get value of DBPROP_STRONGIDENTITY for this rowset
|
|
//if strong identity is VARIANT_TURE then
|
|
if(GetProp(DBPROP_STRONGIDENTITY))
|
|
{
|
|
TESTC_(pIRowsetResynch->GetVisibleData(hNewRow, m_hAccessor,pVisibleData), S_OK);
|
|
|
|
//all columns including the computed columns should be ok
|
|
for(cCount=0; cCount<m_cBinding; cCount++)
|
|
{
|
|
// COMPARE(*(DBSTATUS *)((DWORD)pVisibleData+m_rgBinding[cCount].obStatus),DBSTATUS_S_OK);
|
|
COMPARE(STATUS_BINDING(m_rgBinding[cCount],pVisibleData),DBSTATUS_S_OK);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//allocate memory for GetData
|
|
if(!(pData=PROVIDER_ALLOC(m_cRowSize)))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//get data on the new row handle
|
|
TESTC_(m_pIRowset->GetData(hNewRow, m_hAccessor, pData),S_OK);
|
|
|
|
//all columns including the computed columns should be ok
|
|
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);
|
|
}
|
|
}
|
|
fTestPass = TRUE;
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIRowsetResynch);
|
|
PROVIDER_FREE(pData);
|
|
PROVIDER_FREE(m_pData);
|
|
PROVIDER_FREE(pVisibleData);
|
|
ReleaseRowsetAndAccessor();
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL ComputedColumns::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Forward_Cursor_Immediate)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Forward_Cursor_Immediate - Forward_Cursor_Immediate
|
|
//| Created: 05/07/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Forward_Cursor_Immediate::Init()
|
|
{
|
|
BOOL fTestPass=FALSE;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
DBPROPID DBPropID=DBPROP_IRowsetChange;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,&DBPropID,2,g_rgDBPropID,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Move the cursor to the end of rowset. Insert a new row to the 1st row. Verify the reference count of the row handle.
|
|
// Verify the reference count of the row handle.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Forward_Cursor_Immediate::Variation_1()
|
|
{
|
|
HROW hNewRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
void *pData = NULL;
|
|
DBPROPID DBPropID = DBPROP_IRowsetChange;
|
|
BOOL fTestPass = FALSE;
|
|
HRESULT hr;
|
|
|
|
//move the cursor to the end of rowset
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows-1,0,&cRows,&pHRow),S_OK);
|
|
|
|
//no row should be retrieved
|
|
if(!COMPARE(pHRow, NULL))
|
|
goto CLEANUP;
|
|
|
|
//make data for the 1st row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert the new row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hNewRow),S_OK);
|
|
|
|
//get data on the new row handle
|
|
TESTC_(m_pIRowset->GetData(hNewRow, m_hAccessor, m_pData),S_OK);
|
|
|
|
//the data should be the same
|
|
if(!CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY))
|
|
goto CLEANUP;
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
hNewRow=NULL;
|
|
|
|
//free the memory used by m_pData
|
|
FreeMemory();
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
//re-execute the command
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,&DBPropID,0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND))
|
|
goto CLEANUP;
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
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
|
|
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);
|
|
//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;
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)m_pData);
|
|
break;
|
|
}
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)m_pData);
|
|
}
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData);
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
if(hNewRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Forward_Cursor_Immediate::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Forward_Query_Buffered)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Forward_Query_Buffered - Forward_Query_Buffered
|
|
//| Created: 05/07/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Forward_Query_Buffered::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[3];
|
|
BOOL fTestPass=TEST_FAIL;
|
|
HRESULT hr;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetUpdate;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns
|
|
hr = GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgDBPROPID,2,g_rgDBPropID,ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND);
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
if ( hr == S_OK )
|
|
{
|
|
//we should be on a buffered update mode
|
|
COMPC(BufferedUpdate(), TRUE);
|
|
|
|
fTestPass = TRUE;
|
|
}
|
|
else if ( hr == S_FALSE )
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
}
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Move the cursor to the begining of the rowset. Insert a new row with NULL values to the end of the rowset. Verify ref. count.
|
|
// Insert a new row with NULL values to the end of the rowset.
|
|
// Verify ref. count.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Forward_Query_Buffered::Variation_1()
|
|
{
|
|
HROW hNewRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
ULONG cCount = 0;
|
|
DBORDINAL cColCount = 0;
|
|
DBORDINAL cCol = 0;
|
|
DBORDINAL *rgColNumber = NULL;
|
|
DBPROPID DBPropID = DBPROP_IRowsetChange;
|
|
BOOL fTestPass = FALSE;
|
|
|
|
BOOL fFirstColNullable = FALSE;
|
|
void *pInsertedRowData = NULL;
|
|
void *pFirstRowData = NULL;
|
|
HRESULT hr;
|
|
|
|
//get the nullable and updatable columns
|
|
if(!GetNullableAndUpdatable(&cCol, &rgColNumber))
|
|
goto CLEANUP;
|
|
|
|
//move the cursor to after the 1st row of rowset
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,1,0,&cRows, &pHRow),S_OK);
|
|
|
|
//no row should be retrieved
|
|
if(!COMPARE(pHRow, NULL))
|
|
goto CLEANUP;
|
|
|
|
//make data for the first row
|
|
TESTC_(FillInputBindings(m_pTable, DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pFirstRowData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//make data for the last row
|
|
TESTC_(FillInputBindings(m_pTable, DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pInsertedRowData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
for(cCount=0; cCount<m_cBinding; cCount++)
|
|
{
|
|
for(cColCount=0; cColCount<cCol; cColCount++)
|
|
{
|
|
if(m_rgBinding[cCount].iOrdinal==rgColNumber[cColCount])
|
|
{
|
|
//Is the first column nullable
|
|
if(rgColNumber[cColCount]==1)
|
|
fFirstColNullable = TRUE;
|
|
// *(ULONG *)(dwAddr+m_rgBinding[cCount].obStatus)=DBSTATUS_S_ISNULL;
|
|
*(DBSTATUS*)&STATUS_BINDING(m_rgBinding[cCount],pInsertedRowData)=DBSTATUS_S_ISNULL;
|
|
//exit the inner loop
|
|
cColCount=cCol;
|
|
}
|
|
}
|
|
}
|
|
|
|
//insert the new row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pInsertedRowData, &hNewRow),S_OK);
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
//get data on the new row handle
|
|
TESTC_(m_pIRowset->GetData(hNewRow, m_hAccessor, m_pData),S_OK);
|
|
|
|
//the data should be the same
|
|
if(!CompareBuffer(m_pData, pInsertedRowData, m_cBinding, m_rgBinding, m_pIMalloc,TRUE,FALSE,COMPARE_ONLY))
|
|
goto CLEANUP;
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
hNewRow=NULL;
|
|
|
|
//free the memory used by m_pData
|
|
FreeMemory();
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
//re-execute the command
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,&DBPropID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH, UPDATEABLE_COLS_BOUND))
|
|
goto CLEANUP;
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
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
|
|
TESTC_(m_pIRowset->GetData(*pHRow,m_hAccessor,m_pData),S_OK);
|
|
//make sure GetData should be able to see the change
|
|
if(CompareBuffer(m_pData,pInsertedRowData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE)==TRUE)
|
|
{
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,pHRow,NULL),S_OK);
|
|
fTestPass=TRUE;
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
break;
|
|
}
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
CLEANUP:
|
|
//release the memory of col number array
|
|
PROVIDER_FREE(rgColNumber);
|
|
PROVIDER_FREE(pInsertedRowData);
|
|
PROVIDER_FREE(pFirstRowData);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
if(hNewRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Forward_Query_Buffered::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Static_Cursor_Buffered)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Static_Cursor_Buffered - Static_Cursor_Buffered
|
|
//| Created: 05/07/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Static_Cursor_Buffered::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[2];
|
|
BOOL fTestPass=TEST_SKIPPED;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetUpdate;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//we should be on a buffered update mode
|
|
COMPC(BufferedUpdate(), TRUE);
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
ReleaseRowsetAndAccessor();
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Move the cursor to the begining of the rowset. Insert a new row with NULL values to the middle of rowset. Verify ref. count.
|
|
// Insert a new row with NULL values to the middle of rowset.
|
|
// Verify ref. count.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Static_Cursor_Buffered::Variation_1()
|
|
{
|
|
HROW hNewRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
void *pData = NULL;
|
|
BOOL fTestPass = FALSE;
|
|
DBPROPID rgDBPROPID[2];
|
|
HRESULT hr = S_OK;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetUpdate;
|
|
|
|
TESTC_(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//make data for the middle row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert the new row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hNewRow),S_OK);
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
//get data on the new row handle
|
|
TESTC_(m_pIRowset->GetData(hNewRow, m_hAccessor, m_pData),S_OK);
|
|
|
|
//the data should be the same
|
|
if(!CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY))
|
|
goto CLEANUP;
|
|
|
|
//free the memory used by m_pData
|
|
FreeMemory();
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
hNewRow=NULL;
|
|
|
|
hr = m_pIRowset->RestartPosition(NULL);
|
|
TESTC_(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE);
|
|
|
|
//make sure we can still get the 1st row handle
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
|
|
PROVIDER_FREE(pHRow);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
//re-execute the command
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgDBPROPID,0,NULL,
|
|
ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
|
|
UPDATEABLE_COLS_BOUND))
|
|
goto CLEANUP;
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
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
|
|
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);
|
|
//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(pData);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
if(hNewRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Soft Insert. Check visibility of data while row handle kept using GetData
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Static_Cursor_Buffered::Variation_2()
|
|
{
|
|
HROW hNewRow=DB_NULL_HROW;
|
|
ULONG cRows=0;
|
|
void *pData=NULL;
|
|
BOOL fTestPass=FALSE;
|
|
DBPROPID rgDBPROPID[2];
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetUpdate;
|
|
|
|
TESTC_(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//make data for the middle row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert the new row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hNewRow),S_OK);
|
|
|
|
//get data on the new row handle; the data should be visible before being transmitted
|
|
TESTC_(m_pIRowset->GetData(hNewRow, m_hAccessor, m_pData),S_OK);
|
|
|
|
//the data should be the same
|
|
if(!CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY))
|
|
goto CLEANUP;
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
//free the memory used by m_pData
|
|
FreeMemory();
|
|
hNewRow=DB_NULL_HROW;
|
|
|
|
fTestPass = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
|
|
//release the row handle
|
|
if(hNewRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Static_Cursor_Buffered::Terminate()
|
|
{
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Static_Query_Immediate)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Static_Query_Immediate - Static_Query_Immediate
|
|
//| Created: 05/07/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Static_Query_Immediate::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[5];
|
|
BOOL fTestPass=FALSE;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_CANSCROLLBACKWARDS;
|
|
rgDBPROPID[2]=DBPROP_CANFETCHBACKWARDS;
|
|
rgDBPROPID[3]=DBPROP_CANHOLDROWS;
|
|
rgDBPROPID[4]=DBPROP_IRowsetLocate;
|
|
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,5,rgDBPROPID,2,g_rgDBPropID,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
fTestPass = TRUE;
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Move the cursor to the end of rowset. Insert a new row to the 1st row. Verify the reference count of the row handle.
|
|
// Insert a new row to the 1st row.
|
|
// Verify the reference count of the row handle.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Static_Query_Immediate::Variation_1()
|
|
{
|
|
HROW hNewRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
void *pData = NULL;
|
|
ULONG cCount = 0;
|
|
DBORDINAL cColCount = 0;
|
|
DBORDINAL cCol = 0;
|
|
DBORDINAL *rgColNumber= NULL;
|
|
BOOL fTestPass = TRUE;
|
|
DBPROPID rgDBPROPID[5];
|
|
HRESULT hr;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_CANSCROLLBACKWARDS;
|
|
rgDBPROPID[2]=DBPROP_CANFETCHBACKWARDS;
|
|
rgDBPROPID[3]=DBPROP_CANHOLDROWS;
|
|
rgDBPROPID[4]=DBPROP_IRowsetLocate;
|
|
|
|
//get the nullable and updatable columns
|
|
if(!GetNullableAndUpdatable(&cCol, &rgColNumber))
|
|
goto CLEANUP;
|
|
|
|
fTestPass=FALSE;
|
|
//move the cursor to after the 1st row of rowset
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,1,0,&cRows,&pHRow),S_OK);
|
|
|
|
//no row should be retrieved
|
|
if(!COMPARE(pHRow, NULL))
|
|
goto CLEANUP;
|
|
|
|
//make data for the 13rd row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
for(cCount=0; cCount<m_cBinding; cCount++)
|
|
{
|
|
for(cColCount=0; cColCount<cCol; cColCount++)
|
|
{
|
|
if(m_rgBinding[cCount].iOrdinal==rgColNumber[cColCount])
|
|
{
|
|
// *(ULONG *)(dwAddr+m_rgBinding[cCount].obStatus)=DBSTATUS_S_ISNULL;
|
|
STATUS_BINDING(m_rgBinding[cCount],pData)=DBSTATUS_S_ISNULL;
|
|
//exit the inner loop
|
|
cColCount=cCol;
|
|
}
|
|
}
|
|
}
|
|
|
|
//insert the new row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hNewRow),S_OK);
|
|
|
|
//get data on the new row handle
|
|
TESTC_(m_pIRowset->GetData(hNewRow, m_hAccessor, m_pData),S_OK);
|
|
|
|
//the data should be the same
|
|
if(!CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY))
|
|
goto CLEANUP;
|
|
|
|
//free the memory used by m_pData
|
|
FreeMemory();
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
hNewRow=NULL;
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
//re-execute the command
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,5,rgDBPROPID,0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND))
|
|
goto CLEANUP;
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
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
|
|
TESTC_(m_pIRowset->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)
|
|
{
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,pHRow,NULL),S_OK);
|
|
fTestPass=TRUE;
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)m_pData);
|
|
break;
|
|
}
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)m_pData);
|
|
}
|
|
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData);
|
|
|
|
|
|
CLEANUP:
|
|
//release the memory of col number array
|
|
PROVIDER_FREE(rgColNumber);
|
|
PROVIDER_FREE(pData);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
if(hNewRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Static_Query_Immediate::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Keyset_Cursor_Immediate)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Keyset_Cursor_Immediate - Keyset_Cursor_Immediate
|
|
//| Created: 05/07/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Keyset_Cursor_Immediate::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[6];
|
|
BOOL fTestPass=TEST_SKIPPED;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_OTHERUPDATEDELETE;
|
|
rgDBPROPID[2]=DBPROP_CANHOLDROWS;
|
|
rgDBPROPID[3]=DBPROP_CANFETCHBACKWARDS;
|
|
rgDBPROPID[4]=DBPROP_IRowsetIdentity;
|
|
rgDBPROPID[5]=DBPROP_IRowsetLocate;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,6,rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Move the cursor to the end of rowset. Insert a new row to the 1st row with NULL. Verify the ref count of the row handle.
|
|
//Insert a new row to the 1st row with NULL.
|
|
//Verify the ref count of the row handle.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Keyset_Cursor_Immediate::Variation_1()
|
|
{
|
|
HROW hNewRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
void *pData = NULL;
|
|
void *pDataCpy = NULL;
|
|
ULONG cCount = 0;
|
|
DBORDINAL cColCount = 0;
|
|
DBORDINAL cCol = 0;
|
|
DBORDINAL *rgColNumber = NULL;
|
|
DBPROPID DBPropID[2] = {DBPROP_IRowsetChange,DBPROP_IRowsetLocate};
|
|
BOOL fTestPass = TRUE;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//get the nullable and updatable columns
|
|
if(!GetNullableAndUpdatable(&cCol, &rgColNumber))
|
|
goto CLEANUP;
|
|
|
|
fTestPass=FALSE;
|
|
//move the cursor to after the 60th row of rowset. No Op.
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows,0,&cRows,&pHRow),S_OK);
|
|
|
|
//no row should be retrieved
|
|
if(!COMPARE(pHRow, NULL))
|
|
goto CLEANUP;
|
|
|
|
//make data for the 71st row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
// Duplicate the pData
|
|
pDataCpy = PROVIDER_ALLOC(m_cRowSize);
|
|
TESTC(pDataCpy != NULL);
|
|
memcpy(pDataCpy, pData, (size_t)m_cRowSize);
|
|
|
|
for(cCount=0; cCount<m_cBinding; cCount++)
|
|
{
|
|
for(cColCount=0; cColCount<cCol; cColCount++)
|
|
{
|
|
if(m_rgBinding[cCount].iOrdinal==rgColNumber[cColCount] &&
|
|
m_rgBinding[cCount].iOrdinal!=1 )
|
|
{
|
|
// *(DBSTATUS *)(dwAddr+m_rgBinding[cCount].obStatus)=DBSTATUS_S_ISNULL;
|
|
STATUS_BINDING(m_rgBinding[cCount],pData)=DBSTATUS_S_ISNULL;
|
|
cColCount=cCol;
|
|
}
|
|
}
|
|
}
|
|
|
|
//insert the new row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hNewRow),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 10th row handle
|
|
TESTC_(m_pIRowset->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;
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)m_pData);
|
|
break;
|
|
}
|
|
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)m_pData);
|
|
}
|
|
|
|
if ( hr == DB_S_ENDOFROWSET )
|
|
goto CLEANUP;
|
|
|
|
//free the memory used by m_pData
|
|
if(StrongIdentity())
|
|
CHECK(m_hr=m_pIRowsetIdentity->IsSameRow(*pHRow, hNewRow),S_OK);
|
|
|
|
//release the row handles
|
|
TESTC_(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
hNewRow=NULL;
|
|
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
//re-execute the command
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,DBPropID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND))
|
|
goto CLEANUP;
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Get the last 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_(m_pIRowset->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)
|
|
{
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,pHRow,NULL),S_OK);
|
|
fTestPass=TRUE;
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)m_pData);
|
|
break;
|
|
}
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)m_pData);
|
|
}
|
|
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pDataCpy);
|
|
|
|
|
|
CLEANUP:
|
|
//release the memory of col number array
|
|
PROVIDER_FREE(rgColNumber);
|
|
PROVIDER_FREE(pDataCpy);
|
|
PROVIDER_FREE(pData);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
if(hNewRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Keyset_Cursor_Immediate::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Keyset_Cursor_Buffer)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Keyset_Cursor_Buffer - Keyset_Cursor_Buffer
|
|
//| Created: 05/07/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Keyset_Cursor_Buffer::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[3];
|
|
BOOL fTestPass=TEST_SKIPPED;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_OTHERUPDATEDELETE;
|
|
rgDBPROPID[2]=DBPROP_IRowsetUpdate;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgDBPROPID,0,NULL,
|
|
ON_ROWSET_ACCESSOR,TRUE, DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//we should be on a buffered update mode
|
|
// COMPC(BufferedUpdate(), TRUE);
|
|
|
|
fTestPass = TRUE;
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Move the cursor to the begining of the rowset. Insert a new row to the end of rowset. Verify ref. count.
|
|
// Insert a new row to the end of rowset. .
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Keyset_Cursor_Buffer::Variation_1()
|
|
{
|
|
HROW hNewRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
void *pData = NULL;
|
|
ULONG cCount = 0;
|
|
DBORDINAL cColCount = 0;
|
|
DBORDINAL cCol = 0;
|
|
DBORDINAL *rgColNumber= NULL;
|
|
BOOL fTestPass = TRUE;
|
|
DBPROPID rgDBPROPID[4];
|
|
HRESULT hr;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_OTHERUPDATEDELETE;
|
|
rgDBPROPID[2]=DBPROP_IRowsetLocate;
|
|
rgDBPROPID[3]=DBPROP_IRowsetUpdate;
|
|
|
|
//get the nullable and updatable columns
|
|
if(!GetNullableAndUpdatable(&cCol, &rgColNumber))
|
|
goto CLEANUP;
|
|
|
|
//make data for the 1st row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
fTestPass=FALSE;
|
|
|
|
for(cCount=0; cCount<m_cBinding; cCount++)
|
|
{
|
|
for(cColCount=0; cColCount<cCol; cColCount++)
|
|
{
|
|
if(m_rgBinding[cCount].iOrdinal==rgColNumber[cColCount])
|
|
{
|
|
// *(DBSTATUS *)(dwAddr+m_rgBinding[cCount].obStatus)=DBSTATUS_S_ISNULL;
|
|
STATUS_BINDING(m_rgBinding[cCount],pData)=DBSTATUS_S_ISNULL;
|
|
cColCount=cCol;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//insert the new row
|
|
m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hNewRow);
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
hNewRow=NULL;
|
|
|
|
//make sure we can still get the 1st row handle
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow),S_OK);
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
|
|
PROVIDER_FREE(pHRow);
|
|
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
//re-execute the command
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
|
|
UPDATEABLE_COLS_BOUND))
|
|
|
|
goto CLEANUP;
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
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
|
|
TESTC_(m_pIRowset->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)==TRUE)
|
|
{
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,pHRow,NULL),S_OK);
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
fTestPass=TRUE;
|
|
FreeMemory();
|
|
break;
|
|
}
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
FreeMemory();
|
|
}
|
|
CLEANUP:
|
|
//release the memory of col number array
|
|
PROVIDER_FREE(rgColNumber);
|
|
PROVIDER_FREE(pData);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
if(hNewRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Keyset_Cursor_Buffer::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Dynamic_Cursor_Immediate)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Dynamic_Cursor_Immediate - Dynamic_Cursor_Immediate
|
|
//| Created: 05/07/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Dynamic_Cursor_Immediate::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[3];
|
|
BOOL fTestPass=FALSE;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_OTHERINSERT;
|
|
rgDBPROPID[2]=DBPROP_IRowsetIdentity;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Move the cursor to the end of rowset. Insert a new row wiht NULL to 1st row. Verify the reference count of the row handle.
|
|
// Insert a new row wiht NULL to 1st row.
|
|
// Verify the reference count of the row handle.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Dynamic_Cursor_Immediate::Variation_1()
|
|
{
|
|
HROW hNewRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
void *pData = NULL;
|
|
DBPROPID DBPropID = DBPROP_IRowsetChange;
|
|
BOOL fTestPass = FALSE;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//make data for the 1st row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert the new row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hNewRow),S_OK);
|
|
|
|
//get data on the new row handle
|
|
TESTC_(m_pIRowset->GetData(hNewRow, m_hAccessor, m_pData),S_OK);
|
|
|
|
//the data should be the same
|
|
if(!CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE,FALSE,COMPARE_ONLY))
|
|
goto CLEANUP;
|
|
|
|
//free the memory used by m_pData
|
|
FreeMemory();
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
hNewRow=NULL;
|
|
|
|
//restartpositon
|
|
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
|
|
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);
|
|
//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;
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)m_pData);
|
|
break;
|
|
}
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)m_pData);
|
|
}
|
|
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData);
|
|
|
|
//release the row handle
|
|
//TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
//PROVIDER_FREE(pHRow);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
//re-execute the command
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,&DBPropID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE, DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
|
|
UPDATEABLE_COLS_BOUND))
|
|
goto CLEANUP;
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
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
|
|
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);
|
|
//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;
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)m_pData);
|
|
break;
|
|
}
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)m_pData);
|
|
}
|
|
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData);
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
if(hNewRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Dynamic_Cursor_Immediate::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Dynamic_Query_Buffered)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Dynamic_Query_Buffered - Dynamic_Query_Buffered
|
|
//| Created: 05/07/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Dynamic_Query_Buffered::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[4];
|
|
BOOL fTestPass=TEST_SKIPPED;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[2]=DBPROP_OTHERINSERT;
|
|
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
|
|
//we should be on a buffered update mode
|
|
COMPC(BufferedUpdate(), TRUE);
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Move the cursor to the begining of the rowset. Insert a new row to the middle of the rowset. Verify ref. count.
|
|
// Insert a new row to the middle of the rowset. Verify ref. count.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Dynamic_Query_Buffered::Variation_1()
|
|
{
|
|
HROW hNewRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
void *pData = NULL;
|
|
DBPROPID DBPropID = DBPROP_IRowsetChange;
|
|
BOOL fTestPass = FALSE;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//make data for the 15th row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert the new row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hNewRow),S_OK);
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
//get data on the new row handle
|
|
TESTC_(m_pIRowset->GetData(hNewRow, m_hAccessor, m_pData),S_OK);
|
|
|
|
//the data should be the same
|
|
if(!CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding, m_pIMalloc,TRUE,FALSE,COMPARE_ONLY))
|
|
goto CLEANUP;
|
|
|
|
//free the memory used by m_pData
|
|
FreeMemory();
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
hNewRow=NULL;
|
|
|
|
hr = m_pIRowset->RestartPosition(NULL);
|
|
|
|
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_(m_pIRowset->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;
|
|
FreeMemory();
|
|
break;
|
|
}
|
|
FreeMemory();
|
|
}
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
//re-execute the command
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,&DBPropID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
|
|
UPDATEABLE_COLS_BOUND))
|
|
goto CLEANUP;
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
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
|
|
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);
|
|
//make sure GetData should be able to see the change
|
|
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE)==TRUE)
|
|
{
|
|
fTestPass=TRUE;
|
|
FreeMemory();
|
|
break;
|
|
}
|
|
FreeMemory();
|
|
}
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
if(hNewRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Dynamic_Query_Buffered::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Visible_Static_Command_Immediate)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Visible_Static_Command_Immediate - Visible_Static_Command_Immediate
|
|
//| Created: 05/08/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Visible_Static_Command_Immediate::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[3];
|
|
BOOL fTestPass=FALSE;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_CANHOLDROWS;
|
|
rgDBPROPID[2]=DBPROP_IRowsetLocate;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns. Write only //accessor
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgDBPROPID,
|
|
2,g_rgDBPropID,ON_ROWSET_FETCH_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Create two rowsets on the same table. One rowset insert one row to the end of the rowset. The other rowset should not see.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Visible_Static_Command_Immediate::Variation_1()
|
|
{
|
|
void *pData = NULL;
|
|
DBPROP rgDBProp[2];
|
|
DBPROPSET DBPropSet;
|
|
IUnknown *pIUnknown = NULL;
|
|
IRowset *pIRowset = NULL;
|
|
IAccessor *pIAccessor = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
BOOL fTestPass = FALSE;
|
|
|
|
|
|
if(!m_pIDBCreateCommand)
|
|
return TEST_PASS;
|
|
|
|
//initialize
|
|
DBPropSet.guidPropertySet=DBPROPSET_ROWSET;
|
|
DBPropSet.cProperties=2;
|
|
DBPropSet.rgProperties=rgDBProp;
|
|
DBPropSet.rgProperties[0].dwPropertyID=DBPROP_IRowsetChange;
|
|
DBPropSet.rgProperties[0].dwOptions=DBPROPOPTIONS_REQUIRED;
|
|
DBPropSet.rgProperties[0].colid = DB_NULLID;
|
|
DBPropSet.rgProperties[0].vValue.vt=VT_BOOL;
|
|
V_BOOL(&DBPropSet.rgProperties[0].vValue)=VARIANT_TRUE;
|
|
|
|
DBPropSet.rgProperties[1].dwPropertyID=DBPROP_CANHOLDROWS;
|
|
DBPropSet.rgProperties[1].dwOptions=DBPROPOPTIONS_REQUIRED;
|
|
DBPropSet.rgProperties[1].colid = DB_NULLID;
|
|
DBPropSet.rgProperties[1].vValue.vt=VT_BOOL;
|
|
V_BOOL(&DBPropSet.rgProperties[1].vValue)=VARIANT_TRUE;
|
|
|
|
|
|
//open another rowset
|
|
|
|
TESTC_(m_pTable->ExecuteCommand(SELECT_ORDERBYNUMERIC,IID_IRowsetChange, NULL, NULL, 0, NULL,
|
|
EXECUTE_IFNOERROR, 1, &DBPropSet,NULL, &pIUnknown, NULL),S_OK);
|
|
|
|
//QI for IRowset
|
|
TESTC_(pIUnknown->QueryInterface(IID_IRowset, (LPVOID *)&pIRowset),S_OK);
|
|
|
|
//QI for IAccessor
|
|
TESTC_(pIUnknown->QueryInterface(IID_IAccessor, (LPVOID *)&pIAccessor),S_OK);
|
|
|
|
//make data for insert
|
|
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(DB_NULL_HCHAPTER, m_hAccessor,pData,NULL),S_OK);
|
|
|
|
//create an accessor on the second rowset, on the first column//only
|
|
TESTC_(pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,1,m_rgBinding,0,&hAccessor,NULL),S_OK);
|
|
|
|
// look for the new row from the other rowset interface
|
|
while (S_OK==(m_hr = pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || m_hr == DB_S_ENDOFROWSET )
|
|
{
|
|
if( cRows ==0)
|
|
break;
|
|
//Get the data for the 10th row handle
|
|
TESTC_(pIRowset->GetData(*pHRow,hAccessor,m_pData),S_OK);
|
|
TESTC_(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)==TRUE)
|
|
{
|
|
fTestPass=FALSE;
|
|
FreeMemory();
|
|
break;
|
|
}
|
|
FreeMemory();
|
|
}
|
|
|
|
//if we reach the end of the rowset, the test will pass
|
|
if(COMPARE(m_hr, DB_S_ENDOFROWSET))
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
//release the accessor handle
|
|
if(hAccessor != DB_NULL_HACCESSOR)
|
|
CHECK(pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
//release the interface pointers
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIAccessor);
|
|
SAFE_RELEASE(pIUnknown);
|
|
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding,(BYTE *)pData, TRUE);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Visible_Static_Command_Immediate::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Visible_Keyset_Command_Buffered)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Visible_Keyset_Command_Buffered - Visible_Keyset_Command_Buffered
|
|
//| Created: 05/08/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Visible_Keyset_Command_Buffered::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[4];
|
|
BOOL fTestPass=TEST_SKIPPED;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[1]=DBPROP_OTHERUPDATEDELETE;
|
|
rgDBPROPID[2]=DBPROP_CANHOLDROWS;
|
|
rgDBPROPID[3]=DBPROP_IRowsetLocate;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns. Write only
|
|
//accessor
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgDBPROPID,
|
|
0,NULL,ON_ROWSET_FETCH_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Create two rowsets on the same table. One rowset insert one row to the end of the rowset. The other rowset should not see.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Visible_Keyset_Command_Buffered::Variation_1()
|
|
{
|
|
void *pData = NULL;
|
|
DBPROP rgDBProp[4];
|
|
DBPROPSET DBPropSet;
|
|
IUnknown *pIUnknown = NULL;
|
|
IRowset *pIRowset = NULL;
|
|
IAccessor *pIAccessor = NULL;
|
|
HACCESSOR hAccessor = NULL;
|
|
HROW *pHRow = NULL;
|
|
HROW hRow = NULL;
|
|
HROW *pPendingHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
BOOL fTestPass = FALSE;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if(!m_pIDBCreateCommand)
|
|
return TEST_PASS;
|
|
if(!m_pIRowsetUpdate)
|
|
return TEST_PASS;
|
|
|
|
//initialize
|
|
DBPropSet.guidPropertySet=DBPROPSET_ROWSET;
|
|
DBPropSet.cProperties=4;
|
|
DBPropSet.rgProperties=rgDBProp;
|
|
|
|
DBPropSet.rgProperties[0].dwPropertyID = DBPROP_IRowsetUpdate;
|
|
DBPropSet.rgProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
DBPropSet.rgProperties[0].colid = DB_NULLID;
|
|
DBPropSet.rgProperties[0].vValue.vt = VT_BOOL;
|
|
V_BOOL(&DBPropSet.rgProperties[0].vValue) = VARIANT_TRUE;
|
|
|
|
DBPropSet.rgProperties[1].dwPropertyID = DBPROP_OTHERUPDATEDELETE;
|
|
DBPropSet.rgProperties[1].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
DBPropSet.rgProperties[1].colid = DB_NULLID;
|
|
DBPropSet.rgProperties[1].vValue.vt = VT_BOOL;
|
|
V_BOOL(&DBPropSet.rgProperties[1].vValue) = VARIANT_TRUE;
|
|
|
|
DBPropSet.rgProperties[3].dwPropertyID = DBPROP_OTHERINSERT;
|
|
DBPropSet.rgProperties[3].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
DBPropSet.rgProperties[3].colid = DB_NULLID;
|
|
DBPropSet.rgProperties[3].vValue.vt = VT_BOOL;
|
|
V_BOOL(&DBPropSet.rgProperties[3].vValue) = VARIANT_FALSE;
|
|
|
|
DBPropSet.rgProperties[2].dwPropertyID = DBPROP_IRowsetLocate;
|
|
DBPropSet.rgProperties[2].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
DBPropSet.rgProperties[2].colid = DB_NULLID;
|
|
DBPropSet.rgProperties[2].vValue.vt = VT_BOOL;
|
|
V_BOOL(&DBPropSet.rgProperties[2].vValue) = VARIANT_TRUE;
|
|
|
|
//open another rowset
|
|
hr= m_pTable->ExecuteCommand(SELECT_ORDERBYNUMERIC,IID_IRowsetChange, NULL, NULL, 0, NULL,
|
|
EXECUTE_IFNOERROR, 1, &DBPropSet,NULL, &pIUnknown, NULL);
|
|
|
|
//if thr correct prop are not set no use go on.
|
|
if (hr==DB_S_ERRORSOCCURRED || hr==DB_S_ERRORSOCCURRED)
|
|
{
|
|
fTestPass = TEST_PASS;
|
|
goto CLEANUP;
|
|
}
|
|
if (hr!=S_OK)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//QI for IRowset
|
|
TESTC_(pIUnknown->QueryInterface(IID_IRowset, (LPVOID *)&pIRowset),S_OK);
|
|
|
|
//QI for IAccessor
|
|
TESTC_(pIUnknown->QueryInterface(IID_IAccessor, (LPVOID *)&pIAccessor),S_OK);
|
|
|
|
//make data for insert
|
|
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(DB_NULL_HCHAPTER, m_hAccessor,pData,&hRow),S_OK);
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&hRow,NULL,NULL,NULL),S_OK);
|
|
|
|
|
|
hr = m_pIRowset->RestartPosition(NULL);
|
|
|
|
while (S_OK==(hr = m_pIRowset->GetNextRows(NULL,0,1,&cRows, &pPendingHRow)) || hr == DB_S_ENDOFROWSET )
|
|
{
|
|
if( cRows ==0)
|
|
break;
|
|
//Get the data for the 10th row handle
|
|
TESTC_(m_pIRowset->GetData(*pPendingHRow,m_hAccessor,m_pData),S_OK);
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pPendingHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pPendingHRow);
|
|
//make sure GetData should be able to see the change
|
|
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE)==TRUE)
|
|
{
|
|
fTestPass=TRUE;
|
|
FreeMemory();
|
|
break;
|
|
}
|
|
FreeMemory();
|
|
}
|
|
|
|
//create an accessor on the second rowset, on the first colum
|
|
TESTC_(pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,1,m_rgBinding,0,&hAccessor,NULL),S_OK);
|
|
|
|
while (S_OK==(m_hr = pIRowset->GetNextRows(NULL,0,1,&cRows, &pHRow)) || m_hr == DB_S_ENDOFROWSET )
|
|
{
|
|
if( cRows ==0)
|
|
break;
|
|
//Get the data for row handle
|
|
TESTC_(pIRowset->GetData(*pHRow,hAccessor,m_pData),S_OK);
|
|
TESTC_(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)==TRUE)
|
|
{
|
|
fTestPass=FALSE;
|
|
FreeMemory();
|
|
break;
|
|
}
|
|
FreeMemory();
|
|
}
|
|
|
|
//if we reach the end of the rowset, the test will pass
|
|
if(COMPARE(m_hr, DB_S_ENDOFROWSET))
|
|
{
|
|
fTestPass=TRUE;
|
|
}
|
|
CLEANUP:
|
|
//release the accessor handle
|
|
if(hAccessor != DB_NULL_HACCESSOR)
|
|
CHECK(pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
//release the row handle
|
|
if(pPendingHRow)
|
|
{
|
|
CHECK(pIRowset->ReleaseRows(1,pPendingHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pPendingHRow);
|
|
}
|
|
|
|
|
|
//release the interface pointers
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIAccessor);
|
|
SAFE_RELEASE(pIUnknown);
|
|
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding,(BYTE *)pData,TRUE);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Visible_Keyset_Command_Buffered::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return(TCIRowsetNewRow::Terminate());
|
|
}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Visible_Dynamic_Command_Buffered)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Visible_Dynamic_Command_Buffered - Visible_Dynamic_Command_Buffered
|
|
//| Created: 05/08/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Visible_Dynamic_Command_Buffered::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[3];
|
|
BOOL fTestPass=TEST_SKIPPED;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_OTHERINSERT;
|
|
rgDBPROPID[2]=DBPROP_IRowsetUpdate;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns. Write only accessor
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgDBPROPID,
|
|
0,NULL,ON_ROWSET_FETCH_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//we should be on a buffered update mode
|
|
COMPC(BufferedUpdate(), TRUE);
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Create two rowsets on the same table. One rowset insert one row to the end of the rowset. The other rowset should see insert.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Visible_Dynamic_Command_Buffered::Variation_1()
|
|
{
|
|
void *pData = NULL;
|
|
DBPROP rgDBProp[2];
|
|
DBPROPSET DBPropSet;
|
|
IUnknown *pIUnknown = NULL;
|
|
IRowset *pIRowset = NULL;
|
|
IAccessor *pIAccessor = NULL;
|
|
HACCESSOR hAccessor = NULL;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
BOOL fTestPass = FALSE;
|
|
HRESULT hr;
|
|
|
|
//initialize
|
|
DBPropSet.guidPropertySet=DBPROPSET_ROWSET;
|
|
DBPropSet.cProperties=2;
|
|
DBPropSet.rgProperties=rgDBProp;
|
|
DBPropSet.rgProperties[0].dwPropertyID=DBPROP_IRowsetChange;
|
|
DBPropSet.rgProperties[0].dwOptions=DBPROPOPTIONS_REQUIRED;
|
|
DBPropSet.rgProperties[0].colid = DB_NULLID;
|
|
DBPropSet.rgProperties[0].vValue.vt=VT_BOOL;
|
|
V_BOOL(&DBPropSet.rgProperties[0].vValue)=VARIANT_TRUE;
|
|
|
|
DBPropSet.rgProperties[1].dwPropertyID=DBPROP_OTHERINSERT;
|
|
DBPropSet.rgProperties[1].dwOptions=DBPROPOPTIONS_REQUIRED;
|
|
DBPropSet.rgProperties[1].colid = DB_NULLID;
|
|
DBPropSet.rgProperties[1].vValue.vt=VT_BOOL;
|
|
V_BOOL(&DBPropSet.rgProperties[1].vValue)=VARIANT_TRUE;
|
|
|
|
if(!m_pIDBCreateCommand)
|
|
return TEST_PASS;
|
|
|
|
//open another rowset
|
|
TESTC_(m_pTable->ExecuteCommand(SELECT_ORDERBYNUMERIC,IID_IRowsetChange, NULL, NULL, 0, NULL,
|
|
EXECUTE_IFNOERROR, 1, &DBPropSet,NULL, &pIUnknown, NULL),S_OK);
|
|
|
|
|
|
//QI for IRowset
|
|
TESTC_(pIUnknown->QueryInterface(IID_IRowset,(LPVOID *)&pIRowset),S_OK);
|
|
|
|
//QI for IAccessor
|
|
TESTC_(pIUnknown->QueryInterface(IID_IAccessor, (LPVOID *)&pIAccessor),S_OK);
|
|
|
|
|
|
//make data for insert
|
|
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(DB_NULL_HCHAPTER, m_hAccessor,pData,NULL),S_OK);
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,&cRows, &pHRow,NULL),S_OK);
|
|
|
|
//one row should be updated
|
|
if(!COMPARE(cRows, 1))
|
|
goto CLEANUP;
|
|
|
|
//free the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1, pHRow, NULL, NULL, NULL),S_OK);
|
|
|
|
PROVIDER_FREE(pHRow);
|
|
|
|
//create an accessor on the second rowset.
|
|
TESTC_(pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,0,&hAccessor,NULL),S_OK);
|
|
|
|
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_(m_pIRowset->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,1,m_rgBinding,m_pIMalloc,TRUE)==TRUE)
|
|
{
|
|
fTestPass=TRUE;
|
|
FreeMemory();
|
|
break;
|
|
}
|
|
FreeMemory();
|
|
}
|
|
|
|
|
|
CLEANUP:
|
|
//release the accessor handle
|
|
if(hAccessor)
|
|
CHECK(pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
//release the interface pointers
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIAccessor);
|
|
SAFE_RELEASE(pIUnknown);
|
|
|
|
PROVIDER_FREE(pData);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Visible_Dynamic_Command_Buffered::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Visible_Dynamic_Query_Immediate)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Visible_Dynamic_Query_Immediate - Visible_Dynamic_Query_Immediate
|
|
//| Created: 05/08/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Visible_Dynamic_Query_Immediate::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[3];
|
|
BOOL fTestPass=TEST_SKIPPED;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_OTHERINSERT;
|
|
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns. Write only
|
|
//accessor
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgDBPROPID,
|
|
0,NULL,ON_ROWSET_FETCH_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Create two rowsets on the same table. One rowset insert one row to the end of the rowset. The other rowset should see insert.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Visible_Dynamic_Query_Immediate::Variation_1()
|
|
{
|
|
void *pData = NULL;
|
|
IRowsetInfo *pIRowsetInfo = NULL;
|
|
ICommand *pICommand = NULL;
|
|
IUnknown *pIUnknown = NULL;
|
|
IRowset *pIRowset = NULL;
|
|
IAccessor *pIAccessor = NULL;
|
|
HACCESSOR hAccessor = NULL;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
BOOL fTestPass = FALSE;
|
|
HRESULT hr;
|
|
|
|
if(!m_pIDBCreateCommand)
|
|
return TEST_PASS;
|
|
|
|
//get IRowsetInfo pointer for the rowset
|
|
TESTC_(m_pIAccessor->QueryInterface(IID_IRowsetInfo, (LPVOID *)&pIRowsetInfo),S_OK);
|
|
|
|
//get the pICommand pointer
|
|
TESTC_(pIRowsetInfo->GetSpecification(IID_ICommand, (IUnknown **)&pICommand),S_OK);
|
|
|
|
//open another rowset
|
|
TESTC_(pICommand->Execute(NULL,IID_IRowsetChange,NULL, NULL, &pIUnknown),S_OK);
|
|
|
|
//QI for IRowset
|
|
TESTC_(pIUnknown->QueryInterface(IID_IRowset, (LPVOID *)&pIRowset),S_OK);
|
|
|
|
//QI for IAccessor
|
|
TESTC_(pIUnknown->QueryInterface(IID_IAccessor, (LPVOID *)&pIAccessor),S_OK);
|
|
|
|
//make data for insert. Make the last row
|
|
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(DB_NULL_HCHAPTER, m_hAccessor,pData,NULL),S_OK);
|
|
|
|
//create an accessor on the second rowset
|
|
TESTC_(pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,0,&hAccessor,NULL),S_OK);
|
|
|
|
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_(m_pIRowset->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,1,m_rgBinding,m_pIMalloc,TRUE)==TRUE)
|
|
{
|
|
fTestPass=TRUE;
|
|
FreeMemory();
|
|
break;
|
|
}
|
|
FreeMemory();
|
|
}
|
|
|
|
|
|
CLEANUP:
|
|
//release the accessor handle
|
|
if(hAccessor != DB_NULL_HACCESSOR)
|
|
CHECK(pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
//release the interface pointers
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIAccessor);
|
|
SAFE_RELEASE(pIUnknown);
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
SAFE_RELEASE(pICommand);
|
|
|
|
if(pData)
|
|
PROVIDER_FREE(pData);
|
|
|
|
if(fTestPass)
|
|
return TEST_PASS;
|
|
else
|
|
return TEST_FAIL;
|
|
|
|
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Visible_Dynamic_Query_Immediate::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(BMK_Forward_Query_Immediate)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: BMK_Forward_Query_Immediate - BMK_Forward_Query_Immediate
|
|
//| Created: 05/09/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL BMK_Forward_Query_Immediate::Init()
|
|
{
|
|
BOOL fTestPass=TEST_PASS;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
DBPROPID rgDBPROPID[3];
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetLocate;
|
|
rgDBPROPID[2]=DBPROP_CANHOLDROWS;
|
|
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgDBPROPID,
|
|
3,g_rgDBPropID,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
|
|
UPDATEABLE_COLS_BOUND));
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc call InsertRow insert the first row. Verify IRowsetLocate::GetRowsAt with DBBMK_FIRST.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int BMK_Forward_Query_Immediate::Variation_1()
|
|
{
|
|
void *pData = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
DBBOOKMARK DBBookmark = DBBMK_FIRST;
|
|
BYTE *pBookmark = (BYTE *)&DBBookmark;
|
|
HROW hRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
BOOL fTestPass = TRUE;
|
|
HRESULT hr;
|
|
|
|
//make data for insert. Insert the first row
|
|
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(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),S_OK);
|
|
|
|
PROVIDER_FREE(pData);
|
|
if(!(pData=PROVIDER_ALLOC(m_cRowSize)))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//Get a new row by IRowsetLocate::GetRowsAt
|
|
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRow),S_OK);
|
|
|
|
//GetData
|
|
TESTC_(m_pIRowset->GetData(*pHRow,m_hAccessor,pData),S_OK);
|
|
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL,NULL), S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
|
|
m_hr = m_pIRowset->RestartPosition(NULL);
|
|
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_(m_pIRowset->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)==TRUE)
|
|
{
|
|
fTestPass=TRUE;
|
|
FreeMemory();
|
|
break;
|
|
}
|
|
FreeMemory();
|
|
}
|
|
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow, NULL, NULL, NULL), S_OK);
|
|
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow, NULL, NULL, NULL), S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc InsertRow Data to insert a last row. Verify by IRowsetLocate::GetRowsByBookmark
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int BMK_Forward_Query_Immediate::Variation_2()
|
|
{
|
|
void *pData = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
DBBOOKMARK DBBookmark = DBBMK_LAST;
|
|
BYTE *pBookmark = (BYTE *)&DBBookmark;
|
|
HROW hRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
BOOL fTestPass = TRUE;
|
|
HRESULT hr;
|
|
|
|
//make data for insert. Insert the last row
|
|
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(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),S_OK);
|
|
|
|
/*PROVIDER_FREE(pData);
|
|
|
|
//Get the last row by IRowsetLocate::GetRowsByBookmark
|
|
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRow),S_OK);
|
|
|
|
//GetData
|
|
TESTC_(m_pIRowset->GetData(*pHRow,m_hAccessor,&pData),S_OK);
|
|
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL,NULL), S_OK);
|
|
|
|
PROVIDER_FREE(pHRow);
|
|
*/
|
|
|
|
m_hr = m_pIRowset->RestartPosition(NULL);
|
|
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_(m_pIRowset->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)==TRUE)
|
|
{
|
|
fTestPass=TRUE;
|
|
FreeMemory();
|
|
break;
|
|
}
|
|
FreeMemory();
|
|
}
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow, NULL,NULL,NULL), S_OK);
|
|
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL,NULL), S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL BMK_Forward_Query_Immediate::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(BMK_Static_Query_Buffered)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: BMK_Static_Query_Buffered - BMK_Static_Query_Buffered
|
|
//| Created: 05/09/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL BMK_Static_Query_Buffered::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[5];
|
|
DBPROPID DBPropUnset=DBPROP_OTHERUPDATEDELETE;
|
|
BOOL fTestPass=TEST_SKIPPED;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetLocate;
|
|
rgDBPROPID[2]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[3]=DBPROP_CANSCROLLBACKWARDS;
|
|
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgDBPROPID,
|
|
1,&DBPropUnset,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//we should be on a buffered update mode
|
|
COMPC(BufferedUpdate(), TRUE);
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc call InsertRow insert the last row. Verify IRowsetLocate::GetRowsAt with DBBMK_LAST.
|
|
// @Verify DBPROP_CANHOLDROWS.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int BMK_Static_Query_Buffered::Variation_1()
|
|
{
|
|
void *pData = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
DBBOOKMARK DBBookmark = DBBMK_LAST;
|
|
BYTE *pBookmark = (BYTE *)&DBBookmark;
|
|
HROW hRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
DBROWSTATUS DBRowStatus;
|
|
BOOL fTestPass = FALSE;
|
|
|
|
//make data for insert. Insert the last row
|
|
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. Do not have to call Update yet.
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),S_OK);
|
|
|
|
//Get a new row by IRowsetLocate::GetRowsAt for the last row //we can not hold rows
|
|
if(GetProp(DBPROP_CANHOLDROWS))
|
|
{
|
|
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRow),S_OK);
|
|
}
|
|
else
|
|
{
|
|
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRow),DB_E_ROWSNOTRELEASED);
|
|
}
|
|
|
|
//release the newly inserted row
|
|
TESTC_(m_pIRowset->ReleaseRows(1,&hRow,NULL,NULL,&DBRowStatus),S_OK);
|
|
|
|
COMPARE(DBRowStatus, DBROWSTATUS_S_PENDINGCHANGES);
|
|
hRow=NULL;
|
|
|
|
//call GetRowsAt again for the last row
|
|
if(GetProp(DBPROP_CANHOLDROWS))
|
|
{
|
|
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRow),S_OK);
|
|
}
|
|
else
|
|
{
|
|
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRow),DB_E_ROWSNOTRELEASED);
|
|
|
|
if(!COMPARE(pHRow, NULL))
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//call Update to update the data to the backend
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL, 0, NULL,NULL,NULL,NULL),S_OK);
|
|
|
|
//call GetRowsAt again for the last row
|
|
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,0,1,&cRows,&pHRow),S_OK);
|
|
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow, NULL,NULL,NULL), S_OK);
|
|
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL,NULL), S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL BMK_Static_Query_Buffered::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(BMK_keyset_Cursor_Immediate)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: BMK_keyset_Cursor_Immediate - BMK_keyset_Cursor_Immediate
|
|
//| Created: 05/09/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL BMK_keyset_Cursor_Immediate::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[3];
|
|
BOOL fTestPass=FALSE;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetLocate;
|
|
rgDBPROPID[2]=DBPROP_OTHERUPDATEDELETE;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
ReleaseRowsetAndAccessor();
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Try to set data to the bookmark column. DB_E_ACCESSVIOLATION
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int BMK_keyset_Cursor_Immediate::Variation_1()
|
|
{
|
|
HACCESSOR hAccessor = NULL;
|
|
DBORDINAL ulColToBind=0;
|
|
void *pData = NULL;
|
|
DBCOUNTITEM cBinding;
|
|
DBBINDING *pBinding = NULL;
|
|
DBLENGTH cbRowSize;
|
|
BOOL fTestPass = FALSE;
|
|
DBPROPID rgDBPROPID[3];
|
|
HROW hRow = 1l;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetLocate;
|
|
rgDBPROPID[2]=DBPROP_OTHERUPDATEDELETE;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgDBPROPID,0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//create an accessor on the 0th column
|
|
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, (LONG_PTR *)&ulColToBind),S_OK);
|
|
|
|
if(!(pData=PROVIDER_ALLOC(cbRowSize)))
|
|
goto CLEANUP;
|
|
|
|
//assign the bookmark value to NULL
|
|
// *(DBSTATUS *)(((DWORD)(pData))+pBinding->obStatus)=DBSTATUS_S_ISNULL;
|
|
STATUS_BINDING(*pBinding,pData)=DBSTATUS_S_ISNULL;
|
|
|
|
//set data should fail
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,hAccessor,pData,&hRow),DB_E_ERRORSOCCURRED);
|
|
|
|
COMPARE(hRow,NULL);
|
|
|
|
//verify the status
|
|
if ( GetStatus(pData, pBinding)==DBSTATUS_E_INTEGRITYVIOLATION ||
|
|
GetStatus(pData, pBinding)==DBSTATUS_E_PERMISSIONDENIED
|
|
)
|
|
{
|
|
fTestPass=TRUE;
|
|
}
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
PROVIDER_FREE(pBinding);
|
|
|
|
if(hAccessor)
|
|
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc call InsertRow insert the last row. Verify IRowsetLocate::GetRowsAt with DBBMK_LAST.
|
|
// Verify IRowsetLocate::GetRowsAt with DBBMK_FIRST.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int BMK_keyset_Cursor_Immediate::Variation_2()
|
|
{
|
|
void *pData = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
DBBOOKMARK DBBookmark = DBBMK_FIRST;
|
|
BYTE *pBookmark = (BYTE *)&DBBookmark;
|
|
HROW hRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
BOOL fTestPass = FALSE;
|
|
DBPROPID rgDBPROPID[3];
|
|
HRESULT hr;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetLocate;
|
|
rgDBPROPID[2]=DBPROP_OTHERUPDATEDELETE;
|
|
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgDBPROPID,0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//make data for insert. Insert the last row
|
|
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(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),S_OK);
|
|
|
|
//GetRowsAt returns DB_E_ROWSNOTRELEASED
|
|
if(GetProp(DBPROP_CANHOLDROWS))
|
|
{
|
|
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,m_ulTableRows,1,&cRows,&pHRow),S_OK);
|
|
}
|
|
else
|
|
{
|
|
TESTC_(m_pIRowsetLocate->GetRowsAt(NULL,NULL,1,pBookmark,m_ulTableRows,1,&cRows,&pHRow),DB_E_ROWSNOTRELEASED);
|
|
}
|
|
|
|
//release the newly inserted row
|
|
TESTC_(m_pIRowset->ReleaseRows(1,&hRow,NULL,NULL,NULL),S_OK);
|
|
|
|
hRow=NULL;
|
|
|
|
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_(m_pIRowset->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;
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)m_pData);
|
|
break;
|
|
}
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)m_pData);
|
|
}
|
|
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData);
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow, NULL,NULL,NULL), S_OK);
|
|
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL,NULL), S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc InsertRow Data to insert a middle row. Verify by IRowsetLocate::GetRowsByBookmark
|
|
// Verify by IRowsetLocate::GetRowsByBookmark.Verify DBPROP_CANHOLDROWS
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int BMK_keyset_Cursor_Immediate::Variation_3()
|
|
{
|
|
void *pData =NULL;
|
|
DBBKMARK cbBookmark = 0;
|
|
DBBOOKMARK DBBookmark = DBBMK_LAST;
|
|
BYTE *pLastBookmark = (BYTE *)&DBBookmark;
|
|
BYTE *pBookmark = NULL;
|
|
HROW hRowNew = NULL;
|
|
HROW *pNewHRow = &hRowNew;
|
|
HROW HRow = NULL;
|
|
BOOL fTestPass = FALSE;
|
|
DBPROPID rgDBPROPID[5];
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetLocate;
|
|
rgDBPROPID[2]=DBPROP_OTHERUPDATEDELETE;
|
|
rgDBPROPID[3]=DBPROP_CANHOLDROWS;
|
|
rgDBPROPID[4]=DBPROP_IRowsetIdentity;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,5,rgDBPROPID,0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
odtLog << "1 baloney";
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
odtLog << "2 baloney";
|
|
//make data for insert. Insert the the seond row row
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
odtLog << "3 baloney";
|
|
//insert a new row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,pNewHRow),S_OK);
|
|
|
|
odtLog << "4 baloney";
|
|
//Get a bookmark
|
|
if(S_OK!=GetBookmarkByRow(hRowNew, &cbBookmark, &pBookmark))
|
|
{
|
|
odtLog << "5 baloney";
|
|
// The bookmark column is technically a computed column and some providers may not
|
|
// allow retrieval of computed columns on a newly inserted row.
|
|
if(!GetProperty(DBPROP_SERVERDATAONINSERT, DBPROPSET_ROWSET, m_pIRowset, VARIANT_TRUE))
|
|
{
|
|
odtLog << "6 baloney";
|
|
fTestPass = TRUE;
|
|
}
|
|
goto CLEANUP;
|
|
}
|
|
|
|
odtLog << "7 baloney";
|
|
//Get the row by IRowsetLocate::GetRowsByBookmark
|
|
TESTC_(m_pIRowsetLocate->GetRowsByBookmark(NULL,1,&cbBookmark,(const BYTE **)&pBookmark,&HRow,NULL),S_OK);
|
|
|
|
//GetData
|
|
odtLog << "8 baloney";
|
|
TESTC_(m_pIRowset->GetData(HRow,m_hAccessor,m_pData),S_OK);
|
|
|
|
odtLog << "9 baloney";
|
|
//should be able to see the changes
|
|
if(!CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding, m_pIMalloc,TRUE))
|
|
goto CLEANUP;
|
|
|
|
odtLog << "10 baloney";
|
|
//IsSameRow should return S_OK
|
|
if(StrongIdentity())
|
|
TESTC_(m_pIRowsetIdentity->IsSameRow(HRow, hRowNew),S_OK);
|
|
odtLog << "11 baloney";
|
|
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
//release the bookmark
|
|
PROVIDER_FREE(pBookmark);
|
|
PROVIDER_FREE(pData);
|
|
|
|
if(HRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&HRow, NULL,NULL,NULL), S_OK);
|
|
|
|
if(hRowNew)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRowNew, NULL,NULL,NULL), S_OK);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL BMK_keyset_Cursor_Immediate::Terminate()
|
|
{
|
|
return(TCIRowsetNewRow::Terminate());
|
|
}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(BMK_Dynamic_Cursor_Buffered)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: BMK_Dynamic_Cursor_Buffered - BMK_Dynamic_Cursor_Buffered
|
|
//| Created: 05/09/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL BMK_Dynamic_Cursor_Buffered::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[5];
|
|
BOOL fTestPass=TEST_SKIPPED;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetLocate;
|
|
rgDBPROPID[2]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[3]=DBPROP_CANHOLDROWS;
|
|
rgDBPROPID[4]=DBPROP_OTHERINSERT;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//we should be on a buffered update mode
|
|
COMPC(BufferedUpdate(), TRUE);
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc call InsertRow insert the first row. Verify IRowsetLocate::GetRowsAt with DBBMK_FIRST.
|
|
// Verify IRowsetLocate::GetRowsAt with DBBMK_FIRST.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int BMK_Dynamic_Cursor_Buffered::Variation_1()
|
|
{
|
|
void *pData = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
DBBOOKMARK DBBookmark = DBBMK_FIRST;
|
|
BYTE *pBookmark = (BYTE *)&DBBookmark;
|
|
HROW hRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
BOOL fTestPass = FALSE;
|
|
HRESULT hr;
|
|
|
|
//make data for insert. Insert the first row
|
|
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(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),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;
|
|
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
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_(m_pIRowset->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)==TRUE)
|
|
{
|
|
fTestPass=TRUE;
|
|
FreeMemory();
|
|
break;
|
|
}
|
|
FreeMemory();
|
|
}
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow, NULL,NULL,NULL), S_OK);
|
|
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL,NULL), S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc InsertRow Data to insert a last row. Verify by IRowsetLocate::GetRowsByBookmark
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int BMK_Dynamic_Cursor_Buffered::Variation_2()
|
|
{
|
|
void *pData = NULL;
|
|
DBBKMARK cbBookmark = 0;
|
|
BYTE *pBookmark = NULL;
|
|
HROW HRow = NULL;
|
|
HROW hRowNew = NULL;
|
|
BOOL fTestPass = FALSE;
|
|
|
|
|
|
//make data for insert. Insert the the last row
|
|
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(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRowNew),S_OK);
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&hRowNew,NULL,NULL,NULL),S_OK);
|
|
|
|
// Get a bookmark
|
|
if(S_OK != GetBookmarkByRow(hRowNew, &cbBookmark, &pBookmark))
|
|
{
|
|
// The bookmark column is technically a computed column and some providers may not
|
|
// allow retrieval of computed columns on a newly inserted row.
|
|
if(!GetProperty(DBPROP_SERVERDATAONINSERT, DBPROPSET_ROWSET, m_pIRowset, VARIANT_TRUE))
|
|
fTestPass = TRUE;
|
|
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Get the row by IRowsetLocate::GetRowsByBookmark
|
|
TESTC_(m_pIRowsetLocate->GetRowsByBookmark(NULL,1,&cbBookmark,(const BYTE **)&pBookmark,&HRow,NULL),S_OK);
|
|
|
|
//GetData
|
|
TESTC_(m_pIRowset->GetData(HRow,m_hAccessor,m_pData),S_OK);
|
|
|
|
//should be able to see the changes
|
|
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding, m_pIMalloc,TRUE))
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
//release the bookmark
|
|
PROVIDER_FREE(pBookmark);
|
|
PROVIDER_FREE(pData);
|
|
|
|
if(HRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,&HRow, NULL,NULL,NULL), S_OK);
|
|
}
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL BMK_Dynamic_Cursor_Buffered::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(boundary_keyset_immediate)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: boundary_keyset_immediate - boundary_keyset_immediate
|
|
//| Created: 05/13/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL boundary_keyset_immediate::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[1];
|
|
BOOL fTestPass=FALSE;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
// Test case name is misleading, the cursor is not necessarily keyset
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ALLFROMTBL,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL, ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc hAccessor is NULL accessor and phRow is valid
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int boundary_keyset_immediate::Variation_1()
|
|
{
|
|
|
|
HACCESSOR hAccessor = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
HROW HRow = NULL;
|
|
HROW *pHRow = &HRow;
|
|
BOOL fTestPass = FALSE;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,DB_NULL_HACCESSOR,NULL,NULL),DB_E_BADACCESSORHANDLE);
|
|
|
|
//create a NULL accessor
|
|
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,&hAccessor,NULL),S_OK);
|
|
|
|
//hAccessor is NULL accessor and phRow is valid
|
|
m_hr=m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,hAccessor,NULL,NULL);
|
|
|
|
if(E_FAIL == m_hr || DB_E_INTEGRITYVIOLATION == m_hr)
|
|
{
|
|
|
|
//hAccessor is NULL accessor and phRow is valid
|
|
m_hr = m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,hAccessor,NULL,&HRow);
|
|
|
|
if(!(E_FAIL == m_hr || DB_E_INTEGRITYVIOLATION == m_hr))
|
|
goto CLEANUP;
|
|
|
|
//no row handle should be returned.
|
|
COMPARE(HRow, NULL);
|
|
|
|
//try to get the last row handle
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,1,1,&cRows,&pHRow),S_OK)
|
|
|
|
fTestPass=TRUE;
|
|
|
|
}
|
|
else
|
|
{
|
|
//m_hr has to be S_OK.
|
|
TESTC_(m_hr, S_OK);
|
|
|
|
//hAccessor is NULL accessor and phRow is valid
|
|
m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,hAccessor,NULL,&HRow);
|
|
|
|
if(HRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&HRow,NULL,NULL,NULL),S_OK);
|
|
|
|
HRow=NULL;
|
|
|
|
hr = m_pIRowset->RestartPosition(NULL);
|
|
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
|
|
goto CLEANUP;
|
|
|
|
//try to get the last row handle
|
|
if(CHECK(m_pIRowset->GetNextRows(NULL,m_ulTableRows,1,&cRows,&pHRow),S_OK))
|
|
fTestPass=TRUE;
|
|
}
|
|
|
|
CLEANUP:
|
|
if(hAccessor)
|
|
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
|
|
|
|
if(HRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &HRow, NULL,NULL,NULL),S_OK);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc hAccessor is NULL accessor and phRow is NULL.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int boundary_keyset_immediate::Variation_2()
|
|
{
|
|
HACCESSOR hAccessor=NULL;
|
|
BOOL fTestPass=FALSE;
|
|
|
|
//create a NULL accessor
|
|
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,&hAccessor,NULL),S_OK);
|
|
|
|
//null accessor, pdata=NULL, and pHRow=NULL
|
|
m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,hAccessor,NULL,NULL);
|
|
|
|
//call again
|
|
m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,hAccessor,NULL,NULL);
|
|
|
|
fTestPass=TRUE;
|
|
|
|
|
|
CLEANUP:
|
|
if(hAccessor)
|
|
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
|
|
|
|
if(fTestPass)
|
|
return TEST_PASS;
|
|
else
|
|
return TEST_FAIL;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc hAccessor is valid accessor and phRow is valid. pData is NULL. E_INVALIDARG
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int boundary_keyset_immediate::Variation_3()
|
|
{
|
|
HROW hRow = 1;
|
|
BOOL fTestPass = FALSE;
|
|
|
|
|
|
//hAccessor is valid and pHRow is valid
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,NULL,&hRow),E_INVALIDARG);
|
|
|
|
//the row handle should not be touched
|
|
if(COMPARE(hRow, NULL))
|
|
fTestPass=TRUE;
|
|
|
|
|
|
CLEANUP:
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow,NULL,NULL,NULL),S_OK);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc test DB_E_ROWSNOTRELEASED.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int boundary_keyset_immediate::Variation_4()
|
|
{
|
|
|
|
BOOL fTestPass = FALSE;
|
|
DBCOUNTITEM cRows = 0;
|
|
void *pData = NULL;
|
|
HROW hRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//restartposition
|
|
hr = m_pIRowset->RestartPosition(NULL);
|
|
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
|
|
goto CLEANUP;
|
|
|
|
//get the data for insert
|
|
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 first
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,2,1,&cRows,&pHRow),S_OK);
|
|
|
|
//insert should return DB_E_ROWSNOTRELEASED
|
|
if(GetProp(DBPROP_CANHOLDROWS))
|
|
{
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),S_OK);
|
|
}
|
|
else
|
|
{
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),DB_E_ROWSNOTRELEASED);
|
|
|
|
//no row should be returned
|
|
if(!COMPARE(hRow, NULL))
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1, pHRow, NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
|
|
//insert
|
|
if(!GetProp(DBPROP_CANHOLDROWS))
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow), S_OK);
|
|
|
|
//get next rows should fail
|
|
if(!GetProp(DBPROP_CANHOLDROWS))
|
|
{
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows,&pHRow),DB_E_ROWSNOTRELEASED);
|
|
//no rows should be returned
|
|
if(!COMPARE(pHRow, NULL))
|
|
goto CLEANUP;
|
|
}
|
|
else
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,3,1,&cRows,&pHRow),S_OK);
|
|
|
|
|
|
|
|
//release the row
|
|
TESTC_(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
hRow=NULL;
|
|
|
|
//GetNextRows
|
|
if(CHECK(m_pIRowset->GetNextRows(NULL, 0, 1, &cRows, &pHRow),S_OK))
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
//release the memory
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
//release the row handle
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1, pHRow, NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc hChapter ignored
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int boundary_keyset_immediate::Variation_5()
|
|
{
|
|
BOOL fTestPass = FALSE;
|
|
ULONG cRows = 0;
|
|
void *pData = NULL;
|
|
HROW hRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//restartposition
|
|
hr = m_pIRowset->RestartPosition(NULL);
|
|
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//get the data for insert
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
TESTC_(m_pIRowsetChange->InsertRow(1,m_hAccessor,pData,&hRow),S_OK);
|
|
|
|
fTestPass = TRUE;
|
|
CLEANUP:
|
|
//release the memory
|
|
if(pData)
|
|
{
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
}
|
|
//release the row handle
|
|
if(hRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
}
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL boundary_keyset_immediate::Terminate()
|
|
{
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(boundary_keyset_buffered)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: boundary_keyset_buffered - boundary_keyset_buffered
|
|
//| Created: 05/13/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL boundary_keyset_buffered::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[2];
|
|
BOOL fTestPass=TEST_SKIPPED;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetUpdate;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
// Test case name is misleading, the cursor is not necessarily keyset
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//we should be on a buffered update mode
|
|
COMPC(BufferedUpdate(), TRUE);
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc hAccessor is NULL accessor and phRow is valid.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int boundary_keyset_buffered::Variation_1()
|
|
{
|
|
HACCESSOR hAccessor=NULL;
|
|
HROW hRow=NULL;
|
|
void *pData=&hRow; //pData points to invalid data
|
|
BOOL fTestPass=FALSE;
|
|
|
|
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,DB_NULL_HACCESSOR,NULL,NULL),DB_E_BADACCESSORHANDLE);
|
|
|
|
//create a NULL accessor
|
|
TESTC_(m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,&hAccessor,NULL),S_OK);
|
|
|
|
//hAccessor is NULL accessor and phRow is valid
|
|
m_hr=m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,hAccessor,pData,&hRow);
|
|
|
|
//update
|
|
m_hr=m_pIRowsetUpdate->Update(NULL,1,&hRow,NULL,NULL,NULL);
|
|
|
|
m_hr=m_pIRowsetUpdate->Undo(NULL,1,&hRow,NULL,NULL,NULL);
|
|
|
|
fTestPass=TRUE;
|
|
CLEANUP:
|
|
if(hAccessor)
|
|
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow,NULL,NULL,NULL),S_OK);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc hAccessor is NULL accessor and phRow is NULL.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int boundary_keyset_buffered::Variation_2()
|
|
{
|
|
|
|
BOOL fTestPass=FALSE;
|
|
void *pData=NULL;
|
|
|
|
//get the data for insert
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert should return S_OK
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,NULL), S_OK);
|
|
|
|
//update
|
|
if(CHECK(m_pIRowsetUpdate->Update(NULL,0,NULL,NULL, NULL, NULL),S_OK))
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
//release the memory
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// }}
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL boundary_keyset_buffered::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Invalid_Keyset_Cursor_Immediate)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Invalid_Keyset_Cursor_Immediate - Invalid_Keyset_Cursor_Immediate
|
|
//| Created: 05/13/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Invalid_Keyset_Cursor_Immediate::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[2];
|
|
BOOL fTestPass=FALSE;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_CANHOLDROWS;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
// Test case name is misleading, the cursor is not necessarily keyset
|
|
//create a rowset
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,NO_ACCESSOR));
|
|
|
|
m_cColNumber = GetNotUpdatable();
|
|
m_cColUpdatable = GetFirstUpdatable();
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc The accessor is DBACCESSOR_READ | DBACCCESOR_ROWDATA. DB_E_READONLYACCESSOR.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Invalid_Keyset_Cursor_Immediate::Variation_1()
|
|
{
|
|
DBORDINAL ulColsToBind = 1;
|
|
HROW *pHRow = NULL;
|
|
HROW hRow = NULL;
|
|
void *pData = NULL;
|
|
BOOL fTestPass = FALSE;
|
|
|
|
ulColsToBind=GetLongAndUpdatable();
|
|
|
|
if(ulColsToBind==0)
|
|
{
|
|
fTestPass=TRUE;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//create an accessor that has length binding length only binding is disabled by the spec except for long data
|
|
if(!GetAccessorOnRowset(ON_ROWSET_ACCESSOR, TRUE,DBACCESSOR_ROWDATA,DBPART_LENGTH,
|
|
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,
|
|
1,&ulColsToBind))
|
|
goto CLEANUP;
|
|
|
|
fTestPass=TRUE;
|
|
CLEANUP:
|
|
//release the memory
|
|
PROVIDER_FREE(pData);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1, pHRow, NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
//release the accessor handle
|
|
ReleaseAccessorOnRowset();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Try to set an auto increment column.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Invalid_Keyset_Cursor_Immediate::Variation_2()
|
|
{
|
|
|
|
DBORDINAL rgColsToBind[2] = {1, 1};
|
|
HROW *pHRow = NULL;
|
|
IRowsetInfo *pIRowsetInfo = NULL;
|
|
ICommand *pICommand = NULL;
|
|
HROW hRow = NULL;
|
|
void *pData = NULL;
|
|
IUnknown *pIUnknown = NULL;
|
|
BOOL fTestPass = TRUE;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
//test pass if all columns are updatable
|
|
if(m_cColNumber==0 || m_cColUpdatable==0)
|
|
{
|
|
return TEST_SKIPPED;
|
|
}
|
|
//Set up columns to update
|
|
rgColsToBind[0]=m_cColUpdatable;
|
|
rgColsToBind[1]=m_cColNumber;
|
|
|
|
//reexecute the command so that we can have an accessor on the command to share
|
|
if(!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,rgColsToBind))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
fTestPass = FALSE;
|
|
//get some data to insert
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//get a copy of the original data
|
|
memcpy(m_pData, pData, (size_t)m_cRowSize);
|
|
|
|
if(m_bIndexExists)
|
|
{
|
|
//insert should fail
|
|
hr = m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow);
|
|
|
|
if (hr == DB_E_INTEGRITYVIOLATION)
|
|
{
|
|
//no row should be inserted
|
|
if(!COMPARE(hRow, NULL))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
else if (hr == DB_S_ERRORSOCCURRED)
|
|
{
|
|
//the status of the set columns should be success
|
|
if(!COMPARE(GetStatus(pData, &(m_rgBinding[0])), DBSTATUS_S_OK))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//Check status for the non-updatable column
|
|
if(!COMPARE(GetStatus(pData, &(m_rgBinding[1])),DBSTATUS_E_INTEGRITYVIOLATION))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//a row should be inserted
|
|
if(!COMPARE(hRow!=NULL, TRUE))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
}
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
if(pHRow)
|
|
{
|
|
CHECK(((IRowset *)(pIUnknown))->ReleaseRows(1,pHRow, NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
|
|
SAFE_RELEASE(pIUnknown);
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
SAFE_RELEASE(pICommand);
|
|
|
|
//release the row handle
|
|
if(hRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
}
|
|
|
|
//release the accessor handle
|
|
FreeMemory();
|
|
ReleaseAccessorOnRowset();
|
|
PROVIDER_FREE(pData);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @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_3()
|
|
{
|
|
HROW hRow = NULL;
|
|
HACCESSOR hAccessor = NULL;
|
|
DBBINDSTATUS * prgDBBindStatus = NULL;
|
|
void *pData = NULL;
|
|
BOOL fTestPass = TRUE;
|
|
|
|
//create an accessor which binds to all the updatale columns
|
|
if(!GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
|
|
UPDATEABLE_COLS_BOUND))
|
|
goto CLEANUP;
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// Allocate binding status array
|
|
SAFE_ALLOC(prgDBBindStatus, DBBINDSTATUS, m_cBinding);
|
|
|
|
//get some data to insert
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
fTestPass = FALSE;
|
|
//change to column number of the last binding structure
|
|
m_rgBinding[m_cBinding-1].iOrdinal=m_cBinding+100;
|
|
|
|
//create an accessor
|
|
if(FAILED(m_hr=m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,m_cBinding, m_rgBinding, 0,&hAccessor,prgDBBindStatus)))
|
|
{
|
|
COMPARE(m_hr, DB_E_ERRORSOCCURRED);
|
|
COMPARE(prgDBBindStatus[m_cBinding-1],DBBINDSTATUS_BADORDINAL);
|
|
fTestPass=TRUE;
|
|
hRow=NULL;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//insert should fail
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,hAccessor,pData,&hRow),DB_E_BADORDINAL);
|
|
|
|
//no row should be inserted
|
|
if(COMPARE(hRow, NULL))
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
//release the memory
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
//release the row handle
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
//release the accessor handle
|
|
if(hAccessor)
|
|
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL), S_OK);
|
|
|
|
//release the accessor handle
|
|
ReleaseAccessorOnRowset();
|
|
|
|
SAFE_FREE(prgDBBindStatus);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc The accessor sets the status field of non nullable columns NULL. DB_E_SCHENMAVIOLATION.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Invalid_Keyset_Cursor_Immediate::Variation_4()
|
|
{
|
|
DBORDINAL *rgColsToBind = NULL;
|
|
DBORDINAL cColNumber = 0;
|
|
HROW hRow = NULL;
|
|
void *pData = NULL;
|
|
BOOL fTestPass = TRUE;
|
|
|
|
//get updatble and not nullable columns
|
|
if(!GetNotNullableAndUpdatable(&cColNumber,&rgColsToBind))
|
|
goto CLEANUP;
|
|
|
|
//create an accessor which binds to all updatble
|
|
//but not nullable columns
|
|
if(!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,
|
|
cColNumber,rgColsToBind))
|
|
goto CLEANUP;
|
|
|
|
fTestPass = FALSE;
|
|
//get some data to insert
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//make the last column to NULL
|
|
// *(DBSTATUS *)(((DWORD)pData)+m_rgBinding[m_cBinding-1].obStatus)=DBSTATUS_S_ISNULL;
|
|
STATUS_BINDING(m_rgBinding[m_cBinding-1],pData)=DBSTATUS_S_ISNULL;
|
|
|
|
//insert should fail
|
|
m_hr=m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow);
|
|
|
|
// three possibilites
|
|
if (m_hr == DB_E_INTEGRITYVIOLATION)
|
|
{
|
|
// Provider detects the integrityviolation but is unable to detect the binding that caused it
|
|
// and rejects the insert
|
|
fTestPass = COMPARE(hRow, NULL);
|
|
}
|
|
else if (m_hr == DB_E_ERRORSOCCURRED)
|
|
{
|
|
// Provider detects the integrityviolation and detects the binding that caused it
|
|
// and rejects the insert
|
|
if(COMPARE(GetStatus(pData, &(m_rgBinding[m_cBinding-1])), DBSTATUS_E_INTEGRITYVIOLATION) ||
|
|
COMPARE(GetStatus(pData, &(m_rgBinding[m_cBinding-1])), DBSTATUS_E_PERMISSIONDENIED))
|
|
fTestPass=TRUE;
|
|
|
|
COMPARE(hRow, NULL);
|
|
}
|
|
else if (m_hr == DB_S_ERRORSOCCURRED)
|
|
{
|
|
// Provider detects the integrityviolation and detects the binding that caused it
|
|
// but inserts the row as if the bad bindings had not been made
|
|
if(COMPARE(GetStatus(pData, &(m_rgBinding[m_cBinding-1])), DBSTATUS_E_INTEGRITYVIOLATION) ||
|
|
COMPARE(GetStatus(pData, &(m_rgBinding[m_cBinding-1])), DBSTATUS_E_PERMISSIONDENIED))
|
|
fTestPass=TRUE;
|
|
|
|
COMPARE(hRow!=NULL, TRUE);
|
|
}
|
|
else
|
|
TESTC_(m_hr, DB_E_INTEGRITYVIOLATION); // raise an error, if none of the 3 above cases apply.
|
|
|
|
|
|
CLEANUP:
|
|
//release the memory
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
PROVIDER_FREE(rgColsToBind);
|
|
|
|
//release the row handle
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
|
|
//release the accessor handle
|
|
ReleaseAccessorOnRowset();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc The accessor only has status binding for DBSTATUS_S_OK.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Invalid_Keyset_Cursor_Immediate::Variation_5()
|
|
{
|
|
|
|
ULONG cCount;
|
|
HROW hRow = NULL;
|
|
void *pData = NULL;
|
|
BOOL fTestPass = TRUE;
|
|
|
|
//create an accessor that only has status binding
|
|
if(!GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_STATUS,UPDATEABLE_COLS_BOUND))
|
|
{
|
|
hRow=NULL;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//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;
|
|
}
|
|
|
|
fTestPass = FALSE;
|
|
//insert should fail
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),DB_E_ERRORSOCCURRED);
|
|
|
|
for(cCount=0; cCount<m_cBinding; cCount++)
|
|
{
|
|
if(!COMPARE(GetStatus(pData, &(m_rgBinding[cCount])),DBSTATUS_E_UNAVAILABLE))
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//no row should be inserted
|
|
if(COMPARE(hRow, NULL))
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
//release the memory
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
//release the row handle
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
//release the accessor handle
|
|
ReleaseAccessorOnRowset();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(6)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set a duplicate column on which a unique index is created. DB_E_INTEGRITYVIOLATION. No data is changed.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Invalid_Keyset_Cursor_Immediate::Variation_6()
|
|
{
|
|
DBORDINAL ulColsToBind = 1;
|
|
HROW hRow = NULL;
|
|
void *pData = NULL;
|
|
BOOL fTestPass = TRUE;
|
|
HRESULT hr = S_OK;
|
|
|
|
//create an accessor which binds to 1st column
|
|
if(!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,&ulColsToBind))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass = FALSE;
|
|
//get some data to insert
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//copy the old data
|
|
if(!memcpy(m_pData, pData, (size_t)m_cRowSize))
|
|
goto CLEANUP;
|
|
|
|
if(m_bIndexExists)
|
|
{
|
|
//insert could pass or return DB_E_INTEGRITYVIOLATION if a not null column in not bound
|
|
hr=m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow);
|
|
|
|
if (S_OK!=hr&&DB_E_INTEGRITYVIOLATION!=hr)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//2nd insert should fail with INTEGRITYVIOLATION becuase of inserting duplicate column
|
|
//or because a not null column in not bound
|
|
hr=m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow);
|
|
|
|
//set the status of the buffers to the same so the compare below is equal
|
|
//since this is a error that is not ERRORSOCCURED it is undefined what is in the stauts part
|
|
//of the buffer
|
|
// *(DBSTATUS *)((DWORD)m_pData+m_rgBinding[0].obStatus)=DBSTATUS_S_OK;
|
|
// *(DBSTATUS *)((DWORD)pData+m_rgBinding[0].obStatus)=DBSTATUS_S_OK;
|
|
STATUS_BINDING(m_rgBinding[0],m_pData)=DBSTATUS_S_OK;
|
|
STATUS_BINDING(m_rgBinding[0],pData)=DBSTATUS_S_OK;
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),DB_E_INTEGRITYVIOLATION);
|
|
|
|
//set the status of the buffers to the same so the compare below is equal
|
|
//since this is a error that is not ERRORSOCCURED it is undefined what is in the stauts part
|
|
//of the buffer
|
|
// *(DBSTATUS *)((DWORD)m_pData+m_rgBinding[0].obStatus)=DBSTATUS_S_OK;
|
|
// *(DBSTATUS *)((DWORD)pData+m_rgBinding[0].obStatus)=DBSTATUS_S_OK;
|
|
STATUS_BINDING(m_rgBinding[0],m_pData)=DBSTATUS_S_OK;
|
|
STATUS_BINDING(m_rgBinding[0],pData)=DBSTATUS_S_OK;
|
|
|
|
//no data should be changed
|
|
if(!COMPARE(memcmp(m_pData, pData, (size_t)m_cRowSize), 0))
|
|
goto CLEANUP;
|
|
|
|
//no row should be inserted
|
|
if(COMPARE(hRow, NULL))
|
|
fTestPass=TRUE;
|
|
}
|
|
else
|
|
{
|
|
//insert should succeed
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),S_OK);
|
|
|
|
fTestPass=TRUE;
|
|
}
|
|
|
|
|
|
CLEANUP:
|
|
//release the memory
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
//release the row handle
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
|
|
//release the accessor handle
|
|
ReleaseAccessorOnRowset();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(7)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc The accessor is a parameter accessor. DB_E_BADACCESSORTYPE.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Invalid_Keyset_Cursor_Immediate::Variation_7()
|
|
{
|
|
DBORDINAL ulColsToBind = 1;
|
|
HROW hRow = DB_NULL_HROW;
|
|
void *pData = NULL;
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
DBPROPID rgDBPROPID[3];
|
|
HRESULT hr;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_OTHERUPDATEDELETE;
|
|
rgDBPROPID[2]=DBPROP_IRowsetLocate;
|
|
|
|
if(!m_pIDBCreateCommand)
|
|
{
|
|
return TEST_SKIPPED; // This variation relies on creating on accessor off the command object.
|
|
}
|
|
//release the rowset
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
//create a rowset
|
|
if (S_OK != GetRowsetAndAccessor(SELECT_ALLFROMTBL,3,rgDBPROPID,0,NULL,ON_COMMAND_ACCESSOR, TRUE,
|
|
DBACCESSOR_PARAMETERDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
|
|
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF,DBTYPE_EMPTY,
|
|
1,&ulColsToBind,NO_COLS_OWNED_BY_PROV,DBPARAMIO_INPUT))
|
|
{
|
|
hRow = NULL;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass = FALSE;
|
|
//get some data to insert
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert should fail
|
|
hr = m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow);
|
|
|
|
//DB_E_INVALIDACCESSOR could be ok here if the rowset chooses not to inherit the parameter accessor from the
|
|
//command object
|
|
if( DB_E_BADACCESSORTYPE != hr &&
|
|
DB_E_BADACCESSORHANDLE != hr)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//no row should be inserted
|
|
if(COMPARE(hRow, NULL))
|
|
{
|
|
fTestPass=TRUE;
|
|
}
|
|
CLEANUP:
|
|
//release the memory
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
//release the row handle
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
//release the accessor handle
|
|
ReleaseAccessorOnRowset();
|
|
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// }}
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Invalid_Keyset_Cursor_Immediate::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Invalid_Keyset_Query_Immediate)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Invalid_Keyset_Query_Immediate - Invalid_Keyset_Query_Immediate
|
|
//| Created: 05/13/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Invalid_Keyset_Query_Immediate::Init()
|
|
{
|
|
BOOL fTestPass=FALSE;
|
|
DBPROPID rgDBPROPID[2];
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetLocate;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
// TestCase name is misleading since the cursor is not necessarily keyset
|
|
//create a rowset and a accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC, NUMELEM(rgDBPROPID), rgDBPROPID,0,NULL,NO_ACCESSOR));
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc The accessor is DBACCCESOR_PASSCOLUMNSBYREF. DB_E_READONLYACCESSOR
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Invalid_Keyset_Query_Immediate::Variation_1()
|
|
{
|
|
return TEST_PASS;
|
|
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc The status flag specified in a binding structure is neither DBSTATUS_S_OK nor DBSTATUS_S_ISNULL. DB_E_BADSTATUSVALU
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Invalid_Keyset_Query_Immediate::Variation_2()
|
|
{
|
|
HROW hRow=DB_NULL_HROW;
|
|
ULONG cCount;
|
|
void *pData=NULL;
|
|
BOOL fTestPass=TRUE;
|
|
HRESULT hr = S_OK;
|
|
|
|
//create an accessor which binds to all updatable columns
|
|
if(!GetAccessorOnRowset(ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND))
|
|
goto CLEANUP;
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
fTestPass = FALSE;
|
|
//get some data to insert
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//change the status of columns binding
|
|
// *(DBSTATUS *)((DWORD)pData+m_rgBinding[m_cBinding-1].obStatus)=DBSTATUS_E_INTEGRITYVIOLATION;
|
|
STATUS_BINDING(m_rgBinding[m_cBinding-1],pData)=DBSTATUS_E_INTEGRITYVIOLATION;
|
|
|
|
//insert should fail
|
|
hr = m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow);
|
|
|
|
if ( hr != DB_S_ERRORSOCCURRED && hr != DB_E_ERRORSOCCURRED )
|
|
{
|
|
fTestPass = TEST_FAIL;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//check the status for other data
|
|
for(cCount=0; cCount<m_cBinding; cCount++)
|
|
{
|
|
if(cCount==(m_cBinding-1))
|
|
continue;
|
|
if ( hr == DB_E_ERRORSOCCURRED )
|
|
{
|
|
if(!COMPARE(GetStatus(pData, &(m_rgBinding[cCount])), DBSTATUS_E_UNAVAILABLE))
|
|
goto CLEANUP;
|
|
}
|
|
else
|
|
{
|
|
if (GetStatus(pData, &(m_rgBinding[cCount])) != DBSTATUS_S_OK &&
|
|
GetStatus(pData,&(m_rgBinding[cCount])) != DBSTATUS_S_ISNULL )
|
|
goto CLEANUP;
|
|
|
|
COMPC(hRow==DB_NULL_HROW, FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
if(COMPARE(GetStatus(pData, &(m_rgBinding[m_cBinding-1])), DBSTATUS_E_BADSTATUS))
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
//release the memory
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
//release the row handle
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
|
|
//release the accessor handle
|
|
ReleaseAccessorOnRowset();
|
|
|
|
if(fTestPass)
|
|
return TEST_PASS;
|
|
else
|
|
return TEST_FAIL;
|
|
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc The accessor only has length binding. E_FAIL
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Invalid_Keyset_Query_Immediate::Variation_3()
|
|
{
|
|
ULONG cCount = 0;
|
|
HROW hRow = NULL;
|
|
void *pData = NULL;
|
|
BOOL fTestPass = TRUE;
|
|
HRESULT hr = E_FAIL;
|
|
DBORDINAL cRowsInTableBeforeInsert= 0;
|
|
DBORDINAL cRowsInTableAfterInsert = 0;
|
|
|
|
//create an accessor that has length binding
|
|
if(!GetAccessorOnRowset(ON_ROWSET_ACCESSOR, FALSE,DBACCESSOR_ROWDATA,DBPART_LENGTH,UPDATEABLE_COLS_BOUND))
|
|
goto CLEANUP;
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
if(!(pData=PROVIDER_ALLOC(m_cRowSize)))
|
|
goto CLEANUP;
|
|
|
|
fTestPass = FALSE;
|
|
//mark the bogus length information
|
|
for(cCount=0; cCount<m_cBinding; cCount++)
|
|
{
|
|
// *(ULONG *)((DWORD)pData+m_rgBinding[cCount].obLength)=2;
|
|
LENGTH_BINDING(m_rgBinding[cCount],pData)=2;
|
|
}
|
|
cRowsInTableBeforeInsert = m_pTable->CountRowsOnTable();
|
|
hr = m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow);
|
|
cRowsInTableAfterInsert = m_pTable->CountRowsOnTable();
|
|
|
|
if (hr==DB_E_ERRORSOCCURRED)
|
|
{
|
|
// check count of rows
|
|
COMPC(cRowsInTableBeforeInsert,cRowsInTableAfterInsert);
|
|
|
|
//The row handle should be NULL
|
|
COMPC(hRow, NULL);
|
|
}
|
|
else if (hr==DB_S_ERRORSOCCURRED)
|
|
{
|
|
// check row was added
|
|
COMPC(cRowsInTableBeforeInsert+1,cRowsInTableAfterInsert);
|
|
|
|
//no row should be inserted
|
|
COMPC(hRow!=NULL, TRUE);
|
|
}
|
|
else
|
|
TESTC_(hr, DB_E_ERRORSOCCURRED); // generate error
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
//release the memory
|
|
PROVIDER_FREE(pData);
|
|
|
|
//release the row handle
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
//release the accessor handle
|
|
ReleaseAccessorOnRowset();
|
|
|
|
if(fTestPass)
|
|
return TEST_PASS;
|
|
else
|
|
return TEST_FAIL;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc The iOrdinal is out of range.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Invalid_Keyset_Query_Immediate::Variation_4()
|
|
{
|
|
HROW hRow =1;
|
|
HACCESSOR hAccessor =NULL;
|
|
DBBINDSTATUS * prgDBBindStatus = NULL;
|
|
void *pData =NULL;
|
|
BOOL fTestPass =TRUE;
|
|
|
|
//create an accessor which binds to all the updatale columns
|
|
if(!GetAccessorOnRowset(ON_ROWSET_ACCESSOR, TRUE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
|
|
UPDATEABLE_COLS_BOUND))
|
|
{
|
|
hRow=NULL;
|
|
goto CLEANUP;
|
|
}
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// Allocate binding status array
|
|
SAFE_ALLOC(prgDBBindStatus, DBBINDSTATUS, m_cBinding);
|
|
|
|
|
|
fTestPass = FALSE;
|
|
//get some data to insert
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//change to column number of the last binding structure
|
|
m_rgBinding[m_cBinding-1].iOrdinal=m_cBinding+100;
|
|
|
|
//create an accessor
|
|
if(FAILED(m_hr=m_pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,m_cBinding, m_rgBinding, 0,&hAccessor,prgDBBindStatus)))
|
|
{
|
|
COMPARE(m_hr, DB_E_ERRORSOCCURRED);
|
|
COMPARE(prgDBBindStatus[m_cBinding-1],DBBINDSTATUS_BADORDINAL);
|
|
hRow=NULL;
|
|
fTestPass=TRUE;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
|
|
//insert should fail
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,hAccessor,pData,&hRow),DB_E_BADORDINAL);
|
|
|
|
//no row should be inserted
|
|
if(COMPARE(hRow, NULL))
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
//release the memory
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
//release the row handle
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
//release the accessor handle
|
|
if(hAccessor)
|
|
CHECK(m_pIAccessor->ReleaseAccessor(hAccessor,NULL), S_OK);
|
|
|
|
//release the accessor handle
|
|
ReleaseAccessorOnRowset();
|
|
|
|
SAFE_FREE(prgDBBindStatus);
|
|
|
|
if(fTestPass)
|
|
return TEST_PASS;
|
|
else
|
|
return TEST_FAIL;
|
|
|
|
}
|
|
// }}
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Invalid_Keyset_Query_Immediate::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Valid_Keyset_Cursor_Immediate)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Valid_Keyset_Cursor_Immediate - Valid_Keyset_Cursor_Immediate
|
|
//| Created: 05/14/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Valid_Keyset_Cursor_Immediate::Init()
|
|
{
|
|
BOOL fTestPass=FALSE;
|
|
ULONG cBinding;
|
|
IConvertType *pIConvertType = NULL;
|
|
|
|
m_rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
m_cDBPROPID=1;
|
|
|
|
m_fCanConvertFromArray = TRUE;
|
|
m_fCanConvertFromVector = TRUE;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//The cursor does not have to be keyset
|
|
//create a rowset
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cDBPROPID,m_rgDBPROPID,0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND,FORWARD,NO_COLS_BY_REF));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
if(!VerifyInterface(m_pIRowset, IID_IConvertType,
|
|
ROWSET_INTERFACE,(IUnknown **)&pIConvertType))
|
|
goto CLEANUP;
|
|
|
|
for ( cBinding = 0; cBinding < m_cBinding; cBinding++ )
|
|
{
|
|
m_fCanConvertFromArray &= ( S_OK == pIConvertType->CanConvert( m_rgBinding[cBinding].wType | DBTYPE_ARRAY,
|
|
m_rgBinding[cBinding].wType, DBCONVERTFLAGS_COLUMN));
|
|
m_fCanConvertFromVector &= ( S_OK == pIConvertType->CanConvert( m_rgBinding[cBinding].wType | DBTYPE_VECTOR,
|
|
m_rgBinding[cBinding].wType, DBCONVERTFLAGS_COLUMN));
|
|
}
|
|
|
|
TESTC_(m_pTable->DeleteRows(ALLROWS), S_OK);
|
|
TESTC_(m_pTable->Insert(PRIMARY, 1, g_ulRowCount), S_OK);
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIConvertType);
|
|
ReleaseRowsetAndAccessor();
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Insert the variable length columns, in forward order of the rowset. Value & length binding only.
|
|
//
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Valid_Keyset_Cursor_Immediate::Variation_1()
|
|
{
|
|
HROW hRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
void *pData = NULL;
|
|
BOOL fTestPass = FALSE;
|
|
HRESULT hr;
|
|
|
|
//open a rowset.
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cDBPROPID,m_rgDBPROPID,0,NULL,NO_ACCESSOR));
|
|
|
|
//value and length binding only
|
|
if(!GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_LENGTH,UPDATEABLE_COLS_BOUND,
|
|
FORWARD,NO_COLS_BY_REF, DBTYPE_EMPTY))
|
|
goto CLEANUP;
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//make data for insert
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert should be successful
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),S_OK);
|
|
|
|
//hRow should not be NULL
|
|
if(!hRow)
|
|
goto CLEANUP;
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
hRow=NULL;
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
//get the rowset again
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cDBPROPID,m_rgDBPROPID,0,NULL,ON_ROWSET_ACCESSOR,
|
|
TRUE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_LENGTH,UPDATEABLE_COLS_BOUND,
|
|
FORWARD,NO_COLS_BY_REF, DBTYPE_EMPTY))
|
|
goto CLEANUP;
|
|
|
|
|
|
// the insert should be visible
|
|
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_(m_pIRowset->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;
|
|
FreeMemory();
|
|
break;
|
|
}
|
|
FreeMemory();
|
|
}
|
|
|
|
CLEANUP:
|
|
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1, pHRow, NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Insert the fixed length columns with only value binding.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Valid_Keyset_Cursor_Immediate::Variation_2()
|
|
{
|
|
DBORDINAL *rgColsToBind = NULL;
|
|
DBORDINAL cColsNumber = 0;
|
|
HROW hRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
void *pData = NULL;
|
|
BOOL fTestPass = TRUE;
|
|
HRESULT hr;
|
|
|
|
|
|
//open a rowset.
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cDBPROPID,m_rgDBPROPID,0,NULL,NO_ACCESSOR));
|
|
|
|
//Binds to all fixed length columns.
|
|
if(!GetFixedLengthAndUpdatable(&cColsNumber,&rgColsToBind))
|
|
goto CLEANUP;
|
|
|
|
//value binding only
|
|
// Need status bound as well to avoid accessing data when it is NULL.
|
|
if(!GetAccessorOnRowset(ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS,USE_COLS_TO_BIND_ARRAY,
|
|
FORWARD,NO_COLS_BY_REF, DBTYPE_EMPTY, cColsNumber, rgColsToBind))
|
|
goto CLEANUP;
|
|
|
|
//make data for insert
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
fTestPass = FALSE;
|
|
|
|
//insert a row. Do not care about the result. It could possiblly fail.
|
|
m_hr=m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow);
|
|
|
|
if(FAILED(m_hr))
|
|
{
|
|
if(!CHECK(m_hr, DB_E_ERRORSOCCURRED))
|
|
goto CLEANUP;
|
|
if(!COMPARE(hRow, NULL))
|
|
goto CLEANUP;
|
|
fTestPass=TRUE;
|
|
goto CLEANUP;
|
|
|
|
}
|
|
|
|
//hRow should not be NULL
|
|
if(!hRow)
|
|
goto CLEANUP;
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
hRow=NULL;
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
//get the rowset again (but use status and length bindings)
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cDBPROPID,m_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))
|
|
goto CLEANUP;
|
|
|
|
// the insert should be visible
|
|
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_(m_pIRowset->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;
|
|
FreeMemory();
|
|
break;
|
|
}
|
|
FreeMemory();
|
|
}
|
|
|
|
|
|
|
|
CLEANUP:
|
|
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
PROVIDER_FREE(rgColsToBind);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1, pHRow, NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc DBTYPE_BYREF binding for all columns.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Valid_Keyset_Cursor_Immediate::Variation_3()
|
|
{
|
|
void *pData = NULL;
|
|
void *pValidationData= NULL;
|
|
BOOL fTestPass = TRUE;
|
|
DBBINDING *rgBinding = NULL;
|
|
DBORDINAL cCol = 0;
|
|
HROW *pHRow = NULL;
|
|
DBORDINAL *rgColNumber = NULL;
|
|
HROW hRow;
|
|
DBCOUNTITEM ulInputSeed = g_ulNextRow++;
|
|
|
|
|
|
//create a rowset and accessor that binds to DBTYPE_BYREF
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cDBPROPID,m_rgDBPROPID,0,NULL,NO_ACCESSOR));
|
|
|
|
//GetUpdatable columns
|
|
if(!GetFixedLengthAndUpdatable(&cCol, &rgColNumber))
|
|
goto CLEANUP;
|
|
|
|
if(!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,cCol,rgColNumber))
|
|
goto CLEANUP;
|
|
|
|
fTestPass=FALSE;
|
|
|
|
//create data to set to the last row
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,ulInputSeed,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//set data
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER, m_hAccessor, pData,&hRow),S_OK);
|
|
|
|
ReleaseInputBindingsMemory(m_cBinding,m_rgBinding,(BYTE*)pData);
|
|
ReleaseAccessorOnRowset();
|
|
|
|
if(!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))
|
|
goto CLEANUP;
|
|
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pValidationData,ulInputSeed,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//get data should succeed
|
|
TESTC_(m_pIRowset->GetData(hRow, m_hAccessor, m_pData),S_OK);
|
|
|
|
//compare data should be successful
|
|
if(!CompareBuffer(m_pData,pValidationData,m_cBinding,m_rgBinding,m_pIMalloc,TRUE))
|
|
goto CLEANUP;
|
|
|
|
ReleaseAccessorOnRowset();
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
PROVIDER_FREE(pData);
|
|
PROVIDER_FREE(pValidationData);
|
|
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
PROVIDER_FREE(rgColNumber);
|
|
PROVIDER_FREE(rgBinding);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc DBTYPE_ARRAY binding for all columns.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Valid_Keyset_Cursor_Immediate::Variation_4()
|
|
{
|
|
HROW hRow=1;
|
|
ULONG cCount;
|
|
void *pData=NULL;
|
|
BOOL fTestPass=TRUE;
|
|
|
|
if ( !m_fCanConvertFromArray )
|
|
return TEST_SKIPPED;
|
|
|
|
//open a rowset binds to all updatable columns by DBTYPE_ARRAY
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cDBPROPID,m_rgDBPROPID,0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND,FORWARD,NO_COLS_BY_REF, DBTYPE_ARRAY))
|
|
{
|
|
hRow = NULL;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
fTestPass=FALSE;
|
|
//make data for insert
|
|
if(!(pData=PROVIDER_ALLOC(m_cRowSize)))
|
|
{
|
|
hRow = NULL;
|
|
goto CLEANUP;
|
|
}
|
|
//set the status field
|
|
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;
|
|
|
|
}
|
|
//insert should be successful
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),DB_E_UNSUPPORTEDCONVERSION);
|
|
|
|
//hRow should be NULL
|
|
if(hRow)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
fTestPass=TRUE;
|
|
|
|
|
|
CLEANUP:
|
|
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc DBTYPE_VECTOR binding for all columns.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Valid_Keyset_Cursor_Immediate::Variation_5()
|
|
{
|
|
HROW hRow=1;
|
|
ULONG cCount;
|
|
void *pData=NULL;
|
|
BOOL fTestPass=TEST_FAIL;
|
|
|
|
if (!m_fCanConvertFromVector)
|
|
return TEST_SKIPPED;
|
|
|
|
//open a rowset binds to all updatable columns by DBTYPE_ARRAY
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cDBPROPID,m_rgDBPROPID,0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND,
|
|
FORWARD,NO_COLS_BY_REF, DBTYPE_VECTOR));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//make data for insert
|
|
if(!(pData=PROVIDER_ALLOC(m_cRowSize)))
|
|
goto CLEANUP;
|
|
|
|
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;
|
|
}
|
|
|
|
//insert should be successful
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),DB_E_UNSUPPORTEDCONVERSION);
|
|
|
|
//hRow should not be NULL
|
|
if(hRow)
|
|
goto CLEANUP;
|
|
|
|
fTestPass=TEST_PASS;
|
|
|
|
|
|
CLEANUP:
|
|
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Valid_Keyset_Cursor_Immediate::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Valid_Keyset_Query_Buffered)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Valid_Keyset_Query_Buffered - Valid_Keyset_Query_Buffered
|
|
//| Created: 05/14/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Valid_Keyset_Query_Buffered::Init()
|
|
{
|
|
BOOL fTestPass=TEST_SKIPPED;
|
|
|
|
m_rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
m_rgDBPROPID[1]=DBPROP_IRowsetUpdate;
|
|
|
|
m_cDBPROPID=2;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//Cursor does not have to be keyset
|
|
//create a rowset
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC, m_cDBPROPID, m_rgDBPROPID,
|
|
0,NULL,NO_ACCESSOR));
|
|
|
|
COMPC(BufferedUpdate(), TRUE);
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
ReleaseRowsetAndAccessor();
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Insert the fixed length data type columns with bogus length information.
|
|
// information.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Valid_Keyset_Query_Buffered::Variation_1()
|
|
{
|
|
DBORDINAL *rgColsToBind = NULL;
|
|
DBCOUNTITEM cCount = 0;
|
|
DBORDINAL cColsNumber = 0;
|
|
HROW hRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
DBROWSTATUS rgDBRowStatus[1];
|
|
DBROWSTATUS *pDBRowStatus = rgDBRowStatus;
|
|
DBCOUNTITEM cRows = 0;
|
|
void *pData = NULL;
|
|
DBROWSTATUS DBRowStatus;
|
|
BOOL fTestPass = TRUE;
|
|
HRESULT hr;
|
|
|
|
|
|
//open a rowset.
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cDBPROPID,m_rgDBPROPID,0,NULL,NO_ACCESSOR))
|
|
goto CLEANUP;
|
|
|
|
//Binds to all fixed length columns.
|
|
if(!GetFixedLengthAndUpdatable(&cColsNumber,&rgColsToBind))
|
|
goto CLEANUP;
|
|
|
|
//value and length binding only
|
|
if(!GetAccessorOnRowset(ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH,USE_COLS_TO_BIND_ARRAY,
|
|
FORWARD,NO_COLS_BY_REF, DBTYPE_EMPTY, cColsNumber, rgColsToBind))
|
|
goto CLEANUP;
|
|
|
|
fTestPass=FALSE;
|
|
//make data for insert
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//set the length for the 1st column as 0
|
|
// *(ULONG *)(dwAddr+m_rgBinding[0].obLength)=0;
|
|
LENGTH_BINDING(m_rgBinding[0],pData) = 0;
|
|
|
|
//insert should be successful
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),S_OK);
|
|
|
|
//hRow should not be NULL
|
|
if(!hRow)
|
|
goto CLEANUP;
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL, &DBRowStatus),S_OK);
|
|
hRow=NULL;
|
|
|
|
if(!COMPARE(DBRowStatus, DBROWSTATUS_S_PENDINGCHANGES))
|
|
fTestPass=FALSE;
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,&cCount,&pHRow,&pDBRowStatus),S_OK);
|
|
|
|
if(!COMPARE(cCount, 1))
|
|
goto CLEANUP;
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1, pHRow, NULL,NULL,NULL),S_OK);
|
|
|
|
PROVIDER_FREE(pHRow);
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
//get the rowset again
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cDBPROPID,m_rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH,USE_COLS_TO_BIND_ARRAY,
|
|
FORWARD,NO_COLS_BY_REF, DBTYPE_EMPTY, cColsNumber, rgColsToBind))
|
|
goto CLEANUP;
|
|
|
|
// the insert should be visible
|
|
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_(m_pIRowset->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;
|
|
FreeMemory();
|
|
break;
|
|
}
|
|
FreeMemory();
|
|
}
|
|
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
PROVIDER_FREE(rgColsToBind);
|
|
PROVIDER_FREE(pDBRowStatus);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1, pHRow, NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Insert the whole row with status only. Set everything to NULL
|
|
// Another call clears the value.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Valid_Keyset_Query_Buffered::Variation_2()
|
|
{
|
|
void *pData = NULL;
|
|
DBORDINAL cCols = 0;
|
|
DBORDINAL *rgColsToBind = 0;
|
|
ULONG cCount = 0;
|
|
DBORDINAL cColCount = 0;
|
|
DBCOUNTITEM cRows = 0;
|
|
HROW hRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
IRowsetChange *pIRowsetChange = NULL;
|
|
BOOL fTestPass = TRUE;
|
|
HRESULT hr;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cDBPROPID,m_rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
|
|
UPDATEABLE_COLS_BOUND))
|
|
goto CLEANUP;
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//get the nullable and updatable columns
|
|
if(!GetNullableAndUpdatable(&cCols, &rgColsToBind))
|
|
goto CLEANUP;
|
|
|
|
//make data for the 1st row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
fTestPass=FALSE;
|
|
|
|
for(cCount=0; cCount<m_cBinding; cCount++)
|
|
{
|
|
for(cColCount=0; cColCount<cCols; cColCount++)
|
|
{
|
|
if(m_rgBinding[cCount].iOrdinal==rgColsToBind[cColCount])
|
|
{
|
|
// *(DBSTATUS *)(dwAddr+m_rgBinding[cCount].obStatus)=DBSTATUS_S_ISNULL;
|
|
*(DBSTATUS*)&STATUS_BINDING(m_rgBinding[cCount],pData)=DBSTATUS_S_ISNULL;
|
|
//exit the inner loop
|
|
cColCount=cCols;
|
|
}
|
|
}
|
|
}
|
|
|
|
//insert should be successful
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),S_OK);
|
|
|
|
//hRow should not be NULL
|
|
if(!hRow)
|
|
goto CLEANUP;
|
|
|
|
//release the memory
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding,(BYTE *)pData,TRUE);
|
|
pData=NULL;
|
|
|
|
//make data for the 1st row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//change the data cach
|
|
TESTC_(m_pIRowsetChange->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;
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
//get the rowset again
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,m_cDBPROPID,m_rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND))
|
|
goto CLEANUP;
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
// the insert should be visible
|
|
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_(m_pIRowset->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)
|
|
{
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,pHRow,NULL),S_OK);
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
fTestPass=TRUE;
|
|
FreeMemory();
|
|
break;
|
|
}
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
FreeMemory();
|
|
}
|
|
|
|
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
PROVIDER_FREE(rgColsToBind);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
if(pHRow)
|
|
{
|
|
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 Valid_Keyset_Query_Buffered::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return(TCIRowsetNewRow::Terminate());
|
|
}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Sequence)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Sequence - sequence testing
|
|
//| Created: 05/15/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Sequence::Init()
|
|
{
|
|
if(TCIRowsetNewRow::Init())
|
|
return TRUE;
|
|
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set DBPROP_CanHoldRows. Set 3 rows in a row
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Sequence::Variation_1()
|
|
{
|
|
DBPROPID rgDBPROPID[4];
|
|
ULONG cCount = 0;
|
|
DBCOUNTITEM cRows = 0;
|
|
void *rgpData[25];
|
|
HROW rgHRow[25];
|
|
HROW *pHRow = NULL;
|
|
BOOL fTestPass = TRUE;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_OTHERUPDATEDELETE;
|
|
rgDBPROPID[2]=DBPROP_CANHOLDROWS;
|
|
rgDBPROPID[3]=DBPROP_IRowsetLocate;
|
|
|
|
//Init variables
|
|
for(cCount=0; cCount<25; cCount++)
|
|
{
|
|
rgpData[cCount]=NULL;
|
|
rgHRow[cCount]=NULL;
|
|
}
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgDBPROPID,0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
fTestPass = FALSE;
|
|
|
|
for(cCount=0; cCount<25; cCount++)
|
|
{
|
|
//make data for the 1st row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&(rgpData[cCount]), (g_ulNextRow++),m_cRowsetCols,
|
|
m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[cCount],&(rgHRow[cCount])),S_OK);
|
|
|
|
//hRow should not be NULL
|
|
if(!rgHRow[cCount])
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//release the row handles
|
|
for(cCount=0; cCount<25; cCount++)
|
|
{
|
|
if(rgHRow[cCount])
|
|
{
|
|
TESTC_(m_pIRowset->ReleaseRows(1, &(rgHRow[cCount]),NULL,NULL,NULL),S_OK)
|
|
rgHRow[cCount]=NULL;
|
|
}
|
|
}
|
|
|
|
//reexecute the rowset
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
//get a rowset binds to all updatable columns
|
|
if(S_OK != GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgDBPROPID,0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND))
|
|
goto CLEANUP;
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//make sure all rows are inserted
|
|
for(cCount=0; cCount<25; cCount++)
|
|
{
|
|
//get a row handle
|
|
pHRow=&(rgHRow[cCount]);
|
|
if(cCount==0)
|
|
{
|
|
TESTC_(m_pIRowset->GetNextRows(NULL, m_ulTableRows, 1,&cRows, &pHRow),S_OK);
|
|
}
|
|
else
|
|
{
|
|
TESTC_(m_pIRowset->GetNextRows(NULL, 0, 1,&cRows, &pHRow),S_OK);
|
|
}
|
|
|
|
//get data
|
|
TESTC_(m_pIRowset->GetData(rgHRow[cCount], m_hAccessor, m_pData),S_OK);
|
|
FreeMemory();
|
|
}
|
|
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
//Release the row handle and memory
|
|
for(cCount=0; cCount<25; cCount++)
|
|
{
|
|
if( rgHRow[cCount] )
|
|
CHECK(m_pIRowset->ReleaseRows(1, &(rgHRow[cCount]), NULL,NULL,NULL),S_OK);
|
|
|
|
if( rgpData[cCount] )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding,(BYTE *)rgpData[cCount],TRUE);
|
|
}
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Unset DBPROP_CanHoldrows. Insert 2 rows. DB_E_ROWSNOTRELEASED.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Sequence::Variation_2()
|
|
{
|
|
DBPROPID rgDBPROPID[3];
|
|
DBPROPID DBPropID=DBPROP_CANHOLDROWS;
|
|
ULONG cCount=0;
|
|
void *rgpData[3]={NULL,NULL,NULL};
|
|
HROW rgHRow[3]={NULL,NULL,NULL};
|
|
BOOL fTestPass=TRUE;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_OTHERUPDATEDELETE;
|
|
rgDBPROPID[2]=DBPROP_IRowsetLocate;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgDBPROPID,
|
|
1, &DBPropID,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND));
|
|
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
if(GetProp(DBPROP_CANHOLDROWS)==TRUE)
|
|
goto CLEANUP;
|
|
|
|
fTestPass = FALSE;
|
|
//make data for the 1st row handle
|
|
for(cCount=0; cCount<3; cCount++)
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,(BYTE **)&(rgpData[cCount]),
|
|
g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[0],&(rgHRow[0])),S_OK);
|
|
|
|
//insert the second row. Do not ask for any row handle back.
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[1],NULL),S_OK);
|
|
|
|
//insert the third row. Rows not released.
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[2],&(rgHRow[1])),DB_E_ROWSNOTRELEASED);
|
|
|
|
//release the 1st row
|
|
TESTC_(m_pIRowset->ReleaseRows(1, &(rgHRow[0]), NULL,NULL,NULL),S_OK);
|
|
rgHRow[0]=NULL;;
|
|
|
|
//insert the third row. Successful
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[2],&(rgHRow[1])),S_OK);
|
|
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
//Release the row handle and memory
|
|
for(cCount=0; cCount<3; cCount++)
|
|
{
|
|
if(rgHRow[cCount])
|
|
CHECK(m_pIRowset->ReleaseRows(1, &(rgHRow[cCount]), NULL,NULL,NULL),S_OK);
|
|
if(rgpData[cCount])
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)rgpData[cCount],TRUE);
|
|
}
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Buffered mode. Unset DBPROP_CanHoldRows. Insert 2 rows.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Sequence::Variation_3()
|
|
{
|
|
DBPROPID rgDBPROPID[4];
|
|
DBPROPID DBPropID = DBPROP_CANHOLDROWS;
|
|
DBCOUNTITEM cCount = 0;
|
|
void *rgpData[3] = {NULL,NULL,NULL};
|
|
HROW rgHRow[3] = {NULL,NULL,NULL};
|
|
HROW *pHRow = NULL;
|
|
BOOL fTestPass = TRUE;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_OTHERUPDATEDELETE;
|
|
rgDBPROPID[2]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[3]=DBPROP_IRowsetIdentity;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgDBPROPID,
|
|
1,&DBPropID,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND));
|
|
|
|
if (!m_pIRowsetUpdate)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
fTestPass = FALSE;
|
|
//make data for the 1st row handle
|
|
for(cCount=0; cCount<3; cCount++)
|
|
{
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&(rgpData[cCount]),g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
}
|
|
|
|
//insert one row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[0],&(rgHRow[0])),S_OK);
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&(rgHRow[0]),&cCount,&pHRow,NULL),S_OK);
|
|
|
|
if(!COMPARE(cCount, 1))
|
|
goto CLEANUP;
|
|
|
|
if(StrongIdentity())
|
|
CHECK(m_hr=m_pIRowsetIdentity->IsSameRow(*pHRow, rgHRow[0]),S_OK);
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1, rgHRow, NULL,NULL,NULL),S_OK);
|
|
|
|
rgHRow[0]=NULL;
|
|
PROVIDER_FREE(pHRow);
|
|
|
|
//insert the second row. Should succeed
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[1],NULL),S_OK);
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,&cCount,&pHRow,NULL),S_OK);
|
|
|
|
//insert the third row. Should report Rows not released
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[2],&(rgHRow[2])),DB_E_ROWSNOTRELEASED);
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1, pHRow, NULL,NULL,NULL),S_OK);
|
|
|
|
PROVIDER_FREE(pHRow);
|
|
|
|
//insert the third row. Should be fine
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[2],&(rgHRow[2])),S_OK);
|
|
|
|
//update
|
|
if(CHECK(m_pIRowsetUpdate->Update(NULL,0,NULL,NULL, NULL, NULL),S_OK))
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
//Release the row handle and memory
|
|
for(cCount=0; cCount<3; cCount++)
|
|
{
|
|
|
|
if(rgHRow[cCount])
|
|
CHECK(m_pIRowset->ReleaseRows(1, &(rgHRow[cCount]), NULL,NULL,NULL),S_OK);
|
|
|
|
if(rgpData[cCount])
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)rgpData[cCount],
|
|
TRUE);
|
|
}
|
|
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Insert 50 rows. Update.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Sequence::Variation_4()
|
|
{
|
|
DBPROPID rgDBPROPID[4];
|
|
ULONG cCount = 0;
|
|
DBCOUNTITEM cRows = 0;
|
|
void *rgpData[STRESS_COUNT];
|
|
HROW *pHRow = NULL;
|
|
BOOL fTestPass = TRUE;
|
|
ULONG_PTR ulValue = 0;
|
|
|
|
//init
|
|
for(cCount=0; cCount<STRESS_COUNT; cCount++)
|
|
rgpData[cCount]=NULL;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_OTHERUPDATEDELETE;
|
|
rgDBPROPID[2]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[3]=DBPROP_CANHOLDROWS;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,4,rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND));
|
|
|
|
|
|
GetProperty(DBPROP_MAXPENDINGROWS, DBPROPSET_ROWSET,m_pIRowset,&ulValue);
|
|
|
|
if (!m_pIRowsetUpdate)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass = FALSE;
|
|
|
|
for(cCount=0; cCount<ulValue && cCount<STRESS_COUNT; cCount++)
|
|
{
|
|
//make data for the 1st row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&(rgpData[cCount]),g_ulNextRow++,m_cRowsetCols,
|
|
m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[cCount],NULL),S_OK);
|
|
|
|
}
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,&cRows, &pHRow,NULL),S_OK);
|
|
|
|
if(COMPARE(cRows,(ulValue>STRESS_COUNT? STRESS_COUNT:ulValue) ))
|
|
fTestPass=TRUE;
|
|
|
|
|
|
CLEANUP:
|
|
//Release the row handle and memory
|
|
for(cCount=0; cCount<ulValue && cCount<STRESS_COUNT ; cCount++)
|
|
{
|
|
if(rgpData[cCount])
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding,(BYTE *)rgpData[cCount], TRUE);
|
|
}
|
|
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Buffered mode,DBPROP_CanHoldRows FALSE,Insert row/release it,insert/get another
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Sequence::Variation_5()
|
|
{
|
|
DBPROPID rgDBPROPID[3];
|
|
DBPROPID DBPropID = DBPROP_CANHOLDROWS;
|
|
ULONG cCount = 0;
|
|
DBCOUNTITEM cRows = 1;
|
|
void *rgpData[2] = {NULL,NULL};
|
|
HROW HRow = NULL;
|
|
HROW HRowBad = NULL;
|
|
HROW *pHRowBad = NULL;
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
ULONG cRowsUp = 0;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[2]=DBPROP_IRowsetIdentity;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgDBPROPID,
|
|
1,&DBPropID,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND));
|
|
|
|
if (!m_pIRowsetUpdate)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass = TEST_FAIL;
|
|
|
|
//make data for insert
|
|
for(cCount=0; cCount<2; cCount++)
|
|
{
|
|
//make data for the 1st row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&(rgpData[cCount]),g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
}
|
|
//insert one row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[0],&HRow),S_OK);
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1, &HRow, NULL,NULL,NULL),S_OK);
|
|
|
|
//insert another. Should report Rows not released
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[0],&HRowBad),DB_E_ROWSNOTRELEASED);
|
|
COMPARE(HRowBad,NULL);
|
|
|
|
//get the 1st row handle. Should report Rows not released
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRowBad),DB_E_ROWSNOTRELEASED);
|
|
COMPARE(pHRowBad,NULL);
|
|
COMPARE(cRows,0);
|
|
|
|
//update all changes
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),S_OK);
|
|
|
|
//insert another row. Should be fine
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[1],&HRow),S_OK);
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),S_OK);
|
|
fTestPass=TRUE;
|
|
CLEANUP:
|
|
//Release the row handle and memory
|
|
for(cCount=0; cCount<2; cCount++)
|
|
{
|
|
if(rgpData[cCount])
|
|
{
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)rgpData[cCount], TRUE);
|
|
}
|
|
}
|
|
if(HRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1, &HRow, NULL,NULL,NULL),S_OK);
|
|
}
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// }}
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Sequence::Terminate()
|
|
{
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Related_IRowsetDelete)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Related_IRowsetDelete - test Related_IRowsetDelete wiht IRowsetNewRow
|
|
//| Created: 05/15/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Related_IRowsetDelete::Init()
|
|
{
|
|
BOOL fTestPass=FALSE;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
fTestPass = TRUE;
|
|
|
|
return fTestPass;
|
|
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc In immediately update mode, insert two rows, delete one, the insert another row
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Related_IRowsetDelete::Variation_1()
|
|
{
|
|
void *rgpData[3] = {NULL,NULL,NULL};
|
|
HROW rgHRow[3] = {NULL,NULL,NULL};
|
|
ULONG cCount;
|
|
DBCOUNTITEM cRows;
|
|
HROW *pHRow = NULL;
|
|
DBROWSTATUS DBRowStatus;
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
DBPROPID rgDBPROPID[4];
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_OTHERUPDATEDELETE;
|
|
rgDBPROPID[2]=DBPROP_CANHOLDROWS;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgDBPROPID,0,NULL,
|
|
ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//make data for insert
|
|
for(cCount=0; cCount<3; cCount++)
|
|
{
|
|
//make data for the 1st row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&(rgpData[cCount]),g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
}
|
|
|
|
//insert
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[0],&(rgHRow[0])),S_OK);
|
|
|
|
//insert another row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[1],&(rgHRow[1])),S_OK);
|
|
|
|
//delete the row
|
|
if(GetProp(DBPROP_CHANGEINSERTEDROWS))
|
|
{
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,&(rgHRow[0]),&DBRowStatus),S_OK);
|
|
}
|
|
else
|
|
{
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,&(rgHRow[0]),&DBRowStatus),DB_E_ERRORSOCCURRED);
|
|
COMPARE(DBRowStatus, DBROWSTATUS_E_NEWLYINSERTED);
|
|
}
|
|
|
|
|
|
//insert another row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[2],&(rgHRow[2])),S_OK);
|
|
|
|
//restart position
|
|
hr = m_pIRowset->RestartPosition(NULL);
|
|
|
|
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
|
|
goto CLEANUP;
|
|
|
|
//get next row. We have added 2 rows into the rowset//skip # of rows+3 in the rowset. DB_S_ENDOFROWSET
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,m_ulTableRows+3,1,&cRows,&pHRow),DB_S_ENDOFROWSET);
|
|
|
|
fTestPass=TRUE;
|
|
CLEANUP:
|
|
//Release the row handle and memory
|
|
for(cCount=0; cCount<3; cCount++)
|
|
{
|
|
if(rgHRow[cCount])
|
|
CHECK(m_pIRowset->ReleaseRows(1, &(rgHRow[cCount]), NULL,NULL,NULL),S_OK);
|
|
if(rgpData[cCount])
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)rgpData[cCount], TRUE);
|
|
}
|
|
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow, NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
if(fTestPass)
|
|
return TEST_PASS;
|
|
else
|
|
return TEST_FAIL;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc In immediate update mode, insert one row, change it and delete it.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Related_IRowsetDelete::Variation_2()
|
|
{
|
|
void *rgpData[2] = {NULL,NULL};
|
|
ULONG cCount = 0;
|
|
BOOL fTestPass = FALSE;
|
|
HROW hRow = NULL;
|
|
DBPROPID rgDBPROPID[4];
|
|
DBROWSTATUS DBRowStatus;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_OTHERUPDATEDELETE;
|
|
rgDBPROPID[2]=DBPROP_IRowsetLocate;
|
|
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgDBPROPID,
|
|
0,NULL, ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//make data for insert
|
|
for(cCount=0; cCount<2; 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);
|
|
|
|
//insert
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[0],&hRow),S_OK);
|
|
|
|
//change the row
|
|
if(GetProp(DBPROP_CHANGEINSERTEDROWS))
|
|
{
|
|
TESTC_(m_pIRowsetChange->SetData(hRow,m_hAccessor,rgpData[1]),S_OK);
|
|
|
|
//all columns including the computed columns should be ok
|
|
for(cCount=0; cCount<m_cBinding; cCount++)
|
|
{
|
|
// COMPARE(*(DBSTATUS *)((DWORD)rgpData[1]+m_rgBinding[cCount].obStatus),DBSTATUS_S_OK);
|
|
COMPARE(STATUS_BINDING(m_rgBinding[cCount],rgpData[1]),DBSTATUS_S_OK);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TESTC_(m_pIRowsetChange->SetData(hRow,m_hAccessor,rgpData[1]),DB_E_NEWLYINSERTED);
|
|
}
|
|
|
|
// MSDASQL _ SQLServer/Access/Oracle all three behave differently here!!!
|
|
if(GetProp(DBPROP_CHANGEINSERTEDROWS))
|
|
{
|
|
if ( GetProp(DBPROP_REMOVEDELETED) )
|
|
{
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,&hRow,&DBRowStatus),S_OK);
|
|
}
|
|
else
|
|
{
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,&hRow,&DBRowStatus),DB_E_ERRORSOCCURRED);
|
|
COMPARE(DBRowStatus, DBROWSTATUS_E_DELETED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,&hRow,&DBRowStatus),DB_E_ERRORSOCCURRED);
|
|
COMPARE(DBRowStatus, DBROWSTATUS_E_NEWLYINSERTED);
|
|
}
|
|
|
|
fTestPass=TRUE;
|
|
CLEANUP:
|
|
//Release the row handle and memory
|
|
if(hRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow, NULL,NULL,NULL),S_OK);
|
|
}
|
|
for(cCount=0; cCount<2; cCount++)
|
|
{
|
|
if(rgpData[cCount])
|
|
{
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)rgpData[cCount], TRUE);
|
|
}
|
|
}
|
|
ReleaseRowsetAndAccessor();
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Related_IRowsetDelete::Terminate()
|
|
{
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Related_IRowsetChange)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Related_IRowsetChange - test IRowsetChange and IRowsetNewRow
|
|
//| Created: 05/15/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Related_IRowsetChange::Init()
|
|
{
|
|
BOOL fTestPass=FALSE;
|
|
DBPROPID rgDBPROPID[2];
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_OTHERUPDATEDELETE;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND));
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Ichange the primary key of one row, insert a row with the original primary key. S_OK. Insert another row with the new primary
|
|
// S_OK. Insert another row with the new primary key. DB_E_INTEGRITYVIOLATION.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Related_IRowsetChange::Variation_1()
|
|
{
|
|
DBCOUNTITEM cRows = 0;
|
|
IRowsetChange *pIRowsetChange = NULL;
|
|
HROW hRow = 1;
|
|
HROW *pHRow = NULL;
|
|
void *pData = NULL;
|
|
BOOL fTestPass = FALSE;
|
|
|
|
// This variation tests col uniqueness and this property is available only through non-level 0 interfaces
|
|
// If strict conformance leveling is active, skip this variation
|
|
if (GetModInfo()->IsStrictLeveling())
|
|
return TEST_SKIPPED;
|
|
|
|
//make data for the 1st row. The rowset starts with 10th row.
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//get the 1st row handle
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
|
|
//QI for IRowsetDelete
|
|
TESTC_(m_pIRowset->QueryInterface(IID_IRowsetChange,(LPVOID *)&pIRowsetChange),S_OK);
|
|
|
|
//delete the row handle
|
|
TESTC_(pIRowsetChange->DeleteRows(NULL,1,pHRow,NULL),S_OK);
|
|
|
|
if(GetProp(DBPROP_CANHOLDROWS))
|
|
{
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),S_OK);
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,&hRow,NULL,NULL,NULL),S_OK);
|
|
hRow=NULL;
|
|
}
|
|
else
|
|
//insert the same row. DB_E_ROWSNOTRELEASED
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),DB_E_ROWSNOTRELEASED);
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
|
|
if(GetProp(DBPROP_CANHOLDROWS))
|
|
{
|
|
//insert again
|
|
m_hr=m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,NULL);
|
|
|
|
if(m_bIndexExists)
|
|
{
|
|
TESTC_(m_hr,DB_E_INTEGRITYVIOLATION);
|
|
}
|
|
else
|
|
{
|
|
TESTC_(m_hr,S_OK);
|
|
}
|
|
}
|
|
else
|
|
//insert
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),S_OK);
|
|
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding,(BYTE *)pData, TRUE);
|
|
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow,NULL,NULL,NULL),S_OK);
|
|
|
|
SAFE_RELEASE(pIRowsetChange);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc In immediate update mode, insert two rows, change one of the row. Verify.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Related_IRowsetChange::Variation_2()
|
|
{
|
|
void *rgpData[3]={NULL,NULL,NULL};
|
|
HROW hRow=NULL;
|
|
ULONG cCount;
|
|
DBROWSTATUS DBRowStatus;
|
|
BOOL fTestPass=FALSE;
|
|
|
|
|
|
//make data for insert && change
|
|
for(cCount=0; cCount<3; 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);
|
|
}
|
|
|
|
//insert
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[0],NULL),S_OK);
|
|
|
|
//insert another row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[1],&hRow),S_OK);
|
|
|
|
//change the row
|
|
if(GetProp(DBPROP_CHANGEINSERTEDROWS))
|
|
{
|
|
TESTC_(m_pIRowsetChange->SetData(hRow,m_hAccessor,rgpData[2]),S_OK);
|
|
}
|
|
else
|
|
{
|
|
TESTC_(m_pIRowsetChange->SetData(hRow,m_hAccessor,rgpData[2]),DB_E_NEWLYINSERTED);
|
|
}
|
|
|
|
if(GetProp(DBPROP_CHANGEINSERTEDROWS))
|
|
{
|
|
if ( GetProp(DBPROP_REMOVEDELETED) )
|
|
{
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,&hRow,&DBRowStatus),S_OK);
|
|
}
|
|
else
|
|
{
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,&hRow,&DBRowStatus),DB_E_ERRORSOCCURRED);
|
|
COMPARE(DBRowStatus, DBROWSTATUS_E_DELETED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,&hRow,&DBRowStatus),DB_E_ERRORSOCCURRED);
|
|
COMPARE(DBRowStatus, DBROWSTATUS_E_NEWLYINSERTED);
|
|
}
|
|
|
|
fTestPass=TRUE;
|
|
|
|
|
|
CLEANUP:
|
|
//Release the row handle and memory
|
|
for(cCount=0; cCount<3; cCount++)
|
|
{
|
|
if(rgpData[cCount])
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)rgpData[cCount], TRUE);
|
|
}
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Related_IRowsetChange::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Transaction)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Transaction - testing zombie state
|
|
//| Created: 05/15/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Transaction::Init()
|
|
{
|
|
m_DBPropSet.rgProperties = NULL;
|
|
|
|
if(!CTransaction::Init())
|
|
return TEST_SKIPPED;
|
|
|
|
m_DBPropSet.guidPropertySet=DBPROPSET_ROWSET;
|
|
m_DBPropSet.cProperties = 0;
|
|
m_DBPropSet.rgProperties=(DBPROP *)PROVIDER_ALLOC(3*sizeof(DBPROP));
|
|
|
|
if(!m_DBPropSet.rgProperties)
|
|
return FALSE;
|
|
|
|
//Memset to zeros
|
|
memset(m_DBPropSet.rgProperties, 0, (3*sizeof(DBPROP)));
|
|
|
|
//DBPROP_IRowsetChange
|
|
m_DBPropSet.rgProperties[0].dwPropertyID=DBPROP_IRowsetChange;
|
|
m_DBPropSet.rgProperties[0].dwOptions=DBPROPOPTIONS_REQUIRED;
|
|
m_DBPropSet.rgProperties[0].colid = DB_NULLID;
|
|
m_DBPropSet.rgProperties[0].vValue.vt=VT_BOOL;
|
|
V_BOOL(&m_DBPropSet.rgProperties[0].vValue)=VARIANT_TRUE;
|
|
m_DBPropSet.cProperties++;
|
|
|
|
//DBPROP_CANHOLDROWS
|
|
m_DBPropSet.rgProperties[1].dwPropertyID=DBPROP_CANHOLDROWS;
|
|
m_DBPropSet.rgProperties[1].dwOptions=DBPROPOPTIONS_REQUIRED;
|
|
m_DBPropSet.rgProperties[1].colid = DB_NULLID;
|
|
m_DBPropSet.rgProperties[1].vValue.vt=VT_BOOL;
|
|
V_BOOL(&m_DBPropSet.rgProperties[1].vValue)=VARIANT_TRUE;
|
|
m_DBPropSet.cProperties++;
|
|
|
|
if ( DBPROPFLAGS_WRITE & GetPropInfoFlags(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, m_pIDBCreateSession))
|
|
{
|
|
//DBPROP_UPDATABILITY
|
|
m_DBPropSet.rgProperties[2].dwPropertyID=DBPROP_UPDATABILITY;
|
|
m_DBPropSet.rgProperties[2].dwOptions=DBPROPOPTIONS_REQUIRED;
|
|
m_DBPropSet.rgProperties[2].vValue.vt=VT_I4;
|
|
m_DBPropSet.rgProperties[2].colid = DB_NULLID;
|
|
V_I4(&m_DBPropSet.rgProperties[2].vValue)=DBPROPVAL_UP_INSERT|DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_DELETE;
|
|
m_DBPropSet.cProperties++;
|
|
}
|
|
|
|
// guarantee that we create insert seeds that fit in the transact table
|
|
g_ulNextRow = ( g_ulNextRow <= TRANSACTION_ROW_COUNT ) ? TRANSACTION_ROW_COUNT+1 : g_ulNextRow;
|
|
|
|
//register interface to be tested
|
|
if(!RegisterInterface(ROWSET_INTERFACE, IID_IRowsetChange, 1, &m_DBPropSet))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Commit with fRetaining=TRUE. Query based
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Transaction::Variation_1()
|
|
{
|
|
BOOL fTestPass = FALSE;
|
|
HACCESSOR hAccessor = NULL;
|
|
void *pSetData = NULL;
|
|
void *pSetSecondData = NULL;
|
|
DBLENGTH cRowSize = 0;
|
|
void *pGetData = NULL;
|
|
DBCOUNTITEM cBinding = 0;
|
|
DBBINDING *rgBinding = NULL;
|
|
IRowsetChange *pIRowsetChange = NULL;
|
|
IAccessor *pIAccessor = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
HROW hRow = NULL;
|
|
HROW hSecondRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
IUnknown *pIUnknown = NULL;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
|
|
//start a transaction. Create a rowset with IRowsetNewRow pointer.
|
|
|
|
if(!StartTransaction(SELECT_ORDERBYNUMERIC, (IUnknown **)&pIRowsetChange,
|
|
1, &m_DBPropSet))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//create an accessor on the rowset object
|
|
TESTC_(GetAccessorAndBindings(m_pIRowset,DBACCESSOR_ROWDATA,&hAccessor, &rgBinding, &cBinding, &cRowSize,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND,
|
|
FORWARD,NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//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 data to set
|
|
TESTC_(FillInputBindings(m_pCTable,DBACCESSOR_ROWDATA,cBinding,rgBinding,
|
|
(BYTE **)&pSetSecondData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert
|
|
TESTC_(pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,hAccessor,pSetData,NULL),S_OK);
|
|
|
|
//insert again. Error should occur.
|
|
hr = pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,hAccessor,pSetData,&hRow);
|
|
|
|
// This should be an error indicating that a unique key constraint has been violated.
|
|
COMPC(FAILED(hr), TRUE);
|
|
|
|
//commit the transaction with fRetaining==TRUE
|
|
if(!GetCommit(TRUE))
|
|
goto CLEANUP;
|
|
|
|
if(!m_fCommitPreserve)
|
|
{
|
|
hSecondRow = 1;
|
|
//test zombie
|
|
if(CHECK(pIRowsetChange->InsertRow(DB_NULL_HCHAPTER, hAccessor, pSetSecondData,&hSecondRow),E_UNEXPECTED))
|
|
{
|
|
if(COMPARE(hSecondRow, NULL))
|
|
fTestPass=TRUE;
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
//test the rowset should be fully functional
|
|
TESTC_(pIRowsetChange->InsertRow(DB_NULL_HCHAPTER, hAccessor, pSetSecondData,&hSecondRow),S_OK);
|
|
|
|
//commit the transaction with fRetaining==TRUE
|
|
if(!GetCommit(TRUE))
|
|
goto CLEANUP;
|
|
|
|
//release the accessor
|
|
TESTC_(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
|
|
PROVIDER_FREE(rgBinding);
|
|
hAccessor=NULL;
|
|
|
|
//reexcute the command
|
|
TESTC_(m_pICommand->Execute(NULL,IID_IRowset,NULL,NULL,&pIUnknown),S_OK);
|
|
|
|
//create an accessor on the rowset object
|
|
TESTC_(GetAccessorAndBindings(pIUnknown,DBACCESSOR_ROWDATA,&hAccessor, &rgBinding, &cBinding, &cRowSize,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND,
|
|
FORWARD,NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//get the 1st row of the rowset
|
|
TESTC_(((IRowset *)pIUnknown)->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
|
|
//allocate memory for GetData
|
|
if(!(pGetData=PROVIDER_ALLOC(cRowSize)))
|
|
goto CLEANUP;
|
|
|
|
//get data
|
|
TESTC_(((IRowset *)pIUnknown)->GetData(*pHRow, hAccessor, pGetData),S_OK);
|
|
|
|
fTestPass=TRUE;
|
|
|
|
//the udpate should not be made as the transaction was aborted.
|
|
//TODO Why is this commented?
|
|
// if(!CompareBuffer(pGetData,pSetData,cBinding,rgBinding,
|
|
// m_pIMalloc,TRUE))
|
|
// {
|
|
// fTestPass=TRUE;
|
|
// PROVIDER_FREE(pSetData);
|
|
// }
|
|
CLEANUP:
|
|
//release GetData buffers
|
|
PROVIDER_FREE(pGetData);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(((IRowset *)pIUnknown)->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
//release the accessor
|
|
if(hAccessor)
|
|
{
|
|
//QI for IAccessor. The accessor could be on the 1st rowset
|
|
if(pIUnknown)
|
|
{
|
|
if(CHECK(((IRowset *)pIUnknown)->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 rowsets generated
|
|
SAFE_RELEASE(pIUnknown);
|
|
|
|
//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(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
//release the row handles generated for the second time
|
|
if(hSecondRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hSecondRow, NULL,NULL,NULL),S_OK);
|
|
|
|
SAFE_RELEASE(pIRowsetChange);
|
|
|
|
//clean up. Expected S_OK.
|
|
CleanUpTransaction(S_OK);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Commit with fRetaining=FALSE. Cursor based
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Transaction::Variation_2()
|
|
{
|
|
BOOL fTestPass = FALSE;
|
|
HACCESSOR hAccessor = NULL;
|
|
void *pSetData = NULL;
|
|
void *pGetData = NULL;
|
|
DBLENGTH cRowSize = 0;
|
|
DBCOUNTITEM cBinding = 0;
|
|
DBBINDING *rgBinding = NULL;
|
|
IRowsetChange *pIRowsetChange = NULL;
|
|
IAccessor *pIAccessor = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
HROW hRow = NULL;
|
|
HROW hSecondRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
IUnknown *pIUnknown = NULL;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
|
|
//start a transaction. Create a rowset with IRowsetNewRow pointer.
|
|
|
|
//Cursor based update
|
|
if(!StartTransaction(SELECT_ORDERBYNUMERIC, (IUnknown **)&pIRowsetChange,1, &m_DBPropSet))
|
|
goto CLEANUP;
|
|
|
|
//create an accessor on the rowset object
|
|
TESTC_(GetAccessorAndBindings(m_pIRowset,DBACCESSOR_ROWDATA,&hAccessor, &rgBinding, &cBinding, &cRowSize,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND,
|
|
FORWARD,NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Get data to set
|
|
TESTC_(FillInputBindings(m_pCTable,DBACCESSOR_ROWDATA,cBinding,rgBinding,
|
|
(BYTE **)&pSetData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert
|
|
TESTC_(pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,hAccessor,pSetData,&hRow),S_OK);
|
|
|
|
//commit the transaction with fRetaining==FALSE
|
|
if(!GetCommit(FALSE))
|
|
goto CLEANUP;
|
|
|
|
if(!m_fCommitPreserve)
|
|
{
|
|
hSecondRow = 1;
|
|
//test zombie
|
|
if(CHECK(pIRowsetChange->InsertRow(DB_NULL_HCHAPTER, hAccessor, pSetData,&hSecondRow),E_UNEXPECTED))
|
|
{
|
|
if(COMPARE(hSecondRow, NULL))
|
|
fTestPass=TRUE;
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
//test the rowset should be fully functional//we try to set the same value to the 1st column
|
|
//if(m_bIndexExists)
|
|
//Should return constraints violation
|
|
hr = pIRowsetChange->InsertRow(DB_NULL_HCHAPTER, hAccessor, pSetData, &hSecondRow);
|
|
|
|
// accept either HRESULT since providers differ in their
|
|
// ability to detect which col generated the violation
|
|
COMPC(FAILED(hr), TRUE);
|
|
|
|
//release the accessor
|
|
TESTC_(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
|
|
hAccessor=NULL;
|
|
PROVIDER_FREE(rgBinding);
|
|
|
|
//reexcute the command
|
|
TESTC_(m_pICommand->Execute(NULL,IID_IRowset,NULL,NULL,&pIUnknown),S_OK);
|
|
|
|
//create an accessor on the rowset object
|
|
TESTC_(GetAccessorAndBindings(pIUnknown,DBACCESSOR_ROWDATA,&hAccessor, &rgBinding, &cBinding, &cRowSize,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND,
|
|
FORWARD,NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//get the 1st row of the rowset
|
|
TESTC_(((IRowset *)pIUnknown)->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
|
|
//allocate memory for GetData
|
|
if(!(pGetData=PROVIDER_ALLOC(cRowSize)))
|
|
goto CLEANUP;
|
|
|
|
//get data
|
|
if(CHECK(((IRowset *)pIUnknown)->GetData(*pHRow, hAccessor, pGetData),S_OK))
|
|
fTestPass=TRUE;
|
|
|
|
//the udpate should not be made as the transaction was aborted.
|
|
//TODO Why is this commented?
|
|
// if(!CompareBuffer(pGetData,pSetData,cBinding,rgBinding,
|
|
// m_pIMalloc,TRUE))
|
|
// {
|
|
// fTestPass=TRUE;
|
|
// PROVIDER_FREE(pSetData);
|
|
// }
|
|
|
|
|
|
CLEANUP:
|
|
//release GetData buffers
|
|
PROVIDER_FREE(pGetData);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(((IRowset *)pIUnknown)->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
//release the accessor
|
|
if(hAccessor)
|
|
{
|
|
//QI for IAccessor. The accessor could be on the 1st rowset
|
|
if(pIUnknown)
|
|
{
|
|
if(CHECK(((IRowset *)pIUnknown)->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 rowsets generated
|
|
SAFE_RELEASE(pIUnknown);
|
|
|
|
//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(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
//release the row handles generated for the second time
|
|
if(hSecondRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hSecondRow, NULL,NULL,NULL),S_OK);
|
|
|
|
SAFE_RELEASE(pIRowsetChange);
|
|
|
|
//clean up
|
|
CleanUpTransaction(XACT_E_NOTRANSACTION);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Abort with fRetaining=TRUE. Cursor based.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Transaction::Variation_3()
|
|
{
|
|
BOOL fTestPass = FALSE;
|
|
HACCESSOR hAccessor = NULL;
|
|
void *pSetData = NULL;
|
|
void *pGetData = NULL;
|
|
DBLENGTH cRowSize = 0;
|
|
DBCOUNTITEM cBinding = 0;
|
|
DBBINDING *rgBinding = NULL;
|
|
IRowsetChange *pIRowsetChange = NULL;
|
|
IAccessor *pIAccessor = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
HROW hRow = NULL;
|
|
HROW hSecondRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
IUnknown *pIUnknown = NULL;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
//start a transaction. Create a rowset with IRowsetNewRow pointer.
|
|
if(!StartTransaction(SELECT_ORDERBYNUMERIC, (IUnknown **)&pIRowsetChange,1, &m_DBPropSet))
|
|
goto CLEANUP;
|
|
|
|
//create an accessor on the rowset object
|
|
TESTC_(GetAccessorAndBindings(m_pIRowset,DBACCESSOR_ROWDATA,&hAccessor,&rgBinding,&cBinding,&cRowSize,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND,
|
|
FORWARD,NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//Get data to set
|
|
TESTC_(FillInputBindings(m_pCTable,DBACCESSOR_ROWDATA,cBinding,rgBinding,
|
|
(BYTE **)&pSetData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert
|
|
TESTC_(pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,hAccessor,pSetData,&hRow),S_OK);
|
|
|
|
//abort the transaction with fRetaining==TRUE
|
|
if(!GetAbort(TRUE))
|
|
goto CLEANUP;
|
|
|
|
if(!m_fAbortPreserve)
|
|
{
|
|
hSecondRow = 1;
|
|
//test zombie
|
|
if(CHECK(pIRowsetChange->InsertRow(DB_NULL_HCHAPTER, hAccessor, pSetData,&hSecondRow),E_UNEXPECTED))
|
|
{
|
|
if(COMPARE(hSecondRow, NULL))
|
|
fTestPass=TRUE;
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
//test the rowset should be fully functional//we try to set the same value to the 1st column. Should be
|
|
//fine as the transaction was aborted
|
|
TESTC_(pIRowsetChange->InsertRow(DB_NULL_HCHAPTER, hAccessor, pSetData,&hSecondRow),S_OK);
|
|
|
|
//abort the transaction again
|
|
if(!GetAbort(TRUE))
|
|
goto CLEANUP;
|
|
|
|
//release the accessor
|
|
TESTC_(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
|
|
hAccessor=NULL;
|
|
PROVIDER_FREE(rgBinding);
|
|
|
|
//reexcute the command
|
|
TESTC_(m_pICommand->Execute(NULL,IID_IRowset,NULL,NULL, &pIUnknown),S_OK);
|
|
|
|
//create an accessor on the rowset object
|
|
TESTC_(GetAccessorAndBindings(pIUnknown,DBACCESSOR_ROWDATA,&hAccessor, &rgBinding, &cBinding,&cRowSize,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND,
|
|
FORWARD,NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//make sure no row is actually inserted get the 1st row
|
|
TESTC_(((IRowset *)pIUnknown)->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
|
|
//allocate memory for GetData
|
|
if(!(pGetData=PROVIDER_ALLOC(cRowSize)))
|
|
goto CLEANUP;
|
|
|
|
//get data
|
|
if(CHECK(((IRowset *)pIUnknown)->GetData(*pHRow, hAccessor, pGetData),S_OK))
|
|
fTestPass=TRUE;
|
|
|
|
//the udpate should not be made as the transaction was aborted.
|
|
//TODO Why is this commented?
|
|
// if(!CompareBuffer(pGetData,pSetData,cBinding,rgBinding,
|
|
// m_pIMalloc,TRUE))
|
|
// {
|
|
// fTestPass=TRUE;
|
|
// PROVIDER_FREE(pSetData);
|
|
// }
|
|
|
|
CLEANUP:
|
|
//release GetData buffers
|
|
PROVIDER_FREE(pGetData);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(((IRowset *)pIUnknown)->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
//release the accessor
|
|
if(hAccessor)
|
|
{
|
|
//QI for IAccessor. The accessor could be on the 1st rowset
|
|
if(pIUnknown)
|
|
{
|
|
if(CHECK(((IRowset *)pIUnknown)->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 rowsets generated
|
|
SAFE_RELEASE(pIUnknown);
|
|
|
|
//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(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
//release the row handle on the 1st rowset
|
|
if(hSecondRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hSecondRow, NULL,NULL,NULL),S_OK);
|
|
|
|
SAFE_RELEASE(pIRowsetChange);
|
|
|
|
//clean up
|
|
CleanUpTransaction(S_OK);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Abort with fRetaining=FALSE. Query based
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Transaction::Variation_4()
|
|
{
|
|
BOOL fTestPass = FALSE;
|
|
HACCESSOR hAccessor = NULL;
|
|
void *pSetData = NULL;
|
|
void *pGetData = NULL;
|
|
DBLENGTH cRowSize = 0;
|
|
DBCOUNTITEM cBinding = 0;
|
|
DBBINDING *rgBinding = NULL;
|
|
IRowsetChange *pIRowsetChange = NULL;
|
|
IAccessor *pIAccessor = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
HROW hRow = NULL;
|
|
HROW hSecondRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
IUnknown *pIUnknown = NULL;
|
|
|
|
//start a transaction. Create a rowset with IRowsetNewRow pointer.
|
|
|
|
if(!StartTransaction(SELECT_ORDERBYNUMERIC, (IUnknown **)&pIRowsetChange,1, &m_DBPropSet))
|
|
goto CLEANUP;
|
|
|
|
//create an accessor on the rowset object
|
|
TESTC_(GetAccessorAndBindings(m_pIRowset,DBACCESSOR_ROWDATA,&hAccessor, &rgBinding,&cBinding,&cRowSize,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND,
|
|
FORWARD,NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//Get data to set
|
|
TESTC_(FillInputBindings(m_pCTable,DBACCESSOR_ROWDATA,cBinding,rgBinding,
|
|
(BYTE **)&pSetData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert
|
|
TESTC_(pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,hAccessor,pSetData,&hRow),S_OK);
|
|
|
|
//abort the transaction with fRetaining==FALSE
|
|
if(!GetAbort(FALSE))
|
|
goto CLEANUP;
|
|
|
|
if(!m_fAbortPreserve)
|
|
{
|
|
hSecondRow = 1;
|
|
//test zombie
|
|
if(CHECK(pIRowsetChange->InsertRow(DB_NULL_HCHAPTER, hAccessor, pSetData,&hSecondRow),E_UNEXPECTED))
|
|
{
|
|
if(COMPARE(hSecondRow, NULL))
|
|
fTestPass=TRUE;
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
//test the rowset should be fully functional
|
|
//we try to set the same value to the 1st column. Should be
|
|
//fine as the transaction was aborted
|
|
TESTC_(pIRowsetChange->InsertRow(DB_NULL_HCHAPTER, hAccessor, pSetData,&hSecondRow),S_OK);
|
|
|
|
//release the accessor
|
|
TESTC_(m_pIAccessor->ReleaseAccessor(hAccessor,NULL),S_OK);
|
|
hAccessor=NULL;
|
|
|
|
//reexcute the command
|
|
TESTC_(m_pICommand->Execute(NULL,IID_IRowset,NULL,NULL,&pIUnknown),S_OK);
|
|
|
|
//create an accessor on the rowset object
|
|
TESTC_(GetAccessorAndBindings(pIUnknown,DBACCESSOR_ROWDATA,&hAccessor, &rgBinding, &cBinding,&cRowSize,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND,
|
|
FORWARD,NO_COLS_BY_REF, NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS),S_OK);
|
|
|
|
|
|
//if there are no updatable rows
|
|
if (!cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//make sure one row is actually inserted as fRetaining is FALSE,we are in autocommite mode
|
|
TESTC_(((IRowset *)pIUnknown)->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
|
|
//allocate memory for GetData
|
|
if(!(pGetData=PROVIDER_ALLOC(cRowSize)))
|
|
goto CLEANUP;
|
|
|
|
//get data
|
|
if(CHECK(((IRowset *)pIUnknown)->GetData(*pHRow, hAccessor, pGetData),S_OK))
|
|
fTestPass=TRUE;
|
|
|
|
//the udpate should not be made as the transaction was aborted.
|
|
//TODO Why is this commented?
|
|
// if(COMPARE(CompareBuffer(pGetData,pSetData,cBinding,rgBinding,
|
|
// m_pIMalloc,TRUE),TRUE))
|
|
// {
|
|
// fTestPass=TRUE;
|
|
// PROVIDER_FREE(pSetData);
|
|
// }
|
|
|
|
CLEANUP:
|
|
//release GetData buffers
|
|
PROVIDER_FREE(pGetData);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(((IRowset *)pIUnknown)->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
//release the accessor
|
|
if(hAccessor)
|
|
{
|
|
//QI for IAccessor. The accessor could be on the 1st rowset
|
|
if(pIUnknown)
|
|
{
|
|
if(CHECK(((IRowset *)pIUnknown)->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);
|
|
}
|
|
}
|
|
|
|
SAFE_RELEASE(pIUnknown);
|
|
|
|
//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(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
//release the row handle on the 1st rowset
|
|
if(hSecondRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &hSecondRow, NULL,NULL,NULL),S_OK);
|
|
|
|
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()
|
|
{
|
|
PROVIDER_FREE(m_DBPropSet.rgProperties);
|
|
return(CTransaction::Terminate());
|
|
} // }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(EmptyTable)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: EmptyTable - insert a new row into an empty table
|
|
//| Created: 07/29/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL EmptyTable::Init()
|
|
{
|
|
BOOL fTestPass = FALSE;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
g_p1RowTable->DeleteRows();
|
|
|
|
//set the table. No need to create a table everytime.
|
|
SetTable(g_p1RowTable,DELETETABLE_NO);
|
|
fTestPass = TRUE;
|
|
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Insert a new row into an empty table
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int EmptyTable::Variation_1()
|
|
{
|
|
DBCOUNTITEM cRows = 0;
|
|
HROW *pHRow = NULL;
|
|
void *pData = NULL;
|
|
DBPROPID rgDBPropID[2];
|
|
BOOL fTestPass = FALSE;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
rgDBPropID[0]=DBPROP_IRowsetChange;
|
|
rgDBPropID[1]=DBPROP_OTHERINSERT;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgDBPropID,0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//fill up buffer for a row
|
|
TESTC_(FillInputBindings(g_p1RowTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//InsertRow should succeed
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,NULL),S_OK);
|
|
|
|
//restartposition
|
|
hr = m_pIRowset->RestartPosition(NULL);
|
|
if(!CHECK(hr==S_OK || hr==DB_S_COMMANDREEXECUTED, TRUE))
|
|
goto CLEANUP;
|
|
|
|
//GetNextRows
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
|
|
TESTC_(m_pIRowset->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)==TRUE)
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
|
|
PROVIDER_FREE(pData);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL EmptyTable::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(AppendOnly)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: AppendOnly - test DBPROP_APPENDONLY
|
|
//| Created: 08/06/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL AppendOnly::Init()
|
|
{
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
DBPROPID rgDBPropID[1];
|
|
|
|
rgDBPropID[0]=DBPROP_APPENDONLY;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
{
|
|
return TEST_FAIL;
|
|
}
|
|
if (!SupportedProperty(DBPROP_APPENDONLY, DBPROPSET_ROWSET))
|
|
{
|
|
return TEST_SKIPPED;
|
|
}
|
|
//create a rowset
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgDBPropID,0,NULL,NO_ACCESSOR));
|
|
|
|
fTestPass = TRUE;
|
|
CLEANUP:
|
|
ReleaseRowsetAndAccessor();
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc check props with APPENDONLY
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int AppendOnly::Variation_1()
|
|
{
|
|
ULONG cRows=2;
|
|
HROW *pHRow=NULL;
|
|
DBPROPID rgDBPropID[1];
|
|
BOOL fTestPass=TRUE;
|
|
|
|
rgDBPropID[0]=DBPROP_APPENDONLY;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgDBPropID,0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//make sure DBPROP_APPENDONLY is variant_true
|
|
if(!GetProp(DBPROP_APPENDONLY))
|
|
goto CLEANUP;
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass=TEST_FAIL;
|
|
|
|
//check the implied properties
|
|
if(!GetProp(DBPROP_IRowsetChange))
|
|
goto CLEANUP;
|
|
|
|
if(!GetProp(DBPROP_OWNINSERT))
|
|
goto CLEANUP;
|
|
|
|
if(GetProp(DBPROP_OTHERINSERT))
|
|
goto CLEANUP;
|
|
|
|
if(!CheckProp(DBPROPVAL_UP_INSERT))
|
|
goto CLEANUP;
|
|
|
|
//insert should fail
|
|
if(CHECK(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,NULL,NULL,NULL),DB_E_BADACCESSORHANDLE))
|
|
fTestPass=TEST_PASS;
|
|
CLEANUP:
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
pHRow=NULL;
|
|
}
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//--------------------------------------------------------------------
|
|
// @mfunc AppendOnly conflict with DBPROP_CANSCROLLBACKWARDS, and OTHERINSERT.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int AppendOnly::Variation_2()
|
|
{
|
|
ICommandProperties *pICommandProperties=NULL;
|
|
DBPROPSET DBPropSet;
|
|
DBPROP rgDBProp[5];
|
|
BOOL fTestPass=TEST_FAIL;
|
|
//ULONG cCount;
|
|
|
|
DBPropSet.guidPropertySet=DBPROPSET_ROWSET;
|
|
DBPropSet.cProperties=5;
|
|
DBPropSet.rgProperties=rgDBProp;
|
|
|
|
rgDBProp[0].dwPropertyID=DBPROP_APPENDONLY;
|
|
rgDBProp[0].dwOptions=DBPROPOPTIONS_REQUIRED;
|
|
rgDBProp[0].colid = DB_NULLID;
|
|
rgDBProp[0].vValue.vt=VT_BOOL;
|
|
V_BOOL(&rgDBProp[0].vValue)=VARIANT_TRUE;
|
|
|
|
rgDBProp[1].dwPropertyID=DBPROP_IRowsetChange;
|
|
rgDBProp[1].dwOptions=DBPROPOPTIONS_REQUIRED;
|
|
rgDBProp[1].colid = DB_NULLID;
|
|
rgDBProp[1].vValue.vt=VT_BOOL;
|
|
V_BOOL(&rgDBProp[1].vValue)=VARIANT_TRUE;
|
|
|
|
rgDBProp[2].dwPropertyID=DBPROP_OTHERINSERT;
|
|
rgDBProp[2].dwOptions=DBPROPOPTIONS_REQUIRED;
|
|
rgDBProp[2].colid = DB_NULLID;
|
|
rgDBProp[2].vValue.vt=VT_BOOL;
|
|
V_BOOL(&rgDBProp[2].vValue)=VARIANT_TRUE;
|
|
|
|
rgDBProp[3].dwPropertyID=DBPROP_CANFETCHBACKWARDS;
|
|
rgDBProp[3].dwOptions=DBPROPOPTIONS_REQUIRED;
|
|
rgDBProp[3].colid = DB_NULLID;
|
|
rgDBProp[3].vValue.vt=VT_BOOL;
|
|
V_BOOL(&rgDBProp[3].vValue)=VARIANT_TRUE;
|
|
|
|
rgDBProp[4].dwPropertyID=DBPROP_CANSCROLLBACKWARDS;
|
|
rgDBProp[4].dwOptions=DBPROPOPTIONS_REQUIRED;
|
|
rgDBProp[4].colid = DB_NULLID;
|
|
rgDBProp[4].vValue.vt=VT_BOOL;
|
|
V_BOOL(&rgDBProp[4].vValue)=VARIANT_TRUE;
|
|
|
|
if(!SUCCEEDED(SetRowsetProperties(&DBPropSet, 1)))
|
|
goto CLEANUP;
|
|
|
|
//create the rowset object
|
|
CreateRowsetObject(SELECT_ALLFROMTBL,IID_IRowset,EXECUTE_IFNOERROR);
|
|
|
|
fTestPass=TEST_PASS;
|
|
//conflicting
|
|
//none fo the above a level zero strict i believe
|
|
// for(cCount=0; cCount<5; cCount++)
|
|
// {
|
|
// if(cCount==1)
|
|
// {
|
|
// if(!COMPARE((DBPropSet.rgProperties)[cCount].dwStatus, DBPROPSTATUS_OK))
|
|
// goto CLEANUP;
|
|
// }
|
|
// else
|
|
// {
|
|
// if(!COMPARE((DBPropSet.rgProperties)[cCount].dwStatus, DBPROPSTATUS_CONFLICTING))
|
|
// goto CLEANUP;
|
|
// }
|
|
// }
|
|
CLEANUP:
|
|
SAFE_RELEASE(pICommandProperties);
|
|
|
|
if(fTestPass)
|
|
return TEST_PASS;
|
|
else
|
|
return TEST_FAIL;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE()
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc the rowset is empty.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int AppendOnly::Variation_3()
|
|
{
|
|
DBCOUNTITEM cRows = 0;
|
|
HROW *pHRow = NULL;
|
|
DBPROPID rgDBPropID[1];
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
|
|
rgDBPropID[0]=DBPROP_APPENDONLY;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgDBPropID,0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass = TEST_FAIL;
|
|
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
//get next rows should return DB_E_BADSTARTPOSITION
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),DB_S_ENDOFROWSET);
|
|
|
|
//no row should be retrieved
|
|
if(!COMPARE(cRows, 0))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass=TEST_PASS;
|
|
CLEANUP:
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
pHRow=NULL;
|
|
}
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
// {{ TCW_VAR_PROTOTYPE()
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc REFRESH/RESYNC, should not bring back old rows.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int AppendOnly::Variation_4()
|
|
{
|
|
ULONG cRows = 0;
|
|
HROW HRow = NULL;
|
|
DBPROPID rgDBPropID[3];
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
void *pData = NULL;
|
|
IRowsetResynch *pIRowsetResynch = NULL;
|
|
DBCOUNTITEM cRowsResynched = -1;
|
|
HROW *rghRowsResynched = NULL;
|
|
|
|
|
|
rgDBPropID[0]=DBPROP_APPENDONLY;
|
|
rgDBPropID[2]=DBPROP_IRowsetChange;
|
|
rgDBPropID[1]=DBPROP_IRowsetResynch;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgDBPropID,0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
fTestPass = TEST_FAIL;
|
|
|
|
//get the resynch interface
|
|
if(!VerifyInterface(m_pIRowset, IID_IRowsetResynch,ROWSET_INTERFACE,(IUnknown **)&pIRowsetResynch))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//resync all the rows, since this rowset only show just inserted rows this should come back empty
|
|
TESTC_(pIRowsetResynch->ResynchRows(0, NULL, &cRowsResynched, &rghRowsResynched, NULL),S_OK);
|
|
|
|
//no row should be retrieved
|
|
if(!COMPARE(cRowsResynched, 0))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert a row
|
|
if(CHECK(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&HRow),S_OK))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//resync all the rows, since this rowset only show just inserted rows this should come back 1
|
|
TESTC_(pIRowsetResynch->ResynchRows(0, NULL, &cRowsResynched, &rghRowsResynched, NULL),S_OK);
|
|
|
|
//no row should be retrieved
|
|
if(!COMPARE(cRowsResynched, 1))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
fTestPass=TRUE;
|
|
CLEANUP:
|
|
//release SetData buffers
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
SAFE_RELEASE(pIRowsetResynch);
|
|
|
|
//release the row handle
|
|
if(HRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &HRow, NULL,NULL,NULL),S_OK);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}// {{ TCW_VAR_PROTOTYPE()
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc RestartPosition/Get fetches only newlyinserted rows.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int AppendOnly::Variation_5()
|
|
{
|
|
DBCOUNTITEM cRows = 0;
|
|
DBPROPID rgDBPropID[1];
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
void *pData = NULL;
|
|
void *pData1 = NULL;
|
|
HROW *pHRow = NULL;
|
|
|
|
|
|
rgDBPropID[0]=DBPROP_APPENDONLY;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,1,rgDBPropID,0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
fTestPass = TEST_FAIL;
|
|
|
|
//insert a row at the begining of the rowset
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert a row
|
|
if(!CHECK(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,NULL),S_OK))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//position at the start
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
//get next rows should return the row just inserted
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
|
|
//one row should be retrieved
|
|
if(!COMPARE(cRows, 1))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//GetData
|
|
//get the data from the row
|
|
SAFE_ALLOC(pData1, BYTE, m_cRowSize);
|
|
memset(pData1, 0, (size_t)m_cRowSize);
|
|
TESTC_(m_pIRowset->GetData(*pHRow,m_hAccessor,pData1),S_OK);
|
|
|
|
//should be able to see the new row first, data buffers should match
|
|
if(!CompareBuffer(pData1,pData,m_cBinding,m_rgBinding, m_pIMalloc,TRUE))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
|
|
//get next rows should now being moving off the rowsert
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),DB_S_ENDOFROWSET);
|
|
|
|
fTestPass = TEST_PASS;
|
|
CLEANUP:
|
|
//release pData buffers
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
PROVIDER_FREE(pData1);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
pHRow=NULL;
|
|
}
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}// {{ TCW_VAR_PROTOTYPE()
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Change newly inserted row.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int AppendOnly::Variation_6()
|
|
{
|
|
DBCOUNTITEM cRows = 0;
|
|
HROW HRow = NULL;
|
|
DBPROPID rgDBPropID[1];
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
void *pData = NULL;
|
|
void *pData1 = NULL;
|
|
void *pData2 = NULL;
|
|
BOOL fChangeRow = FALSE;
|
|
HROW hRow = NULL;
|
|
HROW *pHRow = NULL;
|
|
|
|
|
|
rgDBPropID[0]=DBPROP_APPENDONLY;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(USE_SUPPORTED_SELECT_ALLFROMTBL,1,rgDBPropID,0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
fTestPass = TEST_FAIL;
|
|
|
|
//get value of DBPROP_CHANGEINSERTEDROWS for this rowset
|
|
if(GetProp(DBPROP_CHANGEINSERTEDROWS))
|
|
{
|
|
fChangeRow = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fChangeRow = FALSE;
|
|
}
|
|
|
|
//make a data buffer
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert row
|
|
if(!CHECK(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&HRow),S_OK))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//make a new buffer
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData1,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
if(fChangeRow)
|
|
{
|
|
//change the row with the new buffer
|
|
TESTC_(m_pIRowsetChange->SetData(HRow,m_hAccessor,pData1),S_OK);
|
|
}
|
|
else
|
|
{
|
|
TESTC_(m_pIRowsetChange->SetData(HRow,m_hAccessor,pData1),DB_E_NEWLYINSERTED);
|
|
}
|
|
|
|
//release the row handle
|
|
if(HRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &HRow, NULL,NULL,NULL),S_OK);
|
|
|
|
//re-position at the start
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
//get next rows should return the row just inserted
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
|
|
//one row should be retrieved
|
|
if(!COMPARE(cRows, 1))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//GetData
|
|
//get the data from the row
|
|
SAFE_ALLOC(pData2, BYTE, m_cRowSize);
|
|
memset(pData2, 0, (size_t)m_cRowSize);
|
|
TESTC_(m_pIRowset->GetData(*pHRow,m_hAccessor,pData2),S_OK);
|
|
|
|
if(fChangeRow)
|
|
{
|
|
//should be able to see the new row, data bufferes should match
|
|
if(!CompareBuffer(pData2,pData1,m_cBinding,m_rgBinding, m_pIMalloc,TRUE))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//delete the row
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,pHRow,NULL),S_OK);
|
|
}
|
|
else
|
|
{
|
|
//should be able to see the new row, data bufferes should match
|
|
if(!CompareBuffer(pData2,pData,m_cBinding,m_rgBinding, m_pIMalloc,TRUE))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,pHRow,NULL),DB_E_NEWLYINSERTED);
|
|
}
|
|
fTestPass = TRUE;
|
|
CLEANUP:
|
|
//release SetData buffers
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
PROVIDER_FREE(pData1);
|
|
PROVIDER_FREE(pData2);
|
|
|
|
//release the row handle
|
|
if(HRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &HRow, NULL,NULL,NULL),S_OK);
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
pHRow=NULL;
|
|
}
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}// {{ TCW_VAR_PROTOTYPE()
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc update pending,RestartPosition/Get fetches only newlyinserted rows.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int AppendOnly::Variation_7()
|
|
{
|
|
DBCOUNTITEM cRows = 0;
|
|
DBPROPID rgDBPropID[2];
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
void *pData = NULL;
|
|
void *pData1 = NULL;
|
|
HROW *pHRow = NULL;
|
|
BOOL fReturnPendingInsert= FALSE;
|
|
|
|
|
|
rgDBPropID[0]=DBPROP_APPENDONLY;
|
|
rgDBPropID[1]=DBPROP_IRowsetUpdate;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgDBPropID,0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
fTestPass = TEST_FAIL;
|
|
|
|
//get value of DBPROP_RETURNPENDINGINSERTS for this rowset
|
|
if(GetProp(DBPROP_RETURNPENDINGINSERTS))
|
|
{
|
|
fReturnPendingInsert = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fReturnPendingInsert = FALSE;
|
|
}
|
|
|
|
//goto the begining of the rowset
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert a row
|
|
if(!CHECK(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,NULL),S_OK))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//position at the start
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
if (fReturnPendingInsert)
|
|
{
|
|
//get next rows should return the row just inserted
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
//one row should be retrieved
|
|
if(!COMPARE(cRows, 1))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//GetData
|
|
//get the data from the row
|
|
SAFE_ALLOC(pData1, BYTE, m_cRowSize);
|
|
memset(pData1, 0, (size_t)m_cRowSize);
|
|
TESTC_(m_pIRowset->GetData(*pHRow,m_hAccessor,pData1),S_OK);
|
|
|
|
//should be able to see the new row first, data buffers should match
|
|
if(!CompareBuffer(pData1,pData,m_cBinding,m_rgBinding, m_pIMalloc,TRUE))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
PROVIDER_FREE(pData1);
|
|
}
|
|
else
|
|
{
|
|
//get next rows should return the row just inserted
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),DB_S_ENDOFROWSET);
|
|
//one row should be retrieved
|
|
if(!COMPARE(cRows, 0))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
//update (all pendig updates) the insert to the back end
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),S_OK);
|
|
|
|
//free the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
pHRow=NULL;
|
|
}
|
|
|
|
//restart
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
//get next rows should return the row just inserted
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
//one row should be retrieved
|
|
if(!COMPARE(cRows, 1))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//GetData
|
|
//get the data from the row
|
|
SAFE_ALLOC(pData1, BYTE, m_cRowSize);
|
|
memset(pData1, 0, (size_t)m_cRowSize);
|
|
TESTC_(m_pIRowset->GetData(*pHRow,m_hAccessor,pData1),S_OK);
|
|
|
|
//should be able to see the new row first, data buffers should match
|
|
if(!CompareBuffer(pData1,pData,m_cBinding,m_rgBinding, m_pIMalloc,TRUE))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
|
|
//get next rows should now being moving off the rowsert
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),DB_S_ENDOFROWSET);
|
|
|
|
fTestPass = TEST_PASS;
|
|
CLEANUP:
|
|
//release pData buffers
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
PROVIDER_FREE(pData1);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
pHRow=NULL;
|
|
}
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}// {{ TCW_VAR_PROTOTYPE()
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc update pending,REFRESH/RESYNC, should not bring back old rows.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int AppendOnly::Variation_8()
|
|
{
|
|
ULONG cRows = 0;
|
|
HROW HRow = NULL;
|
|
DBPROPID rgDBPropID[2];
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
void *pData = NULL;
|
|
IRowsetResynch *pIRowsetResynch = NULL;
|
|
IRowsetRefresh *pIRowsetRefresh = NULL;
|
|
DBCOUNTITEM cRowsResynched = -1;
|
|
HROW *rghRowsResynched = NULL;
|
|
|
|
|
|
rgDBPropID[0]=DBPROP_APPENDONLY;
|
|
rgDBPropID[1]=DBPROP_IRowsetUpdate;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgDBPropID,0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//get the resynch interface or the refresh interface
|
|
if(!VerifyInterface(m_pIRowset, IID_IRowsetResynch,ROWSET_INTERFACE,(IUnknown **)&pIRowsetResynch))
|
|
{
|
|
if(!VerifyInterface(m_pIRowset, IID_IRowsetRefresh,ROWSET_INTERFACE,(IUnknown **)&pIRowsetRefresh))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass = TEST_FAIL;
|
|
|
|
if (pIRowsetResynch)
|
|
{
|
|
//resync all the rows, since this rowset only show just inserted rows this should come back empty
|
|
TESTC_(pIRowsetResynch->ResynchRows(0, NULL, &cRowsResynched, &rghRowsResynched, NULL),S_OK);
|
|
}
|
|
else
|
|
{
|
|
//refresh all the rows, since this rowset only show just inserted rows this should come back empty
|
|
TESTC_(pIRowsetRefresh->RefreshVisibleData(0, 0, NULL, TRUE, &cRowsResynched, &rghRowsResynched, NULL),S_OK);
|
|
}
|
|
|
|
//no row should be retrieved
|
|
if(!COMPARE(cRowsResynched, 0))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert a row
|
|
if(!CHECK(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&HRow),S_OK))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
if (pIRowsetResynch)
|
|
{
|
|
//resync all the rows, since this rowset only show just inserted rows this should come back 1
|
|
TESTC_(pIRowsetResynch->ResynchRows(0, NULL, &cRowsResynched, &rghRowsResynched, NULL),S_OK);
|
|
}
|
|
else
|
|
{
|
|
//refresh all the rows, since this rowset only show just inserted rows this should come back 1
|
|
TESTC_(pIRowsetRefresh->RefreshVisibleData(0, 0, NULL, TRUE, &cRowsResynched, &rghRowsResynched, NULL),S_OK);
|
|
}
|
|
|
|
//no row should be retrieved
|
|
if(!COMPARE(cRowsResynched, 1))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//update (all pending updates) the insert to the back end
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),S_OK);
|
|
|
|
fTestPass=TRUE;
|
|
CLEANUP:
|
|
//release SetData buffers
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
SAFE_RELEASE(pIRowsetResynch);
|
|
SAFE_RELEASE(pIRowsetRefresh);
|
|
|
|
//release the row handle
|
|
if(HRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1, &HRow, NULL,NULL,NULL),S_OK);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}// {{ TCW_VAR_PROTOTYPE()
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc update pending,Commit.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int AppendOnly::Variation_9()
|
|
{
|
|
ITransactionLocal *pITransactionLocal = NULL;
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
ULONG ulTransactionLevel = 0;
|
|
BOOL fCommitPerserve = FALSE;
|
|
DBPROPID rgDBPropID[2];
|
|
void *pData = NULL;
|
|
void *pData1 = NULL;
|
|
BOOL fReturnPendingInsert= FALSE;
|
|
|
|
|
|
rgDBPropID[0] = DBPROP_APPENDONLY;
|
|
rgDBPropID[1] = DBPROP_IRowsetUpdate;
|
|
|
|
//Get ITransactionLocal on test session
|
|
if(!VerifyInterface(m_pIOpenRowset, IID_ITransactionLocal, SESSION_INTERFACE, (IUnknown **)&pITransactionLocal))
|
|
{
|
|
odtLog << L"ITransactionLocal not supported.\n";
|
|
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,2,rgDBPropID,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
|
|
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
|
|
UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
if (!m_pIRowsetChange)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass=TEST_FAIL;
|
|
|
|
//get value of DBPROP_COMMITPERSERVE for this rowset
|
|
if(GetProp(DBPROP_COMMITPRESERVE))
|
|
{
|
|
fCommitPerserve = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fCommitPerserve = FALSE;
|
|
}
|
|
|
|
//get value of DBPROP_RETURNPENDINGINSERTS for this rowset
|
|
if(GetProp(DBPROP_RETURNPENDINGINSERTS))
|
|
{
|
|
fReturnPendingInsert = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fReturnPendingInsert = FALSE;
|
|
}
|
|
|
|
//insert a row at the begining of the rowset
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert a row
|
|
if(!CHECK(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,NULL),S_OK))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//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_SKIPPED. \n";
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fCommitPerserve)
|
|
{
|
|
if (fReturnPendingInsert)
|
|
{
|
|
//get next rows should return the row just inserted
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
//one row should be retrieved
|
|
if(!COMPARE(cRows, 1))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//GetData
|
|
//get the data from the row
|
|
SAFE_ALLOC(pData1, BYTE, m_cRowSize);
|
|
memset(pData1, 0, (size_t)m_cRowSize);
|
|
TESTC_(m_pIRowset->GetData(*pHRow,m_hAccessor,pData1),S_OK);
|
|
|
|
//should be able to see the new row first, data buffers should match
|
|
if(!CompareBuffer(pData1,pData,m_cBinding,m_rgBinding, m_pIMalloc,TRUE))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
PROVIDER_FREE(pData1);
|
|
}
|
|
else
|
|
{
|
|
//get next rows should return the row just inserted
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),DB_S_ENDOFROWSET);
|
|
//one row should be retrieved
|
|
if(!COMPARE(cRows, 0))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
//update (all pendig updates) the insert to the back end
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),S_OK);
|
|
|
|
//free the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
pHRow=NULL;
|
|
}
|
|
|
|
//restart
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
//get next rows should return the row just inserted
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
//one row should be retrieved
|
|
if(!COMPARE(cRows, 1))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//GetData
|
|
//get the data from the row
|
|
SAFE_ALLOC(pData1, BYTE, m_cRowSize);
|
|
memset(pData1, 0, (size_t)m_cRowSize);
|
|
TESTC_(m_pIRowset->GetData(*pHRow,m_hAccessor,pData1),S_OK);
|
|
|
|
//should be able to see the new row first, data buffers should match
|
|
if(!CompareBuffer(pData1,pData,m_cBinding,m_rgBinding, m_pIMalloc,TRUE))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
|
|
//get next rows should now being moving off the rowsert
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),DB_S_ENDOFROWSET);
|
|
}
|
|
fTestPass=TEST_PASS;
|
|
CLEANUP:
|
|
SAFE_RELEASE(pITransactionLocal);
|
|
//release pData buffers
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
PROVIDER_FREE(pData1);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
pHRow=NULL;
|
|
}
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}// {{ TCW_VAR_PROTOTYPE()
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc update pending,Abort.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int AppendOnly::Variation_10()
|
|
{
|
|
ITransactionLocal *pITransactionLocal = NULL;
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
ULONG ulTransactionLevel = 0;
|
|
BOOL fAbortPerserve = FALSE;
|
|
DBPROPID rgDBPropID[2];
|
|
void *pData = NULL;
|
|
|
|
|
|
rgDBPropID[0] = DBPROP_APPENDONLY;
|
|
rgDBPropID[1] = DBPROP_IRowsetUpdate;
|
|
|
|
//Get ITransactionLocal on test session
|
|
if(!VerifyInterface(m_pIOpenRowset, IID_ITransactionLocal, SESSION_INTERFACE, (IUnknown **)&pITransactionLocal))
|
|
{
|
|
odtLog << L"ITransactionLocal not supported.\n";
|
|
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,2,rgDBPropID,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
|
|
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
|
|
UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
if (!m_pIRowsetChange)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass=TEST_FAIL;
|
|
|
|
//get value of DBPROP_ABORTPERSERVE for this rowset
|
|
if(GetProp(DBPROP_ABORTPRESERVE))
|
|
{
|
|
fAbortPerserve = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fAbortPerserve = FALSE;
|
|
}
|
|
|
|
//insert a row at the begining of the rowset
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert a row
|
|
if(!CHECK(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,NULL),S_OK))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//update (all pending) the insert to the back end
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),S_OK);
|
|
|
|
//abort the session
|
|
if(!COMPARE(pITransactionLocal->Abort(NULL, FALSE, FALSE),S_OK))
|
|
{
|
|
//abort not retaining not supported
|
|
odtLog << L"Non-Retaining Abort not supported, returning TEST_SKIPPED. \n";
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
if (fAbortPerserve)
|
|
{
|
|
//position at the start
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
//get next rows should not see end-of-rowset, the insert was aborted but the buffer should be there
|
|
if(CHECK(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),DB_S_ENDOFROWSET))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//get the data, pending inserts that are aborted should look like a deleted row
|
|
TESTC_(m_pIRowsetUpdate->GetOriginalData(*pHRow,m_hAccessor,pData),DB_E_DELETEDROW);
|
|
|
|
//one row should be retrieved
|
|
if(!COMPARE(cRows, 0))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
fTestPass=TEST_PASS;
|
|
CLEANUP:
|
|
//abort just in case
|
|
pITransactionLocal->Abort(NULL, FALSE, FALSE);
|
|
SAFE_RELEASE(pITransactionLocal);
|
|
//release pData buffers
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
pHRow=NULL;
|
|
}
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}// {{ TCW_VAR_PROTOTYPE()
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Commit.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int AppendOnly::Variation_11()
|
|
{
|
|
ITransactionLocal *pITransactionLocal = NULL;
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
ULONG ulTransactionLevel = 0;
|
|
BOOL fCommitPerserve = FALSE;
|
|
DBPROPID rgDBPropID[1];
|
|
void *pData = NULL;
|
|
void *pData1 = NULL;
|
|
|
|
|
|
rgDBPropID[0] = DBPROP_APPENDONLY;
|
|
|
|
//Get ITransactionLocal on test session
|
|
if(!VerifyInterface(m_pIOpenRowset, IID_ITransactionLocal, SESSION_INTERFACE, (IUnknown **)&pITransactionLocal))
|
|
{
|
|
odtLog << L"ITransactionLocal not supported.\n";
|
|
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,rgDBPropID,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
|
|
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
|
|
UPDATEABLE_COLS_BOUND));
|
|
|
|
|
|
if (!m_pIRowsetChange)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass=TEST_FAIL;
|
|
|
|
//get value of DBPROP_COMMITPERSERVE for this rowset
|
|
if(GetProp(DBPROP_COMMITPRESERVE))
|
|
{
|
|
fCommitPerserve = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fCommitPerserve = FALSE;
|
|
}
|
|
|
|
//insert a row at the begining of the rowset
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert a row
|
|
if(!CHECK(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,NULL),S_OK))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//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_SKIPPED. \n";
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fCommitPerserve)
|
|
{
|
|
//position at the start
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
//get next rows should return the row just inserted
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
|
|
//one row should be retrieved
|
|
if(!COMPARE(cRows, 1))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//GetData
|
|
//get the data from the row
|
|
SAFE_ALLOC(pData1, BYTE, m_cRowSize);
|
|
memset(pData1, 0, (size_t)m_cRowSize);
|
|
TESTC_(m_pIRowset->GetData(*pHRow,m_hAccessor,pData1),S_OK);
|
|
|
|
//should be able to see the new row first, data buffers should match
|
|
if(!CompareBuffer(pData1,pData,m_cBinding,m_rgBinding, m_pIMalloc,TRUE))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
|
|
//get next rows should now being moving off the rowsert
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),DB_S_ENDOFROWSET);
|
|
}
|
|
fTestPass=TEST_PASS;
|
|
CLEANUP:
|
|
SAFE_RELEASE(pITransactionLocal);
|
|
//release pData buffers
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
PROVIDER_FREE(pData1);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
pHRow=NULL;
|
|
}
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}// {{ TCW_VAR_PROTOTYPE()
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Abort.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int AppendOnly::Variation_12()
|
|
{
|
|
ITransactionLocal *pITransactionLocal = NULL;
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
HROW *pHRow = NULL;
|
|
DBCOUNTITEM cRows = 0;
|
|
ULONG ulTransactionLevel = 0;
|
|
BOOL fAbortPerserve = FALSE;
|
|
DBPROPID rgDBPropID[2];
|
|
void *pData = NULL;
|
|
|
|
|
|
rgDBPropID[0] = DBPROP_APPENDONLY;
|
|
rgDBPropID[1] = DBPROP_RETURNPENDINGINSERTS;
|
|
|
|
//Get ITransactionLocal on test session
|
|
if(!VerifyInterface(m_pIOpenRowset, IID_ITransactionLocal, SESSION_INTERFACE, (IUnknown **)&pITransactionLocal))
|
|
{
|
|
odtLog << L"ITransactionLocal not supported.\n";
|
|
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,2,rgDBPropID,0,NULL,ON_ROWSET_ACCESSOR, FALSE,
|
|
DBACCESSOR_ROWDATA,DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
|
|
UPDATEABLE_COLS_BOUND));
|
|
|
|
|
|
if (!m_pIRowsetChange)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass=TEST_FAIL;
|
|
|
|
//get value of DBPROP_ABORTPERSERVE for this rowset
|
|
if(GetProp(DBPROP_ABORTPRESERVE))
|
|
{
|
|
fAbortPerserve = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fAbortPerserve = FALSE;
|
|
}
|
|
|
|
//insert a row at the begining of the rowset
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert a row
|
|
if(!CHECK(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,NULL),S_OK))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//abort the session
|
|
if(!COMPARE(pITransactionLocal->Abort(NULL, FALSE, FALSE),S_OK))
|
|
{
|
|
//abort not retaining not supported
|
|
odtLog << L"Non-Retaining Abort not supported, returning TEST_SKIPPED. \n";
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
if (fAbortPerserve)
|
|
{
|
|
//position at the start
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
//get next rows should the pending inserted row, abort only affects the back end
|
|
TESTC_(m_pIRowset->GetNextRows(NULL,0,1,&cRows,&pHRow),S_OK);
|
|
|
|
//one row should be retrieved
|
|
if(!COMPARE(cRows, 1))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
fTestPass=TEST_PASS;
|
|
CLEANUP:
|
|
pITransactionLocal->Abort(NULL, FALSE, FALSE);
|
|
SAFE_RELEASE(pITransactionLocal);
|
|
//release pData buffers
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
//release the row handle
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
pHRow=NULL;
|
|
}
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}// }}
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL AppendOnly::Terminate()
|
|
{
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
// {{ TCW_TC_PROTOTYPE(BMK_Static_Buffered_OwnInsert)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: BMK_Static_Buffered_OwnInsert - Test static cursors capable of seeing their own inserts
|
|
//| Created: 5-27-98
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL BMK_Static_Buffered_OwnInsert::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[4];
|
|
BOOL fTestPass=TEST_SKIPPED;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetLocate;
|
|
rgDBPROPID[2]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[3]=DBPROP_OWNINSERT;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
COMPC(BufferedUpdate(), TRUE);
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Test visibility of newly inserted row
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int BMK_Static_Buffered_OwnInsert::Variation_1()
|
|
{
|
|
void *pData=NULL;
|
|
DBBOOKMARK DBBookmark=DBBMK_FIRST;
|
|
BYTE *pBookmark=(BYTE *)&DBBookmark;
|
|
HROW hRow=DB_NULL_HROW;
|
|
BOOL fTestPass=FALSE;
|
|
|
|
//make data for insert. Insert the first row
|
|
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(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),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=DB_NULL_HROW;
|
|
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
// Check that the newly inserted row is visible
|
|
TESTC(fTestPass = CheckRowVisible(m_pIRowset, pData, CHECK_ROWVISIBLE));
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow, NULL,NULL,NULL), S_OK);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL BMK_Static_Buffered_OwnInsert::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Buffered_ReturnPendingInsert)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Buffered_ReturnPendingInsert - Check ReturnPendingInsert property
|
|
//| Created: 5-27-98
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Buffered_ReturnPendingInsert::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[3];
|
|
BOOL fTestPass=TEST_SKIPPED;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[2]=DBPROP_RETURNPENDINGINSERTS;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
COMPC(BufferedUpdate(), TRUE);
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Soft Insert, check visibility
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Buffered_ReturnPendingInsert::Variation_1()
|
|
{
|
|
void *pData=NULL;
|
|
DBBOOKMARK DBBookmark=DBBMK_FIRST;
|
|
BYTE *pBookmark=(BYTE *)&DBBookmark;
|
|
HROW hRow=DB_NULL_HROW;
|
|
BOOL fTestPass=FALSE;
|
|
|
|
//make data for insert. Insert the first row
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//soft insert a new row.
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),S_OK);
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,&hRow,NULL,NULL,NULL),S_OK);
|
|
hRow=DB_NULL_HROW;
|
|
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
|
|
// Check that the newly inserted row is visible
|
|
// Should be visible because DBPROP_RETURNPENDINGINSERTS was requested
|
|
TESTC(fTestPass = CheckRowVisible(m_pIRowset, pData, CHECK_ROWVISIBLE));
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),S_OK);
|
|
|
|
TESTC(SUCCEEDED(m_pIRowset->RestartPosition(NULL)));
|
|
// Check that visibility of transmitted row
|
|
if(GetProperty(DBPROP_OWNINSERT, DBPROPSET_ROWSET, m_pIRowset, VARIANT_TRUE))
|
|
{
|
|
TESTC(fTestPass = CheckRowVisible(m_pIRowset, pData, CHECK_ROWVISIBLE));
|
|
}
|
|
else
|
|
{
|
|
TESTC(fTestPass = CheckRowVisible(m_pIRowset, pData, CHECK_ROWNOTVISIBLE));
|
|
}
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pData);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow, NULL,NULL,NULL), S_OK);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL Buffered_ReturnPendingInsert::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Immediate_ServerDataOnInsert)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Immediate_ServerDataOnInsert - Test retrieval of bookmarks on newly inserted rows
|
|
//| Created: 5-27-98
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Immediate_ServerDataOnInsert::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[5];
|
|
BOOL fTestPass=TEST_SKIPPED;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetLocate;
|
|
rgDBPROPID[2]=DBPROP_SERVERDATAONINSERT;
|
|
rgDBPROPID[3]=DBPROP_OWNINSERT;
|
|
rgDBPROPID[4]=DBPROP_CANHOLDROWS;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Test visibility of bookmark
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Immediate_ServerDataOnInsert::Variation_1()
|
|
{
|
|
void *pData=NULL;
|
|
DBBKMARK cbBookmark;
|
|
DBBOOKMARK DBBookmark=DBBMK_LAST;
|
|
BYTE *pLastBookmark=(BYTE *)&DBBookmark;
|
|
BYTE *pBookmark=NULL;
|
|
HROW hRowNew=NULL;
|
|
HROW *pNewHRow=&hRowNew;
|
|
HROW HRow=NULL;
|
|
BOOL fTestPass=FALSE;
|
|
|
|
//make data for insert. Insert the the seond row row
|
|
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(DB_NULL_HCHAPTER,m_hAccessor,pData,pNewHRow),S_OK);
|
|
|
|
//Get a bookmark - must be visible since SERVERDATAONINSERT is on.
|
|
TESTC_(GetBookmarkByRow(hRowNew, &cbBookmark, &pBookmark),S_OK);
|
|
|
|
//Get the row by IRowsetLocate::GetRowsByBookmark
|
|
TESTC_(m_pIRowsetLocate->GetRowsByBookmark(NULL,1,&cbBookmark,(const BYTE **)&pBookmark,&HRow,NULL),S_OK);
|
|
|
|
//GetData
|
|
TESTC_(m_pIRowset->GetData(HRow,m_hAccessor,m_pData),S_OK);
|
|
|
|
//should be able to see the changes
|
|
if(!CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding, m_pIMalloc,TRUE))
|
|
goto CLEANUP;
|
|
|
|
//IsSameRow should return S_OK
|
|
if(StrongIdentity())
|
|
TESTC_(m_pIRowsetIdentity->IsSameRow(HRow, hRowNew),S_OK);
|
|
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
//release the bookmark
|
|
PROVIDER_FREE(pBookmark);
|
|
PROVIDER_FREE(pData);
|
|
|
|
if(HRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&HRow, NULL,NULL,NULL), S_OK);
|
|
|
|
if(hRowNew)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRowNew, NULL,NULL,NULL), S_OK);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL Immediate_ServerDataOnInsert::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Buffered_ServerDataOnInsert)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Buffered_ServerDataOnInsert - Test retrieval of bookmarks on newly inserted rows
|
|
//| Created: 5-27-98
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Buffered_ServerDataOnInsert::Init()
|
|
{
|
|
DBPROPID rgDBPROPID[6];
|
|
BOOL fTestPass=TEST_SKIPPED;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetLocate;
|
|
rgDBPROPID[2]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[3]=DBPROP_CANHOLDROWS;
|
|
rgDBPROPID[4]=DBPROP_SERVERDATAONINSERT;
|
|
rgDBPROPID[5]=DBPROP_OWNINSERT;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
COMPC(BufferedUpdate(), TRUE);
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Test visibility of bookmark
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Buffered_ServerDataOnInsert::Variation_1()
|
|
{
|
|
void *pData = NULL;
|
|
DBBKMARK cbBookmark = 0;
|
|
BYTE *pBookmark = NULL;
|
|
HROW HRow = NULL;
|
|
HROW hRowNew = NULL;
|
|
BOOL fTestPass = FALSE;
|
|
|
|
//make data for insert. Insert the the last row
|
|
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(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRowNew),S_OK);
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&hRowNew,NULL,NULL,NULL),S_OK);
|
|
|
|
// Get a bookmark
|
|
TESTC_(GetBookmarkByRow(hRowNew, &cbBookmark, &pBookmark),S_OK);
|
|
|
|
//Get the row by IRowsetLocate::GetRowsByBookmark
|
|
TESTC_(m_pIRowsetLocate->GetRowsByBookmark(NULL,1,&cbBookmark,(const BYTE **)&pBookmark,&HRow,NULL),S_OK);
|
|
|
|
//GetData
|
|
TESTC_(m_pIRowset->GetData(HRow,m_hAccessor,m_pData),S_OK);
|
|
|
|
//should be able to see the changes
|
|
if(CompareBuffer(m_pData,pData,m_cBinding,m_rgBinding, m_pIMalloc,TRUE))
|
|
fTestPass=TRUE;
|
|
|
|
CLEANUP:
|
|
//release the bookmark
|
|
PROVIDER_FREE(pBookmark);
|
|
PROVIDER_FREE(pData);
|
|
|
|
if(HRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(1,&HRow, NULL,NULL,NULL), S_OK);
|
|
}
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL Buffered_ServerDataOnInsert::Terminate()
|
|
{
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Immediate_ChangeInsertedRow)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Immediate_ChangeInsertedRow - Test DBPROP_CHANGEINSERTEDROW
|
|
//| Created: 5-27-98
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Immediate_ChangeInsertedRow::Init()
|
|
{
|
|
BOOL fTestPass=FALSE;
|
|
DBPROPID rgDBPROPID[2];
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_CHANGEINSERTEDROWS;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND));
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
ReleaseRowsetAndAccessor();
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Explicitly request ChangeInsertedRows
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Immediate_ChangeInsertedRow::Variation_1()
|
|
{
|
|
void *rgpData[2]={NULL,NULL};
|
|
HROW hRow=NULL;
|
|
ULONG cCount=0;
|
|
BOOL fTestPass=FALSE;
|
|
DBPROPID rgDBPROPID[2];
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_CHANGEINSERTEDROWS;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//make data for insert && change
|
|
for(cCount=0; cCount<2; 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);
|
|
}
|
|
|
|
//insert a row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[0],&hRow),S_OK);
|
|
|
|
//change the row
|
|
TESTC_(m_pIRowsetChange->SetData(hRow,m_hAccessor,rgpData[1]),S_OK);
|
|
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
hRow=DB_NULL_HROW;
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// Re-Open and check for visibility
|
|
TESTC_(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND),S_OK);
|
|
|
|
TESTC(fTestPass = CheckRowVisible(m_pIRowset, rgpData[1], CHECK_ROWVISIBLE));
|
|
|
|
CLEANUP:
|
|
//Release the row handle and memory
|
|
for(cCount=0; cCount<2; cCount++)
|
|
{
|
|
if(rgpData[cCount])
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)rgpData[cCount], TRUE);
|
|
}
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL Immediate_ChangeInsertedRow::Terminate()
|
|
{
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Buffered_ChangeInsertedRow)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Buffered_ChangeInsertedRow - Test DBPROP_CHANGEINSERTEDROW in buffered mode
|
|
//| Created: 5-27-98
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL Buffered_ChangeInsertedRow::Init()
|
|
{
|
|
BOOL fTestPass=FALSE;
|
|
DBPROPID rgDBPROPID[3];
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[2]=DBPROP_CHANGEINSERTEDROWS;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND));
|
|
|
|
COMPC(BufferedUpdate(), TRUE);
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
ReleaseRowsetAndAccessor();
|
|
return fTestPass;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Explicitly request ChangeInsertedRows in buffered mode
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Buffered_ChangeInsertedRow::Variation_1()
|
|
{
|
|
void *rgpData[2]={NULL,NULL};
|
|
HROW hRow=NULL;
|
|
ULONG cCount=0;
|
|
BOOL fTestPass=FALSE;
|
|
DBPROPID rgDBPROPID[3];
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[2]=DBPROP_CHANGEINSERTEDROWS;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//make data for insert && change
|
|
for(cCount=0; cCount<2; 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);
|
|
}
|
|
|
|
//insert a row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[0],&hRow),S_OK);
|
|
|
|
//change the row
|
|
TESTC_(m_pIRowsetChange->SetData(hRow,m_hAccessor,rgpData[1]),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=DB_NULL_HROW;
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// Re-Open and check for visibility
|
|
TESTC_(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
TESTC(fTestPass = CheckRowVisible(m_pIRowset, rgpData[1], CHECK_ROWVISIBLE));
|
|
|
|
|
|
CLEANUP:
|
|
//Release the row handle and memory
|
|
for(cCount=0; cCount<2; cCount++)
|
|
{
|
|
if(rgpData[cCount])
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)rgpData[cCount], TRUE);
|
|
}
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Delete a newly inserted row
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Buffered_ChangeInsertedRow::Variation_2()
|
|
{
|
|
void *pData=NULL;
|
|
HROW hRow=NULL;
|
|
BOOL fTestPass=FALSE;
|
|
DBROWSTATUS *pDBRowStatus=NULL;
|
|
DBPROPID rgDBPROPID[3];
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[2]=DBPROP_CHANGEINSERTEDROWS;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//make data for the last row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,
|
|
m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert a row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),S_OK);
|
|
|
|
//delete the row
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,&hRow,NULL),S_OK);
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&hRow,NULL,NULL,&pDBRowStatus),DB_E_ERRORSOCCURRED);
|
|
COMPC(pDBRowStatus[0], DBROWSTATUS_E_DELETED); // deletion of pending insert is a hard-delete
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
hRow=DB_NULL_HROW;
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// Re-Open and check that row is not visible
|
|
TESTC_(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
TESTC(fTestPass = CheckRowVisible(m_pIRowset, pData, CHECK_ROWNOTVISIBLE));
|
|
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pDBRowStatus);
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc SetData on newly inserted followed by Delete
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Buffered_ChangeInsertedRow::Variation_3()
|
|
{
|
|
void *pData=NULL, *pSetData=NULL;
|
|
HROW hRow=NULL;
|
|
BOOL fTestPass=FALSE;
|
|
DBROWSTATUS *pDBRowStatus=NULL;
|
|
DBPROPID rgDBPROPID[3];
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[2]=DBPROP_CHANGEINSERTEDROWS;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//make data for the insert
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,
|
|
m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//make data for the setdata
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pSetData,g_ulNextRow++,m_cRowsetCols,
|
|
m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert a row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&hRow),S_OK);
|
|
|
|
//change the row
|
|
TESTC_(m_pIRowsetChange->SetData(hRow,m_hAccessor,pSetData),S_OK);
|
|
|
|
//delete the row
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,&hRow,NULL),S_OK);
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,1,&hRow,NULL,NULL,&pDBRowStatus),DB_E_ERRORSOCCURRED);
|
|
COMPC(pDBRowStatus[0], DBROWSTATUS_E_DELETED); // deletion of pending insert is a hard-delete
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1, &hRow, NULL,NULL,NULL),S_OK);
|
|
hRow=DB_NULL_HROW;
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// Re-Open and check that row is not visible
|
|
TESTC_(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
TESTC(fTestPass = CheckRowVisible(m_pIRowset, pSetData, CHECK_ROWNOTVISIBLE));
|
|
|
|
TESTC_(m_pIRowset->RestartPosition(NULL),S_OK);
|
|
TESTC(fTestPass = CheckRowVisible(m_pIRowset, pData, CHECK_ROWNOTVISIBLE));
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pDBRowStatus);
|
|
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pSetData, TRUE);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Multiple SetData on newly inserted
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Buffered_ChangeInsertedRow::Variation_4()
|
|
{
|
|
void *pInsertData=NULL, *pFirstSetData=NULL, *pSecondSetData=NULL;
|
|
HROW hRow=NULL;
|
|
BOOL fTestPass=FALSE;
|
|
DBPROPID rgDBPROPID[4];
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[2]=DBPROP_CHANGEINSERTEDROWS;
|
|
rgDBPROPID[3]=DBPROP_CANHOLDROWS;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
//make data for the insert
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pInsertData,g_ulNextRow++,m_cRowsetCols,
|
|
m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
// make data for the first setdata
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pFirstSetData,g_ulNextRow++,m_cRowsetCols,
|
|
m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//make data for the 2nd setdata
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pSecondSetData,g_ulNextRow++,m_cRowsetCols,
|
|
m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert a row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pInsertData,&hRow),S_OK);
|
|
|
|
//change the row
|
|
TESTC_(m_pIRowsetChange->SetData(hRow,m_hAccessor,pFirstSetData),S_OK);
|
|
|
|
//change the row again
|
|
TESTC_(m_pIRowsetChange->SetData(hRow,m_hAccessor,pSecondSetData),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=DB_NULL_HROW;
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// Re-Open and check that 2nd insert is visible
|
|
TESTC_(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
TESTC(fTestPass = CheckRowVisible(m_pIRowset, pSecondSetData, CHECK_ROWVISIBLE));
|
|
|
|
CLEANUP:
|
|
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pInsertData, TRUE);
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pFirstSetData, TRUE);
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pSecondSetData, TRUE);
|
|
|
|
if(hRow)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow, NULL,NULL,NULL),S_OK);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Multilpe newly Inserted and interleaved SetData and Delete ops
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int Buffered_ChangeInsertedRow::Variation_5()
|
|
{
|
|
void *rgpData[6] = {NULL,NULL,NULL,NULL,NULL,NULL};
|
|
HROW hRowFirst = DB_NULL_HROW,hRowSecond=DB_NULL_HROW,hRowThird=DB_NULL_HROW;
|
|
ULONG cCount = 0;
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
DBPROPID rgDBPROPID[4] = {DBPROP_IRowsetChange, DBPROP_IRowsetUpdate, DBPROP_CHANGEINSERTEDROWS, DBPROP_CANHOLDROWS};
|
|
ULONG_PTR cMaxPendingRows = 0;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(GetProperty(DBPROP_MAXPENDINGROWS, DBPROPSET_ROWSET, m_pIRowsetChange, &cMaxPendingRows));
|
|
if (cMaxPendingRows<3)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
fTestPass = TEST_FAIL;
|
|
|
|
//make data for insert && change
|
|
for(cCount=0; cCount<6; 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);
|
|
}
|
|
|
|
//insert a row
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[0],&hRowFirst),S_OK);
|
|
|
|
//change the first row
|
|
TESTC_(m_pIRowsetChange->SetData(hRowFirst,m_hAccessor,rgpData[1]),S_OK);
|
|
|
|
//insert two more rows
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[2],&hRowSecond),S_OK);
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,rgpData[3],&hRowThird),S_OK);
|
|
|
|
//change the third row
|
|
TESTC_(m_pIRowsetChange->SetData(hRowThird,m_hAccessor,rgpData[4]),S_OK);
|
|
|
|
// delete the second row
|
|
TESTC_(m_pIRowsetChange->DeleteRows(NULL,1,&hRowSecond,NULL),S_OK);
|
|
|
|
// change the first row again
|
|
TESTC_(m_pIRowsetChange->SetData(hRowFirst,m_hAccessor,rgpData[5]),S_OK);
|
|
|
|
//update
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),S_OK);
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1, &hRowFirst, NULL,NULL,NULL),S_OK);
|
|
TESTC_(m_pIRowset->ReleaseRows(1, &hRowSecond, NULL,NULL,NULL),S_OK);
|
|
TESTC_(m_pIRowset->ReleaseRows(1, &hRowThird, NULL,NULL,NULL),S_OK);
|
|
|
|
hRowFirst=hRowSecond=hRowThird=DB_NULL_HROW;
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
// Re-Open and check for visibility
|
|
TESTC_(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,NUMELEM(rgDBPROPID),rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,TRUE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND),S_OK);
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
// Check that hRowFirst visible(was updated twice)
|
|
TESTC(fTestPass = CheckRowVisible(m_pIRowset, rgpData[5], CHECK_ROWVISIBLE));
|
|
|
|
// Check that hRowThird (update once)
|
|
TESTC_(m_pIRowset->RestartPosition(NULL),S_OK);
|
|
TESTC(fTestPass = CheckRowVisible(m_pIRowset, rgpData[4], CHECK_ROWVISIBLE));
|
|
|
|
// Check that hRowSecond is not visible (was deleted)
|
|
TESTC_(m_pIRowset->RestartPosition(NULL),S_OK);
|
|
TESTC(fTestPass = CheckRowVisible(m_pIRowset, rgpData[2], CHECK_ROWNOTVISIBLE));
|
|
|
|
CLEANUP:
|
|
//Release the row handle and memory
|
|
for(cCount=0; cCount<6; cCount++)
|
|
{
|
|
if(rgpData[cCount])
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)rgpData[cCount], TRUE);
|
|
}
|
|
|
|
if(hRowFirst)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRowFirst, NULL,NULL,NULL),S_OK);
|
|
|
|
if(hRowSecond)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRowSecond, NULL,NULL,NULL),S_OK);
|
|
|
|
if(hRowThird)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRowThird, NULL,NULL,NULL),S_OK);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL Buffered_ChangeInsertedRow::Terminate()
|
|
{
|
|
// TO DO: Add your own code here
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(InsertDefault)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: InsertDefault - InsertRow using DBSTATUS_S_DEFAULT
|
|
//| Created: 6/24/98
|
|
//*-----------------------------------------------------------------------
|
|
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Builds a list of info about the default property of the columns
|
|
//
|
|
//*-----------------------------------------------------------------------
|
|
BOOL InsertDefault::GetDefaultColumns()
|
|
{
|
|
CRowset Rowset;
|
|
BOOL fTestPass = FALSE;
|
|
ULONG i;
|
|
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;
|
|
DBORDINAL nCol;
|
|
ULONG cCol;
|
|
|
|
// 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, m_pTable->CountColumnsOnTable());
|
|
|
|
for (cCol = 0; cCol < m_pTable->CountColumnsOnTable(); cCol++)
|
|
{
|
|
m_rgbDefault[cCol] = FALSE;
|
|
}
|
|
|
|
// set restrictions and create rowset, accessor and bindings (do not bind bookmark)
|
|
Rowset.SetRestrictions(cRes, rgRes);
|
|
if (S_OK != Rowset.CreateRowset(SELECT_DBSCHEMA_COLUMNS, IID_IRowset, m_pTable, DBACCESSOR_ROWDATA,
|
|
DBPART_ALL, ALL_COLS_EXCEPTBOOKMARK))
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// 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
|
|
if (S_OK != Rowset.GetRowData(hRow, &Rowset.m_pData))
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//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;
|
|
}
|
|
}
|
|
|
|
fTestPass = TRUE;
|
|
|
|
CLEANUP:
|
|
// clean restriction array
|
|
for (i=0; i<cRes; i++)
|
|
{
|
|
VariantClear(&rgRes[i]);
|
|
}
|
|
return fTestPass;
|
|
} // InsertDefault::GetDefaultColumns
|
|
|
|
|
|
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc mask the m_fHasDefault field of columns in m_pTable
|
|
//
|
|
void InsertDefault::MaskDefColumns(BOOL fMask)
|
|
{
|
|
ULONG iCol;
|
|
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;
|
|
} //InsertDefault::MaskDefColumns
|
|
|
|
|
|
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc InsertRow, check it, get data, check it
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL InsertDefault::InsertAndCheckDefault(
|
|
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 hRow;
|
|
ULONG ulStatus;
|
|
ULONG ulStatusCC;
|
|
ULONG ulStatusGet;
|
|
void *pDefault = NULL;
|
|
USHORT cb;
|
|
ULONG size;
|
|
ULONG cBinding;
|
|
CCol col;
|
|
DBORDINAL cOrdinalPos;
|
|
DBORDINAL nCols = m_pTable->CountColumnsOnTable();
|
|
WCHAR *pwszMakeData = NULL;
|
|
|
|
|
|
// make sure pData is not null
|
|
if (NULL == pData)
|
|
{
|
|
odtLog << "ERROR: pData is NULL\n";
|
|
fRes = FALSE;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// carbon copy of original pData in pDataCC
|
|
SAFE_ALLOC(pDataCC, BYTE, m_cRowSize);
|
|
memcpy(pDataCC, pData, (size_t)m_cRowSize);
|
|
|
|
// set data
|
|
hr = m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER, m_hAccessor,pData,&hRow);
|
|
|
|
// check hr
|
|
if (NULL != hrSetData)
|
|
{
|
|
*hrSetData = hr;
|
|
}
|
|
if (fValidate)
|
|
{
|
|
if (S_OK!=hr)
|
|
{
|
|
//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\n";
|
|
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\n";
|
|
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\n";
|
|
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
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hrGetData = m_pIRowset->GetData(hRow,m_hAccessor,pDataOne);
|
|
|
|
// general check for data (data got - pDataOne, against data set - pData
|
|
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++)
|
|
{
|
|
//alloc a string for comparing
|
|
pwszMakeData = (WCHAR *) PROVIDER_ALLOC(sizeof(WCHAR) * MAXDATALEN);
|
|
pwszMakeData[0]=L'\0';
|
|
|
|
// 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);
|
|
|
|
// 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 (S_OK == hr && !COMPARE(DBSTATUS_S_DEFAULT, ulStatus))
|
|
{
|
|
odtLog << "ERROR: Bad return status for column " << col.GetColName() << " in SetData\n";
|
|
fRes = FALSE;
|
|
}
|
|
|
|
if (S_OK != hr)
|
|
continue;
|
|
|
|
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)\n";
|
|
fRes = FALSE;
|
|
}
|
|
break;
|
|
case DBSTATUS_E_UNAVAILABLE:
|
|
break;
|
|
default:
|
|
odtLog << "ERROR in IRowset::GetData for column " << col.GetColName() << "\n";
|
|
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() << "\n";
|
|
fRes = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
SAFE_FREE(pDefault);
|
|
}
|
|
if (pwszMakeData)
|
|
{
|
|
PROVIDER_FREE(pwszMakeData);
|
|
}
|
|
}
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(pDefault);
|
|
if(hRow && m_pIRowset)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow,NULL,NULL,NULL),S_OK);
|
|
if( pDataOne )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pDataOne, TRUE);
|
|
SAFE_FREE(pDataCC);
|
|
|
|
return fRes;
|
|
} //InsertDefault::InsertAndCheckDefault
|
|
|
|
|
|
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc InsertDefault::PrepareToInsert
|
|
// Creates a rowset and accessors, fills the input bindings and
|
|
// set the proper status of the given column
|
|
//
|
|
// @rdesc E_FAIL on insuccess or S_OK on success
|
|
//
|
|
HRESULT InsertDefault::PrepareForInsert(
|
|
DBORDINAL cSelectedColumn, // [in] the ordinal of the selected column (1 based)
|
|
DBSTATUS Status, // [in] the status value for the selected column
|
|
LONG lRowsOffset, // [in] row number for data creation
|
|
BYTE **ppData, // [out] data buffer
|
|
ULONG cPropsToUse // [in] default is 1, set this to 2 to get DBPROP_SERVERDATAONINSERT
|
|
)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
ULONG cBinding;
|
|
// properties asked for the rowset related to bindings
|
|
DBPROPID rgPropertyIDs[] = {DBPROP_IRowsetChange,DBPROP_SERVERDATAONINSERT};
|
|
|
|
|
|
|
|
ASSERT(DBSTATUS_S_DEFAULT == Status || DBSTATUS_S_IGNORE == Status);
|
|
TESTC(NULL != ppData);
|
|
*ppData = NULL;
|
|
|
|
//create an accessor on the command object on a updatable column only
|
|
hr = GetRowsetAndAccessor(SELECT_ALLFROMTBL,cPropsToUse,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);
|
|
if (S_OK!=hr)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//get a new data buffer to set the data
|
|
TESTC_(FillInputBindings( m_pTable,
|
|
DBACCESSOR_ROWDATA,
|
|
m_cBinding,
|
|
m_rgBinding,
|
|
ppData,
|
|
lRowsOffset+1, // 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;
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
CLEANUP:
|
|
return hr;
|
|
} // InsertDefault::PrepareForInsert
|
|
|
|
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL InsertDefault::Init()
|
|
{
|
|
BOOL fRes = FALSE;
|
|
ULONG nCol = 0;
|
|
DBCOLUMNDESC *pColumnDesc = NULL;
|
|
ULONG cColumnDesc = 1;
|
|
HRESULT hr;
|
|
ULONG nDefault = 0;
|
|
ITableDefinition *pITableDefinition = NULL;
|
|
DBORDINAL cColsOnTable = 0;
|
|
|
|
m_pCustomTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
|
|
m_rgbDefault = NULL;
|
|
m_nRows = 12;
|
|
m_cSeed = g_pTable->CountColumnsOnTable () + 1;
|
|
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
// }}
|
|
if(TCIRowsetNewRow::Init())
|
|
{
|
|
// 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, position and column desc for column nCol'th
|
|
CCol& rCol = g_pTable->GetColInfoForUpdate(nCol+1);
|
|
|
|
if (g_pTable->SetDefaultValue(rCol, m_cSeed))
|
|
{
|
|
// build the column description
|
|
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 (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;
|
|
}
|
|
SAFE_FREE(pColumnDesc);
|
|
}
|
|
}
|
|
fRes = TEST_PASS;
|
|
}
|
|
CLEANUP:
|
|
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 InsertDefault::Variation_1()
|
|
{
|
|
BOOL fTestPass = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
DBORDINAL cOrdinalPos;
|
|
ULONG cBinding = 0;
|
|
CCol col;
|
|
ULONG lRowsOffset = 2;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
BYTE *pDataCpy = NULL;
|
|
ULONG nDefault = 0;
|
|
ULONG cIndexInner = 0;
|
|
ULONG cIndexOutter = 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(0, 0), S_OK);
|
|
}
|
|
|
|
// create rowset and accessor and fill input bindings
|
|
TESTC_(PrepareForInsert(0, DBSTATUS_S_DEFAULT, lRowsOffset, &pData), S_OK);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// Duplicate the pData
|
|
pDataCpy = (BYTE*) PROVIDER_ALLOC(m_cRowSize);
|
|
TESTC(pDataCpy != NULL);
|
|
memcpy(pDataCpy, pData, (size_t)m_cRowSize);
|
|
|
|
// 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)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
odtLog << "Skip variation: No default columns were found\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(InsertAndCheckDefault(pData, S_OK));
|
|
fTestPass = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pDataCpy )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pDataCpy, TRUE);
|
|
PROVIDER_FREE(pData);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} 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 InsertDefault::Variation_2()
|
|
{
|
|
BOOL fTestPass = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 98;
|
|
DBORDINAL cSelectedColumn = 0;
|
|
ULONG ulColAttr = 0;
|
|
|
|
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(0, 0), 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))
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
odtLog << "No default column was detected\n";
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
// create rowset and accessor and fill input bindings
|
|
TESTC_(PrepareForInsert(cSelectedColumn, DBSTATUS_S_DEFAULT, lRowsOffset, &pData), S_OK);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(InsertAndCheckDefault(pData, S_OK));
|
|
|
|
fTestPass = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} 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 InsertDefault::Variation_3()
|
|
{
|
|
BOOL fTestPass = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 2;
|
|
DBORDINAL cSelectedColumn = 0;
|
|
ULONG rgColAttr[] = {COL_COND_DEFAULT, COL_COND_NOTNULL};
|
|
ULONG cColAttr = m_fCustomTables? 1: 2;
|
|
BOOL fOldNullable;
|
|
BOOL fPropNULLSet = FALSE;
|
|
WORD i;
|
|
|
|
MaskDefColumns(TRUE);
|
|
|
|
// get a default not nullable column
|
|
if (!g_pTable->GetColWithAttr(cColAttr, rgColAttr, &cSelectedColumn))
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
odtLog << "could not find a default nullable column\n";
|
|
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(0, 0), 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_(PrepareForInsert(cSelectedColumn, DBSTATUS_S_DEFAULT, lRowsOffset, &pData), S_OK);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(InsertAndCheckDefault(pData, S_OK));
|
|
fTestPass = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} 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 InsertDefault::Variation_4()
|
|
{
|
|
BOOL fTestPass = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 2;
|
|
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);
|
|
|
|
// get an implicit default (nullable) column (def == null)
|
|
if (!g_pTable->GetColWithAttr(cColAttr, rgColAttr, &cSelectedColumn))
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
odtLog << "could not find an updateable column\n";
|
|
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(0, 0), S_OK);
|
|
col = m_pTable->GetColInfoForUpdate(cSelectedColumn);
|
|
TESTC(col.GetNullable());
|
|
TESTC(!col.GetHasDefault());
|
|
}
|
|
|
|
// create rowset and accessor and fill input bindings
|
|
TESTC_(PrepareForInsert(cSelectedColumn, DBSTATUS_S_DEFAULT, lRowsOffset, &pData), S_OK);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(InsertAndCheckDefault(pData, S_OK));
|
|
fTestPass = TEST_PASS;
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} 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 InsertDefault::Variation_5()
|
|
{
|
|
BOOL fTestPass = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 2;
|
|
DBORDINAL cSelectedColumn = 0;
|
|
|
|
// get a default, nullable column (def != NULL)
|
|
ULONG rgColAttr[] = {COL_COND_DEFAULT, COL_COND_UPDATEABLE, COL_COND_NULL};
|
|
ULONG cColAttr = 3;
|
|
BOOL fPropNULLSet = FALSE;
|
|
WORD i;
|
|
|
|
// 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))
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
odtLog << "could not identify column with specified attributes\n";
|
|
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(0, 0), S_OK);
|
|
col = m_pTable->GetColInfoForUpdate(cSelectedColumn);
|
|
// set status in bindings
|
|
TESTC(col.GetHasDefault());
|
|
TESTC(col.GetNullable());
|
|
}
|
|
|
|
// create rowset and accessor and fill input bindings
|
|
TESTC_(PrepareForInsert(cSelectedColumn, DBSTATUS_S_DEFAULT, lRowsOffset, &pData), S_OK);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(InsertAndCheckDefault(pData, S_OK));
|
|
fTestPass = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(6)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set default value on a not default column
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertDefault::Variation_6()
|
|
{
|
|
BOOL fTestPass = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 2;
|
|
DBORDINAL cSelectedColumn = 0;
|
|
HRESULT hr;
|
|
BOOL fOldNullable;
|
|
BOOL fPropNULLSet = FALSE;
|
|
WORD i;
|
|
|
|
ULONG rgColAttr[] = {COL_COND_UPDATEABLE, COL_COND_NOTDEFAULT, COL_COND_NOTNULL};
|
|
|
|
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))
|
|
{
|
|
fTestPass = 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(0, 0), S_OK);
|
|
}
|
|
else
|
|
{
|
|
// get an updateable column (not def)
|
|
if (!g_pTable->GetColWithAttr(NUMELEM(rgColAttr), rgColAttr, &cSelectedColumn))
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
col = g_pTable->GetColInfoForUpdate(cSelectedColumn);
|
|
}
|
|
|
|
// create rowset and accessor and fill input bindings
|
|
TESTC_(PrepareForInsert(cSelectedColumn, DBSTATUS_S_DEFAULT, lRowsOffset, &pData), S_OK);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
InsertAndCheckDefault(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)
|
|
);
|
|
}
|
|
fTestPass = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(7)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set default value on a unique default value
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertDefault::Variation_7()
|
|
{
|
|
BOOL fTestPass = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// properties asked for the rowset related to bindings
|
|
DBPROPID rgPropertyIDs[] = {DBPROP_IRowsetChange};
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 2;
|
|
DBORDINAL cSelectedColumn = 0;
|
|
HRESULT hr;
|
|
ULONG rgColAttr[] = {COL_COND_DEFAULT, COL_COND_UNIQUE};
|
|
ULONG cColAttr = 2;
|
|
BOOL fOldNullable;
|
|
BOOL fPropNULLSet = FALSE;
|
|
WORD i;
|
|
|
|
if (!SettableProperty(DBPROP_COL_UNIQUE, DBPROPSET_COLUMN))
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// reset all the columns to their non default value
|
|
MaskDefColumns(TRUE);
|
|
|
|
// 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))
|
|
{
|
|
fTestPass = 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 to DBPROP_COL_NULLABLE, 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_UNIQUE is set to TRUE
|
|
if (rgColumnDesc[col.GetColNum()-1].rgPropertySets->rgProperties[i].dwPropertyID==DBPROP_COL_UNIQUE)
|
|
{
|
|
rgColumnDesc[col.GetColNum()-1].rgPropertySets->rgProperties[i].vValue.boolVal=VARIANT_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(0, 0), 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 rowset and accessor and fill input bindings
|
|
TESTC_(PrepareForInsert(cSelectedColumn, DBSTATUS_S_DEFAULT, lRowsOffset, &pData), S_OK);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(InsertAndCheckDefault(pData, S_OK));
|
|
InsertAndCheckDefault(pData, S_OK, FALSE, &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)
|
|
);
|
|
fTestPass = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(8)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set default values on all default columns (SDI)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertDefault::Variation_8()
|
|
{
|
|
BOOL fTestPass = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
DBORDINAL cOrdinalPos;
|
|
ULONG cBinding = 0;
|
|
CCol col;
|
|
ULONG lRowsOffset = 2;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
BYTE *pDataCpy = NULL;
|
|
ULONG nDefault = 0;
|
|
ULONG cIndexInner = 0;
|
|
ULONG cIndexOutter = 0;
|
|
HRESULT hr;
|
|
|
|
|
|
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(0, 0), S_OK);
|
|
}
|
|
|
|
// create rowset and accessor and fill input bindings, turn on SERVERDATAONINSERT
|
|
hr=PrepareForInsert(0, DBSTATUS_S_DEFAULT, lRowsOffset, &pData,2);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//if SERVERDATAONINSERT is not supported then skip, any other failure is an error
|
|
if (DB_E_ERRORSOCCURRED == hr || DB_S_ERRORSOCCURRED == hr || S_FALSE == hr)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
if(!SUCCEEDED(hr))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// Duplicate the pData
|
|
pDataCpy = (BYTE*) PROVIDER_ALLOC(m_cRowSize);
|
|
TESTC(pDataCpy != NULL);
|
|
memcpy(pDataCpy, pData, (size_t)m_cRowSize);
|
|
|
|
// 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)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
odtLog << "Skip variation: No default columns were found\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(InsertAndCheckDefault(pData, S_OK));
|
|
fTestPass = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
// release buffers
|
|
if( pDataCpy )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pDataCpy, TRUE);
|
|
PROVIDER_FREE(pData);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(9)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set default value on a default column; set many columns, one is asked default (SDI)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertDefault::Variation_9()
|
|
{
|
|
BOOL fTestPass = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 98;
|
|
DBORDINAL cSelectedColumn = 0;
|
|
ULONG ulColAttr;
|
|
HRESULT hr;
|
|
|
|
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(0, 0), 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))
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
odtLog << "No default column was detected\n";
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
// create rowset and accessor and fill input bindings. turn on SERVERDATAONINSERT
|
|
hr=PrepareForInsert(cSelectedColumn, DBSTATUS_S_DEFAULT, lRowsOffset, &pData,2);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//if SERVERDATAONINSERT is not supported then skip, any other failure is an error
|
|
if (DB_E_ERRORSOCCURRED == hr || DB_S_ERRORSOCCURRED == hr || S_FALSE == hr)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
if(!SUCCEEDED(hr))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
|
|
TESTC(InsertAndCheckDefault(pData, S_OK));
|
|
|
|
fTestPass = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(10)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set default value on a not nullable default column (SDI)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertDefault::Variation_10()
|
|
{
|
|
BOOL fTestPass = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 2;
|
|
DBORDINAL cSelectedColumn = 0;
|
|
ULONG rgColAttr[] = {COL_COND_DEFAULT, COL_COND_NOTNULL};
|
|
ULONG cColAttr = m_fCustomTables? 1: 2;
|
|
BOOL fOldNullable;
|
|
BOOL fPropNULLSet = FALSE;
|
|
WORD i;
|
|
HRESULT hr;
|
|
|
|
MaskDefColumns(TRUE);
|
|
|
|
// get a default not nullable column
|
|
if (!g_pTable->GetColWithAttr(cColAttr, rgColAttr, &cSelectedColumn))
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
odtLog << "could not find a default nullable column\n";
|
|
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(0, 0), 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. turn on SERVERDATAONINSERT
|
|
hr=PrepareForInsert(cSelectedColumn, DBSTATUS_S_DEFAULT, lRowsOffset, &pData,2);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//if SERVERDATAONINSERT is not supported then skip, any other failure is an error
|
|
if (DB_E_ERRORSOCCURRED == hr || DB_S_ERRORSOCCURRED == hr || S_FALSE == hr)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
if(!SUCCEEDED(hr))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
|
|
TESTC(InsertAndCheckDefault(pData, S_OK));
|
|
fTestPass = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(11)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set default value on a nullable default column (def == NULL) (SDI)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertDefault::Variation_11()
|
|
{
|
|
BOOL fTestPass = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 2;
|
|
DBORDINAL cSelectedColumn = 0;
|
|
ULONG rgColAttr[] = {COL_COND_UPDATEABLE, COL_COND_NOTDEFAULT, COL_COND_NULL};
|
|
ULONG cColAttr = 3;
|
|
BOOL fPropNULLSet = FALSE;
|
|
WORD i;
|
|
HRESULT hr;
|
|
|
|
// reset all the columns to their non default value
|
|
MaskDefColumns(FALSE);
|
|
|
|
// get an implicit default (nullable) column (def == null)
|
|
if (!g_pTable->GetColWithAttr(cColAttr, rgColAttr, &cSelectedColumn))
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
odtLog << "could not find an updateable column\n";
|
|
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(0, 0), S_OK);
|
|
col = m_pTable->GetColInfoForUpdate(cSelectedColumn);
|
|
TESTC(col.GetNullable());
|
|
TESTC(!col.GetHasDefault());
|
|
}
|
|
|
|
// create rowset and accessor and fill input bindings. turn on SERVERDATAONINSERT
|
|
hr=PrepareForInsert(cSelectedColumn, DBSTATUS_S_DEFAULT, lRowsOffset, &pData,2);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//if SERVERDATAONINSERT is not supported then skip, any other failure is an error
|
|
if (DB_E_ERRORSOCCURRED == hr || DB_S_ERRORSOCCURRED == hr || S_FALSE == hr)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
if(!SUCCEEDED(hr))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
|
|
TESTC(InsertAndCheckDefault(pData, S_OK));
|
|
fTestPass = TEST_PASS;
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(12)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set default value on a nullable default column (def != NULL) (SDI)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertDefault::Variation_12()
|
|
{
|
|
BOOL fTestPass = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 2;
|
|
DBORDINAL cSelectedColumn = 0;
|
|
|
|
// get a default, nullable column (def != NULL)
|
|
ULONG rgColAttr[] = {COL_COND_DEFAULT, COL_COND_UPDATEABLE, COL_COND_NULL};
|
|
ULONG cColAttr = 3;
|
|
BOOL fPropNULLSet = FALSE;
|
|
WORD i;
|
|
HRESULT hr;
|
|
|
|
|
|
// 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))
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
odtLog << "could not identify column with specified attributes\n";
|
|
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(0, 0), S_OK);
|
|
col = m_pTable->GetColInfoForUpdate(cSelectedColumn);
|
|
// set status in bindings
|
|
TESTC(col.GetHasDefault());
|
|
TESTC(col.GetNullable());
|
|
}
|
|
|
|
// create rowset and accessor and fill input bindings. turn on SERVERDATAONINSERT
|
|
hr=PrepareForInsert(cSelectedColumn, DBSTATUS_S_DEFAULT, lRowsOffset, &pData,2);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//if SERVERDATAONINSERT is not supported then skip, any other failure is an error
|
|
if (DB_E_ERRORSOCCURRED == hr || DB_S_ERRORSOCCURRED == hr || S_FALSE == hr)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
if(!SUCCEEDED(hr))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
|
|
TESTC(InsertAndCheckDefault(pData, S_OK));
|
|
fTestPass = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(13)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set default value on a not default column (SDI)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertDefault::Variation_13()
|
|
{
|
|
BOOL fTestPass = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 2;
|
|
DBORDINAL cSelectedColumn = 0;
|
|
HRESULT hr;
|
|
BOOL fOldNullable;
|
|
BOOL fPropNULLSet = FALSE;
|
|
WORD i;
|
|
|
|
|
|
ULONG rgColAttr[] = {COL_COND_UPDATEABLE, COL_COND_NOTDEFAULT, COL_COND_NOTNULL};
|
|
|
|
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))
|
|
{
|
|
fTestPass = 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(0, 0), S_OK);
|
|
}
|
|
else
|
|
{
|
|
// get an updateable column (not def)
|
|
if (!g_pTable->GetColWithAttr(NUMELEM(rgColAttr), rgColAttr, &cSelectedColumn))
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
col = g_pTable->GetColInfoForUpdate(cSelectedColumn);
|
|
}
|
|
|
|
// create rowset and accessor and fill input bindings. turn on SERVERDATAONINSERT
|
|
hr=PrepareForInsert(cSelectedColumn, DBSTATUS_S_DEFAULT, lRowsOffset, &pData,2);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//if SERVERDATAONINSERT is not supported then skip, any other failure is an error
|
|
if (DB_E_ERRORSOCCURRED == hr || DB_S_ERRORSOCCURRED == hr || S_FALSE == hr)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
if(!SUCCEEDED(hr))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
|
|
InsertAndCheckDefault(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)
|
|
);
|
|
}
|
|
fTestPass = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(14)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set default value on a unique default value (SDI)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertDefault::Variation_14()
|
|
{
|
|
BOOL fTestPass = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// properties asked for the rowset related to bindings
|
|
DBPROPID rgPropertyIDs[] = {DBPROP_IRowsetChange};
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 2;
|
|
DBORDINAL cSelectedColumn = 0;
|
|
HRESULT hr;
|
|
ULONG rgColAttr[] = {COL_COND_DEFAULT, COL_COND_UNIQUE};
|
|
ULONG cColAttr = 2;
|
|
BOOL fOldNullable;
|
|
BOOL fPropNULLSet = FALSE;
|
|
WORD i;
|
|
|
|
if (!SettableProperty(DBPROP_COL_UNIQUE, DBPROPSET_COLUMN))
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// reset all the columns to their non default value
|
|
MaskDefColumns(TRUE);
|
|
|
|
// 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))
|
|
{
|
|
fTestPass = 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 to DBPROP_COL_NULLABLE, 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_UNIQUE is set to TRUE
|
|
if (rgColumnDesc[col.GetColNum()-1].rgPropertySets->rgProperties[i].dwPropertyID==DBPROP_COL_UNIQUE)
|
|
{
|
|
rgColumnDesc[col.GetColNum()-1].rgPropertySets->rgProperties[i].vValue.boolVal=VARIANT_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(0, 0), 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 rowset and accessor and fill input bindings. turn on SERVERDATAONINSERT
|
|
hr=PrepareForInsert(cSelectedColumn, DBSTATUS_S_DEFAULT, lRowsOffset, &pData,2);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//if SERVERDATAONINSERT is not supported then skip, any other failure is an error
|
|
if (DB_E_ERRORSOCCURRED == hr || DB_S_ERRORSOCCURRED == hr || S_FALSE == hr)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
if(!SUCCEEDED(hr))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
|
|
TESTC(InsertAndCheckDefault(pData, S_OK));
|
|
InsertAndCheckDefault(pData, S_OK, FALSE, &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)
|
|
);
|
|
fTestPass = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestPass;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL InsertDefault::Terminate()
|
|
{
|
|
// TO DO: Add your own code here
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
SAFE_FREE(m_rgbDefault);
|
|
delete m_pCustomTable;
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(InsertIgnore)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: InsertIgnore - InsertRow using DBSTATUS_S_IGNORE
|
|
//| Created: 6/24/98
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL InsertIgnore::Init()
|
|
{
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
if(InsertDefault::Init())
|
|
// }}
|
|
{
|
|
// TO DO: Add your own code here
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc SetData, check it, get data, check it
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL InsertIgnore::InsertAndCheckIgnore(
|
|
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 hRow;
|
|
|
|
ULONG ulStatus;
|
|
ULONG ulStatusCC;
|
|
ULONG ulStatusGet;
|
|
|
|
ULONG cBinding;
|
|
CCol col;
|
|
DBORDINAL cOrdinalPos;
|
|
DBORDINAL nCols = m_pTable->CountColumnsOnTable();
|
|
|
|
// make sure pData is not null
|
|
if (NULL == pData)
|
|
{
|
|
odtLog << "ERROR: pData is NULL\n";
|
|
fRes = FALSE;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// carbon copy of original pData in pDataCC
|
|
SAFE_ALLOC(pDataCC, BYTE, m_cRowSize);
|
|
memcpy(pDataCC, pData, (size_t)m_cRowSize);
|
|
|
|
// set data from pData
|
|
hr = m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER, m_hAccessor, pData, &hRow);
|
|
|
|
// check hr
|
|
if (NULL != hrSetData)
|
|
*hrSetData = hr;
|
|
if (fValidate && !CHECK(hr, hrSetDataExpected))
|
|
{
|
|
odtLog << "Error in IRowsetChange::SetData return value\n";
|
|
fRes = FALSE;
|
|
}
|
|
|
|
//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
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hrGetData = m_pIRowset->GetData(hRow,m_hAccessor,pDataOne);
|
|
|
|
// general check for data (data got - pDataOne, against data set - pData
|
|
if (!COMPARE(CompareBuffer(pDataOne, pDataCC, m_cBinding, m_rgBinding, m_pIMalloc, TRUE,
|
|
FALSE, COMPARE_ONLY, TRUE), 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);
|
|
|
|
// 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 InsertRow\n";
|
|
fRes = FALSE;
|
|
}
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
// status for getting data
|
|
switch (ulStatusGet)
|
|
{
|
|
case DBSTATUS_S_OK:
|
|
break;
|
|
case DBSTATUS_S_ISNULL:
|
|
if (!col.GetNullable())
|
|
{
|
|
odtLog << "ERROR: mismatch for get statuses: DBSTATUS_S_ISNULL\n";
|
|
fRes = FALSE;
|
|
}
|
|
break;
|
|
case DBSTATUS_E_UNAVAILABLE:
|
|
break;
|
|
default:
|
|
odtLog << "ERROR in IRowset::GetData for column " << col.GetColName() << "\n";
|
|
fRes = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CLEANUP:
|
|
if(hRow && m_pIRowset)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hRow,NULL,NULL,NULL),S_OK);
|
|
|
|
if( pDataOne )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pDataOne, TRUE);
|
|
SAFE_FREE(pDataCC);
|
|
|
|
return fRes;
|
|
} //InsertIgnore::InsertAndCheckIgnore
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Insert ignore values on all updateable columns
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertIgnore::Variation_1()
|
|
{
|
|
BOOL fTestRes = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
DBORDINAL cOrdinalPos;
|
|
ULONG cBinding;
|
|
ULONG lRowsOffset = 21;
|
|
CCol col;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
BYTE *pDataCpy = 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(0, 0), S_OK);
|
|
}
|
|
|
|
// create rowset and accessor and fill input bindings
|
|
TESTC_(PrepareForInsert(0, DBSTATUS_S_IGNORE, lRowsOffset, &pData), S_OK);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestRes = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// Duplicate the pData
|
|
pDataCpy = (BYTE*) PROVIDER_ALLOC(m_cRowSize);
|
|
TESTC(pDataCpy != NULL);
|
|
memcpy(pDataCpy, pData, (size_t)m_cRowSize);
|
|
|
|
// 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 (col.GetHasDefault() || col.GetNullable())
|
|
*(ULONG *)(pData+m_rgBinding[cBinding].obStatus) = DBSTATUS_S_IGNORE;
|
|
}
|
|
|
|
TESTC(InsertAndCheckIgnore(pData, S_OK));
|
|
fTestRes = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pDataCpy )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pDataCpy, TRUE);
|
|
PROVIDER_FREE(pData);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestRes;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Insert ignore value on a column; set many columns, one is asked ignored
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertIgnore::Variation_2()
|
|
{
|
|
BOOL fTestRes = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 98;
|
|
DBORDINAL cSelectedColumn = 0;
|
|
ULONG rgColAttr[] = {COL_COND_DEFAULT, COL_COND_NOTNULL};
|
|
|
|
|
|
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(0, 0), S_OK);
|
|
}
|
|
|
|
// get a default not nullable column
|
|
if (!g_pTable->GetColWithAttr(NUMELEM(rgColAttr), rgColAttr, &cSelectedColumn))
|
|
|
|
{
|
|
fTestRes = TEST_SKIPPED;
|
|
odtLog << "could not find a default nullable column\n";
|
|
goto CLEANUP;
|
|
}
|
|
col = g_pTable->GetColInfoForUpdate(cSelectedColumn);
|
|
|
|
// create rowset and accessor and fill input bindings
|
|
TESTC_(PrepareForInsert(cSelectedColumn, DBSTATUS_S_IGNORE, lRowsOffset, &pData), S_OK);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestRes = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(InsertAndCheckIgnore(pData, S_OK));
|
|
fTestRes = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestRes;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Insert ignore value on a not nullable default column
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertIgnore::Variation_3()
|
|
{
|
|
BOOL fTestRes = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 2;
|
|
DBORDINAL cSelectedColumn = 0;
|
|
ULONG rgColAttr[] = {COL_COND_DEFAULT, COL_COND_NOTNULL};
|
|
ULONG cColAttr = m_fCustomTables? 1: 2;
|
|
BOOL fOldNullable;
|
|
BOOL fPropNULLSet = FALSE;
|
|
WORD i;
|
|
|
|
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\n";
|
|
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(0, 0), 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_(PrepareForInsert(cSelectedColumn, DBSTATUS_S_IGNORE, lRowsOffset, &pData), S_OK);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestRes = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(InsertAndCheckIgnore(pData, S_OK));
|
|
fTestRes = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestRes;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Insert ignore value on a nullable default column (def == NULL)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertIgnore::Variation_4()
|
|
{
|
|
BOOL fTestRes = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 2;
|
|
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);
|
|
|
|
// 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\n";
|
|
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(0, 0), S_OK);
|
|
col = m_pTable->GetColInfoForUpdate(cSelectedColumn);
|
|
TESTC(col.GetNullable());
|
|
TESTC(!col.GetHasDefault());
|
|
}
|
|
|
|
// create rowset and accessor and fill input bindings
|
|
TESTC_(PrepareForInsert(cSelectedColumn, DBSTATUS_S_IGNORE, lRowsOffset, &pData), S_OK);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestRes = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(InsertAndCheckIgnore(pData, S_OK));
|
|
fTestRes = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestRes;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Insert ignore value on a nullable default column (def != NULL)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertIgnore::Variation_5()
|
|
{
|
|
BOOL fTestRes = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 2;
|
|
DBORDINAL cSelectedColumn = 0;
|
|
|
|
// get a default, nullable column (def != NULL)
|
|
ULONG rgColAttr[] = {COL_COND_DEFAULT, COL_COND_UPDATEABLE, COL_COND_NULL};
|
|
ULONG cColAttr = 3;
|
|
BOOL fPropNULLSet = FALSE;
|
|
WORD i;
|
|
|
|
// 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\n";
|
|
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(0, 0), S_OK);
|
|
col = m_pTable->GetColInfoForUpdate(cSelectedColumn);
|
|
// set status in bindings
|
|
TESTC(col.GetHasDefault());
|
|
TESTC(col.GetNullable());
|
|
}
|
|
|
|
// create rowset and accessor and fill input bindings
|
|
TESTC_(PrepareForInsert(cSelectedColumn, DBSTATUS_S_IGNORE, lRowsOffset, &pData), S_OK);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestRes = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(InsertAndCheckIgnore(pData, S_OK));
|
|
fTestRes = TEST_PASS;
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestRes;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(6)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Insert ignore value on a not default column
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertIgnore::Variation_6()
|
|
{
|
|
BOOL fTestRes = TEST_FAIL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = g_pTable->CountColumnsOnTable();
|
|
CCol col;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 2;
|
|
DBORDINAL cSelectedColumn = 0;
|
|
BOOL fOldNullable;
|
|
HRESULT hr;
|
|
BOOL fPropNULLSet = FALSE;
|
|
WORD i;
|
|
|
|
ULONG rgColAttr[] = {COL_COND_UPDATEABLE, COL_COND_NOTDEFAULT, COL_COND_NOTNULL};
|
|
|
|
MaskDefColumns(FALSE);
|
|
|
|
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(0, 0), S_OK);
|
|
}
|
|
else
|
|
{
|
|
// 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 rowset and accessor and fill input bindings
|
|
TESTC_(PrepareForInsert(cSelectedColumn, DBSTATUS_S_IGNORE, lRowsOffset, &pData), S_OK);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestRes = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(InsertAndCheckIgnore(pData, DB_E_INTEGRITYVIOLATION, FALSE, &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:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->SetColumnDesc(NULL, 0);
|
|
m_pCustomTable->DropTable();
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
|
|
return fTestRes;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(7)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set status to DBSTATUS_S_IGNORE on a non updateable column
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertIgnore::Variation_7()
|
|
{
|
|
BOOL fTestRes = TEST_FAIL;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 23;
|
|
DBORDINAL cSelectedColumn = 0;
|
|
|
|
if (m_fCustomTables)
|
|
{
|
|
m_pCustomTable->SetBuildColumnDesc(TRUE); // create ColList again
|
|
TESTC_(m_pCustomTable->CreateTable(0, 0), S_OK);
|
|
}
|
|
// get a non updateable column
|
|
if (!m_pTable->GetColWithAttr(COL_COND_AUTOINC, &cSelectedColumn))
|
|
{
|
|
fTestRes = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// create rowset and accessor and fill input bindings
|
|
TESTC_(PrepareForInsert(cSelectedColumn, DBSTATUS_S_IGNORE, lRowsOffset, &pData), S_OK);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestRes = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(InsertAndCheckIgnore(pData, S_OK));
|
|
fTestRes = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->DropTable();
|
|
|
|
return fTestRes;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(8)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Insert all updateable cols, set status to DBSTATUS_S_IGNORE for half of them
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int InsertIgnore::Variation_8()
|
|
{
|
|
BOOL fTestRes = TEST_FAIL;
|
|
// buffer for row data
|
|
BYTE *pData = NULL;
|
|
ULONG lRowsOffset = 2;
|
|
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(0, 0), S_OK);
|
|
}
|
|
|
|
// create rowset and accessor and fill input bindings
|
|
TESTC_(PrepareForInsert(0, DBSTATUS_S_IGNORE, lRowsOffset, &pData), S_OK);
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestRes = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// set status in bindings
|
|
for (cBinding = 0; cBinding < m_cBinding; cBinding++)
|
|
{
|
|
if ((col.GetHasDefault() || col.GetNullable()) && cBinding % 2)
|
|
{
|
|
*(ULONG *)(pData+m_rgBinding[cBinding].obStatus) = DBSTATUS_S_IGNORE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
TESTC(InsertAndCheckIgnore(pData, S_OK));
|
|
fTestRes = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
// release buffers
|
|
if( pData )
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding, (BYTE *)pData, TRUE);
|
|
|
|
ReleaseRowsetAndAccessor();
|
|
m_pCustomTable->DropTable();
|
|
|
|
return fTestRes;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL InsertIgnore::Terminate()
|
|
{
|
|
// TO DO: Add your own code here
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(InsertDefault::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
// {{ TCW_TC_PROTOTYPE(Sequence)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: Sequence - sequence testing
|
|
//| Created: 05/15/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL ErrorCases::Init()
|
|
{
|
|
if(TCIRowsetNewRow::Init())
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc DB_E_CANTCONVERTVALUE
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int ErrorCases::Variation_1()
|
|
{
|
|
return TRUE;
|
|
}
|
|
// }}
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc DB_E_DATAOVERFLOW
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int ErrorCases::Variation_2()
|
|
{
|
|
return TRUE;
|
|
}
|
|
// }}
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc DB_E_MAXPENDCHANGESEXCEEDED
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int ErrorCases::Variation_3()
|
|
{
|
|
DBPROPID rgDBPROPID[3];
|
|
ULONG cCount = 0;
|
|
DBCOUNTITEM cRows = 0;
|
|
void *pData = NULL;
|
|
HROW *pHRow = NULL;
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
ULONG_PTR ulValue = 0;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_IRowsetUpdate;
|
|
rgDBPROPID[2]=DBPROP_CANHOLDROWS;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,3,rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
GetProperty(DBPROP_MAXPENDINGROWS, DBPROPSET_ROWSET,m_pIRowset,&ulValue);
|
|
|
|
//if there is no limit this error can not be reached
|
|
if (0==ulValue)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass = TEST_FAIL;
|
|
|
|
//insert the max pending rows
|
|
for(cCount=0;cCount<ulValue;cCount++)
|
|
{
|
|
//make data for the row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,
|
|
m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,NULL),S_OK);
|
|
if(pData)
|
|
{
|
|
PROVIDER_FREE(pData);
|
|
}
|
|
}
|
|
|
|
//make data for the row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,
|
|
m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert one more row than allowed into the pending buffer
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,NULL),DB_E_MAXPENDCHANGESEXCEEDED);
|
|
|
|
//update, should still work with the row currently in the buffer
|
|
TESTC_(m_pIRowsetUpdate->Update(NULL,0,NULL,&cRows, &pHRow,NULL),S_OK);
|
|
|
|
fTestPass=TRUE;
|
|
CLEANUP:
|
|
if(pData)
|
|
{
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding,(BYTE *)pData, TRUE);
|
|
}
|
|
if(pHRow)
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(cRows,pHRow,NULL,NULL,NULL),S_OK);
|
|
PROVIDER_FREE(pHRow);
|
|
}
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc DB_E_ROWLIMITEDEXCEEDED
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int ErrorCases::Variation_4()
|
|
{
|
|
DBPROPID rgDBPROPID[2];
|
|
ULONG cCount = 0;
|
|
ULONG cRows = 0;
|
|
void *pData = NULL;
|
|
HROW *pHRow = NULL;
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
ULONG_PTR ulValue = 0;
|
|
HROW *hRow = NULL;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_CANHOLDROWS;
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
GetProperty(DBPROP_MAXOPENROWS, DBPROPSET_ROWSET,m_pIRowset,&ulValue);
|
|
|
|
//if there is no limit this error can not be reached
|
|
if (0==ulValue)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//allocate memory for row handles
|
|
if(!(hRow=(HROW*)PROVIDER_ALLOC(ulValue*sizeof(HROW))))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass = TEST_FAIL;
|
|
|
|
//insert the max pending rows
|
|
for(cCount=0;cCount<ulValue;cCount++)
|
|
{
|
|
//make data for the row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,
|
|
m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&(hRow[cCount])),S_OK);
|
|
if(pData)
|
|
{
|
|
PROVIDER_FREE(pData);
|
|
}
|
|
}
|
|
|
|
//make data for the row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,
|
|
m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert one more row than allowed into the pending buffer
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,&(hRow[cCount])),DB_E_ROWLIMITEXCEEDED);
|
|
|
|
fTestPass=TRUE;
|
|
CLEANUP:
|
|
if(pData)
|
|
{
|
|
ReleaseInputBindingsMemory(m_cBinding, m_rgBinding,(BYTE *)pData, TRUE);
|
|
}
|
|
//insert the max pending rows
|
|
for(cCount=0;cCount<ulValue;cCount++)
|
|
{
|
|
if(hRow[cCount])
|
|
{
|
|
CHECK(m_pIRowset->ReleaseRows(cRows,&(hRow[cCount]),NULL,NULL,NULL),S_OK);
|
|
}
|
|
}
|
|
PROVIDER_FREE(hRow);
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc DB_E_NOTSUPPORTED
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int ErrorCases::Variation_5()
|
|
{
|
|
DBPROPID rgDBPROPID[2];
|
|
void *pData = NULL;
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_CANHOLDROWS;
|
|
|
|
m_ulUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_DELETE;
|
|
|
|
if (!(DBPROPFLAGS_WRITE &GetPropInfoFlags(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, m_pIDBInitialize)))
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//get a rowset binds to all updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_ORDERBYNUMERIC,2,rgDBPROPID,
|
|
0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass = TEST_FAIL;
|
|
|
|
//make data for the row handle
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&pData,g_ulNextRow++,m_cRowsetCols,
|
|
m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
//insert
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,pData,NULL),DB_E_NOTSUPPORTED);
|
|
|
|
fTestPass=TRUE;
|
|
CLEANUP:
|
|
m_ulUpdFlags = DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE;
|
|
|
|
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 ErrorCases::Terminate()
|
|
{
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
// {{ TCW_TC_PROTOTYPE(ServerDataOnInsertII)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: ServerDataOnInsertII - test Fetch computed columns
|
|
//| Created: 07/06/98
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL ServerDataOnInsertII::Init()
|
|
{
|
|
BOOL fTestPass=FALSE;
|
|
|
|
if(!TCIRowsetNewRow::Init())
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc GetData of computed column
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int ServerDataOnInsertII::Variation_1()
|
|
{
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
DBPROPID rgDBPROPID[3];
|
|
void *pVisibleData = NULL;
|
|
HROW hNewRow = NULL;
|
|
ULONG cCount = 0;
|
|
BYTE *pbAddr;
|
|
|
|
rgDBPROPID[0]=DBPROP_IRowsetChange;
|
|
rgDBPROPID[1]=DBPROP_SERVERDATAONINSERT;
|
|
rgDBPROPID[2]=DBPROP_CANHOLDROWS;
|
|
|
|
//this variation wants its own rowset, make sure the one created in the init is gone
|
|
ReleaseRowsetAndAccessor();
|
|
|
|
//create an accessor to bind updatable columns
|
|
TESTC_PROVIDER(GetRowsetAndAccessor(SELECT_COMPUTEDCOLLIST,3,rgDBPROPID,0,NULL,ON_ROWSET_ACCESSOR,FALSE,DBACCESSOR_ROWDATA,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,UPDATEABLE_COLS_BOUND));
|
|
|
|
//if there are no updatable rows
|
|
if (!m_cBinding)
|
|
{
|
|
fTestPass = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fTestPass = TEST_FAIL;
|
|
|
|
TESTC_(FillInputBindings(m_pTable,DBACCESSOR_ROWDATA,m_cBinding,m_rgBinding,
|
|
(BYTE **)&m_pData,g_ulNextRow++,m_cRowsetCols,m_rgTableColOrds,PRIMARY),S_OK);
|
|
|
|
TESTC_(m_pIRowsetChange->InsertRow(DB_NULL_HCHAPTER,m_hAccessor,m_pData,&hNewRow),S_OK);
|
|
|
|
PROVIDER_FREE(m_pData);
|
|
|
|
//allocate memory for the row
|
|
m_pData=PROVIDER_ALLOC(m_cRowSize);
|
|
if(!m_pData)
|
|
{
|
|
goto CLEANUP;
|
|
}
|
|
//Get the data for the row handle
|
|
//This should bring back the computed column because SERVERDATAONINSERT is TRUE
|
|
TESTC_(m_pIRowset->GetData(hNewRow,m_hAccessor,m_pData),S_OK);
|
|
|
|
pbAddr=(BYTE *)m_pData;
|
|
|
|
//the value for this computed column will be zero
|
|
// COMPARE(DBSTATUS_S_OK,(*(DBSTATUS *)(pbAddr+(m_rgBinding[m_cBinding-1].obStatus))));
|
|
// COMPARE(0,(*(ULONG *)(pbAddr+(m_rgBinding[m_cBinding-1].obValue))));
|
|
|
|
//release the row handle
|
|
TESTC_(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
hNewRow=NULL;
|
|
|
|
fTestPass = TRUE;
|
|
CLEANUP:
|
|
PROVIDER_FREE(m_pData);
|
|
if(hNewRow && m_pIRowset)
|
|
CHECK(m_pIRowset->ReleaseRows(1,&hNewRow,NULL,NULL,NULL),S_OK);
|
|
ReleaseRowsetAndAccessor();
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc GetData of default value
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int ServerDataOnInsertII::Variation_2()
|
|
{
|
|
//TODO
|
|
BOOL fTestPass = TEST_SKIPPED;
|
|
|
|
fTestPass = TRUE;
|
|
return fTestPass;
|
|
}
|
|
// }}
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL ServerDataOnInsertII::Terminate()
|
|
{
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(TCIRowsetNewRow::Terminate());
|
|
} // }}
|