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

10204 lines
286 KiB
C++

//--------------------------------------------------------------------
// Microsoft OLE DB Test
//
// Copyright 1995-2000 Microsoft Corporation.
//
// @doc
//
// @module icommand.CPP | icommand source file
//
//--------------------------------------------------------------------
#define DBINITCONSTANTS // Must be defined to initialize constants in OLEDB.H
#define INITGUID
#include "modstandard.hpp"
#include "icommand.h"
#include "msdasql.h" // for kagera specific properties
#include "extralib.h"
#include <time.h>
enum ETXN {ETXN_COMMIT, ETXN_ABORT};
CTable * g_Table2=NULL;
CTable * g_Table3=NULL;
#define CLEANUP(x) if(x) goto CLEANUP;
#define TERMINATE(x) if(x) return FALSE;
#define CONTINUE(x) if(x) return TRUE;
#define PI (IUnknown *)
#define PPI (IUnknown **)
#define PPPI (IUnknown ***)
#define WC (WCHAR *)
#define TESTBEGIN BOOL TESTB = TEST_FAIL;
#define TPASS TESTB = TEST_PASS;
#define TSKIPPED TESTB = TEST_SKIPPED;goto CLEANUP;
enum {THRD_ONE=0, THRD_TWO, THRD_THREE, THRD_FOUR};
enum {ONE_THRD=1,TWO_THRDS,THREE_THRDS, FOUR_THRDS};
//This simply the usage of threads down to 3 lines of code, CREATE/START/END
#define INIT_THRDS(cTh) const ULONG cThreads = cTh; HANDLE rghThread[cThreads]; DWORD rgThreadID[cThreads]
//#define CREATE_THRDS(pFunc,pArgs) CreateThreads(pFunc,pArgs,cThreads,rghThread,rgThreadID)
#define CREATE_THRD(iThread,pFunc,pArg) CreateThreads(pFunc,pArg,ONE_THRD,&rghThread[iThread],&rgThreadID[iThread])
#define START_THRDS() ScreenLogging(FALSE); StartThreads(cThreads,rghThread)
//#define START_THRD(iThread) StartThread(&rghThread[iThread])
#define END_THRDS() EndThreads(cThreads,rghThread);ScreenLogging(TRUE);
//#define END_THRD(iThread) EndThread(&rghThread[iThread])
#define GET_THRDCODE(iThread) GetThreadCode(&rghThread[iThread])
#define THRD_FUNC ((THRDARG*)pv)->pFunc
#define THRD_ARG1 ((THRDARG*)pv)->pArg1
#define THRD_ARG2 ((THRDARG*)pv)->pArg2
#define THRD_ARG4 ((THRDARG*)pv)->pArg4
#define THRD_ARG3 ((THRDARG*)pv)->pArg3
#define THRD_ARG5 ((THRDARG*)pv)->pArg5
struct THRDARG
{
LPVOID pFunc;
LPVOID pArg1;
LPVOID pArg2;
LPVOID pArg3;
LPVOID pArg4;
LPVOID pArg5;
};
#define ThreadSwitch() Sleep(0)
//CQTEST Macros, similar to TEST except they are "QUITE" no error messages
#define CQTEST_(exp,hr) { HRESULT acthr; if(!CQCHECK(acthr=exp,hr)) { HRTRACE(acthr,hr); TRETURN } }
#define CQTESTC_(exp,hr) { HRESULT acthr; if(!CQCHECK(acthr=exp,hr)) { HRTRACE(acthr,hr); goto CLEANUP; } }
#define CQTEST(exp) { CQTEST_(exp,TRUE) }
#define CQTESTC(exp) { CQTESTC_(exp,TRUE) }
#define CQCHECK(exp,hr) (TESTB = ((exp)==(hr)))
#define CQCOMPARE(x,y) (TESTB = ((x)==(y)))
#define HRTRACE(acthr,hr) PRVTRACE(L"***HRTRACE Actual: %x, Expected: %x, File: %s, Line: %d\n",ResultFromScode(acthr),ResultFromScode(hr),LONGSTRING(__FILE__),__LINE__);
// @todo Replace other macros with these ones.
#define TEST_CHECK(exp, hres) { if (!CHECK ((exp), (hres))) { goto CLEANUP; } }
#define TEST_COMPARE(exp, val) { if (!COMPARE ((exp), (val))) { goto CLEANUP; } }
#define TEST_SUPPORTED(exp, hres){ TESTB = TEST_PASS; if((exp) == DB_E_NOTSUPPORTED) { TOUTPUT_LINE(L"NotSupported by Provider, skipping Variation"); TESTB = TEST_SKIPPED; goto CLEANUP;} else if (!CHECK ((exp), (hres))) {TESTB = TEST_FAIL; goto CLEANUP;}}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Module Values
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// {{ TCW_MODULE_GLOBALS
DECLARE_MODULE_CLSID = { 0x2fd3c861, 0x9156, 0x11cf, { 0xaa, 0x86, 0x00, 0xa0, 0xc9, 0x05, 0x41, 0xce }};
DECLARE_MODULE_NAME("ICommand");
DECLARE_MODULE_OWNER("Microsoft");
DECLARE_MODULE_DESCRIP("Test module for ICommand methods");
DECLARE_MODULE_VERSION(829867051);
// TCW_WizardVersion(2)
// TCW_Automation(False)
// }} TCW_MODULE_GLOBALS_END
//---------------------------------------------------------------------------------------------------
// @func ScreenLogging
// Turns the screen logging to litmus window off.
//---------------------------------------------------------------------------------------------------
inline void
ScreenLogging(BOOL fFlag)
{
odtLog.ScreenLogging(fFlag);
}
//---------------------------------------------------------------------------------------------------
// @Global
//---------------------------------------------------------------------------------------------------
//Check whether the provider is read only.
BOOL g_fReadOnlyProvider;
BOOL g_fKagera;
BOOL g_fLuxor;
BOOL g_fSqlServer;
CRITICAL_SECTION g_csExtendedError;
//--------------------------------------------------------------------
// @func Module level initialization routine
//
// @rdesc Success or Failure
// @flag TRUE | Successful initialization
// @flag FALSE | Initialization problems
//
BOOL ModuleInit(CThisTestModule * pThisTestModule)
{
BOOL fSuccess=FALSE;
HRESULT hr=E_FAIL;
IDBCreateCommand *pIDBCreateCommand=NULL;
CTable * pTable = NULL;
DBCOUNTITEM iRow = 0;
InitializeCriticalSection(&g_csExtendedError);
//Get connection and session objects
if(ModuleCreateDBSession(pThisTestModule))
{
LPWSTR wszProviderName=NULL;
// Initialize globals
g_fKagera = FALSE;
g_fLuxor = FALSE;
g_fSqlServer = FALSE;
// Check whether provider is read only
g_fReadOnlyProvider = IsProviderReadOnly((IUnknown *)pThisTestModule->m_pIUnknown2);
// Fail gracefully and quit module if we don't support Commands
if (SUCCEEDED(hr = pThisTestModule->m_pIUnknown2->QueryInterface(
IID_IDBCreateCommand, (void **)&pIDBCreateCommand)))
pIDBCreateCommand->Release();
else
{
// Make sure we returned E_NOINTERFACE if we've failed
if (pThisTestModule->m_pError->Validate(hr,
LONGSTRING(__FILE__), __LINE__, E_NOINTERFACE))
odtLog <<L"Commands are not supported.\n";
return TEST_SKIPPED;
}
// This test doesn't support using an ini file, make sure we're not
if(GetModInfo()->GetFileName())
{
odtLog << L"WARNING: Test does not support using fixed table from ini file.\n";
// Read only providers must use ini file, so don't reset
if (!g_fReadOnlyProvider)
{
odtLog << L"\tResetting to ignore ini file and use tables created by test.\n";
GetModInfo()->ResetIniFile();
}
}
// This test doesn't support using INSERT_ROWSETCHANGE because it needs the command text back
if (GetModInfo()->GetInsert() == INSERT_ROWSETCHANGE)
{
odtLog << L"WARNING: Test does not support using INSERT_ROWSETCHANGE\n";
// Read only providers must use ini file, so don't reset
if (!g_fReadOnlyProvider)
{
odtLog << L"\tResetting to INSERT_COMMAND\n";
GetModInfo()->SetInsert(INSERT_COMMAND);
}
}
// Get the name of the provider
GetProperty(DBPROP_PROVIDERNAME, DBPROPSET_DATASOURCEINFO, pThisTestModule->m_pIUnknown, &wszProviderName);
if (wszProviderName && !wcscmp((LPWSTR)wszProviderName, L"MSDASQL.DLL"))
g_fKagera=TRUE;
if (wszProviderName && !wcscmp((LPWSTR)wszProviderName, L"sqloledb.dll"))
g_fLuxor=TRUE;
PROVIDER_FREE(wszProviderName);
GetProperty(DBPROP_DBMSNAME, DBPROPSET_DATASOURCEINFO, pThisTestModule->m_pIUnknown, &wszProviderName);
if (wszProviderName && !wcscmp((LPWSTR)wszProviderName, L"Microsoft SQL Server"))
g_fSqlServer = TRUE;
PROVIDER_FREE(wszProviderName);
//If the provider is not read only,
//create a table we'll use for the whole test module,
//store it in pVoid for now
pThisTestModule->m_pVoid = new CTable((IUnknown *)pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
pTable = (CTable *)pThisTestModule->m_pVoid;
g_Table2 = new CTable((IUnknown *)pThisTestModule->m_pIUnknown2,(LPWSTR)gwszModuleName);
g_Table3 = new CTable((IUnknown *)pThisTestModule->m_pIUnknown2,(LPWSTR)gwszModuleName);
if (!pTable || !g_Table2 || !g_Table3)
{
odtLog << wszMemoryAllocationError;
goto CLEANUP;
}
// Hack for Kagera. We have to force the insert to use commands otherwise we
// end up getting into QBU mode which can't insert BLOB columns.
if (g_fKagera && !GetModInfo()->GetInsert())
GetModInfo()->SetInsert(INSERT_COMMAND);
//Start with a table with 15 rows and no index
TESTC_(pTable->CreateTable(0, 0), S_OK);
// Lie to the CTable object and tell it we've got an index on column 1
// This will force data to be made in sequential order so an order by
// clause will sort the data properly for verification.
pTable->SetIndexColumn(1);
// Insert MAX_ROWS rows into the table if no rows exist already
if (!pTable->GetRowsOnCTable())
{
for (iRow=pTable->GetNextRowNumber(); iRow <= MAX_ROWS; iRow++)
{
// Force insert
TESTC_(pTable->Insert(iRow), S_OK);
}
}
// Don't use autoincrement column for index column
TESTC_(g_Table2->CreateTable(15), S_OK);
fSuccess = TRUE;
}
CLEANUP:
// No need to cleanup as ModuleTerminate cleans them up.
return fSuccess;
}
//--------------------------------------------------------------------
// @func Module level termination routine
//
// @rdesc Success or Failure
// @flag TRUE | Successful initialization
// @flag FALSE | Initialization problems
//
BOOL ModuleTerminate(CThisTestModule * pThisTestModule)
{
DeleteCriticalSection(&g_csExtendedError);
//If we created the table before,
//we still own the table since all of our testcases
//have only used it and not deleted it.
if (pThisTestModule->m_pVoid)
{
((CTable *)pThisTestModule->m_pVoid)->DropTable();
delete (CTable*)pThisTestModule->m_pVoid;
pThisTestModule->m_pVoid = NULL;
}
if (g_Table2)
{
g_Table2->DropTable();
delete g_Table2;
g_Table2 = NULL;
}
if (g_Table3)
{
delete g_Table3;
g_Table3 = NULL;
}
return ModuleReleaseDBSession(pThisTestModule);
}
////////////////////////////////////////////////////////////////////////
// TCBase - Class for reusing Test Cases.
// This is one of the base classes from which all the Test Case
// classes will inherit. It is used to duplicate test cases, yet
// maintain some sort of distinct identity for each.
//
////////////////////////////////////////////////////////////////////////
class TCBase
{
public:
//constructor
TCBase() { SetTestCaseParam(TC_Rowset); }
//Set the m_fWarning and m_fBinder flags.
virtual void SetTestCaseParam(ETESTCASE eTestCase = TC_Rowset)
{
m_eTestCase = eTestCase;
switch(eTestCase)
{
case TC_Rowset:
break;
case TC_Row:
break;
default:
ASSERT(!L"Unhandled Type...");
break;
};
}
//data
ETESTCASE m_eTestCase;
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Base Class Section
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// @class CCmd Base Class for all ICommand Testcases
class CCmd : public CSessionObject, public TCBase
{
public:
// @cmember Result
HRESULT m_hr;
static BOOL m_fValidateExtended;
// @cmember DSO pointer
IDBInitialize * m_pMyIDBInitialize;
// @cmember Constructor
CCmd(LPWSTR wszTestCaseName) : CSessionObject(wszTestCaseName)
{
m_hr=E_FAIL;
m_pMyIDBInitialize=NULL;
};
// @cmember Destructor
~CCmd()
{
ASSERT(!m_pMyIDBInitialize);
};
// @cmember Common base class initialization
virtual BOOL Init();
// @cmember Common base class termination
virtual BOOL Terminate();
//Helper function for calling pICmd->Execute.
HRESULT Execute(
ICommand* pICmd, //[IN]
IUnknown ** ppRowset, //[OUT]
DBROWCOUNT * pcRowsAffected=NULL, //[OUT]
IUnknown * pUnkOuter=NULL, //[IN]
DBPARAMS * pParams=NULL, //[IN]
IID iid=IID_IDBInfo); //[IN]
// @cmember CreateSession
// must Release *pIUnknown
BOOL CreateSession( REFIID iid, IUnknown** pIUnknown);
// @cmember Gets command ptr from session object based on IID
BOOL GetCommand(REFIID iid, IUnknown ** pIUnknownCommand, IUnknown * pIUnknownSession
);
// @cmember Validate Session Object
BOOL ValidateSessionObject(IUnknown * pIUnknown);
// @cmember Returns true if column is datetime
BOOL IsColDateTime(DBTYPE ProviderType);
// @cmember Returns true if columns is character
BOOL IsColCharacter(DBTYPE ProviderType);
// @cmember Returns true if column is numeric
BOOL IsColNumeric(DBTYPE ProviderType);
// @mfunc Can the data type hold Numeric with a Scale
BOOL IsColNumWithScale (
DBTYPE ProviderType, // @parm [IN] Data type
ULONG Scale // @parm [IN] precision for the data type
);
////////////////////////
// Multi-threading
////////////////////////
static ULONG WINAPI Execute(LPVOID pv);
static ULONG WINAPI Cancel(LPVOID pv);
// Thread routines from Thread test case (copied here)
BOOL CreateThreads(LPTHREAD_START_ROUTINE pFunc,void* pArgs,ULONG cThreads,HANDLE* rghThread,DWORD* rgThreadID);
BOOL StartThreads(ULONG cThreads, LPHANDLE rghThread);
BOOL EndThreads(ULONG cThreads, LPHANDLE rghThread);
HRESULT GetCommandTextAndPrintOut(ICommand * pICommand);
BOOL PropertiesInError(IUnknown * pIUnknown, HRESULT hrExecute);
void DumpCommandProps(IUnknown * pIUnknown, BOOL fPropertiesInError,
ULONG cPropSets=0, DBPROPSET * pPropSets=NULL);
protected:
HRESULT SetRowsetPropertyDefault(DBPROPID DBPropID, ICommand * pICommand = NULL);
void GetQualifierNames(
IUnknown * pSessionIUnknown,// [in] IUnknown off session object
LPWSTR pwszTableName, // [in] the name of the table
LPWSTR *ppwszCatalogName, // [out] catalog name
LPWSTR *ppwszSchemaName // [out] schema name
);
BOOL VerifyAndRemoveRows(CTable * pTable, DBCOUNTITEM ulRowNum, DBCOUNTITEM cRows);
BOOL VerifyThreadingModel(DWORD dwCoInit);
BOOL SetPropertyAndExecute(
ICommand * pICmd,
DBPROPINFOSET * pPropertyInfoSets,
ULONG iSet,
ULONG iProp,
enum SET_OPTION_ENUM eSetOption,
WCHAR * pwszDescription1,
BOOL * pfPropFound);
HRESULT VerifyRowset(REFIID riidRowset, IUnknown * pUnkRowset, ULONG ulStartingRow,
DBORDINAL cRowsetCols, DBORDINAL * rgTableColOrds, BOOL fRelease);
HRESULT VerifyRowObj(REFIID riidRow, IUnknown * pUnkRow, ULONG ulStartingRow,
DBORDINAL cRowsetCols, DBORDINAL * rgTableColOrds, BOOL fRelease);
};
// Initialize static
BOOL CCmd::m_fValidateExtended = FALSE;
BOOL CCmd::PropertiesInError(IUnknown * pIUnknown, HRESULT hrExecute)
{
BOOL fPropertiesInError = FALSE;
DBPROPIDSET rgPropertyIDSets[1];
ICommandProperties * pICmdProp = NULL;
ULONG cPropertySets = 0;
DBPROPSET * pPropertySets = NULL;
HRESULT hrGetProp = E_FAIL;
rgPropertyIDSets[0].rgPropertyIDs = NULL;
rgPropertyIDSets[0].cPropertyIDs = 0;
rgPropertyIDSets[0].guidPropertySet = DBPROPSET_PROPERTIESINERROR;
TESTC(VerifyInterface(pIUnknown, IID_ICommandProperties, COMMAND_INTERFACE,
(IUnknown **)&pICmdProp));
TESTC_(pICmdProp->GetProperties(1, rgPropertyIDSets, &cPropertySets, &pPropertySets), S_OK);
if (cPropertySets)
{
TESTC(pPropertySets != NULL);
}
else
{
TESTC(pPropertySets == NULL);
}
if (pPropertySets)
{
for (ULONG iPropSet = 0; iPropSet < cPropertySets; iPropSet++)
{
if (pPropertySets[iPropSet].cProperties)
fPropertiesInError = TRUE;
for (ULONG iProp = 0; iProp < pPropertySets[iPropSet].cProperties; iProp++)
{
const LPWSTR pwszTrue = L"VARIANT_TRUE";
const LPWSTR pwszFalse = L"VARIANT_FALSE";
const LPWSTR pwszEmpty = L"VT_EMPTY";
const LPWSTR pwszUnexpected = L"UNEXPECTED";
const LPWSTR ppwszStatus[] = {
L"DBPROPSTATUS_OK",
L"DBPROPSTATUS_NOTSUPPORTED",
L"DBPROPSTATUS_BADVALUE",
L"DBPROPSTATUS_BADOPTION",
L"DBPROPSTATUS_BADCOLUMN",
L"DBPROPSTATUS_NOTALLSETTABLE",
L"DBPROPSTATUS_NOTSETTABLE",
L"DBPROPSTATUS_NOTSET",
L"DBPROPSTATUS_CONFLICTING",
L"DBPROPSTATUS_NOTAVAILABLE",
};
LPWSTR pwszValue = pwszUnexpected;
// COMPARE(pPropertySets[iPropSet].rgProperties[iProp].dwStatus != DBPROPSTATUS_OK, TRUE);
if (hrExecute == DB_E_ERRORSOCCURRED)
if (!COMPARE(pPropertySets[iPropSet].rgProperties[iProp].dwStatus, DBPROPSTATUS_CONFLICTING))
odtLog << L"Expected status DBPROPSTATUS_CONFLICTING, received " <<
ppwszStatus[pPropertySets[iPropSet].rgProperties[iProp].dwStatus] << ".\n";
if (hrExecute == DB_S_ERRORSOCCURRED)
if (!COMPARE(pPropertySets[iPropSet].rgProperties[iProp].dwStatus, DBPROPSTATUS_NOTSET))
odtLog << L"Expected status DBPROPSTATUS_NOTSET, received " <<
ppwszStatus[pPropertySets[iPropSet].rgProperties[iProp].dwStatus] << ".\n";
if (V_VT(&pPropertySets[iPropSet].rgProperties[iProp].vValue) == VT_EMPTY)
pwszValue = pwszEmpty;
else if (V_BOOL(&pPropertySets[iPropSet].rgProperties[iProp].vValue) == VARIANT_TRUE)
pwszValue = pwszTrue;
else if (V_BOOL(&pPropertySets[iPropSet].rgProperties[iProp].vValue) == VARIANT_FALSE)
pwszValue = pwszFalse;
{
DBPROPINFO * pPropInfo = NULL;
pPropInfo = GetPropInfo(pPropertySets[iPropSet].rgProperties[iProp].dwPropertyID, pPropertySets[iPropSet].guidPropertySet,
m_pThisTestModule->m_pIUnknown, SESSION_INTERFACE);
if (pPropInfo && pPropInfo->pwszDescription)
{
odtLog << L"\t\t" << iPropSet << L" " << iProp << L" Property " << pPropInfo->pwszDescription << L" " << pwszValue;
PROVIDER_FREE(pPropInfo->pwszDescription);
}
else
odtLog << L"\t\t" << iPropSet << L" " << iProp << L" Property " << pPropertySets[iPropSet].rgProperties[iProp].dwPropertyID << L" " << pwszValue;
if (pPropertySets[iPropSet].rgProperties[iProp].dwOptions == DBPROPOPTIONS_REQUIRED)
odtLog << L" REQUIRED";
else
odtLog << L" OPTIONAL";
if (pPropInfo->dwFlags & DBPROPFLAGS_READ)
odtLog << L" READ";
if (pPropInfo->dwFlags & DBPROPFLAGS_WRITE)
odtLog << L" WRITE";
odtLog << L" " << ppwszStatus[pPropertySets[iPropSet].rgProperties[iProp].dwStatus];
odtLog << L"\n";
PROVIDER_FREE(pPropInfo);
}
}
}
}
CLEANUP:
if (cPropertySets && pPropertySets)
FreeProperties(&cPropertySets, &pPropertySets);
SAFE_RELEASE(pICmdProp);
if (!fPropertiesInError)
odtLog << L"No properties in error were found!\n";
return fPropertiesInError;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Print REQUIRED TRUE command props
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CCmd::DumpCommandProps(IUnknown * pIUnknown, BOOL fPropertiesInError,
ULONG cPropSets, DBPROPSET * pPropSets)
{
DBPROPIDSET rgPropertyIDSets[1];
ICommandProperties * pICmdProp = NULL;
IRowsetInfo * pIRowsetInfo = NULL;
ULONG cPropertySets = 0;
DBPROPSET * pPropertySets = NULL;
HRESULT hrGetProp = E_FAIL;
rgPropertyIDSets[0].rgPropertyIDs = NULL;
rgPropertyIDSets[0].cPropertyIDs = 0;
rgPropertyIDSets[0].guidPropertySet = DBPROPSET_PROPERTIESINERROR;
if (cPropSets && pPropSets)
{
cPropertySets = cPropSets;
pPropertySets = pPropSets;
}
else
{
if (SUCCEEDED(pIUnknown->QueryInterface(IID_ICommandProperties, (void **)&pICmdProp)))
{
ULONG cPropZero = 0;
ULONG cPropZeroNULL = 0;
if (!fPropertiesInError)
{
odtLog << L"Dumping command properties:\n";
pICmdProp->GetProperties(0, NULL, &cPropertySets, &pPropertySets);
}
else if (fPropertiesInError)
{
odtLog << L"Dumping command properties in error:\n";
pICmdProp->GetProperties(1, rgPropertyIDSets, &cPropertySets, &pPropertySets);
}
else
odtLog << L"Invalid option:\n";
}
else if (SUCCEEDED(pIUnknown->QueryInterface(IID_IRowsetInfo, (void **)&pIRowsetInfo)))
{
pIRowsetInfo->GetProperties(0, NULL, &cPropertySets, &pPropertySets);
odtLog << L"Dumping rowset properties:\n";
}
else
odtLog << L"Not a command or rowset interface.\n";
}
if (pPropertySets)
{
for (ULONG iPropSet = 0; iPropSet < cPropertySets; iPropSet++)
{
for (ULONG iProp = 0; iProp < pPropertySets[iPropSet].cProperties; iProp++)
{
const LPWSTR pwszTrue = L"VARIANT_TRUE";
const LPWSTR pwszFalse = L"VARIANT_FALSE";
const LPWSTR pwszEmpty = L"VT_EMPTY";
const LPWSTR pwszUnexpected = L"UNEXPECTED";
WCHAR wszBuff[30] = L"";
const LPWSTR ppwszStatus[] = {
L"DBPROPSTATUS_OK",
L"DBPROPSTATUS_NOTSUPPORTED",
L"DBPROPSTATUS_BADVALUE",
L"DBPROPSTATUS_BADOPTION",
L"DBPROPSTATUS_BADCOLUMN",
L"DBPROPSTATUS_NOTALLSETTABLE",
L"DBPROPSTATUS_NOTSETTABLE",
L"DBPROPSTATUS_NOTSET",
L"DBPROPSTATUS_CONFLICTING",
L"DBPROPSTATUS_NOTAVAILABLE",
};
LPWSTR pwszValue = pwszUnexpected;
switch(V_VT(&pPropertySets[iPropSet].rgProperties[iProp].vValue))
{
case VT_EMPTY:
pwszValue = pwszEmpty;
break;
case VT_BOOL:
if (V_BOOL(&pPropertySets[iPropSet].rgProperties[iProp].vValue) == VARIANT_TRUE)
pwszValue = pwszTrue;
else if (V_BOOL(&pPropertySets[iPropSet].rgProperties[iProp].vValue) == VARIANT_FALSE)
pwszValue = pwszFalse;
break;
case VT_I4:
swprintf(wszBuff, L"%d", V_I4(&pPropertySets[iPropSet].rgProperties[iProp].vValue));
pwszValue = (LPWSTR)wszBuff;
break;
case VT_BSTR:
pwszValue = V_BSTR(&pPropertySets[iPropSet].rgProperties[iProp].vValue);
break;
}
{
DBPROPINFO * pPropInfo = NULL;
pPropInfo = GetPropInfo(pPropertySets[iPropSet].rgProperties[iProp].dwPropertyID, pPropertySets[iPropSet].guidPropertySet,
m_pThisTestModule->m_pIUnknown, SESSION_INTERFACE);
if (pPropInfo && pPropInfo->pwszDescription)
{
odtLog << L"\t" << iPropSet << L" " << iProp << L" Property " << pPropInfo->pwszDescription << L" " << pwszValue;
PROVIDER_FREE(pPropInfo->pwszDescription);
}
else
odtLog << L"\t" << iPropSet << L" " << iProp << L" Property " << pPropertySets[iPropSet].rgProperties[iProp].dwPropertyID << L" " << pwszValue;
if (pPropertySets[iPropSet].rgProperties[iProp].dwOptions == DBPROPOPTIONS_REQUIRED)
odtLog << L" REQUIRED";
else
odtLog << L" OPTIONAL";
if (pPropInfo->dwFlags & DBPROPFLAGS_READ)
odtLog << L" READ";
if (pPropInfo->dwFlags & DBPROPFLAGS_WRITE)
odtLog << L" WRITE";
odtLog << L" " << ppwszStatus[pPropertySets[iPropSet].rgProperties[iProp].dwStatus];
odtLog << L"\n";
PROVIDER_FREE(pPropInfo);
}
}
odtLog << L"\n";
}
// Only free the properties if we obtained them.
if (!(cPropSets && pPropSets))
FreeProperties(&cPropertySets, &pPropertySets);
}
SAFE_RELEASE(pICmdProp);
SAFE_RELEASE(pIRowsetInfo);
}
void CCmd::GetQualifierNames(
IUnknown * pSessionIUnknown,// [in] IUnknown off session object
LPWSTR pwszTableName, // [in] the name of the table
LPWSTR *ppwszCatalogName, // [out] catalog name
LPWSTR *ppwszSchemaName // [out] schema name
)
{
IRowset *pIRowset = NULL;
IDBSchemaRowset * pIDBSchmr = NULL;
ULONG cSchemas = 0;
GUID * pSchemas = NULL;
ULONG * pRestrictionSupport = NULL;
ULONG iSchema, iRestrict;
LONG_PTR rgColsToBind[TABLES_COLS] = {1, 2, 3};
BOOL fTablesRowset = FALSE;
BOOL fTableRestrict = FALSE;
VARIANT rgRestrictions[RESTRICTION_COUNT];
BYTE * pData = NULL;
HACCESSOR hAccessor;
DBBINDING * pBinding = NULL;
DBCOUNTITEM cBinding = 0;
DBLENGTH cbRowSize = 0;
DBCOUNTITEM cRows = 0;
HROW * pRow = NULL;
BOOL fTableFound = FALSE;
ULONG_PTR ulIdentCase = DBPROPVAL_IC_UPPER;
ULONG_PTR ulQuotedIdentCase = DBPROPVAL_IC_UPPER;
// Check args
TESTC(NULL != pwszTableName);
TESTC(NULL != ppwszCatalogName);
TESTC(NULL != ppwszSchemaName);
// See if we can get an IDBSchemaRowset interface
if (!VerifyInterface(pSessionIUnknown, IID_IDBSchemaRowset, SESSION_INTERFACE,
(IUnknown **)&pIDBSchmr))
{
// Then the best we can do is get the catalog name from DBPROP_CURRENTCATALOG
GetProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, pSessionIUnknown, ppwszCatalogName);
goto CLEANUP;
}
// we've got to either remove
// the quotes or convert to proper case if DBPROP_IDENTIFIERCASE happens to
// be different than DBPROP_QUOTEDIDENTIFIERCASE and the QUOTEDIDENTIFIERCASE
// is DBPROPVAL_IC_SENSITIVE.
GetProperty(DBPROP_IDENTIFIERCASE, DBPROPSET_DATASOURCEINFO,
m_pThisTestModule->m_pIUnknown,&ulIdentCase);
GetProperty(DBPROP_QUOTEDIDENTIFIERCASE, DBPROPSET_DATASOURCEINFO,
m_pThisTestModule->m_pIUnknown,&ulQuotedIdentCase);
// Need to convert identifier to upper case or lower case
if (ulIdentCase == DBPROPVAL_IC_UPPER)
_wcsupr(pwszTableName);
else if (ulIdentCase == DBPROPVAL_IC_LOWER)
_wcslwr(pwszTableName);
// Find out of the TABLES rowset is supported
TESTC_(pIDBSchmr->GetSchemas(&cSchemas, &pSchemas, &pRestrictionSupport), S_OK);
for (iSchema = 0; iSchema < cSchemas; iSchema++)
{
if (pSchemas[iSchema] == DBSCHEMA_TABLES)
{
fTablesRowset = TRUE;
// See if the tablename restriction is supported
if (pRestrictionSupport[iSchema] & TABLE_RESTRICT)
fTableRestrict = TRUE;
break;
}
}
if (!fTablesRowset)
{
// Then the best we can do is get the catalog name from DBPROP_CURRENTCATALOG
GetProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, pSessionIUnknown, ppwszCatalogName);
goto CLEANUP;
}
// Initialize restrictions
for (iRestrict = 0; iRestrict < RESTRICTION_COUNT; iRestrict++)
VariantInit(&rgRestrictions[iRestrict]);
// Set the table restriction, if supported
if (fTableRestrict)
{
V_VT(&rgRestrictions[TABLE_RESTRICT-1]) = VT_BSTR;
V_BSTR(&rgRestrictions[TABLE_RESTRICT-1]) = SysAllocString(pwszTableName);
}
//Obtain Schema TABLES Rowset
TESTC_(pIDBSchmr->GetRowset(NULL, DBSCHEMA_TABLES, RESTRICTION_COUNT, rgRestrictions,
IID_IRowset, 0, NULL, (IUnknown **)&pIRowset), S_OK);
TESTC_(GetAccessorAndBindings(
pIRowset, // @parm [IN] Rowset or command to create Accessor for
DBACCESSOR_ROWDATA, // @parm [IN] Properties of the Accessor
&hAccessor, // @parm [OUT] Accessor created
&pBinding, // @parm [OUT] Array of DBBINDINGS
&cBinding, // @parm [OUT] Count of bindings
&cbRowSize, // @parm [OUT] length of a row
DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS, // @parm [IN] Types of binding to do (Value, Status, and/or Length)
USE_COLS_TO_BIND_ARRAY, // @parm [IN] Which columns will be used in the bindings
FORWARD, // @parm [IN] Order to bind columns in accessor
NO_COLS_BY_REF, // @parm [IN] Which columns to bind by reference (fixed, variable, all or none)
NULL, // @parm [OUT] Array of DBCOLUMNINFO
NULL, // @parm [OUT] Count of Columns, also count of ColInfo elements
NULL, // @parm [OUT] ppStringsBuffer
DBTYPE_EMPTY, // @parm [IN] Modifier to be OR'd with each binding type.
TABLES_COLS, // @parm [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
rgColsToBind // @parm [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
), S_OK);
// Allocate a buffer to hold the results
SAFE_ALLOC(pData, BYTE, cbRowSize);
//Try to find the specified row with this table name
while(S_OK == pIRowset->GetNextRows(NULL, 0, 1, &cRows, &pRow))
{
DATA * pCol = (DATA *)(pData + pBinding[2].obStatus);
TESTC(cRows == 1);
//GetData for this row
TESTC_(pIRowset->GetData(*pRow, hAccessor, pData),S_OK);
// If the table name isn't NULL or an error
if(pCol->sStatus ==DBSTATUS_S_OK)
{
// See if it matches
if(!wcscmp(pwszTableName, (LPWSTR)pCol->bValue))
{
DATA * pCatalogName = (DATA *)(pData + pBinding[0].obStatus);
DATA * pSchemaName = (DATA *)(pData + pBinding[1].obStatus);
fTableFound = TRUE;
//Catalog Name
if(pCatalogName->sStatus ==DBSTATUS_S_OK)
*ppwszCatalogName = wcsDuplicate((LPWSTR)pCatalogName->bValue);
//Schema Name
if(pSchemaName->sStatus ==DBSTATUS_S_OK)
*ppwszSchemaName = wcsDuplicate((LPWSTR)pSchemaName->bValue);
break;
}
}
TESTC_(pIRowset->ReleaseRows(cRows, pRow, NULL, NULL, NULL), S_OK);
}
COMPARE(fTableFound, TRUE);
CLEANUP:
if (pIRowset && pRow)
CHECK(pIRowset->ReleaseRows(cRows, pRow, NULL, NULL, NULL), S_OK);
if (fTableRestrict)
VariantClear(&rgRestrictions[TABLE_RESTRICT-1]);
PROVIDER_FREE(pSchemas);
PROVIDER_FREE(pRestrictionSupport);
PROVIDER_FREE(pRow);
PROVIDER_FREE(pData);
PROVIDER_FREE(pBinding);
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pIDBSchmr);
}
//---------------------------------------------------------------------------
// GetCommandTextAndPrintOut
//---------------------------------------------------------------------------
HRESULT CCmd::GetCommandTextAndPrintOut(ICommand * pICommand)
{
HRESULT hr=E_FAIL;
ICommandText * pICommandText=NULL;
WCHAR * sql = NULL;
// make sure everything is alive
if(!pICommand)
return hr;
if(FAILED(hr=pICommand->QueryInterface(IID_ICommandText,(void **)&pICommandText)))
goto CLEANUP;
if(FAILED(hr=pICommandText->GetCommandText(NULL,&sql)))
goto CLEANUP;
odtLog << sql << ENDL;
CLEANUP:
SAFE_RELEASE(pICommandText);
PROVIDER_FREE(sql);
return hr;
}
//---------------------------------------------------------------------------
// CCommand::IsColNumWithScale
//
// @mfunc BOOL |
// CCommand |
// IsColNumWithScale |
// Can the data type hold Numeric values with Scale?
//
//
//---------------------------------------------------------------------------
BOOL CCmd::IsColNumWithScale
(
DBTYPE ProviderType, // @parm [IN] provider data type
ULONG Scale // @parm [IN] precision for the data type
)
{
if (ProviderType & DBTYPE_BYREF)
ProviderType &= ~DBTYPE_BYREF;
switch(ProviderType)
{
case DBTYPE_NUMERIC: // Numeric, Decimal
case DBTYPE_DECIMAL:
if( Scale )
return TRUE;
else
return FALSE;
default:
return FALSE; // Compiler needs this
}
}
//--------------------------------------------------------------------
// @mfunc Base class Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL CCmd::Init()
{
if(COLEDB::Init())
{
if( m_pThisTestModule->m_pIUnknown )
{
m_pIDBInitialize = (IDBInitialize *)m_pThisTestModule->m_pIUnknown;
m_pIDBInitialize->AddRef();
}
if(m_pThisTestModule->m_pIUnknown)
m_pMyIDBInitialize = (IDBInitialize *)m_pThisTestModule->m_pIUnknown;
SetDBSession((IDBCreateCommand *)m_pThisTestModule->m_pIUnknown2);
SetTable((CTable *)m_pThisTestModule->m_pVoid, DELETETABLE_NO);
return TRUE;
}
return FALSE;
}
//--------------------------------------------------------------------
// @mfunc Base Case Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL CCmd::Terminate()
{
// NULL out the Local pointer
m_pMyIDBInitialize = NULL;
// Release the objects
SAFE_RELEASE(m_pIDBInitialize)
ReleaseDBSession();
return(COLEDB::Terminate());
}
//--------------------------------------------------------------------
// @mfunc Helper function for ICommand::Execute
//
// @rdesc HRESULT
//
HRESULT CCmd::Execute(ICommand* pICmd,IUnknown ** ppRowset,DBROWCOUNT * pcRowsAffected,IUnknown * pUnkOuter,DBPARAMS * pParams,IID iid)
{
HRESULT hr = E_FAIL;
TESTC(pICmd != NULL)
if(iid == IID_IDBInfo)
{
if(IFROWSET)
iid = IID_IRowset;
else
iid = IID_IRow;
}
hr = pICmd->Execute(pUnkOuter, iid, pParams, pcRowsAffected, ppRowset);
if(SUCCEEDED(hr))
{
if(ppRowset)
COMPARE(*ppRowset==INVALID(IRowset*), FALSE);
}
if(FAILED(hr))
{
if(ppRowset)
COMPARE(*ppRowset, NULL);
}
CLEANUP:
return hr;
}
//--------------------------------------------------------------------
// CreateThreads
//
//This simply the usage of threads down to 3 lines of code, CREATE/START/END
//--------------------------------------------------------------------
inline BOOL CCmd::CreateThreads
(
LPTHREAD_START_ROUTINE pFunc,
void* pArgs,
ULONG cThreads,
HANDLE* rghThread,
DWORD* rgThreadID
)
{
ASSERT(pFunc && pArgs && rghThread && rgThreadID);
for(ULONG i=0; i<cThreads; i++)
{
rghThread[i] = (void*)_beginthreadex(
NULL,
0,
(UINT(WINAPI*)(void*))pFunc,
pArgs,
CREATE_SUSPENDED,
(UINT*)&rgThreadID[i]);
}
// NOTE: CreateThread (WinAPI) is bad, it doesn't work well with the CrtLib,
// Supposed to use, _beginthreadex... CreateThread is much nicer, and doesn't
// require all the "casting", but _begin thread actually delegates out to eventually...
// rghThread[i] = CreateThread(NULL,0,pFunc,pArgs,CREATE_SUSPENDED,&rgThreadID[i]);
return TEST_PASS;
}
//--------------------------------------------------------------------
// StartThreads
//
//--------------------------------------------------------------------
inline BOOL CCmd::StartThreads(ULONG cThreads, LPHANDLE rghThread)
{
ASSERT(cThreads && rghThread);
for(ULONG i=0; i<cThreads; i++)
ResumeThread(rghThread[i]);
return TEST_PASS;
}
//--------------------------------------------------------------------
// EndThreads
//
//--------------------------------------------------------------------
inline BOOL CCmd::EndThreads(ULONG cThreads, LPHANDLE rghThread)
{
ASSERT(cThreads && rghThread);
WaitForMultipleObjects(cThreads, rghThread, TRUE, INFINITE);
for(ULONG i=0; i<cThreads; i++)
CloseHandle(rghThread[i]);
return TEST_PASS;
}
// Hack to define COINIT value
#define COINIT_MULTITHREADED 0x0
//--------------------------------------------------------------------
// Execute
//
//--------------------------------------------------------------------
ULONG CCmd::Execute(LPVOID pv)
{
BOOL TESTB = TEST_FAIL;
DBROWCOUNT cRowsAffected = -111;
HRESULT hReturnResult = E_FAIL;
HRESULT hrCoInit = E_FAIL;
ASSERT(pv);
ASSERT(THRD_FUNC);
//Thread Stack Variables
CCmd* pThis = (CCmd*)THRD_FUNC;
ASSERT(THRD_ARG2);
// expected result
HRESULT hr = *(HRESULT *)THRD_ARG2;
ASSERT(THRD_ARG3);
// Type of sql statement used.
STATEMENTKIND eStatementKind = *(STATEMENTKIND *)THRD_ARG3;
ASSERT(THRD_ARG4);
// Type of sql statement used.
HRESULT hOptionalResult = *(HRESULT *)THRD_ARG4;
//Local Variables
ICommand * pICommand = (ICommand *)THRD_ARG1;
IUnknown* pUnk = NULL;
ThreadSwitch(); //Let the other thread(s) catch up
TESTC_(hrCoInit = CoInit(COINIT_MULTITHREADED), S_OK);
hReturnResult = pThis->Execute(pICommand, PPI &pUnk, &cRowsAffected);
if (hReturnResult != hr &&
hReturnResult != hOptionalResult &&
hReturnResult != DB_S_STOPLIMITREACHED)
{
// Kagera returns E_FAIL here intermittently, which is a known issue that causes
// problems with the automation runs, therefore we will just print a message so
// we don't get a failures all the time. See Note 3.
if (g_fKagera && hReturnResult == E_FAIL)
odtLog << L"Unexpected return code E_FAIL.\n";
else if (!pThis->m_pError->Validate(hReturnResult, LONGSTRING(__FILE__), __LINE__, hr))
goto CLEANUP;
}
if (m_fValidateExtended)
{
EnterCriticalSection(&g_csExtendedError);
BOOL fSuccess = TRUE;
// It is legal for providers to return DB_S_STOPLIMITREACHED here
// odtLog << L"hReturnResult before ValidateExtended: " << hReturnResult << "\n";
if (hReturnResult != DB_S_STOPLIMITREACHED)
fSuccess = pThis->m_pExtError->ValidateExtended(hReturnResult, pICommand, IID_ICommand,
LONGSTRING(__FILE__), __LINE__);
// if (!fSuccess)
// odtLog << L"hReturnResult: " << hReturnResult << "\n";
pThis->m_pError->Compare(fSuccess == TRUE, LONGSTRING(__FILE__), __LINE__);
LeaveCriticalSection(&g_csExtendedError);
}
if (eStatementKind == eINSERT)
{
// Assuming that the insert statement is just one
if (hReturnResult == S_OK)
{
// Providers are allowed to return DB_COUNTUNAVAILABLE if they don't know
if (cRowsAffected == DB_COUNTUNAVAILABLE)
{
// Since it is legal for providers to returen DB_COUNTUNAVAILABLE we will no longer
// warn here. The warning was just so we knew it was returned, in case a particular
// provider wasn't supposed to return it. But it causes too much noise in the tests.
// COMPAREW(cRowsAffected, 1);
// odtLog << L"Provider did not return cRowsAffected on insert and returned DB_COUNTUNAVAILABLE instead.\n";
}
else if (!pThis->m_pError->Compare(cRowsAffected==1,LONGSTRING(__FILE__), __LINE__) )
goto CLEANUP;
}
else if (hReturnResult == DB_E_CANCELED)
{
if (! pThis->m_pError->Compare(cRowsAffected != 1, LONGSTRING(__FILE__), __LINE__) )
goto CLEANUP;
}
}
else if (eStatementKind == eSELECT)
{
if (hReturnResult == S_OK)
{
if (g_fKagera)
{
// Kagera has an intermittent bug here where they return S_OK but a NULL rowset pointer.
// This causes all sorts of problems with automation runs, that is, failures that show
// up sometimes but not others. Since they have refused to fix this we will merely print
// a message indicating the problem. See Note 2.
if (pUnk == NULL)
odtLog << L"Provider returned S_OK but did not return a valid rowset pointer.\n";
}
else if (! pThis->m_pError->Compare((pUnk != NULL), LONGSTRING(__FILE__), __LINE__) )
goto CLEANUP;
}
else if (hReturnResult == DB_E_CANCELED)
{
if (! pThis->m_pError->Compare((pUnk == NULL), LONGSTRING(__FILE__), __LINE__) )
goto CLEANUP;
}
}
else
{
// Currently not prepare to handle any other types.
ASSERT(!L"NEED MORE CODE");
}
ThreadSwitch(); //Let the other thread(s) catch up
TPASS;
CLEANUP:
SAFE_RELEASE(pUnk);
/*
if (eStatementKind == eINSERT)
PRVTRACE("Insert thread exited with status: %d\n", TESTB);
else
PRVTRACE("Select thread exited with status: %d\n", TESTB);
*/
if (SUCCEEDED(hrCoInit))
CoUninitialize();
_endthreadex(TESTB);
TRETURN
}
//--------------------------------------------------------------------
// Cancel
//
//--------------------------------------------------------------------
ULONG CCmd::Cancel(LPVOID pv)
{
BOOL TESTB = TEST_FAIL;
HRESULT hReturnResult;
HRESULT hrCoInit = E_FAIL;
ASSERT(pv);
//Thread Stack Variables
ASSERT(THRD_FUNC);
CCmd* pThis = (CCmd*)THRD_FUNC;
ASSERT(THRD_ARG1);
ICommand * pICommand = (ICommand *)THRD_ARG1;
ASSERT(THRD_ARG2);
HRESULT hr = *(HRESULT *)THRD_ARG2;
ASSERT(THRD_ARG3);
// Type of sql statement used.
STATEMENTKIND eStatementKind = *(STATEMENTKIND *)THRD_ARG3;
ASSERT(THRD_ARG4);
// Type of sql statement used.
HRESULT hOptionalResult = *(HRESULT *)THRD_ARG4;
ThreadSwitch(); //Let the other thread(s) catch up
TESTC_(hrCoInit = CoInit(COINIT_MULTITHREADED), S_OK);
// (! (pThis->m_pError->Validate(pICommand->Cancel(), LONGSTRING(__FILE__), __LINE__, hr)))
hReturnResult=pICommand->Cancel();
if (! pThis->m_pError->Compare((hReturnResult == hr || hReturnResult == hOptionalResult)==TRUE, LONGSTRING(__FILE__), __LINE__) )
goto CLEANUP;
ThreadSwitch(); //Let the other thread(s) catch up
TPASS
CLEANUP:
if (SUCCEEDED(hrCoInit))
CoUninitialize();
_endthreadex(TESTB);
TRETURN
}
//---------------------------------------------------------------------------
// CCmd::IsColNumeric
//
// @mfunc BOOL |
// CCmd |
// IsColNumeric |
// Can the data type hold numeric values?
//
//
//---------------------------------------------------------------------------
BOOL CCmd::IsColNumeric
(
DBTYPE ProviderType // @parm [IN] provider data type
)
{
if (ProviderType & DBTYPE_BYREF)
ProviderType &= ~DBTYPE_BYREF;
switch(ProviderType)
{
case DBTYPE_NUMERIC: // Numeric, Decimal
case DBTYPE_I4: // Integer
case DBTYPE_I2: // Smallint
case DBTYPE_I1: // Tinyint
case DBTYPE_R8: // Float, Double
case DBTYPE_R4: // Real
case DBTYPE_UI2:
case DBTYPE_UI4:
case DBTYPE_I8:
case DBTYPE_UI8:
return TRUE;
default:
return FALSE; // Compiler needs this
}
}
//---------------------------------------------------------------------------
// CCmd::IsColCharacter
//
// @mfunc BOOL |
// CCmd |
// IsColCharacter |
// Can the data type hold string values?
//
//
//---------------------------------------------------------------------------
BOOL CCmd::IsColCharacter
(
DBTYPE ProviderType // @parm [IN] provider data type
)
{
if (ProviderType & DBTYPE_BYREF)
ProviderType &= ~DBTYPE_BYREF;
switch(ProviderType)
{
case DBTYPE_STR: // Character
case DBTYPE_WSTR:
return TRUE;
default:
return FALSE; // Compiler needs this
}
}
//---------------------------------------------------------------------------
// CCmd::IsColDateTime
//
// @mfunc BOOL |
// CCmd |
// IsColDateTime |
// Can the data type hold DateTime values?
//
//
//---------------------------------------------------------------------------
BOOL CCmd::IsColDateTime
(
DBTYPE ProviderType // @parm [IN] provider data type
)
{
if (ProviderType & DBTYPE_BYREF)
ProviderType &= ~DBTYPE_BYREF;
switch(ProviderType)
{
case DBTYPE_DATE: // OLE Auto. Date
case DBTYPE_DBDATE: // Date
case DBTYPE_DBTIME: // Time
case DBTYPE_DBTIMESTAMP: // TimeStamp
return TRUE;
default:
return FALSE; // Compiler needs this
}
}
//--------------------------------------------------------------------
// CreateSession
//--------------------------------------------------------------------
BOOL CCmd::CreateSession
(
REFIID iid,
IUnknown ** pIUnknown
)
{
BOOL fResult = FALSE;
IDBCreateSession * pIDBCreateSession = NULL;
if(!pIUnknown)
return FALSE;
if(m_pMyIDBInitialize)
{
if(!VerifyInterface(m_pMyIDBInitialize, IID_IDBCreateSession,
DATASOURCE_INTERFACE, (IUnknown**)&pIDBCreateSession))
goto CLEANUP;
if(SUCCEEDED(pIDBCreateSession->CreateSession(NULL,iid,pIUnknown)))
fResult = TRUE;
}
CLEANUP:
SAFE_RELEASE(pIDBCreateSession);
return fResult;
}
//-------------------------------------------------------------------
// GetCommand
//--------------------------------------------------------------------
BOOL CCmd::GetCommand
(
REFIID iid, // [OUT] IID for command
IUnknown ** pIUnknownCommand, // [OUT] command pointer
IUnknown * pIUnknownSession // [IN] session object
)
{
BOOL fResult = FALSE;
IDBCreateCommand * pSession = NULL;
if(!pIUnknownCommand)
return FALSE;
// Get session objects just gets the pointer. No need to release pSession2.
if(pIUnknownSession) {
CLEANUP(!VerifyInterface(pIUnknownSession, IID_IDBCreateCommand,
SESSION_INTERFACE, (IUnknown**)&pSession));
}
else {
CLEANUP(GetSessionObject(IID_IDBCreateCommand, (IUnknown**)&pSession));
}
if(SUCCEEDED(pSession->CreateCommand(NULL,iid,pIUnknownCommand)))
fResult = TRUE;
CLEANUP:
SAFE_RELEASE(pSession);
return fResult;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// ValidateSessionObject
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BOOL CCmd::ValidateSessionObject
(
IUnknown * pIUnknown
)
{
BOOL fResult=FALSE;
IUnknown * pISession=NULL;
if(!pIUnknown)
return FALSE;
// Get Session that created command
TEST_CHECK(GetSessionObject(IID_IUnknown, &pISession), S_OK);
if(COMPARE(pISession, pIUnknown))
fResult = TRUE;
CLEANUP:
SAFE_RELEASE(pISession);
return fResult;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// SetPropertyAndExecute
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BOOL CCmd::SetPropertyAndExecute(
ICommand * pICmd,
DBPROPINFOSET * pPropertyInfoSets,
ULONG iSet,
ULONG iProp,
enum SET_OPTION_ENUM eSetOption,
WCHAR * pwszDescription1,
BOOL * pfPropFound)
{
IRowset * pIRowset = NULL;
IUnknown* pIUnk = NULL;
BOOL fResult = TRUE;
HRESULT hrSetProp = E_FAIL;
HRESULT hr = E_FAIL;
VARIANT vValue;
VariantInit(&vValue);
odtLog << L"Property: " << pPropertyInfoSets[iSet].rgPropertyInfos[iProp].pwszDescription << L"\n";
// If the property is not supported or not writable just skip it
if (pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwFlags == DBPROPFLAGS_NOTSUPPORTED ||
!(pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwFlags & DBPROPFLAGS_WRITE))
{
if (pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwFlags == DBPROPFLAGS_NOTSUPPORTED)
odtLog << L"\tNot supported.\n";
if (!(pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwFlags & DBPROPFLAGS_WRITE))
odtLog << L"\tNot writable.\n";
return TRUE;
}
// Record the current property value so we can reset it to a successful value later
COMPARE(GetProperty(pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwPropertyID,
pPropertyInfoSets[iSet].guidPropertySet, pICmd, &vValue), TRUE);
// Set the property on
hrSetProp = SetRowsetProperty(pICmd, pPropertyInfoSets[iSet].guidPropertySet,
pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwPropertyID, TRUE,
DBPROPOPTIONS_REQUIRED, FALSE);
hr = Execute(pICmd,PPI &pIUnk);
SAFE_RELEASE(pIUnk);
// If this caused DB_E_ERRORSOCCURRED when REQUIRED it's one we want
if (DB_E_ERRORSOCCURRED == hr)
{
odtLog << L"\tDB_E_ERRORSOCCURRED\n";
// DumpCommandProps(pICmd, FALSE);
// Make sure there are properties in error.
COMPARE(PropertiesInError(pICmd, hr), TRUE);
if (pfPropFound)
*pfPropFound = TRUE;
// Now set optional
SetRowsetProperty(pICmd, pPropertyInfoSets[iSet].guidPropertySet,
pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwPropertyID,
TRUE, DBPROPOPTIONS_OPTIONAL, FALSE);
if (!CHECK(hr = Execute(pICmd,PPI &pIUnk),DB_S_ERRORSOCCURRED))
{
WCHAR * pwszDescription = L"NULL property description!!";
WCHAR * pwszDescription2 = L"NULL property description!!";
if (pwszDescription1)
pwszDescription = pwszDescription1;
if (pPropertyInfoSets[iSet].rgPropertyInfos[iProp].pwszDescription)
pwszDescription2 = pPropertyInfoSets[iSet].rgPropertyInfos[iProp].pwszDescription;
odtLog << L"Execute did not return DB_S_ERRORSOCCURRED for OPTIONAL property that causes DB_E_ERRORSOCCURRED when REQUIRED.\n";
if (eSetOption == PAIRED_PROP)
odtLog << L"Property description (REQUIRED): " << pwszDescription1 <<
L"\n Paired with \n";
odtLog << L"Property description (OPTIONAL): " << pwszDescription2 << L"\n\n";
fResult = FALSE;
}
else
{
odtLog << L"\tDB_S_ERRORSOCCURRED\n";
// There should be at least one property in error
COMPARE(PropertiesInError(pICmd, hr), TRUE);
}
SAFE_RELEASE(pIRowset);
}
else
{
HRESULT ExpHr = S_OK;
// At least two properties (DBPROP_IMultipleResults, IRow, IRowset) will cause E_NOINTERFACE, since this causes
// Execute to return an IMultipleResults obj or Row obj, not a rowset object.
if (pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwPropertyID == DBPROP_IMultipleResults ||
pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwPropertyID == DBPROP_IRowChange ||
pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwPropertyID == DBPROP_IRowSchemaChange ||
pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwPropertyID == DBPROP_IRowset ||
pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwPropertyID == DBPROP_IRow)
{
enum DBPROPOPTIONSENUM dwOption = DBPROPOPTIONS_REQUIRED;
if(hrSetProp == DB_E_ERRORSOCCURRED)
{
if(IFROWSET)
ExpHr = S_OK;
else
ExpHr = E_NOINTERFACE;
}
// Some providers can't roll the IRowset prop if this is set REQUIRED
if (IFROW && pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwPropertyID == DBPROP_IRowset)
dwOption = DBPROPOPTIONS_OPTIONAL;
// Turn the property back off so we don't ALWAYS have an IMultipleResults (or Row) object from
// now on.
SetRowsetProperty(pICmd, pPropertyInfoSets[iSet].guidPropertySet,
pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwPropertyID, VARIANT_FALSE,
dwOption);
}
if (hr != E_NOINTERFACE && hr != DB_E_ERRORSOCCURRED && !CHECK(hr, S_OK))
{
WCHAR * pwszDescription = L"NULL property description!!";
if (pPropertyInfoSets[iSet].rgPropertyInfos[iProp].pwszDescription)
pwszDescription = pPropertyInfoSets[iSet].rgPropertyInfos[iProp].pwszDescription;
odtLog << L"Execute did not return S_OK, E_NOINTERFACE, or DB_E_ERRORSOCCURRED for REQUIRED property.\n" <<
L"Property description: " << pwszDescription << L"\n\n";
fResult = FALSE;
}
}
VariantClear(&vValue);
SAFE_RELEASE(pIUnk);
return fResult;
}
HRESULT CCmd::VerifyRowset(REFIID riidRowset, IUnknown * pUnkRowset, ULONG ulStartingRow,
DBORDINAL cRowsetCols, DBORDINAL * rgTableColOrds, BOOL fRelease)
{
BOOL fResult = FALSE;
IRowset * pIRowset = NULL;
IAccessor * pIAccessor = NULL;
HRESULT hr = E_FAIL;
DBCOUNTITEM cRowsObtained=0;
HROW * prghRow = NULL;
HACCESSOR hAccessor = DB_INVALID_HACCESSOR;
DBBINDING * pBindings = NULL;
DBCOUNTITEM cBindings = 0;
DBLENGTH cbRowSize = 0;
BYTE * pData = NULL;
// If we didn't get passed the mapping of rowset cols to table cols we can't compare data
if (!cRowsetCols || !rgTableColOrds)
return E_FAIL;
// Make sure we can get a rowset interface
TESTC(VerifyInterface(pUnkRowset, IID_IRowset,
ROWSET_INTERFACE, (IUnknown **)&pIRowset));
// If we were passed in a rowset interface, use the one passed in
if (riidRowset == IID_IRowset)
{
SAFE_RELEASE(pIRowset);
pIRowset = (IRowset *)pUnkRowset;
}
// Make sure we can get an accessor interface
TESTC(VerifyInterface(pUnkRowset, IID_IAccessor,
ROWSET_INTERFACE, (IUnknown **)&pIAccessor));
TESTC_(GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,
&hAccessor, &pBindings, &cBindings, &cbRowSize,
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF,
NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,
NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_LONG), S_OK);
SAFE_ALLOC(pData, BYTE, cbRowSize * sizeof(BYTE));
// TODO: Use IMultipleResults here if supported in case multiple results are returned??
while (S_OK == (hr = pIRowset->GetNextRows(NULL, 0, 1, &cRowsObtained, &prghRow)))
{
TESTC(cRowsObtained == 1);
CHECK(hr = pIRowset->GetData(*prghRow, hAccessor, pData), S_OK);
if (SUCCEEDED(hr))
{
TESTC(CompareData(
cRowsetCols,
(DB_LORDINAL *)rgTableColOrds,
ulStartingRow,
pData,
cBindings,
pBindings,
m_pTable,
m_pIMalloc,
PRIMARY,
COMPARE_ONLY,
COMPARE_ALL,
TRUE
));
TESTC_(pIRowset->ReleaseRows(cRowsObtained, prghRow, NULL, NULL, NULL), S_OK);
ulStartingRow++;
}
else
// If this GetData failed it's doubtful further GetData's are of much use
goto CLEANUP;
}
TESTC_(hr, DB_S_ENDOFROWSET);
COMPARE(ulStartingRow, m_pTable->GetRowsOnCTable() +1);
fResult = TRUE;
CLEANUP:
if ((hAccessor != DB_INVALID_HACCESSOR) &&
!CHECK(pIAccessor->ReleaseAccessor(hAccessor, NULL), S_OK))
fResult = FALSE;
SAFE_RELEASE(pIAccessor);
// If we passed in a rowset pointer then it gets release below if requested
// otherwise release here.
if (riidRowset != IID_IRowset)
SAFE_RELEASE(pIRowset);
if (fRelease)
SAFE_RELEASE(pUnkRowset);
FreeAccessorBindings(cBindings, pBindings);
PROVIDER_FREE(pData);
PROVIDER_FREE(prghRow);
return fResult ? S_OK : E_FAIL;
}
HRESULT CCmd::VerifyRowObj(REFIID riidRow, IUnknown * pUnkRow, ULONG ulStartingRow,
DBORDINAL cRowsetCols, DBORDINAL * rgTableColOrds, BOOL fRelease)
{
BOOL fResult = FALSE;
CRowObject* pCRow = NULL;
pCRow = new CRowObject();
TESTC(pCRow != NULL)
TESTC_(pCRow->SetRowObject(pUnkRow), S_OK)
//Veify the GetColumns method.
TESTC(pCRow->VerifyGetColumns(ulStartingRow, m_pTable))
fResult = TRUE;
CLEANUP:
SAFE_DELETE(pCRow);
return fResult ? S_OK : E_FAIL;
}
// Verify the specified row number appears in the table cRows times. The
// row number is based on the insert seed number.
BOOL CCmd::VerifyAndRemoveRows(CTable * pTable, DBCOUNTITEM ulRowNum, DBCOUNTITEM cRows)
{
ICommandText * pICommandText = NULL;
ICommand * pICommand = NULL;
IRowset * pIRowset = NULL;
DBORDINAL cCols;
DBCOUNTITEM cRowsObtained;
DB_LORDINAL * pCols = NULL;
HROW * phRows = NULL;
BOOL fResult = FALSE;
WCHAR * pwszSqlStmt = NULL;
TESTC((pICommand = pTable->m_pICommand) != NULL);
// Set command text for a select query using literals.
TESTC_(pTable->CreateSQLStmt(SELECT_ROW_WITH_LITERALS, NULL, &pwszSqlStmt,&cCols,&pCols, ulRowNum), S_OK);
TESTC(VerifyInterface(pICommand, IID_ICommandText,
COMMAND_INTERFACE, (IUnknown**)&pICommandText));
TESTC_(pICommandText->SetCommandText(DBGUID_DEFAULT, pwszSqlStmt), S_OK);
// Retrieve all rows that match the requested row.
TESTC_(pICommand->Execute(NULL, IID_IRowset, NULL,
NULL, (IUnknown **)&pIRowset),S_OK);
// There should be only the number of rows we expect so asking for one more will be ENDOFROWSET
TESTC_(pIRowset->GetNextRows(NULL, 0, cRows+1, &cRowsObtained, &phRows), DB_S_ENDOFROWSET);
if (phRows)
{
pIRowset->ReleaseRows(cRows, phRows, NULL, NULL, NULL);
SAFE_FREE(phRows);
}
SAFE_RELEASE(pIRowset);
// Make sure not fewer rows
fResult = COMPARE(cRowsObtained, cRows);
fResult &= CHECK(pTable->Delete(ulRowNum,PRIMARY,TRUE,NULL), S_OK);
CLEANUP:
if (phRows)
pIRowset->ReleaseRows(cRows, phRows, NULL, NULL, NULL);
SAFE_FREE(phRows);
SAFE_FREE(pCols);
SAFE_FREE(pwszSqlStmt);
SAFE_RELEASE(pICommandText);
SAFE_RELEASE(pIRowset);
return fResult;
}
BOOL CCmd::VerifyThreadingModel(DWORD dwCoInit)
{
ULONG_PTR ulThreadModel;
BOOL fValidThreadModel = FALSE;
HRESULT hr = E_FAIL;
// Get the provider's thread model
if (m_pIDBInitialize)
{
// See if our base thread is in free threaded.
if (SUCCEEDED(hr = CoInit(COINIT_MULTITHREADED)))
CoUninitialize();
switch(hr)
{
case S_FALSE:
// Base thread is multi-threaded apartment model.
odtLog << L"Base thread (LTM) is free threaded.\n";
fValidThreadModel = TRUE;
break;
case E_INVALIDARG:
case RPC_E_CHANGED_MODE:
// The user (LTM) might have called CoInitialize to set apartment model, and the two API's don't
// seem to work together properly to return S_FALSE.
if (SUCCEEDED(hr = CoInitialize(NULL)))
CoUninitialize();
if (S_FALSE == hr)
// Base thread is apartment model.
odtLog << L"Base thread (LTM) is apartment model, not currently supported by test.\n";
else
fValidThreadModel = TRUE;
break;
default:
odtLog << L"Unrecognized base threading model.\n";
}
// Warn that message loop needed for apartment threading
// We don't currently work with apartment threading
if (dwCoInit & COINIT_APARTMENTTHREADED)
{
odtLog << L"Aparment model requested but not currently supported..\n";
fValidThreadModel = FALSE;
}
// If the provider doesn't support the thread model property we
// assume single threaded.
if (!GetProperty(DBPROP_DSOTHREADMODEL, DBPROPSET_DATASOURCEINFO,
m_pIDBInitialize, &ulThreadModel))
ulThreadModel = DBPROPVAL_RT_SINGLETHREAD;
// Warn if the requested model is not supported by the provider.
if ((dwCoInit & COINIT_APARTMENTTHREADED &&
!(ulThreadModel & DBPROPVAL_RT_APTMTTHREAD)) ||
(dwCoInit & COINIT_MULTITHREADED &&
!(ulThreadModel & DBPROPVAL_RT_FREETHREAD)))
{
odtLog << L"Requested threading model doesn't match provider's supported value.\n";
fValidThreadModel = FALSE;
}
}
return fValidThreadModel;
}
// CCmd::SetRowsetPropertyDefault ------------------------------------
//
// Sets the given rowset property using ICommandProperties to the default value
//
//
HRESULT CCmd::SetRowsetPropertyDefault(DBPROPID DBPropID, ICommand * pICommand)
{
ICommandProperties * pICmdProps = NULL;
DBPROPSET DBPropSet;
DBPROP DBProp;
HRESULT hr = E_FAIL;
//Set up the rowset property structure to use the ID passed in
DBPropSet.rgProperties = &DBProp;
DBPropSet.cProperties = 1;
DBPropSet.guidPropertySet = DBPROPSET_ROWSET;
DBProp.dwPropertyID = DBPropID;
DBProp.dwOptions = DBPROPOPTIONS_OPTIONAL;
DBProp.colid = DB_NULLID;
DBProp.vValue.vt = VT_EMPTY; //Causes default to be set
TESTC(pICommand != NULL);
TESTC_(pICommand->QueryInterface(IID_ICommandProperties,
(void **)&pICmdProps), S_OK);
TESTC_(pICmdProps->SetProperties(1, &DBPropSet), S_OK);
hr = S_OK;
CLEANUP:
SAFE_RELEASE(pICmdProps);
return hr;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Test Case Section
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// {{ TCW_TEST_CASE_MAP(CExecute_Rowset)
//--------------------------------------------------------------------
// @class general valid variations
//
class CExecute_Rowset : public CCmd {
public:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(CExecute_Rowset,CCmd);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember S_OK: Multiple Executions on same command object (Select)
int Variation_1();
// @cmember S_OK:Multiple Executions on same command object (Insert)
int Variation_2();
// @cmember S_OK:Prepared command
int Variation_3();
// @cmember S_OK:Prepared and Unprepared Command
int Variation_4();
// @cmember S_OK:Multiple Sessions Open
int Variation_5();
// @cmember S_OK:Multiple Commands Open
int Variation_6();
// @cmember S_OK: 1 cmd obj (3 inserts on their own threads
int Variation_7();
// @cmember S_OK: Query set only
int Variation_8();
// @cmember DB_E_NOCOMMAND: no command set
int Variation_9();
// @cmember DB_E_ERRORSINCOMMAND - (Select)
int Variation_10();
// @cmember DB_E_ERRORSINCOMMAND - (Insert)
int Variation_11();
// @cmember DB_INVALIDARG - cParamSets > 1 and ppRowset was not a null pointer
int Variation_12();
// @cmember DB_E_MULTIPLESTATEMENTS - command contained multiple statements
int Variation_13();
// @cmember DB_S_ERRORSOCCURED - property was not set
int Variation_14();
// @cmember S_OK: Insert, riid=IID_NULL
int Variation_15();
// @cmember S_OK: Insert, riid=IID_IRowset
int Variation_16();
// @cmember S_OK: Insert, riid=IID_IRowsetInfo
int Variation_17();
// @cmember S_OK: Select, riid=IID_IRowset
int Variation_18();
// @cmember S_OK: Select, riid=IID_IRowsetInfo
int Variation_19();
// @cmember E_NOINTERACE: dso iid
int Variation_20();
// @cmember S_OK:valid pcRowsAffected, *pc=0, valid pIRowset (Select)
int Variation_21();
// @cmember S_OK:valid pcRowsAffected, *pc=1, valid pIRowset (Select)
int Variation_22();
// @cmember S_OK:valid pcRowsAffected, *pc=0, valid pIRowset (Insert)
int Variation_23();
// @cmember S_OK:valid pcRowsAffected, *pc=1, valid pIRowset (Insert)
int Variation_24();
// @cmember S_OK:NULL pcRowsAffected, valid pIRowset (Select)
int Variation_25();
// @cmember E_INVALIDARG:NULL pcRowsAffected, NULL pIRowset (Select)
int Variation_26();
// @cmember S_OK:NULL pcRowsAffected, valid pIRowset (Insert)
int Variation_27();
// @cmember S_OK:NULL pcRowsAffected, NULL pIRowset (Insert)
int Variation_28();
// @cmember S_OK:valid pcRowsAffected, *pc=0, valid pIRowsetLocate (Select)
int Variation_29();
// @cmember S_OK:valid pcRowsAffected, *pc=1, valid pIRowsetLocate (Select)
int Variation_30();
// @cmember S_OK:valid pcRowsAffected, *pc=0, valid pIRowsetLocate (Insert)
int Variation_31();
// @cmember S_OK:NULL pcRowsAffected, valid pIRowsetLocate (Select)
int Variation_32();
// @cmember E_INVALIDARG:NULL pcRowsAffected, NULL pIRowsetLocate (Select)
int Variation_33();
// @cmember S_OK:NULL pcRowsAffected, valid pIRowsetLocate (Insert)
int Variation_34();
// @cmember S_OK:NULL pcRowsAffected, NULL pIRowsetLocate (Insert)
int Variation_35();
// @cmember S_OK:valid pcRowsAffected, *pc=0, valid pIColumnsInfo (Select)
int Variation_36();
// @cmember S_OK:valid pcRowsAffected, *pc=1, valid pIColumnsInfo (Select)
int Variation_37();
// @cmember S_OK:valid pcRowsAffected, *pc=0, valid pIColumnsInfo (Insert)
int Variation_38();
// @cmember S_OK:valid pcRowsAffected, *pc=1, valid pIColumnsInfo (Insert)
int Variation_39();
// @cmember S_OK:NULL pcRowsAffected, valid pIColumnsInfo (Select)
int Variation_40();
// @cmember E_INVALIDARG:NULL pcRowsAffected, NULL pIColumnsInfo (Select)
int Variation_41();
// @cmember S_OK:NULL pcRowsAffected, valid pIColumnsInfo (Insert)
int Variation_42();
// @cmember S_OK:NULL pcRowsAffected, NULL pIColumnsInfo (Insert)
int Variation_43();
// @cmember E_INVALIDARG:riid != IID_NULL, ppRowset==NULL
int Variation_44();
// @cmember DB_E_CANTCONVERTVALUE: string (22005)
int Variation_45();
// @cmember DB_E_CANTCONVERTVALUE: implicit (22005)
int Variation_46();
// @cmember DB_E_CANTCONVERTVALUE: implicit (22008)
int Variation_47();
// @cmember DB_E_DATAOVERFLOW: math (22003)
int Variation_48();
// @cmember DB_E_DATAOVERFLOW: string right (22001
int Variation_49();
// @cmember DB_E_ERRORSINCOMMAND - Create Table statement on a table that already exists (S0001)
int Variation_50();
// @cmember DB_E_ERRORSINCOMMAND - Create View statement on a view that already exists (S0001)
int Variation_51();
// @cmember DB_E_ERRORSINCOMMAND - Select statement with invalid table name (S0002)
int Variation_52();
// @cmember DB_E_ERRORSINCOMMAND - Drop Table statement on a table that does not exist (S0002)
int Variation_53();
// @cmember DB_E_ERRORSINCOMMAND - Drop View statement on a view that does not exist (S0002)
int Variation_54();
// @cmember DB_E_ERRORSINCOMMAND - Select statement with invalid column name (S0022)
int Variation_55();
// @cmember S_OK - Numeric Truncation (01004)
int Variation_56();
// @cmember DB_E_ERRORSINCOMMAND - Invalid nodes in a command (37000)
int Variation_57();
// @cmember S_OK: riid = IUnknown
int Variation_58();
// @cmember S_OK: cParam=0
int Variation_59();
// @cmember S_OK: select * from sp_tables
int Variation_60();
// @cmember DB_E_ERRORSINCOMMAND: create current exisiting table
int Variation_61();
// @cmember Query TimeOut
int Variation_62();
// @cmember Query TimeOut
int Variation_63();
// @cmember Firehose mode
int Variation_64();
// @cmember Aggregation - Open a rowset on aggregated command
int Variation_65();
// @cmember S_OK: Select, IID_NULL, ppRowset NULL
int Variation_66();
// @cmember Test all IID's of object
int Variation_67();
// @cmember E_NOINTERFACE - Ask for unsupported interface with ppRowset == NULL
int Variation_68();
// @cmember DB_E_INTEGRITYVIOLATION - Insert a duplicate key value
int Variation_69();
// @cmember S_OK - select with qualified name
int Variation_70();
// @cmember S_OK - select with quoted name
int Variation_71();
// @cmember S_OK - select distinct
int Variation_72();
// @cmember DB_E_ERRORSOCCURRED - select distinct with DBPROP_UNIQUEROWS REQUIRED
int Variation_73();
// @cmember DB_E_ERRORSINCOMMAND - select with invalid group by clause
int Variation_74();
// @cmember DB_S_ERRORSOCCURRED - select distinct with DBPROP_UNIQUEROWS OPTIONAL
int Variation_75();
// @cmember DB_E_ERRORSINCOMMAND - (Insert with mis-spelled keyword)
int Variation_76();
// @cmember S_OK: Multiple commands, 2 initial and 1 later
int Variation_77();
// @cmember S_OK: Create index in descending order
int Variation_78();
// @cmember S_OK: All rows with singleton select
int Variation_79();
// @cmember S_OK: Select ABC and Col List
int Variation_80();
// @cmember S_OK: Select duplicate columns
int Variation_81();
// @cmember S_OK: Select Count
int Variation_82();
// @cmember S_OK: Select empty rowset
int Variation_83();
// @cmember S_OK: Select Change col name
int Variation_84();
// @cmember S_OK: Aggregated rowset
int Variation_85();
// @cmember Last Variation - Final Verification
int Variation_86();
// }} TCW_TESTVARS_END
};
// }}
// }}
// {{ TCW_TESTCASE(CExecute_Rowset)
#define THE_CLASS CExecute_Rowset
BEG_TEST_CASE(CExecute_Rowset, CCmd, L"general valid variations")
TEST_VARIATION(1, L"S_OK: Multiple Executions on same command object (Select)")
TEST_VARIATION(2, L"S_OK:Multiple Executions on same command object (Insert)")
TEST_VARIATION(3, L"S_OK:Prepared command")
TEST_VARIATION(4, L"S_OK:Prepared and Unprepared Command")
TEST_VARIATION(5, L"S_OK:Multiple Sessions Open")
TEST_VARIATION(6, L"S_OK:Multiple Commands Open")
TEST_VARIATION(7, L"S_OK: 1 cmd obj (3 inserts on their own threads")
TEST_VARIATION(8, L"S_OK: Query set only")
TEST_VARIATION(9, L"DB_E_NOCOMMAND: no command set")
TEST_VARIATION(10, L"DB_E_ERRORSINCOMMAND - (Select)")
TEST_VARIATION(11, L"DB_E_ERRORSINCOMMAND - (Insert)")
TEST_VARIATION(12, L"DB_INVALIDARG - cParamSets > 1 and ppRowset was not a null pointer")
TEST_VARIATION(13, L"DB_E_MULTIPLESTATEMENTS - command contained multiple statements")
TEST_VARIATION(14, L"DB_S_ERRORSOCCURED - property was not set")
TEST_VARIATION(15, L"S_OK: Insert, riid=IID_NULL")
TEST_VARIATION(16, L"S_OK: Insert, riid=IID_IRowset")
TEST_VARIATION(17, L"S_OK: Insert, riid=IID_IRowsetInfo")
TEST_VARIATION(18, L"S_OK: Select, riid=IID_IRowset")
TEST_VARIATION(19, L"S_OK: Select, riid=IID_IRowsetInfo")
TEST_VARIATION(20, L"E_NOINTERACE: dso iid")
TEST_VARIATION(21, L"S_OK:valid pcRowsAffected, *pc=0, valid pIRowset (Select)")
TEST_VARIATION(22, L"S_OK:valid pcRowsAffected, *pc=1, valid pIRowset (Select)")
TEST_VARIATION(23, L"S_OK:valid pcRowsAffected, *pc=0, valid pIRowset (Insert)")
TEST_VARIATION(24, L"S_OK:valid pcRowsAffected, *pc=1, valid pIRowset (Insert)")
TEST_VARIATION(25, L"S_OK:NULL pcRowsAffected, valid pIRowset (Select)")
TEST_VARIATION(26, L"E_INVALIDARG:NULL pcRowsAffected, NULL pIRowset (Select)")
TEST_VARIATION(27, L"S_OK:NULL pcRowsAffected, valid pIRowset (Insert)")
TEST_VARIATION(28, L"S_OK:NULL pcRowsAffected, NULL pIRowset (Insert)")
TEST_VARIATION(29, L"S_OK:valid pcRowsAffected, *pc=0, valid pIRowsetLocate (Select)")
TEST_VARIATION(30, L"S_OK:valid pcRowsAffected, *pc=1, valid pIRowsetLocate (Select)")
TEST_VARIATION(31, L"S_OK:valid pcRowsAffected, *pc=0, valid pIRowsetLocate (Insert)")
TEST_VARIATION(32, L"S_OK:NULL pcRowsAffected, valid pIRowsetLocate (Select)")
TEST_VARIATION(33, L"E_INVALIDARG:NULL pcRowsAffected, NULL pIRowsetLocate (Select)")
TEST_VARIATION(34, L"S_OK:NULL pcRowsAffected, valid pIRowsetLocate (Insert)")
TEST_VARIATION(35, L"S_OK:NULL pcRowsAffected, NULL pIRowsetLocate (Insert)")
TEST_VARIATION(36, L"S_OK:valid pcRowsAffected, *pc=0, valid pIColumnsInfo (Select)")
TEST_VARIATION(37, L"S_OK:valid pcRowsAffected, *pc=1, valid pIColumnsInfo (Select)")
TEST_VARIATION(38, L"S_OK:valid pcRowsAffected, *pc=0, valid pIColumnsInfo (Insert)")
TEST_VARIATION(39, L"S_OK:valid pcRowsAffected, *pc=1, valid pIColumnsInfo (Insert)")
TEST_VARIATION(40, L"S_OK:NULL pcRowsAffected, valid pIColumnsInfo (Select)")
TEST_VARIATION(41, L"E_INVALIDARG:NULL pcRowsAffected, NULL pIColumnsInfo (Select)")
TEST_VARIATION(42, L"S_OK:NULL pcRowsAffected, valid pIColumnsInfo (Insert)")
TEST_VARIATION(43, L"S_OK:NULL pcRowsAffected, NULL pIColumnsInfo (Insert)")
TEST_VARIATION(44, L"E_INVALIDARG:riid != IID_NULL, ppRowset==NULL")
TEST_VARIATION(45, L"DB_E_CANTCONVERTVALUE: string (22005)")
TEST_VARIATION(46, L"DB_E_CANTCONVERTVALUE: implicit (22005)")
TEST_VARIATION(47, L"DB_E_CANTCONVERTVALUE: implicit (22008)")
TEST_VARIATION(48, L"DB_E_DATAOVERFLOW: math (22003)")
TEST_VARIATION(49, L"DB_E_DATAOVERFLOW: string right (22001")
TEST_VARIATION(50, L"DB_E_ERRORSINCOMMAND - Create Table statement on a table that already exists (S0001)")
TEST_VARIATION(51, L"DB_E_ERRORSINCOMMAND - Create View statement on a view that already exists (S0001)")
TEST_VARIATION(52, L"DB_E_ERRORSINCOMMAND - Select statement with invalid table name (S0002)")
TEST_VARIATION(53, L"DB_E_ERRORSINCOMMAND - Drop Table statement on a table that does not exist (S0002)")
TEST_VARIATION(54, L"DB_E_ERRORSINCOMMAND - Drop View statement on a view that does not exist (S0002)")
TEST_VARIATION(55, L"DB_E_ERRORSINCOMMAND - Select statement with invalid column name (S0022)")
TEST_VARIATION(56, L"S_OK - Numeric Truncation (01004)")
TEST_VARIATION(57, L"DB_E_ERRORSINCOMMAND - Invalid nodes in a command (37000)")
TEST_VARIATION(58, L"S_OK: riid = IUnknown")
TEST_VARIATION(59, L"S_OK: cParam=0")
TEST_VARIATION(60, L"S_OK: select * from sp_tables")
TEST_VARIATION(61, L"DB_E_ERRORSINCOMMAND: create current exisiting table")
TEST_VARIATION(62, L"Query TimeOut")
TEST_VARIATION(63, L"Query TimeOut")
TEST_VARIATION(64, L"Firehose mode")
TEST_VARIATION(65, L"Aggregation - Open a rowset on aggregated command")
TEST_VARIATION(66, L"S_OK: Select, IID_NULL, ppRowset NULL")
TEST_VARIATION(67, L"Test all IID's of object")
TEST_VARIATION(68, L"E_NOINTERFACE - Ask for unsupported interface with ppRowset == NULL")
TEST_VARIATION(69, L"DB_E_INTEGRITYVIOLATION - Insert a duplicate key value")
TEST_VARIATION(70, L"S_OK - select with qualified name")
TEST_VARIATION(71, L"S_OK - select with quoted name")
TEST_VARIATION(72, L"S_OK - select distinct")
TEST_VARIATION(73, L"DB_E_ERRORSOCCURRED - select distinct with DBPROP_UNIQUEROWS REQUIRED")
TEST_VARIATION(74, L"DB_E_ERRORSINCOMMAND - select with invalid group by clause")
TEST_VARIATION(75, L"DB_S_ERRORSOCCURRED - select distinct with DBPROP_UNIQUEROWS OPTIONAL")
TEST_VARIATION(76, L"DB_E_ERRORSINCOMMAND - (Insert with mis-spelled keyword)")
TEST_VARIATION(77, L"S_OK: Multiple commands, 2 initial and 1 later")
TEST_VARIATION(78, L"S_OK: Create index in descending order")
TEST_VARIATION(79, L"S_OK: All rows with singleton select")
TEST_VARIATION(80, L"S_OK: Select ABC and Col List")
TEST_VARIATION(81, L"S_OK: Select duplicate columns")
TEST_VARIATION(82, L"S_OK: Select Count")
TEST_VARIATION(83, L"S_OK: Select empty rowset")
TEST_VARIATION(84, L"S_OK: Select Change col name")
TEST_VARIATION(85, L"S_OK: Aggregated rowset")
TEST_VARIATION(86, L"Last Variation - Final Verification")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(CDBSession)
//--------------------------------------------------------------------
// @class general cases
//
class CDBSession : public CCmd {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(CDBSession,CCmd);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember S_OK: IRowsetInfo::GetSpecification, get same IUnknown
int Variation_1();
// @cmember S_OK: Don't execute command, get same IUnknown
int Variation_2();
// @cmember E_NOINTERFACE: dso iid, valid ptr
int Variation_4();
// @cmember E_NOINTERFACE: iid_null, valid ptr
int Variation_5();
// @cmember E_INVALIDARG: valid session id, ptr==NULL
int Variation_6();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(CDBSession)
#define THE_CLASS CDBSession
BEG_TEST_CASE(CDBSession, CCmd, L"general cases")
TEST_VARIATION(1, L"S_OK: IRowsetInfo::GetSpecification, get same IUnknown")
TEST_VARIATION(2, L"S_OK: Don't execute command, get same IUnknown")
TEST_VARIATION(4, L"E_NOINTERFACE: dso iid, valid ptr")
TEST_VARIATION(5, L"E_NOINTERFACE: iid_null, valid ptr")
TEST_VARIATION(6, L"E_INVALIDARG: valid session id, ptr==NULL")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(Zombie)
//--------------------------------------------------------------------
// @class Induce zombie states
//
class Zombie : public CTransaction {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(Zombie,CTransaction);
// }} TCW_DECLARE_FUNCS_END
int Zombie::TestTxn(ETXN eTxn,BOOL fRetaining);
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember State 1:Abort with fRetaining set to TRUE
int Variation_1();
// @cmember State 2:Abort with fRetaining set to FALSE
int Variation_2();
// @cmember State 3:Commit with fRetaining set to TRUE
int Variation_3();
// @cmember State 4:Commit with fRetaining set to FALSE
int Variation_4();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(Zombie)
#define THE_CLASS Zombie
BEG_TEST_CASE(Zombie, CTransaction, L"Induce zombie states")
TEST_VARIATION(1, L"State 1:Abort with fRetaining set to TRUE")
TEST_VARIATION(2, L"State 2:Abort with fRetaining set to FALSE")
TEST_VARIATION(3, L"State 3:Commit with fRetaining set to TRUE")
TEST_VARIATION(4, L"State 4:Commit with fRetaining set to FALSE")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(CCancel)
//--------------------------------------------------------------------
// @class general cases
//
class CCancel : public CCmd {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(CCancel,CCmd);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember S_OK,S_OK: 2 cmd obj (Select & Insert), cancel each during execution
int Variation_1();
// @cmember S_OK,S_OK: 2 cmd obj (Select & Insert), cancel 1 during, cancel 1 after execution
int Variation_2();
// @cmember S_OK,S_OK: 2 cmd obj (Select & Insert), cancel 1 before, cancel 1 during execution
int Variation_3();
// @cmember S_OK,S_OK: 2 cmd obj, cancel 1 before, cancel 1 after
int Variation_4();
// @cmember S_OK: 1 cmd obj (Select), cancel before execution
int Variation_5();
// @cmember S_OK: 1 cmd obj (Select), cancel after execution
int Variation_6();
// @cmember S_OK: 1 cmd obj (Select), execute, cancel cancel
int Variation_7();
// @cmember S_OK: 1 cmd obj (Insert), cancel before execution
int Variation_8();
// @cmember S_OK: 1 cmd obj (Insert), cancel after execution
int Variation_9();
// @cmember S_OK: 1 cmd obj (Insert), execute, cancel cancel
int Variation_10();
// @cmember No Query Set, 1 Cancel per Thread, Before Execution
int Variation_11();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(CCancel)
#define THE_CLASS CCancel
BEG_TEST_CASE(CCancel, CCmd, L"general cases")
TEST_VARIATION(1, L"S_OK,S_OK: 2 cmd obj (Select & Insert), cancel each during execution")
TEST_VARIATION(2, L"S_OK,S_OK: 2 cmd obj (Select & Insert), cancel 1 during, cancel 1 after execution")
TEST_VARIATION(3, L"S_OK,S_OK: 2 cmd obj (Select & Insert), cancel 1 before, cancel 1 during execution")
TEST_VARIATION(4, L"S_OK,S_OK: 2 cmd obj, cancel 1 before, cancel 1 after")
TEST_VARIATION(5, L"S_OK: 1 cmd obj (Select), cancel before execution")
TEST_VARIATION(6, L"S_OK: 1 cmd obj (Select), cancel after execution")
TEST_VARIATION(7, L"S_OK: 1 cmd obj (Select), execute, cancel cancel")
TEST_VARIATION(8, L"S_OK: 1 cmd obj (Insert), cancel before execution")
TEST_VARIATION(9, L"S_OK: 1 cmd obj (Insert), cancel after execution")
TEST_VARIATION(10, L"S_OK: 1 cmd obj (Insert), execute, cancel cancel")
TEST_VARIATION(11, L"No Query Set, 1 Cancel per Thread, Before Execution")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCExtendedErrors)
//--------------------------------------------------------------------
// @class Extended Errors
//
class TCExtendedErrors : public CCmd {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
//@cmember Extended error object
CExtError * m_pExtError;
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCExtendedErrors,CCmd);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Valid ICommand call with previous error object existing.
int Variation_1();
// @cmember Invalid Execute call with previous error object existing
int Variation_2();
// @cmember Invalid GetDBSession calls with previous error object existing
int Variation_3();
// @cmember Invalid GetDBSession calls with no previous error object existing
int Variation_4();
// @cmember E_NOINTERFACE Execute call with no previous error object existing
int Variation_5();
// @cmember DB_E_NOCOMMAND Execute call with no previous error object existing
int Variation_6();
// @cmember DB_E_CANCELED Check extended error info when Execute is canceled
int Variation_7();
// }} TCW_TESTVARS_END
};
// {{ TCW_TESTCASE(TCExtendedErrors)
#define THE_CLASS TCExtendedErrors
BEG_TEST_CASE(TCExtendedErrors, CCmd, L"Extended Errors")
TEST_VARIATION(1, L"Valid ICommand call with previous error object existing.")
TEST_VARIATION(2, L"Invalid Execute call with previous error object existing")
TEST_VARIATION(3, L"Invalid GetDBSession calls with previous error object existing")
TEST_VARIATION(4, L"Invalid GetDBSession calls with no previous error object existing")
TEST_VARIATION(5, L"E_NOINTERFACE Execute call with no previous error object existing")
TEST_VARIATION(6, L"DB_E_NOCOMMAND Execute call with no previous error object existing")
TEST_VARIATION(7, L"DB_E_CANCELED Check extended error info when Execute is canceled")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// }} END_DECLARE_TEST_CASES()
////////////////////////////////////////////////////////////////////////
// Copying Test Cases to make duplicate ones.
//
////////////////////////////////////////////////////////////////////////
#define COPY_TEST_CASE(theClass, baseClass) \
class theClass : public baseClass \
{ \
public: \
static const WCHAR m_wszTestCaseName[]; \
DECLARE_TEST_CASE_FUNCS(theClass, baseClass); \
}; \
const WCHAR theClass::m_wszTestCaseName[] = { L#theClass }; \
#define TEST_CASE_WITH_PARAM(iCase, theClass, param) \
case iCase: \
pCTestCase = new theClass(NULL); \
((theClass*)pCTestCase)->SetTestCaseParam(param); \
pCTestCase->SetOwningMod(iCase-1, pCThisTestModule); \
return pCTestCase;
COPY_TEST_CASE(CExecute_Row, CExecute_Rowset)
#if 0
// {{ TCW_TESTMODULE(ThisModule)
TEST_MODULE(5, ThisModule, gwszModuleDescrip)
TEST_CASE(1, CExecute_Rowset)
TEST_CASE(2, CDBSession)
TEST_CASE(3, Zombie)
TEST_CASE(4, CCancel)
TEST_CASE(5, TCExtendedErrors)
END_TEST_MODULE()
// }} TCW_TESTMODULE_END
#else
TEST_MODULE(6, ThisModule, gwszModuleDescrip)
TEST_CASE_WITH_PARAM(1, CExecute_Rowset, TC_Rowset)
TEST_CASE_WITH_PARAM(2, CExecute_Row, TC_Row)
TEST_CASE(3, CDBSession)
TEST_CASE(4, Zombie)
TEST_CASE(5, CCancel)
TEST_CASE(6, TCExtendedErrors)
END_TEST_MODULE()
#endif
// {{ TCW_TC_PROTOTYPE(CExecute_Rowset)
//*-----------------------------------------------------------------------
//| Test Case: CExecute_Rowset - general valid variations
//| Created: 04/08/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL CExecute_Rowset::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(CCmd::Init())
// }}
{
ULONG_PTR ulOleObj = 0;
if(!GetProperty(DBPROP_OLEOBJECTS, DBPROPSET_DATASOURCEINFO,
GetModInfo()->GetThisTestModule()->m_pIUnknown, &ulOleObj) ||
!(ulOleObj & DBPROPVAL_OO_SINGLETON))
{
if(IFROW)
{
odtLog<<L"INFO: Obtaining row objects directly from commands is not supported.\n";
return TEST_SKIPPED;
}
}
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Multiple Executions on same command object (Select)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_1()
{
ICommand * pICmd1 = NULL;
IUnknown* pIUnk1 = NULL;
IUnknown* pIUnk2 = NULL;
IUnknown* pIUnk3 = NULL;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1, PPI &pIUnk1),S_OK));
CLEANUP(!CHECK(m_hr = Execute(pICmd1, PPI &pIUnk2),S_OK));
CLEANUP(!CHECK(m_hr = Execute(pICmd1, PPI &pIUnk3),S_OK));
TESTC(pIUnk1 && pIUnk2 && pIUnk3)
CLEANUP:
SAFE_RELEASE(pIUnk1);
SAFE_RELEASE(pIUnk2);
SAFE_RELEASE(pIUnk3);
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc S_OK:Multiple Executions on same command object (Insert)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_2()
{
ICommand* pICmd1=NULL;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1,NULL,NULL,NULL,NULL,IID_NULL),S_OK));
m_pTable->AddRow();
// Have to reset the command text to make sure the new row will be unique
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1,NULL,NULL,NULL,NULL,IID_NULL),S_OK));
m_pTable->AddRow();
// Have to reset the command text to make sure the new row will be unique
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1,NULL,NULL,NULL,NULL,IID_NULL),S_OK));
m_pTable->AddRow();
// Set text again and execute again.
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1,NULL,NULL,NULL,NULL,IID_NULL),S_OK));
m_pTable->AddRow();
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc S_OK:Prepared command
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_3()
{
ICommand* pICmd1=NULL;
DBROWCOUNT cRowsAffected=0;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(FAILED(PrepareCommand(pICmd1,PREPARE,1)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1,NULL,NULL,NULL,NULL,IID_NULL),S_OK));
m_pTable->AddRow();
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc S_OK:Prepared and Unprepared Command
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_4()
{
DBROWCOUNT cRowsAffected=0;
ICommand* pICmd1=NULL;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(FAILED(PrepareCommand(pICmd1,BOTH,1)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1,NULL,NULL,NULL,NULL,IID_NULL),S_OK));
m_pTable->AddRow();
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc S_OK:Multiple Sessions Open
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_5()
{
TESTBEGIN
ULONG_PTR ulMaxSessions=0;
IUnknown * pUnk1=NULL;
IUnknown * pUnk3=NULL;
// first session object is still in coledb classes
IDBCreateCommand * pCreateCmd1=NULL;
IDBCreateCommand * pCreateCmd2=NULL;
IDBCreateCommand * pCreateCmd3=NULL;
//first command object is still in m_pICommand
ICommand * pICmd1=NULL;
ICommand * pICmd2=NULL;
ICommand * pICmd3=NULL;
// Check the Session Limit
GetProperty(DBPROP_ACTIVESESSIONS,
DBPROPSET_DATASOURCEINFO, m_pMyIDBInitialize, &ulMaxSessions);
// Need atleast 4 sessions to run the variation
if( ulMaxSessions && ulMaxSessions < 4 )
return TEST_SKIPPED;
// Get Session Pointers
CLEANUP(!CreateSession(IID_IDBCreateCommand,PPI &pCreateCmd1));
CLEANUP(!CreateSession(IID_IDBCreateCommand,PPI &pCreateCmd2));
CLEANUP(!CreateSession(IID_IDBCreateCommand,PPI &pCreateCmd3));
// Get Command Pointers
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,pCreateCmd1));
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd2,pCreateCmd2));
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd3,pCreateCmd3))
// First session object's command
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1,PPI &pUnk1),S_OK));
//If the provider is read only or does not understand SQL, skip variation.
if( !g_fReadOnlyProvider && m_pTable->GetSQLSupport() != DBPROPVAL_SQL_NONE )
{
// Second session object's command
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd2,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd2,NULL,NULL,NULL,NULL,IID_NULL),S_OK));
m_pTable->AddRow();
}
// Third session object's command
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd3,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd3,PPI &pUnk3),S_OK));
TPASS
CLEANUP:
SAFE_RELEASE(pCreateCmd1);
SAFE_RELEASE(pCreateCmd2);
SAFE_RELEASE(pCreateCmd3);
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pICmd2);
SAFE_RELEASE(pICmd3);
SAFE_RELEASE(pUnk1);
SAFE_RELEASE(pUnk3);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc S_OK:Multiple Commands Open
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_6()
{
TESTBEGIN
IUnknown * pUnk1=NULL;
IUnknown * pUnk3=NULL;
ICommand * pICmd1=NULL;
ICommand * pICmd2=NULL;
ICommand * pICmd3=NULL;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd2,NULL));
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd3,NULL));
if(!pICmd2 || !pICmd2 || !pICmd3)
goto CLEANUP;
// First session object's command
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1,PPI &pUnk1),S_OK));
//If the provider is read only or does not understand SQL, skip variation.
if( !g_fReadOnlyProvider && m_pTable->GetSQLSupport() != DBPROPVAL_SQL_NONE )
{
// Second session object's command
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd2,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd2,NULL,NULL,NULL,NULL,IID_NULL),S_OK));
m_pTable->AddRow();
}
// Third session object's command
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd3,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd3,PPI &pUnk3),S_OK));
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pICmd2);
SAFE_RELEASE(pICmd3);
SAFE_RELEASE(pUnk1);
SAFE_RELEASE(pUnk3);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc S_OK: 1 cmd obj (3 inserts on their own threads
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_7()
{
ICommand * pICmd1=NULL;
HRESULT hrExecute1=S_OK;
HRESULT hrExecuteOr=S_OK;
STATEMENTKIND eStatementKind = eINSERT;
UWORD ThreadNum=0;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
// Make sure the threading model is correct for this variation. We only
// support Free threaded.
if (!VerifyThreadingModel(COINIT_MULTITHREADED))
return TEST_SKIPPED;
TESTBEGIN
INIT_THRDS(THREE_THRDS);
// Get a command object.
CLEANUP(!GetCommand(IID_ICommand, PPI &pICmd1,NULL));
// Initialize the thread function argument.
{
THRDARG ExecuteFirstCmd = { this, pICmd1, &hrExecute1, &eStatementKind, &hrExecuteOr };
// Set text in command object
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)))
//Create Thread
CREATE_THRD(THRD_ONE,Execute,&ExecuteFirstCmd);
CREATE_THRD(THRD_TWO,Execute,&ExecuteFirstCmd);
CREATE_THRD(THRD_THREE,Execute,&ExecuteFirstCmd);
}
//Start Thread
START_THRDS();
// End Thread
END_THRDS();
// Verify the rows got inserted. Note they violate the automaketable row definitions since they're
// all the same.
TESTC(VerifyAndRemoveRows(m_pTable, m_pTable->GetNextRowNumber(), THREE_THRDS));
// Since Delete thinks it removed one row from the table but the insert never added one
// we need to adjust here
m_pTable->AddRow();
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN;
}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Query set only
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_8()
{
ICommand* pICmd1=NULL;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1,NULL,NULL,NULL,NULL,IID_NULL),S_OK));
m_pTable->AddRow();
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc DB_E_NOCOMMAND: no command set
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_9()
{
ICommand* pICmd1=NULL;
IUnknown * pUnk=NULL;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(!CHECK(m_hr = Execute(pICmd1,PPI &pUnk),DB_E_NOCOMMAND));
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc DB_E_ERRORSINCOMMAND - (Select)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_10()
{
ICommand* pICmd1=NULL;
IUnknown * pUnk=NULL;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
// Set command text to select statement with no table name
TEST_SUPPORTED(m_hr = m_pTable->ExecuteCommand(SELECT_NO_TABLE, IID_IUnknown,
NULL,NULL,NULL, NULL, EXECUTE_NEVER, 0, NULL,
NULL, NULL, &pICmd1), S_OK);
TEST2C_(m_hr = Execute(pICmd1,PPI &pUnk),DB_E_ERRORSINCOMMAND, DB_E_NOTABLE);
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pUnk);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc DB_E_ERRORSINCOMMAND - (Insert)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_11()
{
ICommand* pICmd1=NULL;
IUnknown * pUnk=NULL;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
// Set command text to select statement with no table name
TEST_SUPPORTED(m_hr = m_pTable->ExecuteCommand(INSERT_NO_TABLE, IID_IUnknown,
NULL,NULL,NULL, NULL, EXECUTE_NEVER, 0, NULL,
NULL, NULL, &pICmd1), S_OK);
TEST2C_(m_hr = Execute(pICmd1,PPI &pUnk),DB_E_ERRORSINCOMMAND, DB_E_NOTABLE);
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pUnk);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(12)
//--------------------------------------------------------------------
// @mfunc DB_INVALIDARG - cParamSets > 1 and ppRowset was not a null pointer
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_12()
{
odtLog << L"No longer necessary due to multiple result sets\n";
// Delete this variation.
return TEST_PASS;
}
// {{ TCW_VAR_PROTOTYPE(13)
//--------------------------------------------------------------------
// @mfunc DB_E_MULTIPLESTATEMENTS - command contained multiple statements
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_13()
{
TESTBEGIN;
ICommand* pICmd1=NULL;
ICommandText * pICmdTxt = NULL;
IRowset * pRowset=INVALID(IRowset *);
IRow * pRow=INVALID(IRow *);
WCHAR * pTempSQL=NULL;
WCHAR * pSQL=NULL;
HRESULT Exphr=S_OK;
ULONG_PTR ulMultipleResults=0;
DBORDINAL cRowsetCols;
DBORDINAL * rgTableColOrds = NULL;
HRESULT hrSetProp = E_FAIL;
// Check for IMultipleResults support
GetProperty(DBPROP_MULTIPLERESULTS, DBPROPSET_DATASOURCEINFO,
m_pMyIDBInitialize, &ulMultipleResults);
CLEANUP(FAILED(m_hr=m_pTable->CreateSQLStmt(SELECT_VALIDATIONORDER,NULL,&pTempSQL,&cRowsetCols,(DB_LORDINAL **)&rgTableColOrds)));
pSQL = (WCHAR *) m_pIMalloc->Alloc(((wcslen(pTempSQL) + wcslen(pTempSQL) + 1) * sizeof(WCHAR)) + sizeof(WCHAR));
CLEANUP(!pSQL);
wcscpy(pSQL, pTempSQL);
wcscat(pSQL, wszSemicolon);
wcscat(pSQL, pTempSQL);
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSQL,NO_QUERY,pSQL)));
TESTC(VerifyInterface(pICmd1, IID_ICommandText,
COMMAND_INTERFACE, (IUnknown**)&pICmdTxt));
// If the provider supports the DBPROP_IMultipleResults property make sure it's off
SetRowsetProperty(pICmd1, DBPROPSET_ROWSET, DBPROP_IMultipleResults, FALSE);
// If the property above is not settable then it might still be on.
if (GetProperty(DBPROP_IMultipleResults, DBPROPSET_ROWSET, pICmd1))
{
odtLog << L"Couldn't turn off DBPROP_IMultipleResults property and so can't generate error.\n";
TSKIPPED;
goto CLEANUP;
}
// Can't validate data at this time for row objects w/o ini file (if any extra row object columns)
if (IFROW && !g_fLuxor && !GetModInfo()->GetFileName())
{
odtLog << L"Can't verify row object data w/o ini file at this time.\n";
TSKIPPED;
goto CLEANUP;
}
// Some providers can't retrieve BLOB data without this property or IRowsetLocate on. Can't turn on IRowsetLocate
// for batch SQL as Sql Server driver will turn back off when it detects batch stmt.
// If the property is not supported then this may fail, but there's nothing we can do about that
if (g_fKagera && SupportedProperty(DBPROP_ACCESSORDER, DBPROPSET_ROWSET, m_pThisTestModule->m_pIUnknown,SESSION_INTERFACE))
hrSetProp = SetRowsetProperty(pICmd1, DBPROPSET_ROWSET, DBPROP_ACCESSORDER, (LONG_PTR)DBPROPVAL_AO_RANDOM);
// Spec change: Providers are allowed to return DB_E_ERRORSINCOMMAND rather than DB_E_MULTIPLESTATEMENTS here
// Spec change: Providers are allowed to return S_OK and the first result set, discarding
// any further results.
m_hr = pICmd1->Execute(NULL,IID_IRowset,NULL,NULL,PPI &pRowset);
// Allow S_OK
if (S_OK == m_hr)
{
// Make sure we have a rowset
if (!COMPARE(pRowset != NULL, TRUE))
goto CLEANUP;
// Validate data
TESTC_(VerifyRowset(IID_IRowset, (IUnknown *)pRowset, 1,
cRowsetCols, rgTableColOrds, FALSE), S_OK);
SAFE_RELEASE(pRowset);
}
else
{
// Allow DB_E_ERRORSINCOMMAND or DB_E_NOTABLE
TEST2C_(m_hr, DB_E_ERRORSINCOMMAND, DB_E_NOTABLE);
COMPARE(pRowset, NULL);
goto CLEANUP;
}
if(IFROW)
{
// m_hr = pICmd1->Execute(NULL,IID_IRow,NULL,NULL,PPI &pRow);
m_hr = pICmdTxt->Execute(NULL,IID_IRow,NULL,NULL,PPI &pRow);
// Allow S_OK
if (S_OK == m_hr)
{
// Make sure we have a rowset
if (!COMPARE(pRow != NULL, TRUE))
goto CLEANUP;
// Validate data
// Note this will fail if not using an ini file if there are additional
// row object columns beyond the last one. In that case just limit the
// compare to those that we can match w/o ini file.
TESTC_(VerifyRowObj(IID_IRow, (IUnknown *)pRow, 1,
cRowsetCols, rgTableColOrds, FALSE), S_OK);
SAFE_RELEASE(pRow);
}
else
{
// Allow DB_E_ERRORSINCOMMAND or DB_E_NOTABLE
TEST2C_(m_hr, DB_E_ERRORSINCOMMAND, DB_E_NOTABLE);
COMPARE(pRow, NULL);
goto CLEANUP;
}
}
TPASS;
CLEANUP:
if(pRowset != INVALID(IRowset *))
SAFE_RELEASE(pRowset);
if(pRow != INVALID(IRow *))
SAFE_RELEASE(pRow);
if (hrSetProp == S_OK)
CHECK(SetRowsetProperty(pICmd1, DBPROPSET_ROWSET, DBPROP_ACCESSORDER, (LONG_PTR)DBPROPVAL_AO_RANDOM, DBPROPOPTIONS_OPTIONAL), S_OK);
PROVIDER_FREE(pSQL);
PROVIDER_FREE(pTempSQL);
PROVIDER_FREE(rgTableColOrds);
SAFE_RELEASE(pICmdTxt);
SAFE_RELEASE(pICmd1);
TRETURN;
}
// {{ TCW_VAR_PROTOTYPE(14)
//--------------------------------------------------------------------
// @mfunc DB_S_ERRORSOCCURED - property was not set
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_14()
{
TESTRESULT fResult = TEST_FAIL;
ICommand* pICmd1=NULL;
IRowset * pIRowset=NULL;
IUnknown* pIUnk = NULL;
IRowsetInfo * pIRowsetInfo=NULL;
IDBProperties * pIDBProperties = NULL;
ICommandProperties * pICommandProperties = NULL;
DBPROPINFO * pPropInfo = NULL;
DBPROPIDSET rgPropertyIDSets[1];
DBPROPINFOSET * pPropertyInfoSets = NULL;
DBPROPSET * pPropertySets = NULL;
DBPROPSET * pPropertySetsReq = NULL;
DBPROPSET * pPropertySetsReqCopy = NULL;
WCHAR * pDescBuffer = NULL;
ULONG cPropertyInfoSets = 0;
ULONG cPropertySetsReq = 0;
ULONG cPropertySets = 0;
ULONG iProp, iProp2;
ULONG iSet, iSet2;
BOOL fPropFound = FALSE;
HRESULT hr = E_FAIL;
rgPropertyIDSets[0].rgPropertyIDs = NULL;
rgPropertyIDSets[0].cPropertyIDs = NULL;
rgPropertyIDSets[0].guidPropertySet = DBPROPSET_ROWSETALL;
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,NULL));
// Get an IDBProperties interface
TESTC(VerifyInterface(m_pThisTestModule->m_pIUnknown, IID_IDBProperties,
DATASOURCE_INTERFACE, (IUnknown**)&pIDBProperties));
// Get an ICommandProperties interface
TESTC(VerifyInterface(pICmd1, IID_ICommandProperties,
COMMAND_INTERFACE, (IUnknown**)&pICommandProperties));
// Save the existing command properties so we can put them back
TESTC_(pICommandProperties->GetProperties(0, NULL, &cPropertySets, &pPropertySets), S_OK);
// Set the command text
TESTC_(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL), S_OK);
// odtLog << L"\n\nBefore successful Execute call:\n";
// DumpCommandProps(pICmd1, FALSE, cPropertySets, pPropertySets);
TESTC_(hr = pICmd1->Execute(NULL,IID_IRowsetInfo,NULL,NULL,PPI &pIRowsetInfo), S_OK);
// odtLog << L"\n\nAfter successful Execute call:\n";
// DumpCommandProps(pICmd1, FALSE, cPropertySets, pPropertySets);
// Get a copy of the existing properties we can modify
TESTC_(pIRowsetInfo->GetProperties(0, NULL, &cPropertySetsReq, &pPropertySetsReq), S_OK);
// odtLog << L"\n\nFrom IRowsetInfo:\n";
// DumpCommandProps(pICmd1, FALSE, cPropertySetsReq, pPropertySetsReq);
SAFE_RELEASE(pIRowsetInfo);
// Make a copy of the prop array from the rowset. We have to remove nonsettable props
// or change them to their default values. Set to default.
for (iSet = 0; iSet < cPropertySetsReq; iSet++)
{
ULONG cProps = pPropertySetsReq[iSet].cProperties;
for (iProp=0; iProp < cProps ; iProp++)
{
// Set all settable props required except DBPROP_IRow and IMultipleResults
// since those props create a non-rowset object.
/*
if (pPropertySetsReq[iSet].rgProperties[iProp].dwPropertyID != DBPROP_IRow &&
pPropertySetsReq[iSet].rgProperties[iProp].dwPropertyID != DBPROP_IMultipleResults &&
SettableProperty(pPropertySetsReq[iSet].rgProperties[iProp].dwPropertyID,
pPropertySetsReq[iSet].guidPropertySet, m_pIDBInitialize))
*/
// if (pPropertySetsReq[iSet].rgProperties[iProp].dwPropertyID == DBPROP_IRowset ||
// pPropertySetsReq[iSet].rgProperties[iProp].dwPropertyID == DBPROP_IRow)
// odtLog << L"Props found\n";
// If we want a row object back, make sure we don't require IRowset TRUE, as this will
// conflict with IID_IRow
if (IFROW && pPropertySetsReq[iSet].rgProperties[iProp].dwPropertyID == DBPROP_IRowset)
V_BOOL(&pPropertySetsReq[iSet].rgProperties[iProp].vValue) = VARIANT_FALSE;
// If we want a row object back, make sure we require IRow TRUE, otherwise if it is
// FALSE by default then we'll end up with it REQUIRED FALSE and be unable to get
// a row object, since some providers have IRowset non settable TRUE as the default
if (IFROW && pPropertySetsReq[iSet].rgProperties[iProp].dwPropertyID == DBPROP_IRow)
V_BOOL(&pPropertySetsReq[iSet].rgProperties[iProp].vValue) = VARIANT_TRUE;
// If we want a rowset object back, make sure we don't require IRow TRUE, as this will
// conflict with IID_IRowset
if (!IFROW && pPropertySetsReq[iSet].rgProperties[iProp].dwPropertyID == DBPROP_IRow)
V_BOOL(&pPropertySetsReq[iSet].rgProperties[iProp].vValue) = VARIANT_FALSE;
// Luxor needs a server cursor for a row object if access order is random. Other providers
// may not have this limitation
if (IFROW && g_fLuxor && pPropertySetsReq[iSet].rgProperties[iProp].dwPropertyID == DBPROP_SERVERCURSOR)
V_BOOL(&pPropertySetsReq[iSet].rgProperties[iProp].vValue) = VARIANT_TRUE;
if (SettableProperty(pPropertySetsReq[iSet].rgProperties[iProp].dwPropertyID,
pPropertySetsReq[iSet].guidPropertySet, m_pIDBInitialize))
{
// Make REQUIRED
pPropertySetsReq[iSet].rgProperties[iProp].dwOptions = DBPROPOPTIONS_REQUIRED;
}
else
{
// Set to VT_EMPTY if not settable to force default
VariantClear(&pPropertySetsReq[iSet].rgProperties[iProp].vValue);
// Have to set this property OPTIONAL because the default value set as REQUIRED may
// preclude successfully getting a ROW object, since the provider won't be able to
// roll the prop
pPropertySetsReq[iSet].rgProperties[iProp].dwOptions = DBPROPOPTIONS_OPTIONAL;
}
}
}
// odtLog << L"Modified props\n";
// DumpCommandProps(pICmd1, FALSE, cPropertySetsReq, pPropertySetsReq);
// Make another copy of the prop array, because some providers muck with my array
SAFE_ALLOC(pPropertySetsReqCopy, DBPROPSET, cPropertySetsReq * sizeof(DBPROPSET));
memset(pPropertySetsReqCopy, 0, cPropertySetsReq * sizeof(DBPROPSET));
for (iSet = 0; iSet < cPropertySetsReq; iSet++)
{
pPropertySetsReqCopy[iSet].guidPropertySet = pPropertySetsReq[iSet].guidPropertySet;
pPropertySetsReqCopy[iSet].cProperties = pPropertySetsReq[iSet].cProperties;
SAFE_ALLOC(pPropertySetsReqCopy[iSet].rgProperties , DBPROP,
pPropertySetsReq[iSet].cProperties * sizeof(DBPROP));
memcpy(pPropertySetsReqCopy[iSet].rgProperties, pPropertySetsReq[iSet].rgProperties,
pPropertySetsReq[iSet].cProperties * sizeof(DBPROP));
}
// Retrieve all rowset properties
TESTC_(pIDBProperties->GetPropertyInfo(1, rgPropertyIDSets, &cPropertyInfoSets, &pPropertyInfoSets,
&pDescBuffer), S_OK);
hr = pICommandProperties->SetProperties(cPropertySetsReq, pPropertySetsReq);
if (S_OK != hr)
DumpCommandProps(pICmd1, FALSE, cPropertySetsReq, pPropertySetsReq);
TESTC_(hr, S_OK);
// Now make sure the provider didn't muck with the properties
for (iSet = 0; iSet < cPropertySetsReq; iSet++)
{
for (iProp=0; iProp < pPropertySetsReq[iSet].cProperties; iProp++)
{
BOOL fCmp = TRUE;
LONG lCmp;
// Compare the option
fCmp &= COMPARE(pPropertySetsReq[iSet].rgProperties[iProp].dwOptions,
pPropertySetsReqCopy[iSet].rgProperties[iProp].dwOptions);
// Compare the propid
fCmp &= COMPARE(pPropertySetsReq[iSet].rgProperties[iProp].dwPropertyID,
pPropertySetsReqCopy[iSet].rgProperties[iProp].dwPropertyID);
// Compare the value
lCmp = memcmp(&pPropertySetsReq[iSet].rgProperties[iProp].vValue,
&pPropertySetsReqCopy[iSet].rgProperties[iProp].vValue, sizeof(VARIANT));
fCmp &= COMPARE(lCmp, 0);
if (!fCmp)
odtLog << L"Error: Provider changed properties passed to SetProperties!\n";
}
}
// Make sure I can still open a rowset or row (props should have no effect on row obj).
hr = Execute(pICmd1,PPI &pIUnk);
if (S_OK != hr)
{
// Dump current command props
DumpCommandProps(pICmd1, FALSE);
// Dump properties in error
DumpCommandProps(pICmd1, TRUE);
}
TESTC_(hr, S_OK);
SAFE_RELEASE(pIUnk);
// All the setup code worked. Now assume success until we know otherwise
fResult = TEST_PASS;
// Go through properties until we find one
// that returns DB_E_ERRORSOCCURRED when set REQUIRED
for (iSet = 0; iSet < cPropertyInfoSets && !fPropFound; iSet++)
{
for (iProp=0; iProp < pPropertyInfoSets[iSet].cPropertyInfos && !fPropFound; iProp++)
{
if (!SetPropertyAndExecute(pICmd1, pPropertyInfoSets, iSet, iProp,
SINGLE_PROP, NULL, &fPropFound))
fResult = TEST_FAIL;
if (fPropFound)
// Set the property back off since we set it on in SetPropertyAndExecute
SetRowsetProperty(pICmd1,pPropertyInfoSets[iSet].guidPropertySet,
pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwPropertyID, FALSE,
DBPROPOPTIONS_REQUIRED, FALSE);
}
}
if (!fPropFound)
{
odtLog << L"Couldn't find a set of properties that will return DB_S_ERRORSOCCURRED.\n";
fResult = TEST_SKIPPED;
goto CLEANUP;
}
// If we made it this far we know that there is at least one combination of properties that will result
// in DB_S_ERRORSOCCURRED, otherwise we tried setting them all TRUE REQUIRED and didn't find any that will.
// Now we check for other combinations
// Set the original properties required again. We must first set all the props
// to their default values before attempting to set our blob of props due to
// provider-specific order of processing, that is, the provider may return the props
// to us in any order and may find a prop conflicting with this set even though the set
// itself is consistent and valid.
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pICommandProperties);
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,NULL));
// Get an ICommandProperties interface
TESTC(VerifyInterface(pICmd1, IID_ICommandProperties,
COMMAND_INTERFACE, (IUnknown**)&pICommandProperties));
// Set the command text again
TESTC_(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL), S_OK);
// Set the original properties required again.
TESTC_(pICommandProperties->SetProperties(cPropertySetsReq, pPropertySetsReq), S_OK);
// Now set additional properties one at a time
for (iSet = 0; iSet < cPropertyInfoSets; iSet++)
{
for (iProp=0; iProp < pPropertyInfoSets[iSet].cPropertyInfos; iProp++)
{
TESTC_(pICommandProperties->SetProperties(cPropertySetsReq, pPropertySetsReq), S_OK);
// If the property is already on then skip it
if (GetProperty(pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwPropertyID,
pPropertyInfoSets[iSet].guidPropertySet, pICommandProperties))
continue;
if (!SetPropertyAndExecute(pICmd1, pPropertyInfoSets, iSet, iProp,
SINGLE_PROP, NULL, NULL))
fResult = TEST_FAIL;
}
}
//End variation here if its a row object we are testing.
if(IFROW)
{
fResult = TEST_PASS;
goto CLEANUP;
}
// Now set them in pairs to find a combination that gives DB_E_ERRORSOCCURRED.
for (iSet = 0; iSet < cPropertyInfoSets; iSet++)
{
for (iProp=0; iProp < pPropertyInfoSets[iSet].cPropertyInfos; iProp++)
{
// Put the original properties back
TESTC_(pICommandProperties->SetProperties(cPropertySetsReq, pPropertySetsReq), S_OK);
// If the property is not supported or not writable just skip it
if (pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwFlags == DBPROPFLAGS_NOTSUPPORTED ||
!(pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwFlags & DBPROPFLAGS_WRITE))
continue;
// Set property on
SetRowsetProperty(pICmd1,pPropertyInfoSets[iSet].guidPropertySet,
pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwPropertyID, TRUE,
DBPROPOPTIONS_REQUIRED, FALSE);
// If this property causes Execute to fail then we don't want it
hr = pICmd1->Execute(NULL,IID_IRowset,NULL,NULL,PPI &pIRowset);
SAFE_RELEASE(pIRowset);
// Set property back off
SetRowsetProperty(pICmd1,pPropertyInfoSets[iSet].guidPropertySet,
pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwPropertyID, FALSE,
DBPROPOPTIONS_REQUIRED, FALSE);
if (S_OK != hr)
{
// This is the expected failure if required property can't be supported on rowset
// All single property values were tested previously and errors were posted above.
// Don't post them again
// CHECK(hr, DB_E_ERRORSOCCURRED);
continue;
}
for (iSet2 = 0; iSet2 < cPropertyInfoSets; iSet2++)
{
for (iProp2=0; iProp2 < pPropertyInfoSets[iSet2].cPropertyInfos; iProp2++)
{
// Don't bother if it's the same property. Some providers will return
// DB_S_ERRORSOCCURRED at Execute any time the same property is set twice.
if (iSet == iSet2 && iProp == iProp2)
continue;
// Put the original properties back REQUIRED
TESTC_(pICommandProperties->SetProperties(cPropertySetsReq, pPropertySetsReq), S_OK);
// If the property is not supported or not writable just skip it
if (pPropertyInfoSets[iSet2].rgPropertyInfos[iProp2].dwFlags == DBPROPFLAGS_NOTSUPPORTED ||
!(pPropertyInfoSets[iSet2].rgPropertyInfos[iProp2].dwFlags & DBPROPFLAGS_WRITE))
continue;
// If the second property is already set on then skip it
if (GetProperty(pPropertyInfoSets[iSet2].rgPropertyInfos[iProp2].dwPropertyID,
pPropertyInfoSets[iSet2].guidPropertySet, pICommandProperties))
continue;
// Set second property on
SetRowsetProperty(pICmd1,pPropertyInfoSets[iSet2].guidPropertySet,
pPropertyInfoSets[iSet2].rgPropertyInfos[iProp2].dwPropertyID, TRUE,
DBPROPOPTIONS_REQUIRED, FALSE);
// If this property causes Execute to fail then we don't want it
hr = pICmd1->Execute(NULL,IID_IRowset,NULL,NULL,PPI &pIRowset);
SAFE_RELEASE(pIRowset);
if (S_OK != hr)
{
// This is the expected failure if required property can't be supported on rowset
// All single property values were tested previously and errors were posted above.
// Don't post them again
// CHECK(hr, DB_E_ERRORSOCCURRED);
// Set property back off
SetRowsetProperty(pICmd1,pPropertyInfoSets[iSet2].guidPropertySet,
pPropertyInfoSets[iSet2].rgPropertyInfos[iProp2].dwPropertyID, FALSE,
DBPROPOPTIONS_REQUIRED, FALSE);
continue;
}
// Put the original properties back REQUIRED
TESTC_(pICommandProperties->SetProperties(cPropertySetsReq, pPropertySetsReq), S_OK);
// Set one property on
SetRowsetProperty(pICmd1,pPropertyInfoSets[iSet].guidPropertySet,
pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwPropertyID, TRUE,
DBPROPOPTIONS_REQUIRED, FALSE);
if (!SetPropertyAndExecute(pICmd1, pPropertyInfoSets, iSet2, iProp2,
PAIRED_PROP, pPropertyInfoSets[iSet].rgPropertyInfos[iProp].pwszDescription, NULL))
fResult = TEST_FAIL;
// Set properties back off REQUIRED
SetRowsetProperty(pICmd1,pPropertyInfoSets[iSet].guidPropertySet,
pPropertyInfoSets[iSet].rgPropertyInfos[iProp].dwPropertyID, FALSE,
DBPROPOPTIONS_REQUIRED, FALSE);
SetRowsetProperty(pICmd1,pPropertyInfoSets[iSet2].guidPropertySet,
pPropertyInfoSets[iSet2].rgPropertyInfos[iProp2].dwPropertyID, FALSE,
DBPROPOPTIONS_REQUIRED, FALSE);
}
}
}
}
CLEANUP:
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pIUnk);
SAFE_RELEASE(pIRowsetInfo);
// Put the properties back
CHECK(pICommandProperties->SetProperties(cPropertySets, pPropertySets), S_OK);
// Free the copies of the properties. We can't call FreeProperties because we didn't
// make a copy of bstr values, they're the same as the original
for (iSet = 0; iSet < cPropertySetsReq; iSet++)
SAFE_FREE(pPropertySetsReqCopy[iSet].rgProperties);
SAFE_FREE(pPropertySetsReqCopy);
// Free the property sets
FreeProperties(&cPropertyInfoSets, &pPropertyInfoSets, &pDescBuffer);
FreeProperties(&cPropertySetsReq, &pPropertySetsReq);
FreeProperties(&cPropertySets, &pPropertySets);
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIDBProperties);
SAFE_RELEASE(pICommandProperties);
return fResult;
}
// }}
// {{ TCW_VAR_PROTOTYPE(15)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Insert, riid=IID_NULL
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_15()
{
DBROWCOUNT cRowsAffected=0;
ICommand* pICmd1=NULL;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1,NULL,&cRowsAffected,NULL,NULL,IID_NULL),S_OK));
TEST_COMPARE(cRowsAffected, 1);
m_pTable->AddRow();
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Insert, riid=IID_IRowset
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_16()
{
DBROWCOUNT cRowsAffected=0;
ICommand* pICmd1=NULL;
IUnknown* pIUnk=INVALID(IUnknown *);
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1, PPI &pIUnk, &cRowsAffected),S_OK));
TEST_COMPARE(cRowsAffected, 1);
// Rowset pointer should be nulled out.
TEST_COMPARE(pIUnk, NULL);
m_pTable->AddRow();
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
if(pIUnk != INVALID(IUnknown *))
SAFE_RELEASE(pIUnk);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(17)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Insert, riid=IID_IRowsetInfo
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_17()
{
DBROWCOUNT cRowsAffected=0;
ICommand* pICmd1=NULL;
IRowsetInfo *pIRowsetInfo=INVALID(IRowsetInfo *);
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
ONLYROWSETVAR;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = pICmd1->Execute(NULL,IID_IRowsetInfo,NULL,&cRowsAffected, (IUnknown **)&pIRowsetInfo),S_OK));
m_pTable->AddRow();
TEST_COMPARE(cRowsAffected, 1);
// Is pIRowsetInfo nulled out.
if (!pIRowsetInfo)
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
if(pIRowsetInfo != INVALID(IRowsetInfo *))
SAFE_RELEASE(pIRowsetInfo);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(18)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Select, riid=IID_IRowset
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_18()
{
ICommand* pICmd1=NULL;
IRowset* pIRowset=NULL;
DBORDINAL cRowsetCols;
DBORDINAL * rgTableColOrds = NULL;
ONLYROWSETVAR;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
TESTC_(m_pTable->ExecuteCommand(SELECT_VALIDATIONORDER, IID_IRowset, NULL,
NULL, &cRowsetCols, (DB_LORDINAL **)&rgTableColOrds, EXECUTE_IFNOERROR, 0, NULL, NULL, (IUnknown**)&pIRowset,
&pICmd1), S_OK);
TESTC(pIRowset != NULL);
TESTC_(VerifyRowset(IID_IRowset, (IUnknown *)pIRowset, 1,
cRowsetCols, rgTableColOrds, FALSE), S_OK);
TPASS;
CLEANUP:
SAFE_FREE(rgTableColOrds);
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIRowset);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(19)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Select, riid=IID_IRowsetInfo
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_19()
{
ICommand* pICmd1=NULL;
IRowsetInfo* pIRowsetInfo=NULL;
ONLYROWSETVAR;
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
TEST_CHECK(pICmd1->Execute(NULL,IID_IRowsetInfo,NULL,NULL,PPI &pIRowsetInfo),S_OK);
// We do expect a rowset back.
if (pIRowsetInfo)
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIRowsetInfo);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(20)
//--------------------------------------------------------------------
// @mfunc E_NOINTERACE: dso iid
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_20()
{
ICommand* pICmd1=NULL;
IUnknown* pIUnk=INVALID(IUnknown *);
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
TEST_CHECK(pICmd1->Execute(NULL,IID_IDBProperties,NULL,NULL,PPI &pIUnk),E_NOINTERFACE);
if(!pIUnk)
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
if(pIUnk != INVALID(IUnknown*))
SAFE_RELEASE(pIUnk);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(21)
//--------------------------------------------------------------------
// @mfunc S_OK:valid pcRowsAffected, *pc=0, valid pIRowset (Select)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_21()
{
DBROWCOUNT cRowsAffected=0;
ICommand* pICmd1=NULL;
IUnknown* pIUnk=NULL;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1, PPI &pIUnk, &cRowsAffected),S_OK));
COMPARE(cRowsAffected==DB_COUNTUNAVAILABLE ||
(ULONG)cRowsAffected==m_pTable->GetRowsOnCTable(), TRUE);
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIUnk);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(22)
//--------------------------------------------------------------------
// @mfunc S_OK:valid pcRowsAffected, *pc=1, valid pIRowset (Select)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_22()
{
DBROWCOUNT cRowsAffected=1;
ICommand* pICmd1=NULL;
IUnknown* pIUnk=NULL;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1, PPI &pIUnk, &cRowsAffected),S_OK));
COMPARE(cRowsAffected==DB_COUNTUNAVAILABLE ||
(ULONG)cRowsAffected==m_pTable->GetRowsOnCTable(), TRUE);
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIUnk);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(23)
//--------------------------------------------------------------------
// @mfunc S_OK:valid pcRowsAffected, *pc=0, valid pIRowset (Insert)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_23()
{
DBROWCOUNT cRowsAffected=0;
ICommand* pICmd1=NULL;
IUnknown* pIUnk=INVALID(IUnknown *);
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1, PPI &pIUnk, &cRowsAffected),S_OK));
m_pTable->AddRow();
TEST_COMPARE(cRowsAffected, 1);
if(!pIUnk)
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
if(pIUnk != INVALID(IUnknown *))
SAFE_RELEASE(pIUnk);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(24)
//--------------------------------------------------------------------
// @mfunc S_OK:valid pcRowsAffected, *pc=1, valid pIRowset (Insert)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_24()
{
DBROWCOUNT cRowsAffected=1;
ICommand* pICmd1=NULL;
IUnknown* pIUnk=INVALID(IUnknown *);
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1, PPI &pIUnk, &cRowsAffected),S_OK));
m_pTable->AddRow();
TEST_COMPARE(cRowsAffected, 1);
if(!pIUnk)
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
if(pIUnk != INVALID(IUnknown *))
SAFE_RELEASE(pIUnk);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(25)
//--------------------------------------------------------------------
// @mfunc S_OK:NULL pcRowsAffected, valid pIRowset (Select)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_25()
{
ICommand* pICmd1=NULL;
IUnknown* pIUnk=NULL;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1, PPI &pIUnk),S_OK));
if (pIUnk)
{
TPASS;
}
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIUnk);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(26)
//--------------------------------------------------------------------
// @mfunc E_INVALIDARG:NULL pcRowsAffected, NULL pIRowset (Select)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_26()
{
ICommand* pICmd1=NULL;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1, NULL),E_INVALIDARG));
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(27)
//--------------------------------------------------------------------
// @mfunc S_OK:NULL pcRowsAffected, valid pIRowset (Insert)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_27()
{
ICommand* pICmd1=NULL;
IUnknown* pIUnk=NULL;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1,PPI &pIUnk),S_OK));
m_pTable->AddRow();
if (!pIUnk)
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIUnk);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(28)
//--------------------------------------------------------------------
// @mfunc S_OK:NULL pcRowsAffected, NULL pIRowset (Insert)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_28()
{
ICommand* pICmd1=NULL;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1,NULL,NULL,NULL,NULL,IID_NULL),S_OK));
m_pTable->AddRow();
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(29)
//--------------------------------------------------------------------
// @mfunc S_OK:valid pcRowsAffected, *pc=0, valid pIRowsetLocate (Select)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_29()
{
DBROWCOUNT cRowsAffected=0;
ICommand* pICmd1=NULL;
IRowsetLocate * pIRowsetLocate=NULL;
ONLYROWSETVAR;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
// Make sure the property is supported and settable before proceeding
if(FAILED(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_IRowsetLocate, TRUE, DBPROPOPTIONS_REQUIRED, FALSE)))
{
odtLog << L"IRowsetLocate is not supported by this provider.\n";
TSKIPPED;
}
CLEANUP(!CHECK(m_hr = pICmd1->Execute(NULL,IID_IRowsetLocate,NULL,&cRowsAffected,PPI &pIRowsetLocate),S_OK));
if (pIRowsetLocate)
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIRowsetLocate);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(30)
//--------------------------------------------------------------------
// @mfunc S_OK:valid pcRowsAffected, *pc=1, valid pIRowsetLocate (Select)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_30()
{
DBROWCOUNT cRowsAffected=1;
ICommand* pICmd1=NULL;
IRowsetLocate * pIRowsetLocate=NULL;
ONLYROWSETVAR;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
// Make sure the property is supported and settable before proceeding
if(FAILED(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_IRowsetLocate, TRUE, DBPROPOPTIONS_REQUIRED, FALSE)))
{
odtLog << L"IRowsetLocate is not supported by this provider.\n";
TSKIPPED;
}
CLEANUP(!CHECK(m_hr = pICmd1->Execute(NULL,IID_IRowsetLocate,NULL,&cRowsAffected,PPI &pIRowsetLocate),S_OK));
if (pIRowsetLocate)
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIRowsetLocate);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(31)
//--------------------------------------------------------------------
// @mfunc S_OK:valid pcRowsAffected, *pc=0, valid pIRowsetLocate (Insert)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_31()
{
DBROWCOUNT cRowsAffected=1;
ICommand* pICmd1=NULL;
IRowsetLocate * pIRowsetLocate=INVALID(IRowsetLocate *);
ONLYROWSETVAR;
TESTBEGIN;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
// Make sure the property is supported and settable before proceeding
if(FAILED(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_IRowsetLocate, TRUE, DBPROPOPTIONS_REQUIRED, FALSE)))
{
odtLog << L"IRowsetLocate is not supported by this provider.\n";
TSKIPPED;
}
CLEANUP(!CHECK(m_hr = pICmd1->Execute(NULL,IID_IRowsetLocate,NULL,&cRowsAffected,PPI &pIRowsetLocate),S_OK));
m_pTable->AddRow();
// Expecting a NULL pIRowsetLocate for an Insert statement.
if (!pIRowsetLocate)
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
// Since we set to a bogus value don't free it if it's still bogus
if (pIRowsetLocate != INVALID(IRowsetLocate *))
SAFE_RELEASE(pIRowsetLocate);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(32)
//--------------------------------------------------------------------
// @mfunc S_OK:NULL pcRowsAffected, valid pIRowsetLocate (Select)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_32()
{
ICommand* pICmd1=NULL;
IRowsetLocate * pIRowsetLocate=NULL;
ONLYROWSETVAR;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
// Make sure the property is supported and settable before proceeding
if(FAILED(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_IRowsetLocate, TRUE, DBPROPOPTIONS_REQUIRED, FALSE)))
{
odtLog << L"IRowsetLocate is not supported by this provider.\n";
TSKIPPED;
}
CLEANUP(!CHECK(pICmd1->Execute(NULL,IID_IRowsetLocate,NULL,NULL,PPI &pIRowsetLocate),S_OK));
if (pIRowsetLocate)
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIRowsetLocate);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(33)
//--------------------------------------------------------------------
// @mfunc E_INVALIDARG:NULL pcRowsAffected, NULL pIRowsetLocate (Select)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_33()
{
ICommand* pICmd1=NULL;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
// Make sure the property is supported and settable before proceeding
if(FAILED(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_IRowsetLocate, TRUE, DBPROPOPTIONS_REQUIRED, FALSE)))
{
odtLog << L"IRowsetLocate is not supported by this provider.\n";
TSKIPPED;
}
m_hr = pICmd1->Execute(NULL,IID_IRowsetLocate,NULL,NULL,NULL);
if(IFROWSET)
TESTC_(m_hr, E_INVALIDARG)
if(IFROW)
TEST2C_(m_hr, E_INVALIDARG, E_NOINTERFACE)
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(34)
//--------------------------------------------------------------------
// @mfunc S_OK:NULL pcRowsAffected, valid pIRowsetLocate (Insert)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_34()
{
ICommand* pICmd1=NULL;
IRowsetLocate* pIRowsetLocate=NULL;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
ONLYROWSETVAR;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
// Make sure the property is supported and settable before proceeding
if(FAILED(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_IRowsetLocate, TRUE, DBPROPOPTIONS_REQUIRED, FALSE)))
{
odtLog << L"IRowsetLocate is not supported by this provider.\n";
TSKIPPED;
}
CLEANUP(!CHECK(m_hr = pICmd1->Execute(NULL,IID_IRowsetLocate,NULL,NULL,PPI &pIRowsetLocate),S_OK));
m_pTable->AddRow();
if(!pIRowsetLocate)
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIRowsetLocate)
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(35)
//--------------------------------------------------------------------
// @mfunc S_OK:NULL pcRowsAffected, NULL pIRowsetLocate (Insert)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_35()
{
// @todo :: Delete this variation.
PRVTRACE (L"Bogus Variation\n");
return TEST_PASS;
}
// }}
// {{ TCW_VAR_PROTOTYPE(36)
//--------------------------------------------------------------------
// @mfunc S_OK:valid pcRowsAffected, *pc=0, valid pIColumnsInfo (Select)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_36()
{
ICommand* pICmd1=NULL;
IColumnsInfo* pIColumnsInfo=NULL;
DBROWCOUNT cRowsAffected=0;
EINTERFACE eIF = ROWSET_INTERFACE;
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
if(IFROW)
{
eIF = ROW_INTERFACE;
CHECK(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,
DBPROP_IRow,TRUE,DBPROPOPTIONS_REQUIRED), S_OK);
}
CLEANUP(!CHECK(m_hr = pICmd1->Execute(NULL,IID_IColumnsInfo,NULL,&cRowsAffected,PPI &pIColumnsInfo),S_OK));
TESTC(DefaultObjectTesting(pIColumnsInfo, eIF))
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIColumnsInfo);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(37)
//--------------------------------------------------------------------
// @mfunc S_OK:valid pcRowsAffected, *pc=1, valid pIColumnsInfo (Select)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_37()
{
ICommand* pICmd1=NULL;
IColumnsInfo* pIColumnsInfo=NULL;
DBROWCOUNT cRowsAffected=1;
EINTERFACE eIF = ROWSET_INTERFACE;
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
if(IFROW)
{
eIF = ROW_INTERFACE;
CHECK(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,
DBPROP_IRow,TRUE,DBPROPOPTIONS_REQUIRED), S_OK);
}
CLEANUP(!CHECK(m_hr = pICmd1->Execute(NULL,IID_IColumnsInfo,NULL,&cRowsAffected,PPI &pIColumnsInfo),S_OK));
TESTC(DefaultObjectTesting(pIColumnsInfo, eIF))
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIColumnsInfo);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(38)
//--------------------------------------------------------------------
// @mfunc S_OK:valid pcRowsAffected, *pc=0, valid pIColumnsInfo (Insert)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_38()
{
ICommand* pICmd1=NULL;
IColumnsInfo* pIColumnsInfo=NULL;
DBROWCOUNT cRowsAffected=0;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
if(IFROW)
CHECK(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,
DBPROP_IRow,TRUE,DBPROPOPTIONS_REQUIRED), S_OK);
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = pICmd1->Execute(NULL,IID_IColumnsInfo,NULL,&cRowsAffected,PPI &pIColumnsInfo),S_OK));
m_pTable->AddRow();
COMPARE(cRowsAffected, 1);
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIColumnsInfo);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(39)
//--------------------------------------------------------------------
// @mfunc S_OK:valid pcRowsAffected, *pc=1, valid pIColumnsInfo (Insert)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_39()
{
ICommand* pICmd1=NULL;
IColumnsInfo* pIColumnsInfo=NULL;
DBROWCOUNT cRowsAffected=1;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
if(IFROW)
CHECK(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,
DBPROP_IRow,TRUE,DBPROPOPTIONS_REQUIRED), S_OK);
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = pICmd1->Execute(NULL,IID_IColumnsInfo,NULL,&cRowsAffected,PPI &pIColumnsInfo),S_OK));
m_pTable->AddRow();
COMPARE(cRowsAffected, 1);
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIColumnsInfo);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(40)
//--------------------------------------------------------------------
// @mfunc S_OK:NULL pcRowsAffected, valid pIColumnsInfo (Select)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_40()
{
ICommand* pICmd1=NULL;
IColumnsInfo* pIColumnsInfo=NULL;
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
if(IFROW)
CHECK(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,
DBPROP_IRow,TRUE,DBPROPOPTIONS_REQUIRED), S_OK);
CLEANUP(!CHECK(m_hr = pICmd1->Execute(NULL,IID_IColumnsInfo,NULL,NULL,PPI &pIColumnsInfo),S_OK));
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIColumnsInfo);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(41)
//--------------------------------------------------------------------
// @mfunc E_INVALIDARG:NULL pcRowsAffected, NULL pIColumnsInfo (Select)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_41()
{
ICommand* pICmd1=NULL;
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
if(IFROW)
CHECK(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,
DBPROP_IRow,TRUE,DBPROPOPTIONS_REQUIRED), S_OK);
CLEANUP(!CHECK(m_hr = pICmd1->Execute(NULL,IID_IColumnsInfo,NULL,NULL,NULL),E_INVALIDARG));
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(42)
//--------------------------------------------------------------------
// @mfunc S_OK:NULL pcRowsAffected, valid pIColumnsInfo (Insert)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_42()
{
ICommand* pICmd1=NULL;
IColumnsInfo* pIColumnsInfo=NULL;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
if(IFROW)
CHECK(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,
DBPROP_IRow,TRUE,DBPROPOPTIONS_REQUIRED), S_OK);
CLEANUP(!CHECK(m_hr = pICmd1->Execute(NULL,IID_IColumnsInfo,NULL,NULL,PPI &pIColumnsInfo),S_OK));
COMPARE(pIColumnsInfo, NULL);
m_pTable->AddRow();
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIColumnsInfo);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(43)
//--------------------------------------------------------------------
// @mfunc S_OK:NULL pcRowsAffected, NULL pIColumnsInfo (Insert)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_43()
{
ICommand* pICmd1=NULL;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
CLEANUP(!CHECK(m_hr = pICmd1->Execute(NULL,IID_NULL,NULL,NULL,NULL),S_OK));
m_pTable->AddRow();
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(44)
//--------------------------------------------------------------------
// @mfunc E_INVALIDARG:riid != IID_NULL, ppRowset==NULL
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_44()
{
ICommand* pICmd1=NULL;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
if(IFROW)
CHECK(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,
DBPROP_IRow,TRUE,DBPROPOPTIONS_REQUIRED), S_OK);
CLEANUP(!CHECK(m_hr = Execute(pICmd1,NULL),E_INVALIDARG));
TPASS
CLEANUP:
if (SUCCEEDED(m_hr))
m_pTable->AddRow();
SAFE_RELEASE(pICmd1);
TRETURN
}
// {{ TCW_VAR_PROTOTYPE(45)
//--------------------------------------------------------------------
// @mfunc DB_E_CANTCONVERTVALUE: string (22005)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_45()
{
BOOL fSuccess = FALSE; // Variation passed or failed
HRESULT hr = E_FAIL; // HRESULT
ICommand* pICommand = NULL; // ICommand Object
WCHAR * pwszSQLStmt = NULL; // SQL Statement
WCHAR * pTableName = NULL; // Name of the table
WCHAR * pwszValue = NULL; // String value
DBORDINAL pcColumns = 0; // Count of columns
DBLENGTH ColSize = 0; // Column Size
ULONG count = 0; // Loop counter
CList <WCHAR* ,WCHAR*> NativeTypesList;
CCol NewCol(m_pIMalloc); // Class CCol
IUnknown * pIUnk=NULL;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
// Creates a column list from the Ctable
pcColumns = m_pTable->CountColumnsOnTable();
// Loop thru column types
for( count=1; count <= pcColumns; count++)
{
m_pTable->GetColInfo(count, NewCol);
// We want a non-long character column
if( IsColCharacter(NewCol.GetProviderType()) && !NewCol.GetIsLong())
break;
}
if (count > pcColumns)
{
odtLog << L"Couldn't find a non-Long char column for this test.\n";
return TEST_SKIPPED;
}
NativeTypesList.AddHead(NewCol.GetProviderTypeName());
// Create a table
if(!CHECK(g_Table3->CreateTable(NativeTypesList,
1, // Number of rows to insert
0, // Column to put index on
NULL, // Table name
PRIMARY), // Primary or secondary values
S_OK))
{
// Free memory in the list
NativeTypesList.RemoveAll();
return TEST_FAIL;
}
// Get the name of the table just created
pTableName = g_Table3->GetTableName();
// Get Column Size
ColSize = NewCol.GetMaxSize();
// Alloc Memory
pwszValue= (WCHAR *) m_pIMalloc->Alloc( sizeof(WCHAR) +
(sizeof(WCHAR)*(ColSize+1)) );
pwszSQLStmt = (WCHAR *) m_pIMalloc->Alloc( sizeof(WCHAR) + (sizeof(WCHAR) *
(wcslen(wszInsertInvalidCharValue) + wcslen(pTableName) + ColSize+1)) );
// Create String value out of range
wcscpy(pwszValue, L"\0");
for(count=1; count <= ColSize+1; count++)
wcscat(pwszValue, L"A");
// Format SQL Statement
swprintf(pwszSQLStmt, wszInsertInvalidCharValue, pTableName, pwszValue);
// Command to return a ICommand with Text Set
if( !CHECK(g_Table3->BuildCommand(pwszSQLStmt, IID_IRowset,
EXECUTE_NEVER, 0, NULL, NULL, NULL, NULL, &pICommand), S_OK) )
goto END;
// Compare the HRESULT
if( CHECK(Execute(pICommand, PPI &pIUnk), DB_E_DATAOVERFLOW) )
fSuccess = TRUE;
END:
// Free memory in the list
NativeTypesList.RemoveAll();
SAFE_RELEASE(pIUnk);
SAFE_RELEASE_(pICommand);
// Free Memory
PROVIDER_FREE(pwszSQLStmt);
PROVIDER_FREE(pwszValue);
// Drop the table
g_Table3->DropTable();
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// {{ TCW_VAR_PROTOTYPE(46)
//--------------------------------------------------------------------
// @mfunc DB_E_CANTCONVERTVALUE: implicit (22005)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_46()
{
BOOL fSuccess = FALSE; // Variation passed or failed
HRESULT hr = E_FAIL; // HRESULT
ICommand* pICommand = NULL; // ICommand Object
WCHAR * pwszSQLStmt = NULL; // SQL Statement
WCHAR * pTableName = NULL; // Name of the table
WCHAR * pwszNumeric = NULL; // Numeric value
DBORDINAL pcColumns = 0; // Count of columns
ULONG count = 0; // Loop counter
CList <DBTYPE, DBTYPE> DBTypeList;
CCol NewCol(m_pIMalloc); // Class CCol
IUnknown * pIUnk=NULL;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
// Creates a column list from the Ctable
pcColumns = m_pTable->CountColumnsOnTable();
// Loop thru column types
for( count=1; count <= pcColumns; count++)
{
m_pTable->GetColInfo(count, NewCol);
// We need an updatable numeric column
if( IsNumericType(NewCol.GetProviderType()) && NewCol.GetUpdateable())
break;
}
if (count > pcColumns)
{
odtLog << L"Couldn't find an updatable numeric column for this test.\n";
return TEST_SKIPPED;
}
DBTypeList.AddHead(NewCol.GetProviderType());
// Create a table
if(!CHECK(g_Table3->CreateTable(DBTypeList,
1, // Number of rows to insert
0, // Column to put index on
NULL, // Table name
PRIMARY), // Primary or secondary values
S_OK))
{
// Free memory in the list
DBTypeList.RemoveAll();
return TEST_FAIL;
}
// Get the name of the table just created
pTableName = g_Table3->GetTableName();
// Alloc Memory
pwszSQLStmt = (WCHAR *) m_pIMalloc->Alloc( sizeof(WCHAR) + (sizeof(WCHAR) *
(wcslen(wszInsertInvalidChar) + wcslen(pTableName))) );
// Format SQL Statement
swprintf(pwszSQLStmt, wszInsertInvalidChar, pTableName);
// Command to return a ICommand with Text Set
if( !CHECK(g_Table3->BuildCommand(pwszSQLStmt, IID_IRowset,
EXECUTE_NEVER, 0, NULL, NULL, NULL, NULL, &pICommand), S_OK) )
goto END;
if( CHECK(Execute(pICommand,PPI &pIUnk),DB_E_CANTCONVERTVALUE) )
fSuccess = TRUE;
END:
// Free memory in the list
DBTypeList.RemoveAll();
// Free Memory
if( pwszSQLStmt )
m_pIMalloc->Free(pwszSQLStmt);
SAFE_RELEASE(pIUnk);
SAFE_RELEASE_(pICommand);
// Drop the table
g_Table3->DropTable();
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// {{ TCW_VAR_PROTOTYPE(47)
//--------------------------------------------------------------------
// @mfunc DB_E_CANTCONVERTVALUE: implicit (22008)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_47()
{
BOOL fSuccess = FALSE; // Variation passed or failed
HRESULT hr = E_FAIL; // HRESULT
ICommand* pICommand = NULL; // ICommand Object
WCHAR * pwszSQLStmt = NULL; // SQL Statement
WCHAR * pTableName = NULL; // Name of the table
WCHAR * pPrefix = NULL; // Prefix of DataType
WCHAR * pSuffix = NULL; // Suffix of DataType
WCHAR * pwszDateTime = NULL; // DateTime value
ULONG ColPrec = 0; // Column Precision
DBORDINAL pcColumns = 0; // Count of columns
ULONG count = 0; // Loop counter
CList <DBTYPE, DBTYPE> DBTypeList;
CCol NewCol(m_pIMalloc); // Class CCol
IID iid = IID_IRowset;
if(IFROW)
iid = IID_IRow;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
// Creates a column list from the Ctable
pcColumns = m_pTable->CountColumnsOnTable();
// Loop thru column types
for( count=1; count <= pcColumns; count++)
{
m_pTable->GetColInfo(count, NewCol);
// If first column is already datetime then were done
if( IsColDateTime(NewCol.GetProviderType()) )
break;
}
if (count > pcColumns)
{
odtLog << L"Couldn't find a datetime column for this test.\n";
return TEST_SKIPPED;
}
DBTypeList.AddHead(NewCol.GetProviderType());
// Create a table
if(!CHECK(g_Table3->CreateTable(DBTypeList,
1, // Number of rows to insert
0, // Column to put index on
NULL, // Table name
PRIMARY), // Primary or secondary values
S_OK))
{
// Free memory in the list
DBTypeList.RemoveAll();
return TEST_FAIL;
}
// Get the name of the table just created
pTableName = g_Table3->GetTableName();
// Get Numeric Precision
ColPrec = NewCol.GetPrecision();
// Get DataType Prefix
pPrefix = NewCol.GetPrefix();
// Get DataType Suffix
pSuffix = NewCol.GetSuffix();
// Alloc Memory
pwszSQLStmt = (WCHAR *) m_pIMalloc->Alloc( sizeof(WCHAR) +
(sizeof(WCHAR) * (wcslen(wszInsertInvalidDateValue) +
wcslen(pTableName) +
wcslen(pPrefix) +
wcslen(pSuffix) +
wcslen(wszInvalidDateTime))) );
// Format SQL Statement
swprintf(pwszSQLStmt, wszInsertInvalidDateValue, pTableName, pPrefix, wszInvalidDateTime, pSuffix);
// Command to return a ICommand with Text Set
if( CHECK(g_Table3->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand), DB_E_CANTCONVERTVALUE) )
fSuccess = TRUE;
// Free memory in the list
DBTypeList.RemoveAll();
SAFE_RELEASE_(pICommand)
PROVIDER_FREE(pwszSQLStmt);
g_Table3->DropTable();
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// {{ TCW_VAR_PROTOTYPE(48)
//--------------------------------------------------------------------
// @mfunc DB_E_DATAOVERFLOW: math (22003)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_48()
{
BOOL fSuccess = FALSE; // Variation passed or failed
HRESULT hr = E_FAIL; // HRESULT
ICommand* pICommand = NULL; // ICommand Object
ICommandPrepare* pICommandPrep = NULL; // ICommandPrepare Object
WCHAR * pwszSQLStmt = NULL; // SQL Statement
WCHAR * pTableName = NULL; // Name of the table
WCHAR * pwszNumeric = NULL; // Numeric value
DBORDINAL pcColumns = 0; // Count of columns
ULONG ColPrec = 0; // Column Precision
ULONG count = 0; // Loop counter
CList <DBTYPE, DBTYPE> DBTypeList;
CCol NewCol(m_pIMalloc); // Class CCol
IID iid = IID_IRowset;
if(IFROW)
iid = IID_IRow;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
pcColumns = m_pTable->CountColumnsOnTable();
// Loop thru column types
for( count=1; count <= pcColumns; count++)
{
m_pTable->GetColInfo(count, NewCol);
// If first column is already numeric then were done
if( (IsColNumWithScale(NewCol.GetProviderType(),NewCol.GetScale())) &&
(NewCol.GetUpdateable()) )
break;
}
if (count > pcColumns)
{
odtLog << L"Couldn't find a numeric column with scale.\n";
return TEST_SKIPPED;
}
DBTypeList.AddHead(NewCol.GetProviderType());
// Create a table
if(!CHECK(g_Table3->CreateTable(DBTypeList,
1, // Number of rows to insert
0, // Column to put index on
NULL, // Table name
PRIMARY), // Primary or secondary values
S_OK))
{
// Free memory in the list
DBTypeList.RemoveAll();
return TEST_FAIL;
}
// Get the name of the table just created
pTableName = g_Table3->GetTableName();
// Get Numeric Precision
ColPrec = NewCol.GetPrecision();
// Alloc Memory
pwszNumeric= (WCHAR *) m_pIMalloc->Alloc( sizeof(WCHAR) +
(sizeof(WCHAR)*(ColPrec+1)) );
pwszSQLStmt = (WCHAR *) m_pIMalloc->Alloc( sizeof(WCHAR) + (sizeof(WCHAR) *
(wcslen(wszInsertInvalidValue) + wcslen(pTableName) + ColPrec+1)) );
// Create Numeric Valus out of range
wcscpy(pwszNumeric, L"\0");
for(count=1; count <= ColPrec+1; count++)
wcscat(pwszNumeric, L"9");
// Format SQL Statement
swprintf(pwszSQLStmt, wszInsertInvalidValue, pTableName, pwszNumeric);
// Command to return a ICommand with Text Set
if( CHECK(g_Table3->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand), DB_E_DATAOVERFLOW) )
fSuccess = TRUE;
// Free memory in the list
DBTypeList.RemoveAll();
SAFE_RELEASE_(pICommand);
PROVIDER_FREE(pwszSQLStmt);
PROVIDER_FREE(pwszNumeric)
g_Table3->DropTable();
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// {{ TCW_VAR_PROTOTYPE(49)
//--------------------------------------------------------------------
// @mfunc DB_E_DATAOVERFLOW: string right (22001
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_49()
{
BOOL fSuccess = FALSE; // Variation passed or failed
HRESULT hr = E_FAIL; // HRESULT
ICommand* pICommand = NULL; // ICommand Object
ICommandPrepare* pICommandPrep = NULL; // ICommandPrepare Object
WCHAR * pwszSQLStmt = NULL; // SQL Statement
WCHAR * pTableName = NULL; // Name of the table
WCHAR * pTableNCpy = NULL; // Copy of the Table Name
WCHAR * pwszValue = NULL; // String value
IUnknown * pIUnk=NULL;
DBORDINAL pcColumns = 0; // Count of columns
DBLENGTH ColSize = 0; // Column Size
ULONG count = 0; // Loop counter
CCol NewCol(m_pIMalloc); // Class CCol
IID iid = IID_IRowset;
if(IFROW)
iid = IID_IRow;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || g_Table3->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
// should fail on buckhorn (sql 6.0) due
// to driver limitation
// if this fails on access, it is a driver bug
if( !CHECK(g_Table3->CreateTable(1, // Number of rows to insert
1, // Column to put index on
NULL, // Table name
PRIMARY), // Primary or secondary val
S_OK) )
return TEST_FAIL;
// Creates a column list from the Ctable
pcColumns = g_Table3->CountColumnsOnTable();
// Loop thru column types to find a char column with create params
// When the single column table is created below we assume create params (length)
// and use (length-1) to avoid the SQL Server invalid error code when char(255) is used.
for( count=1; count <= pcColumns; count++)
{
g_Table3->GetColInfo(count, NewCol);
// If first column is already non-long character with create params then were done
if( IsColCharacter(NewCol.GetProviderType()) &&
NewCol.GetCreateParams() &&
!NewCol.GetIsLong())
break;
}
if (count > pcColumns)
{
odtLog << L"Couldn't find a non-Long char column for this test.\n";
return TEST_SKIPPED;
}
// Get the name of the table just created
pTableName = g_Table3->GetTableName();
// Get a copy of the table name
pTableNCpy = (WCHAR *) m_pIMalloc->Alloc((wcslen(pTableName) *
sizeof(WCHAR)) + sizeof(WCHAR));
wcscpy(pTableNCpy, pTableName);
// Get Column Size
ColSize = NewCol.GetMaxSize();
// Create a table
pwszSQLStmt = (WCHAR *) m_pIMalloc->Alloc( sizeof(WCHAR) + (sizeof(WCHAR) *
(wcslen(wszCreateStringTable) + wcslen(pTableNCpy) +
wcslen(NewCol.GetProviderTypeName()) + 3)) );
// Format SQL Statement
swprintf(pwszSQLStmt, wszCreateStringTable, pTableNCpy, NewCol.GetProviderTypeName(), ColSize-1);
// Drop the table, also deletes the table name
g_Table3->DropTable();
// Command to return a ICommand with Text Set
if( !CHECK(g_Table3->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand), S_OK) )
goto END;
// Set the TableName
g_Table3->SetTableName(pTableNCpy);
// Alloc Memory
pwszValue= (WCHAR *) m_pIMalloc->Alloc( sizeof(WCHAR) +
(sizeof(WCHAR)*(ColSize)) );
PROVIDER_FREE(pwszSQLStmt);
pwszSQLStmt = (WCHAR *) m_pIMalloc->Alloc( sizeof(WCHAR) + (sizeof(WCHAR) *
(wcslen(wszInsertInvalidCharValue) + wcslen(pTableNCpy) + ColSize)) );
// Create String value out of range
wcscpy(pwszValue, L"\0");
for(count=1; count <= ColSize; count++)
wcscat(pwszValue, L"A");
// Format SQL Statement
swprintf(pwszSQLStmt, wszInsertInvalidCharValue, pTableNCpy, pwszValue);
// Command to return a ICommand with Text Set
if( CHECK(g_Table3->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand), DB_E_DATAOVERFLOW) )
fSuccess = TRUE;
END:
// Release Objects
SAFE_RELEASE(pICommandPrep);
SAFE_RELEASE_(pICommand);
// Free Memory
PROVIDER_FREE(pTableNCpy);
PROVIDER_FREE(pwszSQLStmt);
PROVIDER_FREE(pwszValue);
// Drop the table
g_Table3->DropTable();
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// {{ TCW_VAR_PROTOTYPE(50)
//*-----------------------------------------------------------------------
// @mfunc DB_E_ERRORSINCOMMAND - Create Table statement on a table that already exists (S0001)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_50()
{
BOOL fSuccess = FALSE; // Variation passed or failed
HRESULT hr = E_FAIL; // HRESULT
CTable cTable((IUnknown *)m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
{
odtLog << L"Can't create a table on a read-only provider.\n";
return TEST_SKIPPED;
}
// Save the values we may change to force command usage
BOOL fITableDef = GetModInfo()->IsUsingITableDefinition();
// Set the values to force command usage
GetModInfo()->UseITableDefinition(FALSE);
// Save the existing table name since CreateTable will release it
hr = cTable.CreateTable((DBCOUNTITEM)0, (DBORDINAL)0, m_pTable->GetTableName());
GetModInfo()->UseITableDefinition(fITableDef);
TESTC_(hr, DB_E_ERRORSINCOMMAND);
fSuccess = TRUE;
CLEANUP:
return fSuccess;
}
// }}
// {{ TCW_VAR_PROTOTYPE(51)
//*-----------------------------------------------------------------------
// @mfunc DB_E_ERRORSINCOMMAND - Create View statement on a view that already exists (S0001)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_51()
{
BOOL fSuccess = FALSE; // Variation passed or failed
WCHAR* pwszSQLStmt = NULL; // SQL Statement
WCHAR* pTableName = NULL; // Name of the table
WCHAR* pViewName = NULL; // Name of the view
HRESULT hr = E_FAIL; // HRESULT
ICommand* pICommand = NULL; // ICommand Object
IID iid = IID_IRowset;
if(IFROW)
iid = IID_IRow;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
{
odtLog << L"Can't create a view on a read-only provider.\n";
return TEST_SKIPPED;
}
// Get the name of the table just created
pTableName = m_pTable->GetTableName();
// Alloc Memory
pwszSQLStmt = (WCHAR *) m_pIMalloc->Alloc( (sizeof(WCHAR) *
(wcslen(wszCreateView) + wcslen(pTableName) +
wcslen(pTableName) + 1)) + sizeof(WCHAR) );
pViewName = (WCHAR *) m_pIMalloc->Alloc( (sizeof(WCHAR) *
(wcslen(pTableName) + 1)) + sizeof(WCHAR) );
// Make a view name
wcscpy(pViewName, pTableName);
wcscat(pViewName, L"v");
// Put the SQL statement together for Create View
swprintf(pwszSQLStmt, wszCreateView, pViewName, pTableName);
// Create View
hr = m_pTable->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand);
// check to see if the create view failed
if(FAILED(hr))
{
odtLog<<L"Create view not supported" <<ENDL;
fSuccess = TRUE;
goto END;
}
// Command to return a ICommand with Text Set
if( CHECK(m_pTable->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand), DB_E_ERRORSINCOMMAND) )
fSuccess = TRUE;
END:
// Put the SQL statement together for Drop View
swprintf(pwszSQLStmt, wszDropView, pViewName);
// Drop View
hr = m_pTable->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand);
if( hr != S_OK)
{
// Access Driver HACK (Drop Table on the View)
swprintf(pwszSQLStmt, wszDropTable, pViewName);
hr = m_pTable->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand);
}
SAFE_RELEASE_(pICommand);
// Free Memory
PROVIDER_FREE(pwszSQLStmt);
PROVIDER_FREE(pViewName);
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// }}
// {{ TCW_VAR_PROTOTYPE(52)
//*-----------------------------------------------------------------------
// @mfunc DB_E_ERRORSINCOMMAND - Select statement with invalid table name (S0002)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_52()
{
BOOL fSuccess = FALSE; // Variation passed or failed
WCHAR* pwszSQLStmt = NULL; // SQL Statement
HRESULT hr = E_FAIL; // HRESULT
ICommand* pICommand = NULL; // ICommand Object
WCHAR* pszStartTblName = NULL;
IID iid = IID_IRowset;
if(IFROW)
iid = IID_IRow;
// Create a SQL Stmt and Set the Command
m_pTable->CreateSQLStmt(SELECT_INVALIDTBLNAME,
NULL, &pwszSQLStmt, NULL, NULL);
// Command to return a ICommand with Text Set
if( CHECK(m_pTable->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand), DB_E_NOTABLE) )
fSuccess = TRUE;
SAFE_RELEASE_(pICommand);
PROVIDER_FREE(pwszSQLStmt);
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// }}
// {{ TCW_VAR_PROTOTYPE(53)
//*-----------------------------------------------------------------------
// @mfunc DB_E_ERRORSINCOMMAND - Drop Table statement on a table that does not exist (S0002)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_53()
{
BOOL fSuccess = FALSE; // Variation passed or failed
WCHAR* pwszSQLStmt = NULL; // SQL Statement
WCHAR* pTableName = NULL; // Name of the table
WCHAR* pTableNCpy = NULL; // Name of the table
HRESULT hr = E_FAIL; // HRESULT
ICommand* pICommand = NULL; // ICommand Object
IID iid = IID_IRowset;
if(IFROW)
iid = IID_IRow;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || g_Table3->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
if( !CHECK(g_Table3->CreateTable(1, // Number of rows to insert
1, // Column to put index on
NULL, // Table name
PRIMARY), // Primary or secondary val
S_OK) )
return TEST_FAIL;
// Get the name of the table just created
pTableName = g_Table3->GetTableName();
// Alloc Memory
pwszSQLStmt = (WCHAR *) m_pIMalloc->Alloc( (sizeof(WCHAR) *
(wcslen(wszDropTable) + wcslen(pTableName))) + sizeof(WCHAR) );
// Get a copy of the table name
pTableNCpy = (WCHAR *) m_pIMalloc->Alloc((wcslen(pTableName) *
sizeof(WCHAR)) + sizeof(WCHAR));
wcscpy(pTableNCpy, pTableName);
// Drop the table, also deletes the table name
g_Table3->DropTable();
// Put the SQL statement together
swprintf(pwszSQLStmt, wszDropTable, pTableNCpy);
// Command to return a ICommand with Text Set
if( CHECK(m_pTable->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand), DB_E_NOTABLE) )
fSuccess = TRUE;
SAFE_RELEASE_(pICommand);
PROVIDER_FREE(pwszSQLStmt);
PROVIDER_FREE(pTableNCpy);
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// }}
// {{ TCW_VAR_PROTOTYPE(54)
//*-----------------------------------------------------------------------
// @mfunc DB_E_ERRORSINCOMMAND - Drop View statement on a view that does not exist (S0002)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_54()
{
BOOL fSuccess = FALSE; // Variation passed or failed
WCHAR* pwszSQLStmt = NULL; // SQL Statement
WCHAR* pTableName = NULL; // Name of the table
WCHAR* pViewName = NULL; // Name of the view
HRESULT hr = E_FAIL; // HRESULT
ICommand* pICommand = NULL; // ICommand Object
IID iid = IID_IRowset;
if(IFROW)
iid = IID_IRow;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
// Get the name of the table just created
pTableName = m_pTable->GetTableName();
// Alloc Memory
pwszSQLStmt = (WCHAR *) m_pIMalloc->Alloc( (sizeof(WCHAR) *
(wcslen(wszCreateView) + wcslen(pTableName) +
wcslen(pTableName) + 1)) + sizeof(WCHAR) );
pViewName = (WCHAR *) m_pIMalloc->Alloc( (sizeof(WCHAR) *
(wcslen(pTableName) + 1)) + sizeof(WCHAR) );
// Make a view name
wcscpy(pViewName, pTableName);
wcscat(pViewName, L"v");
// Put the SQL statement together for Create View
swprintf(pwszSQLStmt, wszCreateView, pViewName, pTableName);
// Create View
hr = m_pTable->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand);
// check to see if the create view failed
if(FAILED(hr))
{
odtLog<<L"Create view not supported" <<ENDL;
fSuccess = TRUE;
goto END;
}
// Put the SQL statement together for Drop View
swprintf(pwszSQLStmt, wszDropView, pViewName);
// Drop View
hr = m_pTable->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand);
if( hr != S_OK)
{
// Access Driver HACK (Drop Table on the View)
swprintf(pwszSQLStmt, wszDropTable, pViewName);
if( !CHECK(m_pTable->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand), S_OK) )
goto END;
}
// Command to return a ICommand with Text Set
if( CHECK(m_pTable->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand), DB_E_NOTABLE) )
fSuccess = TRUE;
END:
SAFE_RELEASE_(pICommand);
PROVIDER_FREE(pwszSQLStmt);
PROVIDER_FREE(pViewName);
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// }}
// {{ TCW_VAR_PROTOTYPE(55)
//*-----------------------------------------------------------------------
// @mfunc DB_E_ERRORSINCOMMAND - Select statement with invalid column name (S0022)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_55()
{
BOOL fSuccess = FALSE; // Variation passed or failed
WCHAR* pwszSQLStmt = NULL; // SQL Statement
WCHAR* pTableName = NULL; // Name of the table
HRESULT hr = E_FAIL; // HRESULT
ICommand* pICommand = NULL; // ICommand Object
IID iid = IID_IRowset;
if(IFROW)
iid = IID_IRow;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
// if this fails on access, it is a driver bug
// Get the name of the table just created
pTableName = m_pTable->GetTableName();
// Alloc Memory
pwszSQLStmt = (WCHAR *) m_pIMalloc->Alloc( (sizeof(WCHAR) *
(wcslen(wszSelectBadColName) + wcslen(pTableName))) + sizeof(WCHAR) );
// Put the SQL statement together
swprintf(pwszSQLStmt, wszSelectBadColName, pTableName);
// Command to return a ICommand with Text Set
if( CHECK(m_pTable->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand), DB_E_ERRORSINCOMMAND) )
fSuccess = TRUE;
// Cleanup
SAFE_RELEASE_(pICommand);
// Free Memory
PROVIDER_FREE(pwszSQLStmt);
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// }}
// {{ TCW_VAR_PROTOTYPE(56)
//*-----------------------------------------------------------------------
// @mfunc S_OK - Numeric Truncation (01004)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_56()
{
BOOL fSuccess = FALSE; // Variation passed or failed
HRESULT hr = E_FAIL; // HRESULT
ICommand* pICommand = NULL; // ICommand Object
WCHAR * pwszSQLStmt = NULL; // SQL Statement
WCHAR * pTableName = NULL; // Name of the table
WCHAR * pwszNumeric = NULL; // Numeric value
DBORDINAL pcColumns = 0; // Count of columns
ULONG ColScale = 0; // Column Scale
ULONG count = 0; // Loop counter
CList <WCHAR* ,WCHAR*> NativeTypesList;
CCol NewCol(m_pIMalloc); // Class CCol
IID iid = IID_IRowset;
if(IFROW)
iid = IID_IRow;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
// Creates a column list from the Ctable
pcColumns = m_pTable->CountColumnsOnTable();
// Loop thru column types
for( count=1; count <= pcColumns; count++)
{
m_pTable->GetColInfo(count, NewCol);
// If first column is already numeric then were done
if( IsColNumWithScale(NewCol.GetProviderType(),
NewCol.GetScale()) )
break;
}
if (count > pcColumns)
{
odtLog << L"Couldn't find a numeric column for this test.\n";
return TEST_SKIPPED;
}
NativeTypesList.AddHead(NewCol.GetProviderTypeName());
// Create a table
if(!CHECK(g_Table3->CreateTable(NativeTypesList,
1, // Number of rows to insert
0, // Column to put index on
NULL, // Table name
PRIMARY), // Primary or secondary values
S_OK))
{
// Free memory in the list
NativeTypesList.RemoveAll();
return TEST_FAIL;
}
// Get the name of the table just created
pTableName = g_Table3->GetTableName();
// Get Numeric Scale
ColScale = NewCol.GetScale();
// Alloc Memory
pwszNumeric = (WCHAR *) m_pIMalloc->Alloc( sizeof(WCHAR) +
(sizeof(WCHAR)*(ColScale+3)) );
pwszSQLStmt = (WCHAR *) m_pIMalloc->Alloc( sizeof(WCHAR) + (sizeof(WCHAR) *
(wcslen(wszInsertInvalidValue) + wcslen(pTableName) + (ColScale+3))) );
// Create Numeric Valus out of range
wcscpy(pwszNumeric, L"1.");
for(count=1; count <= ColScale+1; count++)
wcscat(pwszNumeric, L"1");
// Format SQL Statement
swprintf(pwszSQLStmt, wszInsertInvalidValue, pTableName, pwszNumeric);
// Command to return a ICommand with Text Set
if( CHECK(g_Table3->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand), S_OK) )
fSuccess = TRUE;
// Free memory in the list
NativeTypesList.RemoveAll();
// Cleanup
SAFE_RELEASE_(pICommand);
// Free Memory
PROVIDER_FREE(pwszSQLStmt);
PROVIDER_FREE(pwszNumeric);
// Drop the table
g_Table3->DropTable();
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// }}
// {{ TCW_VAR_PROTOTYPE(57)
//*-----------------------------------------------------------------------
// @mfunc DB_E_ERRORSINCOMMAND - Invalid nodes in a command (37000)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_57()
{
BOOL fSuccess = FALSE; // Variation passed or failed
HRESULT hr = E_FAIL; // HRESULT
WCHAR * pTableName = NULL; // Name of the table
WCHAR * pwszSQLStmt = NULL; // SQL Statement
ICommand* pICommand = NULL; // ICommand Object
IID iid = IID_IRowset;
if(IFROW)
iid = IID_IRow;
// Alloc Memory
pwszSQLStmt = (WCHAR *) m_pIMalloc->Alloc( (sizeof(WCHAR) *
(wcslen(wszSelectBadSelect))) + sizeof(WCHAR) );
// Put the SQL statement together
wcscpy(pwszSQLStmt, wszSelectBadSelect);
// Command to return a ICommand with Text Set
TEST2C_(m_pTable->BuildCommand(pwszSQLStmt, iid,
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, &pICommand), DB_E_ERRORSINCOMMAND, DB_E_NOTABLE);
fSuccess = TRUE;
CLEANUP:
SAFE_RELEASE_(pICommand);
PROVIDER_FREE(pwszSQLStmt);
return fSuccess;
}
// }}
// {{ TCW_VAR_PROTOTYPE(58)
//--------------------------------------------------------------------
// @mfunc S_OK: riid = IUnknown
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_58()
{
ICommand* pICmd1=NULL;
IUnknown * pIUnknown=NULL;
EINTERFACE eI = ROWSET_INTERFACE;
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
if(IFROW)
{
eI = ROW_INTERFACE;
CHECK(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,
DBPROP_IRow,TRUE,DBPROPOPTIONS_REQUIRED), S_OK);
}
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(m_hr = pICmd1->Execute(NULL,IID_IUnknown,NULL,NULL,PPI &pIUnknown),S_OK));
COMPARE(DefaultObjectTesting(pIUnknown, eI), TRUE);
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIUnknown);
TRETURN
}
// }}
// }}
// {{ TCW_VAR_PROTOTYPE(59)
//--------------------------------------------------------------------
// @mfunc S_OK: cParam=0
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_59()
{
ICommand* pICmd1=NULL;
IUnknown * pIUnknown=NULL;
DBPARAMS pParams;
HRESULT hr = NOERROR;
EINTERFACE eI = ROWSET_INTERFACE;
if(IFROW)
eI = ROW_INTERFACE;
pParams.pData=NULL;
pParams.cParamSets=0;
pParams.hAccessor = DB_NULL_HACCESSOR;
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
if (FAILED(hr=PrepareCommand(pICmd1,PREPARE,1)))
CLEANUP(!CHECK(hr, E_NOINTERFACE));
CLEANUP(!CHECK(m_hr = Execute(pICmd1,PPI &pIUnknown,NULL,NULL,&pParams),S_OK));
COMPARE(DefaultObjectTesting(pIUnknown, eI), TRUE);
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIUnknown);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(60)
//--------------------------------------------------------------------
// @mfunc S_OK: select * from sp_tables
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_60()
{
ICommand* pICmd1=NULL;
IUnknown * pIUnk=NULL;
HRESULT hr = E_FAIL;
WCHAR wszSQL[]=L"sp_tables";
TESTBEGIN
// Due to the sp_tables proc used in the select this is a SQL Server specific test.
if (!g_fSqlServer)
{
odtLog << L"This test variation is only valid against SQL Server.\n";
TSKIPPED;
}
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSQL,SELECT_ALLFROMTBL,wszSQL)));
//since the property setting is logged in SetRowsetProperty, we don't have to check here
//Also, we don't want to get bunch of errors if they are not supported by the provider
SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_BOOKMARKS,TRUE, DBPROPOPTIONS_SETIFCHEAP, TRUE);
SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_IRowsetLocate,TRUE,DBPROPOPTIONS_SETIFCHEAP, TRUE);
SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_CANSCROLLBACKWARDS,TRUE,DBPROPOPTIONS_SETIFCHEAP, TRUE);
SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_CANFETCHBACKWARDS,TRUE,DBPROPOPTIONS_SETIFCHEAP, TRUE);
// currently not supported
SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_IRowsetScroll,TRUE,DBPROPOPTIONS_SETIFCHEAP, TRUE);
SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_OTHERUPDATEDELETE,TRUE,DBPROPOPTIONS_SETIFCHEAP, TRUE);
SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_IRowsetResynch,TRUE,DBPROPOPTIONS_SETIFCHEAP, TRUE);
SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_OWNINSERT,TRUE,DBPROPOPTIONS_SETIFCHEAP, TRUE);
SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_OWNUPDATEDELETE,TRUE,DBPROPOPTIONS_SETIFCHEAP, TRUE);
// Only supported against Kagera
if (g_fKagera)
SetRowsetProperty(pICmd1,DBPROPSET_PROVIDERROWSET,KAGPROP_POSITIONONNEWROW,TRUE,
DBPROPOPTIONS_SETIFCHEAP, TRUE);
// This may return DB_S_ERRORSOCCURRED because it wasn't cheap to set the properties
hr = Execute(pICmd1, PPI &pIUnk);
// Rowset and row object creation may return DB_S_ERRORSOCCURRED if the props above were not set
TEST2C_(hr, S_OK, DB_S_ERRORSOCCURRED);
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIUnk);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(61)
//--------------------------------------------------------------------
// @mfunc DB_E_ERRORSINCOMMAND: create current exisiting table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_61()
{
ICommand* pICmd1=NULL;
IUnknown * pIUnknown=NULL;
WCHAR wszSQL[]=L"create table %s (col1 str)";
WCHAR * pwszSQL=NULL;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN
// plus 1 for the null terminator
pwszSQL = (WCHAR *) m_pIMalloc->Alloc(
(wcslen(wszSQL) +
wcslen(m_pTable->GetTableName() + 1))
* sizeof(WCHAR *));
if(!pwszSQL)
goto CLEANUP;
swprintf(pwszSQL,wszSQL,m_pTable->GetTableName());
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSQL,SELECT_ALLFROMTBL,pwszSQL)));
//CLEANUP(FAILED(PrepareCommand(pICmd1,PREPARE,1)));
CLEANUP(!CHECK(m_hr = Execute(pICmd1,PPI &pIUnknown),DB_E_ERRORSINCOMMAND));
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIUnknown);
PROVIDER_FREE(pwszSQL);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(62)
//--------------------------------------------------------------------
// @mfunc Query TimeOut
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_62()
{
/*
Problem is that command time out is being reset
ADO said they request COMMAND_TIMEOUT as ifcheap
1)Open a rowset in fire-house mode. Keep the rowset around
2)On a command, set text and set time out
Execution of command should time out
3)On another command, set text
4) Re-execute command from 2, should still timeout
but wasn't (so that was the bug)
Not all properties are supported by access, so I'm making
it a sql server test only
*/
ICommand* pICmdRowset=NULL;
IUnknown * pIUnknownCmdRowset=NULL;
ICommand* pICmd1=NULL;
ICommand* pICmd2=NULL;
IUnknown * pIUnknown1=NULL;
IUnknown * pIUnknown2=NULL;
ICommandProperties * pICommandProperties=NULL;
DBPROPSET dbPropSet[1];
DBPROP dbProp[1];
ULONG i=0;
ULONG j=0;
HRESULT hr = S_OK;
LPWSTR pwszCmd = NULL;
LPWSTR pwszText = NULL;
LPWSTR pwszWaitFor = L"waitfor delay '000:00:20';"; // Wait 20s
BOOL bSqlServer=FALSE;
DBPROPIDSET rgDBPROPIDSET[1];
DBPROPID rgDBPROPID[1];
ULONG cDBPROPSET=0;
DBPROPSET* rgDBPROPSET=NULL;
// properties
IDBProperties* pIDBProp=NULL;
rgDBPROPIDSET[0].guidPropertySet = DBPROPSET_DATASOURCEINFO;
rgDBPROPIDSET[0].cPropertyIDs = 1;
rgDBPROPIDSET[0].rgPropertyIDs = &rgDBPROPID[0];
rgDBPROPID[0] = DBPROP_DBMSNAME;
// only test if we are on a sql server database
TESTBEGIN
if(!m_pIDBInitialize)
{
odtLog << L"m_pIDBInitialize is null\n";
return TEST_FAIL;
}
if(!CHECK(m_pIDBInitialize->QueryInterface(
IID_IDBProperties,
(void **)&pIDBProp),S_OK))
goto CLEANUP;
//if DBPROP_DBMSNAME is not supported skip the test
hr=pIDBProp->GetProperties(
1, rgDBPROPIDSET, &cDBPROPSET, &rgDBPROPSET);
if (hr==DB_E_ERRORSOCCURRED)
{
if(rgDBPROPSET[0].rgProperties[0].dwStatus!=DBPROPSTATUS_NOTSUPPORTED)
goto CLEANUP;
else
{
TPASS
goto CLEANUP;
}
}
for ( i = 0; i < cDBPROPSET; i++ )
{
if (rgDBPROPSET[0].guidPropertySet == DBPROPSET_DATASOURCEINFO )
{
for (ULONG j = 0 ; j < rgDBPROPSET[i].cProperties; j++ )
{
if (rgDBPROPSET[i].rgProperties[j].dwPropertyID == DBPROP_DBMSNAME)
{
if (!wcscmp (V_BSTR(&(rgDBPROPSET[i].rgProperties[j].vValue)), L"Microsoft SQL Server"))
{
bSqlServer = TRUE;
}
}
}
}
}
if(!bSqlServer)
{
odtLog << L"Not a sql server\n";
TPASS
goto CLEANUP;
}
//get rowset in firehose mode and keep it around
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmdRowset,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmdRowset,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(m_hr = pICmdRowset->Execute(NULL,IID_IUnknown,NULL,NULL,PPI &pIUnknownCmdRowset),S_OK));
//set text, then time out, then execute on this command
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
// Modify the commmand text for SQL Server to add a wait statement and force the timeout
if (CHECK(m_pTable->CreateSQLStmt(SELECT_LEFTOUTERJOIN, g_Table2->GetTableName(), &pwszText, NULL, NULL, 1, g_Table2), S_OK))
{
SAFE_ALLOC(pwszCmd, WCHAR, wcslen(pwszWaitFor) + wcslen(pwszText)+1);
if (pwszCmd)
{
wcscpy(pwszCmd, pwszWaitFor);
wcscat(pwszCmd, pwszText);
}
hr = m_pTable->BuildCommand(pwszCmd, IID_IRowset,
EXECUTE_NEVER, 0, NULL, NULL, NULL, NULL, &pICmd1);
}
TESTC_(hr, S_OK);
CLEANUP(!CHECK(pICmd1->QueryInterface(IID_ICommandProperties,(void**)&pICommandProperties),S_OK));
// status not set but have to check when it comes back
VariantInit(&(dbProp[0].vValue));
dbProp[0].dwPropertyID= DBPROP_COMMANDTIMEOUT;
dbProp[0].dwOptions = DBPROPOPTIONS_SETIFCHEAP;
dbProp[0].colid = DB_NULLID;
dbProp[0].vValue.vt = VT_I4;
V_I4(&dbProp[0].vValue) = 5;// set to 2 in ADO's bug
dbPropSet[0].guidPropertySet = DBPROPSET_ROWSET;
dbPropSet[0].cProperties = 1;
dbPropSet[0].rgProperties = dbProp;
if(!CHECK(pICommandProperties->SetProperties(1,dbPropSet),S_OK))
{
odtLog << L"Property ["
<< dbProp[0].dwPropertyID
<< L"] failure: "
<< dbProp[0].dwStatus
<< ENDL;
}
VariantClear(&(dbProp[0].vValue));
//Look for return code DB_E_ABORTLIMITREACHED
m_hr = Execute(pICmd1,PPI &pIUnknown1);
// This may actually succeed if a fast processor or server
if (SUCCEEDED(m_hr))
{
TESTW_(m_hr, DB_E_ABORTLIMITREACHED);
TESTC(pIUnknown1 != NULL);
SAFE_RELEASE(pIUnknown1);
}
else
TESTC_(m_hr, DB_E_ABORTLIMITREACHED);
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd2,NULL))
hr = m_pTable->BuildCommand(pwszCmd, IID_IRowset,
EXECUTE_NEVER, 0, NULL, NULL, NULL, NULL, &pICmd2);
TESTC_(hr, S_OK);
m_hr = Execute(pICmd1,PPI &pIUnknown1);
// This may actually succeed if a fast processor or server
if (SUCCEEDED(m_hr))
{
TESTW_(m_hr, DB_E_ABORTLIMITREACHED);
TESTC(pIUnknown1 != NULL);
SAFE_RELEASE(pIUnknown1);
}
else
TESTC_(m_hr, DB_E_ABORTLIMITREACHED);
TPASS
CLEANUP:
SAFE_FREE(pwszCmd);
SAFE_FREE(pwszText);
SAFE_RELEASE(pIDBProp);
FreeProperties(&cDBPROPSET, &rgDBPROPSET);
SAFE_RELEASE(pIUnknown1);
SAFE_RELEASE(pIUnknown2);
SAFE_RELEASE(pIUnknownCmdRowset);
SAFE_RELEASE(pICmdRowset);
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pICmd2);
SAFE_RELEASE(pICommandProperties);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(63)
//--------------------------------------------------------------------
// @mfunc Query TimeOut
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_63()
{
/*
Problem is that timeout return code is being returned as
DB_E_ERRORSINCOMMAND instead of DB_E_ABORTLIMITREACHED
I asked ADO if the previous variation would cover
this bug and he said no, so that is why it is here.
ADO said all this bug is about is setting time out,
and making sure the right error return code is
set back.
He said they request COMMAND_TIMEOUT as ifcheap
Not all properties are supported by access, so I'm making
it a sql server test only
*/
ICommand* pICmd1=NULL;
IUnknown * pIUnknown1=NULL;
ICommandProperties * pICommandProperties=NULL;
DBPROPSET dbPropSet[1];
DBPROP dbProp[1];
TESTBEGIN
ULONG i=0;
ULONG j=0;
HRESULT hr = S_OK;
LPWSTR pwszCmd = NULL;
LPWSTR pwszText = NULL;
LPWSTR pwszWaitFor = L"waitfor delay '000:00:20';"; // Wait 20s
BOOL bSqlServer=FALSE;
DBPROPIDSET rgDBPROPIDSET[1];
DBPROPID rgDBPROPID[1];
ULONG cDBPROPSET=0;
DBPROPSET* rgDBPROPSET=NULL;
time_t tstart = 0;
time_t tend = 0;
LONG timeout = 5; // Set timeout to 5s, rather than 2s, to allow better resolution.
// properties
IDBProperties* pIDBProp=NULL;
rgDBPROPIDSET[0].guidPropertySet = DBPROPSET_DATASOURCEINFO;
rgDBPROPIDSET[0].cPropertyIDs = 1;
rgDBPROPIDSET[0].rgPropertyIDs = rgDBPROPID;
rgDBPROPID[0] = DBPROP_DBMSNAME;
// only test if we are on a sql server database
if(!m_pIDBInitialize)
{
odtLog << L"m_pIDBInitialize is null\n";
return TEST_FAIL;
}
if(!CHECK(m_pIDBInitialize->QueryInterface(
IID_IDBProperties,
(void **)&pIDBProp),S_OK))
goto CLEANUP;
//if DBPROP_DBMSNAME is not supported skip the test
hr=pIDBProp->GetProperties(
1, rgDBPROPIDSET, &cDBPROPSET, &rgDBPROPSET);
if (hr==DB_E_ERRORSOCCURRED)
{
if(rgDBPROPSET[0].rgProperties[0].dwStatus!=DBPROPSTATUS_NOTSUPPORTED)
goto CLEANUP;
else
{
TPASS
goto CLEANUP;
}
}
for ( i = 0; i < cDBPROPSET; i++ )
{
if (rgDBPROPSET[0].guidPropertySet == DBPROPSET_DATASOURCEINFO )
{
for (ULONG j = 0 ; j < rgDBPROPSET[i].cProperties; j++ )
{
if (rgDBPROPSET[i].rgProperties[j].dwPropertyID == DBPROP_DBMSNAME)
{
if (!wcscmp (V_BSTR(&(rgDBPROPSET[i].rgProperties[j].vValue)), L"Microsoft SQL Server"))
{
bSqlServer = TRUE;
}
}
}
}
}
if(!bSqlServer)
{
odtLog << L"Not a sql server\n";
TSKIPPED;
goto CLEANUP;
}
//set text, then time out, then execute on this command
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,g_Table2->GetTableName(),
eSELECT,SELECT_LEFTOUTERJOIN,NULL,NULL,NULL,g_Table2)));
CLEANUP(!CHECK(pICmd1->QueryInterface(IID_ICommandProperties,(void**)&pICommandProperties),S_OK));
// status not set but have to check when it comes back
VariantInit(&(dbProp[0].vValue));
dbProp[0].dwPropertyID= DBPROP_COMMANDTIMEOUT;
dbProp[0].dwOptions = DBPROPOPTIONS_SETIFCHEAP;
dbProp[0].colid = DB_NULLID;
dbProp[0].vValue.vt = VT_I4;
V_I4(&dbProp[0].vValue) = timeout;// set to 2 in ADO's bug
dbPropSet[0].guidPropertySet = DBPROPSET_ROWSET;
dbPropSet[0].cProperties = 1;
dbPropSet[0].rgProperties = dbProp;
if(!CHECK(pICommandProperties->SetProperties(1,dbPropSet),S_OK))
{
odtLog << L"Property ["
<< dbProp[0].dwPropertyID
<< L"] failure: "
<< dbProp[0].dwStatus
<< ENDL;
}
VariantClear(&(dbProp[0].vValue));
// Get time
time(&tstart);
m_hr = Execute(pICmd1,PPI &pIUnknown1);
// Get time
time(&tend);
// Make sure time diff is not greater than timeout
TESTC(tend-tstart <= timeout+1);
// Look for return code DB_E_ABORTLIMITREACHED
// This may actually succeed if a fast processor or server
if (SUCCEEDED(m_hr))
{
TESTW_(m_hr, DB_E_ABORTLIMITREACHED);
TESTC(pIUnknown1 != NULL);
}
else
TESTC_(m_hr, DB_E_ABORTLIMITREACHED);
TPASS
CLEANUP:
SAFE_FREE(pwszCmd);
SAFE_FREE(pwszText);
SAFE_RELEASE(pIDBProp);
FreeProperties(&cDBPROPSET, &rgDBPROPSET);
SAFE_RELEASE(pIUnknown1);
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pICommandProperties);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(64)
//--------------------------------------------------------------------
// @mfunc Firehose mode
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_64()
{
/*
Verify that when the first statement
is opened in one cursor mode that other statements
can be opened in other cursor modes
Sub Bug_FieldEnumeratorError2()
Dim rs As New Recordset, rs2 As New Recordset
Dim conn As New Connection
On Error GoTo errfound
conn.Open "adotsql65", "adolab", "adolab"
rs.Open "select * from azpt1dao", conn // Forward Only/Read Only
rs2.Open "select * from azpt1dao", conn, adOpenStatic, adLockOptimistic
rs2.Close
rs2.Open "select * from azpt1dao", conn, adOpenStatic, adLockOptimistic '<-- error here
rs2.Close
Exit Sub
1) rs is opened in firehose mode
2) rs2 causes another connection to be opened and
the first rs2.Open statement succeeds
3) rs2 is closed and the connection is freed
4)rs2.open (second case) - for some reason
Kagera isn't detecting that the first statement
is opened in firehose mode and tries to open the
cursor on the first connection
adOpenStatic:
OWNINSERT
OWNUPDATEDELETE
IRowsetLocate
CANSCROLLBACKWARDS
CANHOLDROWS
IRowsetResynch
REMOVEDELETED
KAGPROP_POSITIONONNEWROW
adLockOptimistic:
IRowsetChange
UPDATABILITY (
DBPROPVAL_UP_INSERT |
DBPROPVAL_UP_DELETE |
DBPROPVAL_UP_CHANGE)
CONCURRENCY (
KAGPROP_CONCUR_VALUES |
KAGPROP_CONCUR_ROWVER)
every ADO command gets MAXROWS==1, and COMMANDTIMEOUT==???
really don't know which props are supposed to be
required and which setifcheap
Not all properties are supported by access, so I'm making
it a sql server test only
*/
ICommand* pICmd1=NULL;
IUnknown * pIUnknown1=NULL;
ICommand* pICmd2=NULL;
IUnknown * pIUnknown2=NULL;
ICommandProperties * pICommandProperties1=NULL;
ICommandProperties * pICommandProperties2=NULL;
DBPROPSET* rgDBPROPSET=NULL;
IDBProperties* pIDBProp=NULL;
HRESULT hr=E_FAIL;
DBPROPSET dbPropSet[1];
DBPROP dbProp[1];
ULONG i=0;
ULONG j=0;
ULONG cDBPROPSET=0;
TESTBEGIN
//set text, then time out, then execute on this command
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(hr=SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(hr=pICmd1->QueryInterface(IID_ICommandProperties,(void**)&pICommandProperties1),S_OK));
// status not set but have to check when it comes back
VariantInit(&(dbProp[0].vValue));
dbProp[0].dwPropertyID= DBPROP_COMMANDTIMEOUT;
dbProp[0].dwOptions = DBPROPOPTIONS_SETIFCHEAP;
dbProp[0].colid = DB_NULLID;
dbProp[0].vValue.vt = VT_I4;
V_I4(&dbProp[0].vValue) = 100;// set to 2 in ADO's bug
dbPropSet[0].guidPropertySet = DBPROPSET_ROWSET;
dbPropSet[0].cProperties = 1;
dbPropSet[0].rgProperties = dbProp;
// Not all providers support command timeout. It's not critical if not supported.
if(FAILED(hr=pICommandProperties1->SetProperties(1,dbPropSet)))
{
CHECK(hr,DB_E_ERRORSOCCURRED);
if (dbProp[0].dwStatus != DBPROPSTATUS_NOTSUPPORTED)
{
odtLog << L"Property ["
<< dbProp[0].dwPropertyID
<< L"] failure: "
<< dbProp[0].dwStatus
<< ENDL;
}
}
VariantClear(&(dbProp[0].vValue));
// status not set but have to check when it comes back
VariantInit(&(dbProp[0].vValue));
dbProp[0].dwPropertyID=DBPROP_MAXROWS;
dbProp[0].dwOptions = DBPROPOPTIONS_SETIFCHEAP;
dbProp[0].colid = DB_NULLID;
dbProp[0].vValue.vt = VT_I4;
V_I4(&dbProp[0].vValue) = 1; // set to 1 in ADO's bug
dbPropSet[0].guidPropertySet = DBPROPSET_ROWSET;
dbPropSet[0].cProperties = 1;
dbPropSet[0].rgProperties = dbProp;
// We don't really care if this property gets set if it's not supported
if(FAILED(hr=pICommandProperties1->SetProperties(1,dbPropSet)))
{
CHECK(hr,DB_E_ERRORSOCCURRED);
if (dbProp[0].dwStatus != DBPROPSTATUS_NOTSUPPORTED &&
dbProp[0].dwStatus != DBPROPSTATUS_NOTSETTABLE)
{
odtLog << L"Property ["
<< dbProp[0].dwPropertyID
<< L"] failure: "
<< dbProp[0].dwStatus
<< ENDL;
}
}
VariantClear(&(dbProp[0].vValue));
// status not set but have to check when it comes back
VariantInit(&(dbProp[0].vValue));
dbProp[0].dwPropertyID=DBPROP_UPDATABILITY;
dbProp[0].dwOptions = DBPROPOPTIONS_SETIFCHEAP;
dbProp[0].colid = DB_NULLID;
dbProp[0].vValue.vt = VT_I4;
V_I4(&dbProp[0].vValue) = 0; // Not updatable
dbPropSet[0].guidPropertySet = DBPROPSET_ROWSET;
dbPropSet[0].cProperties = 1;
dbPropSet[0].rgProperties = dbProp;
// Set the updatability property. This will fail if not supported, but we don't care
pICommandProperties1->SetProperties(1,dbPropSet);
VariantClear(&(dbProp[0].vValue));
if (g_fKagera)
{
// status not set but have to check when it comes back
VariantInit(&(dbProp[0].vValue));
dbProp[0].dwPropertyID=KAGPROP_CONCURRENCY;
dbProp[0].dwOptions = DBPROPOPTIONS_SETIFCHEAP;
dbProp[0].colid = DB_NULLID;
dbProp[0].vValue.vt = VT_I4;
V_I4(&dbProp[0].vValue) = KAGPROPVAL_CONCUR_READ_ONLY;
dbPropSet[0].guidPropertySet = DBPROPSET_PROVIDERROWSET;
dbPropSet[0].cProperties = 1;
dbPropSet[0].rgProperties = dbProp;
if(FAILED(hr=pICommandProperties1->SetProperties(1,dbPropSet)))
{
CHECK(hr,S_OK);
odtLog << L"Property ["
<< dbProp[0].dwPropertyID
<< L"] failure: "
<< dbProp[0].dwStatus
<< ENDL;
}
VariantClear(&(dbProp[0].vValue));
}
// We want to set a bunch of properties that will likely force a FORWARD ONLY/READ ONLY cursor, but we need to
// igore the return code in case one of the properties isn't supported.
// SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_OWNINSERT, FALSE, DBPROPOPTIONS_REQUIRED, FALSE);
// SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_OWNUPDATEDELETE,FALSE, DBPROPOPTIONS_REQUIRED, FALSE);
SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_IRowsetLocate,FALSE, DBPROPOPTIONS_REQUIRED, FALSE);
SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_CANSCROLLBACKWARDS,FALSE, DBPROPOPTIONS_REQUIRED, FALSE);
SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_CANHOLDROWS,FALSE, DBPROPOPTIONS_REQUIRED, FALSE);
SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_IRowsetResynch,FALSE, DBPROPOPTIONS_REQUIRED, FALSE);
// SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_REMOVEDELETED,FALSE, DBPROPOPTIONS_REQUIRED, FALSE);
SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_IRowsetChange,FALSE, DBPROPOPTIONS_REQUIRED, FALSE);
SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_BOOKMARKS,FALSE, DBPROPOPTIONS_REQUIRED, FALSE);
SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,DBPROP_CANFETCHBACKWARDS,FALSE, DBPROPOPTIONS_REQUIRED, FALSE);
if (g_fKagera)
CHECK(hr=SetRowsetProperty(pICmd1,DBPROPSET_PROVIDERROWSET,KAGPROP_POSITIONONNEWROW,FALSE, DBPROPOPTIONS_REQUIRED, TRUE),S_OK);
// We require a FO/RO cursor here, so if Execute fails we can't proceed with the test
hr = Execute(pICmd1,PPI &pIUnknown1);
if(IFROW)
TESTC_(hr, S_OK);
// A generic provider may not support FO/RO. This is DB_E/S_ERRORSOCCURRED.
if (hr == DB_E_ERRORSOCCURRED || hr == DB_S_ERRORSOCCURRED)
{
odtLog << L"Couldn't obtain Forward Only/Read Only rowset against this provider.\n";
TSKIPPED;
}
// Should be successful
TEST2C_(hr, S_OK, DB_S_ERRORSOCCURRED);
//set text, then time out, then execute on this command
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd2,NULL))
CLEANUP(FAILED(hr=SetCommandText(m_pIMalloc,pICmd2,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(hr=pICmd2->QueryInterface(IID_ICommandProperties,(void**)&pICommandProperties2),S_OK));
// status not set but have to check when it comes back
VariantInit(&(dbProp[0].vValue));
dbProp[0].dwPropertyID=DBPROP_COMMANDTIMEOUT;
dbProp[0].dwOptions = DBPROPOPTIONS_SETIFCHEAP;
dbProp[0].colid = DB_NULLID;
dbProp[0].vValue.vt = VT_I4;
V_I4(&dbProp[0].vValue) = 100;
dbPropSet[0].guidPropertySet = DBPROPSET_ROWSET;
dbPropSet[0].cProperties = 1;
dbPropSet[0].rgProperties = dbProp;
if(FAILED(hr=pICommandProperties2->SetProperties(1,dbPropSet)))
{
CHECK(hr,DB_E_ERRORSOCCURRED);
if (dbProp[0].dwStatus != DBPROPSTATUS_NOTSUPPORTED)
{
odtLog << L"Property ["
<< dbProp[0].dwPropertyID
<< L"] failure: "
<< dbProp[0].dwStatus
<< ENDL;
}
}
VariantClear(&(dbProp[0].vValue));
// status not set but have to check when it comes back
VariantInit(&(dbProp[0].vValue));
dbProp[0].dwPropertyID=DBPROP_MAXROWS;
dbProp[0].dwOptions = DBPROPOPTIONS_SETIFCHEAP;
dbProp[0].colid = DB_NULLID;
dbProp[0].vValue.vt = VT_I4;
V_I4(&dbProp[0].vValue) = 1;
dbPropSet[0].guidPropertySet = DBPROPSET_ROWSET;
dbPropSet[0].cProperties = 1;
dbPropSet[0].rgProperties = dbProp;
// We don't really care if this property gets set if it's not supported
if(FAILED(hr=pICommandProperties2->SetProperties(1,dbPropSet)))
{
CHECK(hr,DB_E_ERRORSOCCURRED);
if (dbProp[0].dwStatus != DBPROPSTATUS_NOTSUPPORTED &&
dbProp[0].dwStatus != DBPROPSTATUS_NOTSETTABLE)
{
odtLog << L"Property ["
<< dbProp[0].dwPropertyID
<< L"] failure: "
<< dbProp[0].dwStatus
<< ENDL;
}
}
VariantClear(&(dbProp[0].vValue));
// status not set but have to check when it comes back
VariantInit(&(dbProp[0].vValue));
dbProp[0].dwPropertyID=DBPROP_UPDATABILITY;
dbProp[0].dwOptions = DBPROPOPTIONS_SETIFCHEAP;
dbProp[0].colid = DB_NULLID;
dbProp[0].vValue.vt = VT_I4;
V_I4(&dbProp[0].vValue) =
DBPROPVAL_UP_INSERT |
DBPROPVAL_UP_DELETE |
DBPROPVAL_UP_CHANGE;
dbPropSet[0].guidPropertySet = DBPROPSET_ROWSET;
dbPropSet[0].cProperties = 1;
dbPropSet[0].rgProperties = dbProp;
pICommandProperties2->SetProperties(1,dbPropSet);
VariantClear(&(dbProp[0].vValue));
if (g_fKagera)
{
// status not set but have to check when it comes back
VariantInit(&(dbProp[0].vValue));
dbProp[0].dwPropertyID=KAGPROP_CONCURRENCY;
dbProp[0].dwOptions = DBPROPOPTIONS_SETIFCHEAP;
dbProp[0].colid = DB_NULLID;
dbProp[0].vValue.vt = VT_I4;
V_I4(&dbProp[0].vValue) =
KAGPROPVAL_CONCUR_VALUES |
KAGPROPVAL_CONCUR_ROWVER;
dbPropSet[0].guidPropertySet = DBPROPSET_PROVIDERROWSET;
dbPropSet[0].cProperties = 1;
dbPropSet[0].rgProperties = dbProp;
if(FAILED(hr=pICommandProperties2->SetProperties(1,dbPropSet)))
{
CHECK(hr,S_OK);
odtLog << L"Property ["
<< dbProp[0].dwPropertyID
<< L"] failure: "
<< dbProp[0].dwStatus
<< ENDL;
}
VariantClear(&(dbProp[0].vValue));
}
// We want to set a property that will likely force a non-FORWARD ONLY/non-READ ONLY cursor, but we need to
// igore the return code in case one of the properties isn't supported.
hr = SetRowsetProperty(pICmd2,DBPROPSET_ROWSET,DBPROP_CANSCROLLBACKWARDS,TRUE, DBPROPOPTIONS_REQUIRED, FALSE);
if (!SUCCEEDED(hr))
hr = SetRowsetProperty(pICmd2,DBPROPSET_ROWSET,DBPROP_OWNUPDATEDELETE,TRUE, DBPROPOPTIONS_REQUIRED, FALSE);
if (!SUCCEEDED(hr))
hr = SetRowsetProperty(pICmd2,DBPROPSET_ROWSET,DBPROP_IRowsetLocate,TRUE, DBPROPOPTIONS_REQUIRED, FALSE);
if (!SUCCEEDED(hr))
hr = SetRowsetProperty(pICmd2,DBPROPSET_ROWSET,DBPROP_OWNINSERT,TRUE, DBPROPOPTIONS_REQUIRED, FALSE);
if (!SUCCEEDED(hr))
hr = SetRowsetProperty(pICmd2,DBPROPSET_ROWSET,DBPROP_CANHOLDROWS,TRUE, DBPROPOPTIONS_REQUIRED, FALSE);
if (!SUCCEEDED(hr))
hr = SetRowsetProperty(pICmd2,DBPROPSET_ROWSET,DBPROP_IRowsetResynch,TRUE, DBPROPOPTIONS_REQUIRED, FALSE);
if (!SUCCEEDED(hr))
hr = SetRowsetProperty(pICmd2,DBPROPSET_ROWSET,DBPROP_REMOVEDELETED,TRUE, DBPROPOPTIONS_REQUIRED, FALSE);
if (!SUCCEEDED(hr))
hr = SetRowsetProperty(pICmd2,DBPROPSET_ROWSET,DBPROP_IRowsetChange,TRUE, DBPROPOPTIONS_REQUIRED, FALSE);
if (g_fKagera && !SUCCEEDED(hr))
CHECK(hr=SetRowsetProperty(pICmd2,DBPROPSET_PROVIDERROWSET,KAGPROP_POSITIONONNEWROW,TRUE,
DBPROPOPTIONS_REQUIRED, TRUE),S_OK);
CLEANUP(!CHECK(hr = Execute(pICmd2,PPI &pIUnknown2),S_OK ));
COMPARE(DefaultObjectTesting(pIUnknown2, IFROW ? ROW_INTERFACE : ROWSET_INTERFACE), TRUE);
SAFE_RELEASE(pIUnknown2);
// Failure should repro here if it's going to
CLEANUP(!CHECK(hr = Execute(pICmd2,PPI &pIUnknown2),S_OK ));
TPASS
CLEANUP:
FreeProperties(&cDBPROPSET, &rgDBPROPSET);
SAFE_RELEASE(pIDBProp);
SAFE_RELEASE(pIUnknown1);
SAFE_RELEASE(pIUnknown2);
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pICmd2);
SAFE_RELEASE(pICommandProperties1);
SAFE_RELEASE(pICommandProperties2);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(65)
//*-----------------------------------------------------------------------
// @mfunc Aggregation - Open a rowset on aggregated command
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_65()
{
ICommand * pIAggCommand = NULL;
IRowset * pIRowset = NULL;
TESTRESULT testresult = TEST_FAIL;
HRESULT hr = E_FAIL, hrSetProp = E_FAIL;
DBORDINAL cRowsetCols;
DBORDINAL * rgTableColOrds = NULL;
IUnknown * pIAggUnknown = NULL;
IUnknown* pIUnk = NULL;
IID iid = IID_IRowset;
if(IFROW)
iid = IID_IRow;
CAggregate Aggregate;
// Create a new ICommandText object aggregated from IDBCreateCommand object.
hr = m_pIDBCreateCommand->CreateCommand(&Aggregate, IID_IUnknown,
(IUnknown **)&pIAggUnknown);
Aggregate.SetUnkInner(pIAggUnknown);
TESTC(Aggregate.VerifyAggregationQI(hr, IID_ICommand));
// See if we can get ICommandText off our aggregated object
TESTC_(Aggregate.QueryInterface(IID_ICommand, (void **)&pIAggCommand), S_OK);
// Kagera can't retrieve BLOB data without IRowsetLocate on.
// if (g_fKagera)
// CHECK(hrSetProp = SetRowsetProperty(pIAggCommand, DBPROPSET_ROWSET, DBPROP_IRowsetLocate, TRUE), S_OK);
if (g_fKagera && SupportedProperty(DBPROP_ACCESSORDER, DBPROPSET_ROWSET, m_pThisTestModule->m_pIUnknown,SESSION_INTERFACE))
hrSetProp = SetRowsetProperty(pIAggCommand, DBPROPSET_ROWSET, DBPROP_ACCESSORDER, (LONG_PTR)DBPROPVAL_AO_RANDOM);
// Set command text and execute
TESTC_(m_pTable->ExecuteCommand(SELECT_VALIDATIONORDER, iid, NULL,
NULL, &cRowsetCols, (DB_LORDINAL **)&rgTableColOrds, EXECUTE_IFNOERROR, 0, NULL, NULL, (IUnknown**)&pIUnk,
&pIAggCommand), S_OK);
if(IFROWSET)
TESTC_(VerifyRowset(IID_IRowset, (IUnknown *)pIUnk, 1,
cRowsetCols, rgTableColOrds, FALSE), S_OK);
if(IFROW)
TESTC_(VerifyRowObj(IID_IRow, (IUnknown *)pIUnk, 1,
cRowsetCols, rgTableColOrds, FALSE), S_OK);
// Now release our aggregated command text object and IUnknown
// We expect the aggregated object to go away when the last ref is released.
SAFE_RELEASE(pIUnk);
// Reset ACCESSORDER
if (hrSetProp == S_OK)
CHECK(SetRowsetProperty(pIAggCommand, DBPROPSET_ROWSET, DBPROP_ACCESSORDER, (LONG_PTR)DBPROPVAL_AO_RANDOM, DBPROPOPTIONS_OPTIONAL), S_OK);
SAFE_RELEASE(pIAggCommand);
TESTC(Aggregate.GetRefCount()==1); // Object gone!
testresult = TEST_PASS;
CLEANUP:
SAFE_FREE(rgTableColOrds);
SAFE_RELEASE(pIUnk);
// Reset again just in case of failure above.
if (hrSetProp == S_OK && pIAggCommand)
CHECK(SetRowsetProperty(pIAggCommand, DBPROPSET_ROWSET, DBPROP_IRowsetLocate, TRUE, DBPROPOPTIONS_OPTIONAL), S_OK);
SAFE_RELEASE(pIAggUnknown);
SAFE_RELEASE(pIAggCommand);
return testresult;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(66)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Select, IID_NULL, ppRowset NULL
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_66()
{
ICommand* pICmd1=NULL;
DBROWCOUNT cRowsAffected=0;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(FAILED(PrepareCommand(pICmd1,PREPARE,1)));
CLEANUP(!CHECK(m_hr = pICmd1->Execute(NULL,IID_NULL,NULL,&cRowsAffected,NULL),S_OK));
// Note for a select stmt cRowsAffected will be "undefined" per spec, so we don't test it.
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(67)
//*-----------------------------------------------------------------------
// @mfunc Test all IID's of object
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_67()
{
IUnknown* pIUnknown = NULL;
ICommand* pICmd1 = NULL;
EINTERFACE eI = ROWSET_INTERFACE;
if(IFROW)
eI = ROW_INTERFACE;
TESTBEGIN;
//Obtain the Rowset IIDs
ULONG i, cRowsetIIDs = 0;
INTERFACEMAP* rgRowsetIIDs = NULL;
TESTC(GetInterfaceArray(eI, &cRowsetIIDs, &rgRowsetIIDs));
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,NULL));
if(IFROW)
{
CHECK(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,
DBPROP_IRow,TRUE,DBPROPOPTIONS_REQUIRED), S_OK);
}
//Loop through all rowset IIDs...
for(i=0; i<cRowsetIIDs; i++)
{
odtLog << rgRowsetIIDs[i].pwszName << L"\n";
//Asking for IID_I* is requesting a rowset that supports this interface
//This is implicilty like requesting DBPROP_I* ahead of time...
TESTC_(SetCommandText(m_pIMalloc,pICmd1,g_Table2,NULL,eSELECT,SELECT_ALLFROMTBL,NULL), S_OK);
TEST2C_(m_hr=pICmd1->Execute(NULL,*rgRowsetIIDs[i].pIID,NULL,NULL,&pIUnknown),S_OK, E_NOINTERFACE);
//Success, verify this interface...
if(m_hr == S_OK)
{
if(!ValidInterface(*rgRowsetIIDs[i].pIID, pIUnknown))
TERROR(L"Interface Incorrect for " << GetInterfaceName(*rgRowsetIIDs[i].pIID) << "\n");
TESTC(DefaultObjectTesting(pIUnknown, eI));
}
else
{
//Make sure this is allowed to not be required
TCOMPARE_(!rgRowsetIIDs[i].fMandatory);
}
SAFE_RELEASE(pIUnknown);
}
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIUnknown);
TRETURN;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(68)
//*-----------------------------------------------------------------------
// @mfunc E_NOINTERFACE - Ask for unsupported interface with ppRowset == NULL
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_68()
{
ICommand* pICmd1=NULL;
HRESULT hrExec = E_FAIL;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
hrExec = pICmd1->Execute(NULL,IID_IDBProperties,NULL,NULL,NULL);
// Depending on checking order, provider may return either failure
TEST2C_(hrExec, E_NOINTERFACE, E_INVALIDARG);
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(69)
//*-----------------------------------------------------------------------
// @mfunc DB_E_INTEGRITYVIOLATION - Insert a duplicate key value
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_69()
{
DBROWCOUNT cRowsAffected=0;
ICommand* pICmd1=NULL;
CCol ColIndex;
DBORDINAL ulIndexCol = 1;
HRESULT hrCreateIndex = E_FAIL;
TESTBEGIN;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
{
TSKIPPED;
}
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,NULL));
// If the index column happens to be an autoincrement or non-updatable column
// then the insert query below will not contain that column and the integrity
// violation will not occur. To prevent this create another index.
ulIndexCol = g_Table2->GetIndexColumn();
TESTC_(g_Table2->GetColInfo(ulIndexCol, ColIndex), S_OK);
if (ColIndex.GetAutoInc())
{
ULONG iNewIndex;
for (iNewIndex = 1; iNewIndex <= g_Table2->CountColumnsOnTable();
iNewIndex++)
{
if (iNewIndex == ulIndexCol)
continue;
TESTC_(g_Table2->GetColInfo(iNewIndex, ColIndex), S_OK);
if (!ColIndex.GetAutoInc() && ColIndex.GetUpdateable())
break;
}
TESTC(iNewIndex <= g_Table2->CountColumnsOnTable());
// Since there's already an index with the default name we need to
// create one with a new name.
TESTC_(g_Table2->GetColInfo(iNewIndex, ColIndex), S_OK);
hrCreateIndex = g_Table2->CreateIndex(iNewIndex, UNIQUE, ColIndex.GetColName());
TESTC_(hrCreateIndex, S_OK);
}
// Cause the CTable object to create a duplicate row. Note g_Table2 has an
// index so we can't insert a dupicate row.
g_Table2->SubtractRow();
if(S_OK == (m_hr = SetCommandText(m_pIMalloc,pICmd1,g_Table2,NULL,eINSERT,NO_QUERY,NULL)))
m_hr = pICmd1->Execute(NULL,IID_NULL,NULL,&cRowsAffected,NULL);
// Set CTable to have proper row count
g_Table2->AddRow();
TESTC_(m_hr, DB_E_INTEGRITYVIOLATION);
if (cRowsAffected != DB_COUNTUNAVAILABLE)
TESTC(cRowsAffected == 0);
TPASS;
CLEANUP:
// The extra index if will be dropped when the table is dropped
SAFE_RELEASE(pICmd1);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(70)
//*-----------------------------------------------------------------------
// @mfunc S_OK - select with qualified name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_70()
{
ICommand* pICmd1=NULL;
LPWSTR pwszTableName = NULL;
LPWSTR pwszQualifiedName = NULL;
LPWSTR pwszCatalogName = NULL;
LPWSTR pwszSchemaName = NULL;
DBORDINAL cRowsetCols;
DBORDINAL * rgTableColOrds = NULL;
IUnknown * pIUnk = NULL;
IID iid = IID_IRowset;
if(IFROW)
iid = IID_IRow;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN;
pwszTableName = wcsDuplicate(m_pTable->GetTableName());
TESTC(pwszTableName != NULL);
GetQualifierNames(m_pThisTestModule->m_pIUnknown2, pwszTableName,
&pwszCatalogName, &pwszSchemaName);
TESTC_(m_pTable->GetQualifiedName(pwszCatalogName, pwszSchemaName,
pwszTableName,&pwszQualifiedName), S_OK);
m_pTable->SetTableName(pwszQualifiedName);
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,NULL));
TESTC_(m_pTable->ExecuteCommand(SELECT_VALIDATIONORDER, iid, NULL,
NULL, &cRowsetCols, (DB_LORDINAL **)&rgTableColOrds, EXECUTE_IFNOERROR, 0, NULL, NULL, (IUnknown**)&pIUnk,
&pICmd1), S_OK);
if(IFROWSET)
TESTC_(VerifyRowset(IID_IRowset, (IUnknown *)pIUnk, 1,
cRowsetCols, rgTableColOrds, FALSE), S_OK);
if(IFROW)
TESTC_(VerifyRowObj(IID_IRow, (IUnknown *)pIUnk, 1,
cRowsetCols, rgTableColOrds, FALSE), S_OK);
TPASS;
CLEANUP:
m_pTable->SetTableName(pwszTableName);
SAFE_RELEASE(pIUnk);
SAFE_RELEASE(pICmd1);
SAFE_FREE(pwszTableName);
SAFE_FREE(pwszQualifiedName);
SAFE_FREE(pwszCatalogName);
SAFE_FREE(pwszSchemaName);
SAFE_FREE(rgTableColOrds);
TRETURN;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(71)
//*-----------------------------------------------------------------------
// @mfunc S_OK - select with quoted name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_71()
{
ICommand* pICmd1=NULL;
LPWSTR pwszTableName = NULL;
LPWSTR pwszQuotedName = NULL;
DBORDINAL cRowsetCols;
DBORDINAL * rgTableColOrds = NULL;
IUnknown * pIUnk = NULL;
IID iid = IID_IRowset;
if(IFROW)
iid = IID_IRow;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN;
pwszTableName = wcsDuplicate(m_pTable->GetTableName());
TESTC(pwszTableName != NULL);
TESTC_(m_pTable->GetQuotedName(pwszTableName,&pwszQuotedName), S_OK);
m_pTable->SetTableName(pwszQuotedName);
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,NULL));
TESTC_(m_pTable->ExecuteCommand(SELECT_VALIDATIONORDER, iid, NULL,
NULL, &cRowsetCols, (DB_LORDINAL **)&rgTableColOrds, EXECUTE_IFNOERROR, 0, NULL, NULL, (IUnknown**)&pIUnk,
&pICmd1), S_OK);
if(IFROWSET)
TESTC_(VerifyRowset(IID_IRowset, (IUnknown *)pIUnk, 1,
cRowsetCols, rgTableColOrds, FALSE), S_OK);
if(IFROW)
TESTC_(VerifyRowObj(IID_IRow, (IUnknown *)pIUnk, 1,
cRowsetCols, rgTableColOrds, FALSE), S_OK);
TPASS;
CLEANUP:
m_pTable->SetTableName(pwszTableName);
SAFE_RELEASE(pIUnk);
SAFE_RELEASE(pICmd1);
SAFE_FREE(pwszTableName);
SAFE_FREE(pwszQuotedName);
TRETURN;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(72)
//*-----------------------------------------------------------------------
// @mfunc S_OK - select distinct
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_72()
{
ICommand* pICmd1=NULL;
ICommandText * pICommandText = NULL;
IAccessor * pIAccessor = NULL;
DBORDINAL cCols;
DBCOUNTITEM cRowsObtained;
ULONG iCol;
LONG cRows = LONG_MAX;
HROW * phRows = NULL;
DB_LORDINAL * pCols = NULL;
IRowset * pIRowset = NULL;
WCHAR * pwszSqlStmt = NULL;
HRESULT hr, hrExec;
ULONG iRow, jRow;
BOOL fDup = FALSE;
BYTE * pData1 = NULL;
BYTE * pData2 = NULL;
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
DBBINDING * pBindings = NULL;
DBCOUNTITEM cBindings;
DBLENGTH cbRowSize;
ULONG ulHiddenColumns = 0;
TESTBEGIN;
ONLYROWSETVAR;
// If the provider doesn't understand SQL then skip test if not using ini file
if(m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE &&
!GetModInfo()->GetFileName())
{
odtLog << L"Provider doesn't support SQL and not using ini file.\n";
return TEST_SKIPPED;
}
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,NULL));
TESTC(VerifyInterface(pICmd1, IID_ICommandText,
COMMAND_INTERFACE, (IUnknown**)&pICommandText));
// Try to insert a duplicate row. This will fail for r/o providers.
if (!g_fReadOnlyProvider)
TESTC_(m_pTable->Insert(m_pTable->GetNextRowNumber()-1), S_OK);
// Since providers will likely try to allocate cRows * sizeof(HROW) for this case,
// and max allocation size if LONG_MAX (release), or less than LONG_MAX (debug)
cRows = LONG_MAX/(sizeof(HROW)*100);
// Set CANHOLDROWS on so we can hold more than one row on some providers (prop is required)
TESTC_(SetRowsetProperty(pICmd1, DBPROPSET_ROWSET, DBPROP_CANHOLDROWS, TRUE), S_OK);
for (iCol = 1; iCol <= g_Table2->CountColumnsOnTable(); iCol++)
{
CCol TempCol;
HRESULT hrCreateStmt = E_FAIL;
TESTC_(m_pTable->GetColInfo(iCol, TempCol), S_OK);
// Some providers can't do an order-by on a LONG column, so allow an error
if (TempCol.GetIsLong())
hrExec = DB_E_ERRORSINCOMMAND;
else
hrExec = S_OK;
// Set command text for a select distinct query.
hrCreateStmt = m_pTable->CreateSQLStmt(SELECT_DISTINCTCOLLISTORDERBY, NULL, &pwszSqlStmt,&cCols,&pCols, 0, NULL, iCol);
TESTC_PROVIDER(hrCreateStmt == S_OK);
TESTC_(pICommandText->SetCommandText(DBGUID_DEFAULT, pwszSqlStmt), S_OK);
// Retrieve all rows that match the requested row.
hr = pICmd1->Execute(NULL, IID_IRowset, NULL, NULL, (IUnknown **)&pIRowset);
if (FAILED(hr))
CHECK(hr, hrExec);
// If we succeeded then validate results
if (S_OK == hr)
{
TESTC(VerifyInterface(pIRowset, IID_IAccessor,
ROWSET_INTERFACE, (IUnknown**)&pIAccessor));
TESTC_(GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,
&hAccessor, &pBindings, &cBindings, &cbRowSize,
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF,
NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,
NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_LONG), S_OK);
// Allocate a couple of row buffers for comparisons
SAFE_ALLOC(pData1, BYTE, cbRowSize);
SAFE_ALLOC(pData2, BYTE, cbRowSize);
// Retrieve all the rows and validate no duplicates
while (SUCCEEDED(hr) && hr != DB_S_ENDOFROWSET)
{
TESTC_(hr = pIRowset->GetNextRows(NULL, 0, cRows, &cRowsObtained, &phRows), DB_S_ENDOFROWSET);
TESTC(phRows != NULL);
TESTC(cRowsObtained > 0);
if (phRows)
{
for (iRow = 0; iRow < cRowsObtained; iRow++)
{
TESTC_(pIRowset->GetData(phRows[iRow], hAccessor, pData1), S_OK);
for (jRow = 0; jRow < cRowsObtained; jRow++)
{
TESTC_(pIRowset->GetData(phRows[jRow], hAccessor, pData2), S_OK);
// Of course we expect corresponding rows to match
if (iRow == jRow)
{
TESTC(CompareBuffer(pData1, pData2, cBindings, pBindings, NULL, FALSE, FALSE, COMPARE_ONLY));
}
else
{
BOOL fCmp = CompareBuffer(pData1, pData2, cBindings, pBindings, NULL, FALSE, FALSE, COMPARE_ONLY, FALSE, 0, NULL, TRUE);
if (fCmp)
odtLog << L"Data compared when it should not have, row " << iRow << " and row " << jRow << "\n";
TESTC(!fCmp);
}
TESTC_(ReleaseInputBindingsMemory(cBindings, pBindings, pData2), S_OK);
}
TESTC_(ReleaseInputBindingsMemory(cBindings, pBindings, pData1), S_OK);
}
TESTC_(pIRowset->ReleaseRows(cRowsObtained, phRows, NULL, NULL, NULL), S_OK);
SAFE_FREE(phRows);
}
}
if (hAccessor != DB_NULL_HACCESSOR)
{
pIAccessor->ReleaseAccessor(hAccessor, NULL);
hAccessor = DB_NULL_HACCESSOR;
}
SAFE_RELEASE(pIAccessor);
SAFE_RELEASE(pIRowset);
SAFE_FREE(pBindings);
SAFE_FREE(pData1);
SAFE_FREE(pData2);
}
SAFE_FREE(pwszSqlStmt);
SAFE_FREE(pCols);
}
TPASS;
CLEANUP:
if(!g_fReadOnlyProvider)
{
// Adjust table object's row count
m_pTable->SubtractRow();
// Delete the duplicate row (deletes both rows)
CHECK(m_pTable->Delete(m_pTable->GetNextRowNumber()-1), S_OK);
// Now reinsert one row
CHECK(m_pTable->Insert(m_pTable->GetNextRowNumber()), S_OK);
}
if (phRows && pIRowset)
pIRowset->ReleaseRows(cRowsObtained, phRows, NULL, NULL, NULL);
if (pData1)
CHECK(ReleaseInputBindingsMemory(cBindings, pBindings, pData1), S_OK);
if (pData2)
CHECK(ReleaseInputBindingsMemory(cBindings, pBindings, pData2), S_OK);
if (hAccessor != DB_NULL_HACCESSOR)
{
pIAccessor->ReleaseAccessor(hAccessor, NULL);
hAccessor = DB_NULL_HACCESSOR;
}
SAFE_FREE(pBindings);
SAFE_FREE(pData1);
SAFE_FREE(pData2);
SAFE_FREE(phRows);
SAFE_FREE(pCols);
SAFE_FREE(pwszSqlStmt);
SAFE_RELEASE(pIAccessor);
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pICommandText);
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(73)
//*-----------------------------------------------------------------------
// @mfunc DB_E_ERRORSOCCURRED - select distinct with DBPROP_UNIQUEROWS REQUIRED
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_73()
{
ICommand* pICmd1=NULL;
ICommandText * pICommandText = NULL;
IAccessor * pIAccessor = NULL;
DBORDINAL cCols;
DBCOUNTITEM cRowsObtained;
ULONG iCol;
LONG cRows = LONG_MAX;
HROW * phRows = NULL;
DB_LORDINAL * pCols = NULL;
IRowset * pIRowset = NULL;
WCHAR * pwszSqlStmt = NULL;
HRESULT hr, hrExec, hrExecLong, hrUnique, hrCreateStmt;
ULONG iRow, jRow;
BOOL fDup = FALSE;
BYTE * pData1 = NULL;
BYTE * pData2 = NULL;
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
DBBINDING * pBindings = NULL;
DBCOUNTITEM cBindings;
DBLENGTH cbRowSize;
ULONG_PTR ulHiddenColumns = 0;
TESTBEGIN;
ONLYROWSETVAR;
// If the provider doesn't understand SQL then skip test if not using ini file
if(m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE &&
!GetModInfo()->GetFileName())
{
odtLog << L"Provider doesn't support SQL and not using ini file.\n";
return TEST_SKIPPED;
}
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,NULL));
TESTC(VerifyInterface(pICmd1, IID_ICommandText,
COMMAND_INTERFACE, (IUnknown**)&pICommandText));
// Try to insert a duplicate row. This will fail for r/o providers.
if (!g_fReadOnlyProvider)
TESTC_(m_pTable->Insert(m_pTable->GetNextRowNumber()-1), S_OK);
// Since providers will likely try to allocate cRows * sizeof(HROW) for this case,
// and max allocation size if LONG_MAX (release), or less than LONG_MAX (debug)
cRows = LONG_MAX/(sizeof(HROW)*100);
// Set CANHOLDROWS on so we can hold more than one row on some providers (prop is required)
TESTC_(SetRowsetProperty(pICmd1, DBPROPSET_ROWSET, DBPROP_CANHOLDROWS, TRUE), S_OK);
// Set UNIQUEROWS on because some providers fail to retrieve "distinct" values when on
if (S_OK == SetRowsetProperty(pICmd1, DBPROPSET_ROWSET, DBPROP_UNIQUEROWS, TRUE))
hrUnique = DB_E_ERRORSOCCURRED;
else
hrUnique = S_OK;
for (iCol = 1; iCol <= g_Table2->CountColumnsOnTable(); iCol++)
{
CCol TempCol;
TESTC_(m_pTable->GetColInfo(iCol, TempCol), S_OK);
// Some providers can't do an order-by on a LONG column, so allow an error
if (TempCol.GetIsLong())
hrExecLong = DB_E_ERRORSINCOMMAND;
else
hrExecLong = S_OK;
// Set command text for a select distinct query.
hrCreateStmt = m_pTable->CreateSQLStmt(SELECT_DISTINCTCOLLISTORDERBY, NULL, &pwszSqlStmt,&cCols,&pCols, 0, NULL, iCol);
TESTC_PROVIDER(hrCreateStmt == S_OK);
TESTC_(pICommandText->SetCommandText(DBGUID_DEFAULT, pwszSqlStmt), S_OK);
// Retrieve all rows that match the requested row.
hr = pICmd1->Execute(NULL, IID_IRowset, NULL, NULL, (IUnknown **)&pIRowset);
// If there are no hidden columns then the fact the property was set is immaterial
if (pIRowset && S_OK == GetProperty(DBPROP_HIDDENCOLUMNS, DBPROPSET_ROWSET, pIRowset, &ulHiddenColumns) &&
!ulHiddenColumns)
hrUnique = S_OK;
// If the property was successfully set, then we really expect Execute can't
// support UNIQUEROWS and distinct.
hrExec = hrUnique;
// But if we think Execute will succeed we still need to take into account
// the column may be long
if (hrExec == S_OK)
hrExec = hrExecLong;
CHECK(hr, hrExec);
// If we got DB_E_ERRORSOCCURRED then we expect properties in error
if (hr == DB_E_ERRORSOCCURRED)
COMPARE(PropertiesInError(pICmd1, hr), TRUE);
// If we succeeded then validate results
if (S_OK == hr)
{
TESTC(VerifyInterface(pIRowset, IID_IAccessor,
ROWSET_INTERFACE, (IUnknown**)&pIAccessor));
TESTC_(GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,
&hAccessor, &pBindings, &cBindings, &cbRowSize,
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF,
NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,
NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_LONG), S_OK);
// Allocate a couple of row buffers for comparisons
SAFE_ALLOC(pData1, BYTE, cbRowSize);
SAFE_ALLOC(pData2, BYTE, cbRowSize);
// Retrieve all the rows and validate no duplicates
while (SUCCEEDED(hr) && hr != DB_S_ENDOFROWSET)
{
TESTC_(hr = pIRowset->GetNextRows(NULL, 0, cRows, &cRowsObtained, &phRows), DB_S_ENDOFROWSET);
TESTC(phRows != NULL);
TESTC(cRowsObtained > 0);
if (phRows)
{
for (iRow = 0; iRow < cRowsObtained; iRow++)
{
TESTC_(pIRowset->GetData(phRows[iRow], hAccessor, pData1), S_OK);
for (jRow = 0; jRow < cRowsObtained; jRow++)
{
TESTC_(pIRowset->GetData(phRows[jRow], hAccessor, pData2), S_OK);
// Of course we expect corresponding rows to match
if (iRow == jRow)
{
TESTC(CompareBuffer(pData1, pData2, cBindings, pBindings, NULL, 0, 0, COMPARE_ONLY));
}
else
{
// TESTC(!CompareBuffer(pData1, pData2, cBindings, pBindings, NULL, 0, 0, COMPARE_ONLY));
BOOL fCmp = CompareBuffer(pData1, pData2, cBindings, pBindings, NULL, FALSE, FALSE, COMPARE_ONLY, FALSE, 0, NULL, TRUE);
if (fCmp)
odtLog << L"Data compared when it should not have, row " << iRow << " and row " << jRow << "\n";
TESTC(!fCmp);
}
TESTC_(ReleaseInputBindingsMemory(cBindings, pBindings, pData2), S_OK);
}
TESTC_(ReleaseInputBindingsMemory(cBindings, pBindings, pData1), S_OK);
}
TESTC_(pIRowset->ReleaseRows(cRowsObtained, phRows, NULL, NULL, NULL), S_OK);
SAFE_FREE(phRows);
}
}
if (hAccessor != DB_NULL_HACCESSOR)
{
pIAccessor->ReleaseAccessor(hAccessor, NULL);
hAccessor = DB_NULL_HACCESSOR;
}
SAFE_RELEASE(pIAccessor);
SAFE_RELEASE(pIRowset);
SAFE_FREE(pBindings);
SAFE_FREE(pData1);
SAFE_FREE(pData2);
}
SAFE_FREE(pwszSqlStmt);
SAFE_FREE(pCols);
}
TPASS;
CLEANUP:
if(!g_fReadOnlyProvider)
{
// Adjust table object's row count
m_pTable->SubtractRow();
// Delete the duplicate row (deletes both rows)
CHECK(m_pTable->Delete(m_pTable->GetNextRowNumber()-1), S_OK);
// Now reinsert one row
CHECK(m_pTable->Insert(m_pTable->GetNextRowNumber()), S_OK);
}
if (phRows && pIRowset)
pIRowset->ReleaseRows(cRowsObtained, phRows, NULL, NULL, NULL);
if (pData1)
CHECK(ReleaseInputBindingsMemory(cBindings, pBindings, pData1), S_OK);
if (pData2)
CHECK(ReleaseInputBindingsMemory(cBindings, pBindings, pData2), S_OK);
if (hAccessor != DB_NULL_HACCESSOR)
{
pIAccessor->ReleaseAccessor(hAccessor, NULL);
hAccessor = DB_NULL_HACCESSOR;
}
SAFE_FREE(pBindings);
SAFE_FREE(pData1);
SAFE_FREE(pData2);
SAFE_FREE(phRows);
SAFE_FREE(pCols);
SAFE_FREE(pwszSqlStmt);
SAFE_RELEASE(pIAccessor);
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pICommandText);
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(74)
//*-----------------------------------------------------------------------
// @mfunc DB_E_ERRORSINCOMMAND - select with invalid group by clause
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_74()
{
ICommand* pICmd1=NULL;
DBORDINAL cRowsetCols;
LONG * rgTableColOrds = NULL;
IUnknown * pIUnk = NULL;
IID iid = IID_IRowset;
HRESULT hrExec = E_FAIL;
if(IFROW)
iid = IID_IRow;
// If the provider doesn't understand SQL then skip test if not using ini file
if(m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE &&
!GetModInfo()->GetFileName())
{
odtLog << L"Provider doesn't support SQL and not using ini file.\n";
return TEST_SKIPPED;
}
TESTBEGIN;
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,NULL));
hrExec = m_pTable->ExecuteCommand(SELECT_INVALIDGROUPBY, iid, NULL,
NULL, &cRowsetCols, (DB_LORDINAL **)&rgTableColOrds, EXECUTE_IFNOERROR, 0, NULL, NULL, (IUnknown**)&pIUnk,
&pICmd1);
TESTC_PROVIDER(hrExec != DB_E_NOTSUPPORTED);
TESTC_(hrExec, DB_E_ERRORSINCOMMAND);
TPASS;
CLEANUP:
SAFE_FREE(rgTableColOrds);
SAFE_RELEASE(pIUnk);
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(75)
//*-----------------------------------------------------------------------
// @mfunc DB_S_ERRORSOCCURRED - select distinct with DBPROP_UNIQUEROWS OPTIONAL
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_75()
{
ICommand* pICmd1=NULL;
ICommandText * pICommandText = NULL;
IAccessor * pIAccessor = NULL;
DBORDINAL cCols;
DBCOUNTITEM cRowsObtained;
ULONG iCol;
LONG cRows = LONG_MAX;
HROW * phRows = NULL;
DB_LORDINAL * pCols = NULL;
IRowset * pIRowset = NULL;
WCHAR * pwszSqlStmt = NULL;
HRESULT hr, hrExec, hrCreateStmt;
ULONG iRow, jRow;
BOOL fDup = FALSE;
BYTE * pData1 = NULL;
BYTE * pData2 = NULL;
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
DBBINDING * pBindings = NULL;
DBCOUNTITEM cBindings;
DBLENGTH cbRowSize;
ULONG_PTR ulHiddenColumns = 0;
BOOL fUniqueRows = FALSE; // Assume we couldn't set the property on
ONLYROWSETVAR;
// If the provider doesn't understand SQL then skip test if not using ini file
if(m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE &&
!GetModInfo()->GetFileName())
{
odtLog << L"Provider doesn't support SQL and not using ini file.\n";
return TEST_SKIPPED;
}
TESTBEGIN;
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,NULL));
TESTC(VerifyInterface(pICmd1, IID_ICommandText,
COMMAND_INTERFACE, (IUnknown**)&pICommandText));
// Try to insert a duplicate row. This will fail for r/o providers.
if (!g_fReadOnlyProvider)
TESTC_(m_pTable->Insert(m_pTable->GetNextRowNumber()-1), S_OK);
// Since providers will likely try to allocate cRows * sizeof(HROW) for this case,
// and max allocation size if LONG_MAX (release), or less than LONG_MAX (debug)
cRows = LONG_MAX/(sizeof(HROW)*100);
// Set CANHOLDROWS on so we can hold more than one row on some providers (prop is required)
TESTC_(SetRowsetProperty(pICmd1, DBPROPSET_ROWSET, DBPROP_CANHOLDROWS, TRUE), S_OK);
// Set UNIQUEROWS on because some providers fail to retrieve "distinct" values when on
if (S_OK == SetRowsetProperty(pICmd1, DBPROPSET_ROWSET, DBPROP_UNIQUEROWS,
TRUE, DBPROPOPTIONS_OPTIONAL))
fUniqueRows = TRUE;
for (iCol = 1; iCol <= g_Table2->CountColumnsOnTable(); iCol++)
{
CCol TempCol;
// If we were able to turn on UNIQUEROWS then we expect DB_S_ERRORSOCCURRED
if (fUniqueRows)
hrExec = DB_S_ERRORSOCCURRED;
else
hrExec = S_OK;
// Set command text for a select distinct query.
hrCreateStmt = m_pTable->CreateSQLStmt(SELECT_DISTINCTCOLLISTORDERBY, NULL, &pwszSqlStmt,&cCols,&pCols, 0, NULL, iCol);
TESTC_PROVIDER(hrCreateStmt == S_OK);
TESTC_(pICommandText->SetCommandText(DBGUID_DEFAULT, pwszSqlStmt), S_OK);
// Retrieve all rows that match the requested row.
hr = pICmd1->Execute(NULL, IID_IRowset, NULL, NULL, (IUnknown **)&pIRowset);
if (FAILED(hr))
{
// Providers generally can't do an order-by on a LONG column,
// so allow an error to pass
TESTC_(m_pTable->GetColInfo(iCol, TempCol), S_OK);
if (TempCol.GetIsLong())
hrExec = DB_E_ERRORSINCOMMAND;
}
else if (DB_S_ERRORSOCCURRED != hr)
{
// If there are no hidden columns then the fact the property was set is immaterial
// Some providers will succeed since they actually don't have hidden columns and
// so will not need to disallow the UNIQUEROWS property
if (pIRowset && S_OK == GetProperty(DBPROP_HIDDENCOLUMNS, DBPROPSET_ROWSET, pIRowset, &ulHiddenColumns) &&
!ulHiddenColumns)
hrExec = S_OK;
}
CHECK(hr, hrExec);
// If we got DB_S_ERRORSOCCURRED then we expect properties in error
if (hr == DB_S_ERRORSOCCURRED)
COMPARE(PropertiesInError(pICmd1, hr), TRUE);
// If we succeeded then validate results
if (SUCCEEDED(hr))
{
TESTC(VerifyInterface(pIRowset, IID_IAccessor,
ROWSET_INTERFACE, (IUnknown**)&pIAccessor));
TESTC_(GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,
&hAccessor, &pBindings, &cBindings, &cbRowSize,
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF,
NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,
NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_LONG), S_OK);
// Allocate a couple of row buffers for comparisons
SAFE_ALLOC(pData1, BYTE, cbRowSize);
SAFE_ALLOC(pData2, BYTE, cbRowSize);
// Retrieve all the rows and validate no duplicates
while (SUCCEEDED(hr) && hr != DB_S_ENDOFROWSET)
{
TESTC_(hr = pIRowset->GetNextRows(NULL, 0, cRows, &cRowsObtained, &phRows), DB_S_ENDOFROWSET);
TESTC(phRows != NULL);
TESTC(cRowsObtained > 0);
if (phRows)
{
for (iRow = 0; iRow < cRowsObtained; iRow++)
{
TESTC_(pIRowset->GetData(phRows[iRow], hAccessor, pData1), S_OK);
for (jRow = 0; jRow < cRowsObtained; jRow++)
{
TESTC_(pIRowset->GetData(phRows[jRow], hAccessor, pData2), S_OK);
// Of course we expect corresponding rows to match
if (iRow == jRow)
{
TESTC(CompareBuffer(pData1, pData2, cBindings, pBindings, NULL));
}
else
{
TESTC(!CompareBuffer(pData1, pData2, cBindings, pBindings, NULL));
}
TESTC_(ReleaseInputBindingsMemory(cBindings, pBindings, pData2), S_OK);
}
TESTC_(ReleaseInputBindingsMemory(cBindings, pBindings, pData1), S_OK);
}
TESTC_(pIRowset->ReleaseRows(cRowsObtained, phRows, NULL, NULL, NULL), S_OK);
SAFE_FREE(phRows);
}
}
if (hAccessor != DB_NULL_HACCESSOR)
{
pIAccessor->ReleaseAccessor(hAccessor, NULL);
hAccessor = DB_NULL_HACCESSOR;
}
SAFE_RELEASE(pIAccessor);
SAFE_RELEASE(pIRowset);
SAFE_FREE(pBindings);
SAFE_FREE(pData1);
SAFE_FREE(pData2);
}
SAFE_FREE(pwszSqlStmt);
SAFE_FREE(pCols);
}
TPASS;
CLEANUP:
if(!g_fReadOnlyProvider)
{
// Adjust table object's row count
m_pTable->SubtractRow();
// Delete the duplicate row (deletes both rows)
CHECK(m_pTable->Delete(m_pTable->GetNextRowNumber()-1), S_OK);
// Now reinsert one row
CHECK(m_pTable->Insert(m_pTable->GetNextRowNumber()), S_OK);
}
if (phRows && pIRowset)
pIRowset->ReleaseRows(cRowsObtained, phRows, NULL, NULL, NULL);
if (pData1)
CHECK(ReleaseInputBindingsMemory(cBindings, pBindings, pData1), S_OK);
if (pData2)
CHECK(ReleaseInputBindingsMemory(cBindings, pBindings, pData2), S_OK);
if (hAccessor != DB_NULL_HACCESSOR)
{
pIAccessor->ReleaseAccessor(hAccessor, NULL);
hAccessor = DB_NULL_HACCESSOR;
}
SAFE_FREE(pBindings);
SAFE_FREE(pData1);
SAFE_FREE(pData2);
SAFE_FREE(phRows);
SAFE_FREE(pCols);
SAFE_FREE(pwszSqlStmt);
SAFE_RELEASE(pIAccessor);
SAFE_RELEASE(pIRowset);
SAFE_RELEASE(pICommandText);
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(76)
//*-----------------------------------------------------------------------
// @mfunc DB_E_ERRORSINCOMMAND - (Insert with mis-spelled keyword)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_76()
{
ICommand* pICmd1=NULL;
IRowset * pRowset=INVALID(IRowset *);
IID iid = IID_IRowset;
if(IFROW)
iid = IID_IRow;
// If the provider doesn't understand SQL then skip test if not using ini file
if(m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE &&
!GetModInfo()->GetFileName())
{
odtLog << L"Provider doesn't support SQL and not using ini file.\n";
return TEST_SKIPPED;
}
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
// Set command text to insert statement with invalid keyword (inot instead of into)
m_hr = m_pTable->ExecuteCommand(INSERT_INVALID_KEYWORD, IID_IUnknown,
NULL,NULL,NULL, NULL, EXECUTE_NEVER, 0, NULL,
NULL, NULL, &pICmd1);
// Make sure there's support for this statement
TEST_SUPPORTED(m_hr, S_OK);
// Now execute expecting DB_E_ERRORSINCOMMAND
TESTC_(pICmd1->Execute(NULL,iid,NULL,NULL,PPI &pRowset),DB_E_ERRORSINCOMMAND);
TESTC(pRowset == NULL);
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
if (pRowset != INVALID(IRowset *))
SAFE_RELEASE(pRowset);
TRETURN;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(77)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Multiple commands, 2 initial and 1 later
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_77()
{
// Some providers cannot support two open rowsets on the same command, which may cause a
// bug where the third command object will fail also. We allow the second command object to
// fail execute in order to not unfairly penalize providers here.
TBEGIN;
HRESULT hr = E_FAIL;
HRESULT hrExp = S_OK;
IMultipleResults * pMultRes1=NULL;
IUnknown * pUnk=NULL;
DBROWCOUNT cRowsAffected2=0;
LPWSTR pwszSqlStmt = NULL;
LPWSTR pwszSqlMult = NULL;
ULONG_PTR ulMultipleResults = 0;
ICommand * pICmd1=NULL;
ICommand * pICmd2=NULL;
ICommand * pICmd3=NULL;
// Get a pointer to the session object. There are no commands active at this time
IDBCreateCommand * pIDBCreateCommand = (IDBCreateCommand *)m_pThisTestModule->m_pIUnknown2;
// Make sure we have a valid interface
TESTC(pIDBCreateCommand != NULL);
// Since this variation requires a multiple results object check for support
if (!GetProperty(DBPROP_MULTIPLERESULTS, DBPROPSET_DATASOURCEINFO,
m_pMyIDBInitialize, &ulMultipleResults) ||
ulMultipleResults == DBPROPVAL_MR_NOTSUPPORTED)
{
odtLog << L"Multiple results objects are not supported.\n";
hrExp = E_NOINTERFACE;
}
// We don't know the syntax for non Sql Server multiple results objects
if (!g_fSqlServer)
{
odtLog << L"Syntax for multiple results is only known for Sql Server.\n";
TSKIPPED;
}
// Get two command objects off the session
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,pIDBCreateCommand));
TESTC(GetCommand(IID_ICommand,PPI &pICmd2,pIDBCreateCommand));
TESTC(pICmd1 != NULL && pICmd2 != NULL);
// Get statement with multiple results
TESTC_(m_pTable->CreateSQLStmt(SELECT_ALLFROMTBL, NULL, &pwszSqlStmt,NULL,NULL), S_OK);
// Allocate space for two copies of stmt plus a ';' and a null terminator
SAFE_ALLOC(pwszSqlMult, WCHAR, wcslen(pwszSqlStmt)*2 + 2*sizeof(WCHAR));
// Build the final statement
wcscpy(pwszSqlMult, pwszSqlStmt);
wcscat(pwszSqlMult, L";");
wcscat(pwszSqlMult, pwszSqlStmt);
// First session object's first command
TESTC_(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSQL,SELECT_ALLFROMTBL,pwszSqlMult), S_OK);
TESTC_(pICmd1->Execute(NULL,IID_IMultipleResults,NULL,NULL,PPI &pMultRes1),hrExp);
// First session object's second command
TESTC_(SetCommandText(m_pIMalloc,pICmd2,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL), S_OK);
hr = Execute(pICmd2,PPI &pUnk);
// Don't check the hr for Execute, because at least one provider can't support a second open rowset on
// the same session, but if a new command object is created then it can. Nice implementation.
// Third command object on same session
TESTC(GetCommand(IID_ICommand,PPI &pICmd3,pIDBCreateCommand));
TESTC(pICmd3 != NULL);
// Third session object's command
TESTC_(SetCommandText(m_pIMalloc,pICmd3,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL), S_OK);
TESTC_(pICmd3->Execute(NULL,IID_NULL,NULL,&cRowsAffected2,NULL), S_OK);
TPASS;
CLEANUP:
SAFE_FREE(pwszSqlStmt);
SAFE_FREE(pwszSqlMult);
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pICmd2);
SAFE_RELEASE(pICmd3);
SAFE_RELEASE(pMultRes1);
SAFE_RELEASE(pUnk);
TRETURN;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(78)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Create index in descending order
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_78()
{
BOOL fSuccess = FALSE; // Variation passed or failed
WCHAR* pwszSQLStmt = NULL; // SQL Statement
HRESULT hr = E_FAIL; // HRESULT
LPWSTR pszStartTblName = NULL;
LPWSTR pwszIndexSuffix = L"IdxDesc";
WCHAR wszIndexName[100] = L"";
DBORDINAL cIndexCols =1;
DB_LORDINAL rgIndexCols[1];
DB_LORDINAL * prgIndexCols = &rgIndexCols[0];
ULONG iCol;
DBORDINAL cTableCols;
CCol TempCol;
// If the provider doesn't understand SQL then skip test if not using ini file
if(m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE &&
!GetModInfo()->GetFileName())
{
odtLog << L"Provider doesn't support SQL and not using ini file.\n";
return TEST_SKIPPED;
}
TBEGIN;
// Find a column that will qualify for an index. We'll use the first numeric column.
cTableCols = m_pTable->CountColumnsOnTable();
for (iCol = 1; iCol <= cTableCols; iCol++)
{
TESTC_(m_pTable->GetColInfo(iCol, TempCol), S_OK);
if (IsNumericType(TempCol.GetProviderType()))
{
// Column index needed by CREATE_INDEX and CREATE_INDEX_DESC is 0 based.
rgIndexCols[0] = iCol-1;
break;
}
}
// Create the index name. This will be the table name and the suffix, since we may already have
// an index using the table name, and we need a unique value that won't collide with other index
// names from other tests running simultaneously.
wcscpy(wszIndexName, m_pTable->GetTableName());
wcscat(wszIndexName, pwszIndexSuffix);
hr = m_pTable->ExecuteCommand(CREATE_INDEX_DESC, IID_NULL, wszIndexName, NULL, &cIndexCols, &prgIndexCols);
if (hr == DB_E_NOTSUPPORTED)
{
TESTC_PROVIDER(hr == S_OK);
}
TESTC_(hr, S_OK);
TPASS;
CLEANUP:
// Try to drop the index created above. Some providers (Access/Jolt) have different syntax
// for dropping indexes so don't check return code
m_pTable->ExecuteCommand(DROP_INDEX, IID_NULL, wszIndexName, NULL, NULL, NULL);
TRETURN;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(79)
//*-----------------------------------------------------------------------
// @mfunc S_OK: All rows with singleton select
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_79()
{
TBEGIN
IID iid = IID_IRowset;
ULONG ulIndex = 0;
DBCOUNTITEM cRows = g_Table2->GetRowsOnCTable();
BYTE* pData = NULL;
HROW* rghRows = NULL;
DB_LORDINAL* rgColumnsOrd = NULL;
DBORDINAL cColumns = 0;
DBCOUNTITEM cRowsObtained = 0;
DBLENGTH cbRowSize = 0;
DBCOUNTITEM cBindings = 0;
DBCOUNTITEM cTableBindings, iBind;
DBORDINAL cTableCols;
DBBINDING* rgBindings = NULL;
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
HACCESSOR* phAccessor = NULL;
CRowObject* pCRow = NULL;
IUnknown* pIUnk=NULL;
HRESULT hrCreateStmt = E_FAIL;
WCHAR * pwszSqlStmt = NULL;
if(IFROW)
iid = IID_IRow;
hrCreateStmt = m_pTable->CreateSQLStmt(SELECT_ROW_WITH_LITERALS, NULL, &pwszSqlStmt,&cColumns,&rgColumnsOrd, 0, NULL, 1);
SAFE_FREE(pwszSqlStmt);
SAFE_FREE(rgColumnsOrd);
TESTC_PROVIDER(hrCreateStmt == S_OK);
TESTC(g_Table2->GetQueryInfo(SELECT_ALLFROMTBL, &cColumns,
&rgColumnsOrd, NULL,NULL,NULL,NULL))
for(ulIndex=0; ulIndex<cRows; ulIndex++)
// for(ulIndex=0; ulIndex<1; ulIndex++)
{
BLOBTYPE dwBlobType = NO_BLOB_COLS | BLOB_IID_IUNKNOWN;
TESTC_(g_Table2->Select(NULL, ulIndex+1, iid, 0, NULL, NULL, PPI &pIUnk), S_OK)
if(IFROW)
{
phAccessor = NULL;
// Do not request IUnknown UDT for row object use, not supported
dwBlobType |= BLOB_BIND_UDT_NO_IUNKNOWN;
}
else
phAccessor = &hAccessor;
TESTC_(GetAccessorAndBindings(pIUnk,
DBACCESSOR_ROWDATA,phAccessor, &rgBindings,
&cBindings, &cbRowSize, DBPART_VALUE | DBPART_LENGTH | DBPART_STATUS,
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF,
NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
dwBlobType,
NULL),S_OK)
//Allocate a new data buffer
SAFE_ALLOC(pData, BYTE, cbRowSize);
if(IFROWSET)
{
TESTC_(((IRowset*)pIUnk)->GetNextRows(NULL, 0, 2, &cRowsObtained, &rghRows), DB_S_ENDOFROWSET)
COMPARE(cRowsObtained, 1);
TESTC(cRowsObtained > 0);
//Initialize pData and call GetData for a row.
memset(pData, 0, (size_t) cbRowSize);
//We are sure that pIUnk is IRowset. Hence the
//cast used below is safe.
TESTC_(((IRowset*)pIUnk)->GetData(*rghRows, hAccessor, pData),S_OK)
CHECK(((IRowset*)pIUnk)->ReleaseRows(cRowsObtained, rghRows, NULL, NULL, NULL), S_OK);
}
if(IFROW)
{
pCRow = new CRowObject();
TESTC(pCRow != NULL)
TESTC_(pCRow->SetRowObject(pIUnk), S_OK)
TESTC_(pCRow->GetColumns(cBindings, rgBindings, pData), S_OK)
}
// The first N columns in the rowset are columns from the table, for
// which we must use the proper ordinals in m_rgCompOrds. Columns
// N+1 to cBindings are extra row object columns if this is a row
// object. We cannot use m_rgCompOrds for these columns as they
// have no relation to the "base" columns in the table.
cTableCols = g_Table2->CountColumnsOnTable();
cTableBindings = cBindings;
// Find the last binding within the table
for (iBind = 0; iBind < cBindings; iBind++)
{
if (rgBindings[iBind].iOrdinal > cTableCols)
{
cTableBindings = iBind;
break;
}
}
//Verify data value, length and status are what is expected
if (!COMPARE(CompareData(cTableCols,
rgColumnsOrd,
ulIndex+1,
pData,
cTableBindings,
rgBindings,
g_Table2,
m_pIMalloc,
PRIMARY,
COMPARE_ONLY), TRUE))
{
m_hr = E_FAIL;
break;
}
// If there are extra bindings, then compare them without m_rgCompOrds
// This is currently not possible with the existing test design, because
// the test requires two tables. With two tables, one cannot use an ini
// file, and without using an ini file one cannot compare the row object's
// extra columns. So just print a warning until we can restructure the test.
if (cBindings > cTableBindings)
{
odtLog << L"Extra row object columns not compared.\n";
COMPAREW(0, 1);
/*
//Verify data value, length and status are what is expected
if (!COMPARE(CompareData(0,
NULL,
ROW_SEED+i,
pData,
cBindings - cTableBindings,
rgBindings + cTableBindings,
m_pSelectTable,
CMultResults::s_pIMalloc,
PRIMARY), TRUE))
{
m_hr = E_FAIL;
break;
}
*/
}
/*
TESTC(CompareData(cColumns, rgColumnsOrd, ulIndex+1,
pData, cBindings, rgBindings, g_Table2,
m_pIMalloc, PRIMARY, COMPARE_ONLY))
*/
CHECK(ReleaseInputBindingsMemory(cBindings, rgBindings, pData), S_OK);
FreeAccessorBindings(cBindings, rgBindings);
rgBindings = NULL;
SAFE_FREE(pData);
SAFE_FREE(rghRows);
SAFE_DELETE(pCRow);
SAFE_RELEASE(pIUnk);
// pIUnk->Release();
}
CLEANUP:
ReleaseInputBindingsMemory(cBindings, rgBindings, pData);
if (rgBindings)
FreeAccessorBindings(cBindings, rgBindings);
SAFE_FREE(rgColumnsOrd);
SAFE_FREE(pData);
SAFE_DELETE(pCRow);
SAFE_RELEASE(pIUnk);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(80)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Select ABC and Col List
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_80()
{
TBEGIN
HRESULT hr = E_FAIL;
LONG_PTR rgColsToBind[1];
DBLENGTH cbRowSize = 0;
DBCOUNTITEM cBindings = 0;
DBBINDING* rgBindings = NULL;
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
HACCESSOR* phAccessor = &hAccessor;
DBCOUNTITEM cRowsObtained = 0;
DBCOUNTITEM cGotRows = 0;
HROW* rghRows = NULL;
BYTE* pData = NULL;
CRowObject* pCRow = NULL;
ICommand* pICmd1=NULL;
IUnknown* pIUnk=NULL;
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,NULL));
if(IFROW)
CHECK(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,
DBPROP_IRow,TRUE,DBPROPOPTIONS_REQUIRED), S_OK);
TESTC_(SetCommandText(m_pIMalloc,pICmd1,g_Table2,NULL,eSELECT,SELECT_ABCANDCOLLIST,NULL), S_OK)
TESTC_(m_hr = Execute(pICmd1,PPI &pIUnk),S_OK);
TESTC(pIUnk != NULL);
rgColsToBind[0] = 1;
if(IFROW)
phAccessor = NULL;
TESTC_(GetAccessorAndBindings(pIUnk,
DBACCESSOR_ROWDATA,phAccessor, &rgBindings,
&cBindings, &cbRowSize, DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS,
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF,
NULL, NULL, NULL, DBTYPE_EMPTY, 1, rgColsToBind,
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
NO_BLOB_COLS, NULL),S_OK)
COMPARE(rgBindings[0].wType == DBTYPE_WSTR ||
rgBindings[0].wType == DBTYPE_STR, TRUE);
//Allocate a new data buffer
SAFE_ALLOC(pData, BYTE, cbRowSize);
if(IFROWSET)
{
while(S_OK==(((IRowset*)pIUnk)->GetNextRows(NULL, 0, 1, &cRowsObtained, &rghRows)))
{
COMPARE(cRowsObtained, 1);
//Initialize pData and call GetData for a row.
memset(pData, 0, (size_t) cbRowSize);
//We are sure that pIUnk is IRowset. Hence the
//cast used below is safe.
TESTC_(((IRowset*)pIUnk)->GetData(*rghRows, hAccessor, pData),S_OK)
CHECK(((IRowset*)pIUnk)->ReleaseRows(cRowsObtained, rghRows, NULL, NULL, NULL), S_OK);
if(rgBindings[0].wType == DBTYPE_WSTR)
TESTC(wcscmp((WCHAR*)((BYTE *)pData+rgBindings[0].obValue), L"ABC") == 0)
else if(rgBindings[0].wType == DBTYPE_STR)
TESTC(strcmp((CHAR*)((BYTE *)pData+rgBindings[0].obValue), "ABC") == 0)
CHECK(ReleaseInputBindingsMemory(cBindings, rgBindings, pData), S_OK);
SAFE_FREE(rghRows);
cGotRows++;
}
COMPARE(cGotRows, g_Table2->GetRowsOnCTable());
}
if(IFROW)
{
pCRow = new CRowObject();
TESTC(pCRow != NULL)
TESTC_(pCRow->SetRowObject(pIUnk), S_OK)
TESTC_(pCRow->GetColumns(cBindings, rgBindings, pData), S_OK)
if(rgBindings[0].wType == DBTYPE_WSTR)
TESTC(wcscmp((WCHAR*)((BYTE *)pData+rgBindings[0].obValue), L"ABC") == 0)
else if(rgBindings[0].wType == DBTYPE_STR)
TESTC(strcmp((CHAR*)((BYTE *)pData+rgBindings[0].obValue), "ABC") == 0)
}
CLEANUP:
ReleaseInputBindingsMemory(cBindings, rgBindings, pData);
FreeAccessorBindings(cBindings, rgBindings);
SAFE_FREE(pData);
SAFE_DELETE(pCRow);
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIUnk);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(81)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Select duplicate columns
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_81()
{
TBEGIN
IID iid = IID_IRowset;
DBORDINAL ulCol = 0;
BYTE* pData = NULL;
HROW* rghRows = NULL;
DB_LORDINAL* rgColumnsOrd = NULL;
DBORDINAL cColumns = 0;
DBCOUNTITEM cRowsObtained = 0;
DBLENGTH cbRowSize = 0;
DBCOUNTITEM cBindings = 0;
DBCOUNTITEM cBindingsOrg = 0;
DBBINDING* rgBindings = NULL;
DBBINDING* rgBindingsOrg = NULL;
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
HACCESSOR* phAccessor = NULL;
CRowObject* pCRow = NULL;
IUnknown* pIUnk=NULL;
ICommand* pICmd1=NULL;
BLOBTYPE dwBlobType = NO_BLOB_COLS;
if(IFROW)
{
iid = IID_IRow;
// Do not request IUnknown UDT for row object use, not supported
dwBlobType |= BLOB_BIND_UDT_NO_IUNKNOWN;
}
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,NULL));
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cColumns,
&rgColumnsOrd, NULL,NULL,NULL,NULL))
TESTC_(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_DUPLICATECOLUMNS,NULL), S_OK)
TESTC_(m_hr = Execute(pICmd1,PPI &pIUnk),S_OK);
if(IFROW)
phAccessor = NULL;
else
phAccessor = &hAccessor;
TESTC_(GetAccessorAndBindings(pIUnk,
DBACCESSOR_ROWDATA,phAccessor, &rgBindingsOrg,
&cBindingsOrg, &cbRowSize, DBPART_VALUE,
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF,
NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
dwBlobType, NULL),S_OK)
//Allocate a new data buffer
SAFE_ALLOC(pData, BYTE, cbRowSize);
if(IFROWSET)
{
TESTC_(((IRowset*)pIUnk)->GetNextRows(NULL, 0, 1, &cRowsObtained, &rghRows), S_OK)
COMPARE(cRowsObtained, 1);
//Initialize pData and call GetData for a row.
memset(pData, 0, (size_t) cbRowSize);
//We are sure that pIUnk is IRowset. Hence the
//cast used below is safe.
TESTC_(((IRowset*)pIUnk)->GetData(*rghRows, hAccessor, pData),S_OK)
CHECK(((IRowset*)pIUnk)->ReleaseRows(cRowsObtained, rghRows, NULL, NULL, NULL), S_OK);
}
if(IFROW)
{
pCRow = new CRowObject();
TESTC(pCRow != NULL)
TESTC_(pCRow->SetRowObject(pIUnk), S_OK)
TESTC_(pCRow->GetColumns(cBindingsOrg, rgBindingsOrg, pData), S_OK)
}
cBindings = cBindingsOrg/2;
rgBindings = rgBindingsOrg;
TESTC(CompareData(cColumns, rgColumnsOrd, 1,
pData, cBindings, rgBindings, m_pTable,
m_pIMalloc, PRIMARY, COMPARE_ONLY))
rgBindings = &(rgBindingsOrg[cBindings]);
for(ulCol=0; ulCol<cBindings; ulCol++)
rgBindings[ulCol].iOrdinal = rgBindingsOrg[ulCol].iOrdinal;
TESTC(CompareData(cColumns, rgColumnsOrd, 1,
pData, cBindings, rgBindings, m_pTable,
m_pIMalloc, PRIMARY, COMPARE_ONLY))
CLEANUP:
ReleaseInputBindingsMemory(cBindingsOrg, rgBindingsOrg, pData);
FreeAccessorBindings(cBindingsOrg, rgBindingsOrg);
SAFE_FREE(pData);
SAFE_FREE(rghRows);
SAFE_DELETE(pCRow);
SAFE_RELEASE(pIUnk);
SAFE_RELEASE(pICmd1);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(82)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Select Count
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_82()
{
TBEGIN
HRESULT hr = E_FAIL;
LONG_PTR rgColsToBind[1];
DBLENGTH cbRowSize = 0;
DBCOUNTITEM cBindings = 0;
DBBINDING* rgBindings = NULL;
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
DBCOUNTITEM cRowsObtained = 0;
DBCOUNTITEM cGotRows = 0;
HROW* rghRows = NULL;
BYTE* pData = NULL;
CRowObject* pCRow = NULL;
ICommand* pICmd1=NULL;
IUnknown* pIUnk=NULL;
IAccessor* pIA = NULL;
//If the provider does not understand SQL, skip variation.
if(g_Table2->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,NULL));
if(IFROW)
CHECK(SetRowsetProperty(pICmd1,DBPROPSET_ROWSET,
DBPROP_IRow,TRUE,DBPROPOPTIONS_REQUIRED), S_OK);
TESTC_(SetCommandText(m_pIMalloc,pICmd1,g_Table2,NULL,eSELECT,SELECT_COUNT,NULL), S_OK)
TESTC_(m_hr = Execute(pICmd1,PPI &pIUnk),S_OK);
TESTC(pIUnk != NULL);
rgColsToBind[0] = 1;
TESTC_(GetAccessorAndBindings(pIUnk,
DBACCESSOR_ROWDATA,NULL, &rgBindings,
&cBindings, &cbRowSize, DBPART_VALUE,
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF,
NULL, NULL, NULL, DBTYPE_EMPTY, 1, rgColsToBind,
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
NO_BLOB_COLS, NULL),S_OK)
if(IFROWSET)
{
TESTC(VerifyInterface(pIUnk, IID_IAccessor, ROWSET_INTERFACE, PPI &pIA))
if(rgBindings[0].wType != DBTYPE_I4)
rgBindings[0].wType = DBTYPE_WSTR;
TESTC_(pIA->CreateAccessor(DBACCESSOR_ROWDATA,
cBindings, rgBindings, cbRowSize, &hAccessor,NULL), S_OK)
}
//Allocate a new data buffer
SAFE_ALLOC(pData, BYTE, cbRowSize);
if(IFROWSET)
{
TESTC_(((IRowset*)pIUnk)->GetNextRows(NULL, 0, 2, &cRowsObtained, &rghRows), DB_S_ENDOFROWSET)
COMPARE(cRowsObtained, 1);
//Initialize pData and call GetData for a row.
memset(pData, 0, (size_t) cbRowSize);
//We are sure that pIUnk is IRowset. Hence the
//cast used below is safe.
TESTC_(((IRowset*)pIUnk)->GetData(*rghRows, hAccessor, pData),S_OK)
CHECK(((IRowset*)pIUnk)->ReleaseRows(cRowsObtained, rghRows, NULL, NULL, NULL), S_OK);
}
if(IFROW)
{
pCRow = new CRowObject();
TESTC(pCRow != NULL)
TESTC_(pCRow->SetRowObject(pIUnk), S_OK)
TESTC_(pCRow->GetColumns(cBindings, rgBindings, pData), S_OK)
}
if(rgBindings[0].wType == DBTYPE_I4)
COMPARE(*(ULONG*)((BYTE *)pData+rgBindings[0].obValue), g_Table2->GetRowsOnCTable());
else
COMPARE((ULONG)_wtoi((WCHAR*)((BYTE *)pData+rgBindings[0].obValue)), g_Table2->GetRowsOnCTable());
CLEANUP:
ReleaseInputBindingsMemory(cBindings, rgBindings, pData);
FreeAccessorBindings(cBindings, rgBindings);
SAFE_FREE(rghRows);
SAFE_FREE(pData);
SAFE_DELETE(pCRow);
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIA);
SAFE_RELEASE(pIUnk);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(83)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Select empty rowset
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_83()
{
TBEGIN
HROW* rghRows = NULL;
DBCOUNTITEM cRowsObtained = 0;
ICommand* pICmd1=NULL;
IUnknown* pIUnk=NULL;
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,NULL));
TESTC_(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_EMPTYROWSET,NULL), S_OK)
TEST2C_(m_hr = Execute(pICmd1,PPI &pIUnk),S_OK, DB_E_NOTFOUND);
if(IFROW)
{
TESTC_(m_hr, DB_E_NOTFOUND)
goto CLEANUP;
}
TESTC_(m_hr, S_OK)
TESTC(pIUnk != NULL)
TESTC_(((IRowset*)pIUnk)->GetNextRows(NULL, 0, 1, &cRowsObtained, &rghRows), DB_S_ENDOFROWSET)
COMPARE(cRowsObtained, 0);
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIUnk);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(84)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Select Change col name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_84()
{
TBEGIN
IID iid = IID_IRowset;
BYTE* pData = NULL;
HROW* rghRows = NULL;
DB_LORDINAL* rgColumnsOrd = NULL;
DBORDINAL cColumns = 0;
DBCOUNTITEM cRowsObtained = 0;
DBLENGTH cbRowSize = 0;
DBCOUNTITEM cBindings = 0;
DBBINDING* rgBindings = NULL;
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
HACCESSOR* phAccessor = NULL;
CRowObject* pCRow = NULL;
IUnknown* pIUnk=NULL;
ICommand* pICmd1=NULL;
if(IFROW)
iid = IID_IRow;
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,NULL));
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cColumns,
&rgColumnsOrd, NULL,NULL,NULL,NULL))
// Renaming the columns destroys our ability to look up UDT columns by column name. So we will create our accessor using
// non-renamed columns and just use it again after renaming the columns. It should still work...
TESTC_(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL), S_OK)
TESTC_(m_hr = Execute(pICmd1,PPI &pIUnk),S_OK);
if(IFROW)
phAccessor = NULL;
else
phAccessor = &hAccessor;
SAFE_RELEASE(pIUnk);
TESTC_(GetAccessorAndBindings(pICmd1,
DBACCESSOR_ROWDATA,phAccessor, &rgBindings,
&cBindings, &cbRowSize, DBPART_VALUE,
ALL_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, NULL),S_OK)
TESTC_(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_CHANGECOLNAME,NULL), S_OK)
TESTC_(m_hr = Execute(pICmd1,PPI &pIUnk),S_OK);
//Allocate a new data buffer
SAFE_ALLOC(pData, BYTE, cbRowSize);
if(IFROWSET)
{
TESTC_(((IRowset*)pIUnk)->GetNextRows(NULL, 0, 1, &cRowsObtained, &rghRows), S_OK)
COMPARE(cRowsObtained, 1);
//Initialize pData and call GetData for a row.
memset(pData, 0, (size_t) cbRowSize);
//We are sure that pIUnk is IRowset. Hence the
//cast used below is safe.
TESTC_(((IRowset*)pIUnk)->GetData(*rghRows, hAccessor, pData),S_OK)
CHECK(((IRowset*)pIUnk)->ReleaseRows(cRowsObtained, rghRows, NULL, NULL, NULL), S_OK);
}
if(IFROW)
{
pCRow = new CRowObject();
TESTC(pCRow != NULL)
TESTC_(pCRow->SetRowObject(pIUnk), S_OK)
TESTC_(pCRow->BindingsToColAccess(cBindings, rgBindings, &pCRow->m_pData, &pCRow->m_cColAccess, &pCRow->m_rgColAccess), S_OK);
TESTC_(pCRow->GetColumns(cBindings, rgBindings, pData), S_OK)
}
TESTC(CompareData(cColumns, rgColumnsOrd, 1,
pData, cBindings, rgBindings, m_pTable,
m_pIMalloc, PRIMARY, COMPARE_ONLY))
CLEANUP:
ReleaseInputBindingsMemory(cBindings, rgBindings, pData);
FreeAccessorBindings(cBindings, rgBindings);
SAFE_FREE(pData);
SAFE_FREE(rghRows);
SAFE_DELETE(pCRow);
SAFE_RELEASE(pIUnk);
SAFE_RELEASE(pICmd1);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(85)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Aggregated rowset
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_85()
{
TESTRESULT testresult = TEST_FAIL;
HRESULT hr = E_FAIL, hrSetProp = E_FAIL;
DBORDINAL cRowsetCols;
DBORDINAL * rgTableColOrds = NULL;
IUnknown * pIUnkInner = NULL;
IUnknown * pIUnk;
IID iid = IID_IRowset;
if(IFROW)
{
iid = IID_IRow;
// For aggregation case, since we must specify IID_IUnknown, we have to set DBPROP_IRow
CHECK(SetRowsetProperty(m_pTable->m_pICommand, DBPROPSET_ROWSET, DBPROP_IRow, TRUE), S_OK);
}
CAggregate Aggregate(m_pTable->m_pICommand);
// Kagera can't retrieve BLOB data without ACCESSORDER RANDOM.
if (g_fKagera && SupportedProperty(DBPROP_ACCESSORDER, DBPROPSET_ROWSET, m_pThisTestModule->m_pIUnknown,SESSION_INTERFACE))
hrSetProp = SetRowsetProperty(m_pTable->m_pICommand, DBPROPSET_ROWSET, DBPROP_ACCESSORDER, (LONG_PTR)DBPROPVAL_AO_RANDOM);
// Set the command text to execute
TESTC_(m_pTable->ExecuteCommand(SELECT_VALIDATIONORDER, IID_IRowset, NULL,
NULL, &cRowsetCols, (DB_LORDINAL **)&rgTableColOrds, EXECUTE_NEVER, 0, NULL, NULL, (IUnknown**)&pIUnk, &m_pTable->m_pICommand), S_OK);
TESTC_(hr = m_pTable->m_pICommand->Execute(&Aggregate, IID_IUnknown, NULL, NULL, &pIUnkInner), S_OK);
Aggregate.SetUnkInner(pIUnkInner);
TESTC(Aggregate.VerifyAggregationQI(hr, iid));
// Get IRowset (or IRow) from the aggregated object
TESTC_(Aggregate.QueryInterface(iid, (void **)&pIUnk), S_OK);
if(IFROWSET)
TESTC_(VerifyRowset(IID_IRowset, (IUnknown *)pIUnk, 1,
cRowsetCols, rgTableColOrds, FALSE), S_OK);
if(IFROW)
TESTC_(VerifyRowObj(IID_IRow, (IUnknown *)pIUnk, 1,
cRowsetCols, rgTableColOrds, FALSE), S_OK);
// Now release our aggregated rowset object and IUnknown
// We expect the aggregated object to go away when the last ref is released.
SAFE_RELEASE(pIUnkInner);
SAFE_RELEASE(pIUnk);
TESTC(Aggregate.GetRefCount()==1);
testresult = TEST_PASS;
CLEANUP:
SAFE_RELEASE(pIUnkInner);
SAFE_RELEASE(pIUnk);
Aggregate.ReleaseInner();
SAFE_FREE(rgTableColOrds);
// Reset again just in case of failure above.
if (hrSetProp == S_OK)
CHECK(SetRowsetProperty(m_pTable->m_pICommand, DBPROPSET_ROWSET, DBPROP_ACCESSORDER, (LONG_PTR)DBPROPVAL_AO_RANDOM, DBPROPOPTIONS_OPTIONAL), S_OK);
// Set DBROP_IRow back to default value.
if(IFROW)
CHECK(SetRowsetPropertyDefault(DBPROP_IRow, m_pTable->m_pICommand), S_OK);
return testresult;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(86)
//*-----------------------------------------------------------------------
// @mfunc Last Variation - Final Verification
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CExecute_Rowset::Variation_86()
{
TBEGIN
ICommand* pICmd1=NULL;
IUnknown* pIUnk=NULL;
WCHAR * pSQL=NULL;
DBORDINAL cRowsetCols=0;
DBORDINAL * rgTableColOrds = NULL;
HRESULT hrSetProp = E_FAIL;
TESTC(GetCommand(IID_ICommand,PPI &pICmd1,NULL));
TESTC_(m_pTable->CreateSQLStmt(SELECT_VALIDATIONORDER,NULL,&pSQL,&cRowsetCols,(DB_LORDINAL **)&rgTableColOrds), S_OK)
TESTC_(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSQL,NO_QUERY,pSQL), S_OK)
// Some providers can't retrieve BLOB data without this property or IRowsetLocate on. Can't turn on IRowsetLocate
// for batch SQL as Sql Server driver will turn back off when it detects batch stmt.
// If the property is not supported then this may fail, but there's nothing we can do about that
if (g_fKagera && SupportedProperty(DBPROP_ACCESSORDER, DBPROPSET_ROWSET, m_pThisTestModule->m_pIUnknown,SESSION_INTERFACE))
hrSetProp = SetRowsetProperty(pICmd1, DBPROPSET_ROWSET, DBPROP_ACCESSORDER, (LONG_PTR)DBPROPVAL_AO_RANDOM);
TESTC_(m_hr = Execute(pICmd1,PPI &pIUnk, NULL, NULL, NULL, IID_IRowset),S_OK);
TESTC(pIUnk != NULL);
//Make sure the rowset has correct number of rows,
//and data.
TESTC_(VerifyRowset(IID_IRowset, (IUnknown *)pIUnk, 1,
cRowsetCols, rgTableColOrds, FALSE), S_OK);
CLEANUP:
SAFE_FREE(pSQL);
SAFE_FREE(rgTableColOrds);
SAFE_RELEASE(pIUnk);
if (hrSetProp == S_OK)
CHECK(SetRowsetProperty(pICmd1, DBPROPSET_ROWSET, DBPROP_ACCESSORDER, (LONG_PTR)DBPROPVAL_AO_RANDOM, DBPROPOPTIONS_OPTIONAL), S_OK);
SAFE_RELEASE(pICmd1);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL CExecute_Rowset::Terminate()
{
// {{ TCW_TERM_BASECLASS_CHECK2
return(CCmd::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(CDBSession)
//*-----------------------------------------------------------------------
//| Test Case: CDBSession - general cases
//| Created: 04/08/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL CDBSession::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(CCmd::Init())
// }}
{
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc S_OK: IRowsetInfo::GetSpecification, get same IUnknown
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CDBSession::Variation_1()
{
ICommand* pICmd1 = NULL;
IRowsetInfo* pIRowsetInfo = NULL;
ICommand* pICmd2 = NULL;
IUnknown* pIUnknown = NULL;
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(m_hr = pICmd1->Execute(NULL,IID_IRowsetInfo,NULL,NULL,PPI &pIRowsetInfo),S_OK));
CLEANUP(!CHECK(m_hr = pIRowsetInfo->GetSpecification(IID_ICommand,PPI &pICmd2),S_OK));
CLEANUP(!CHECK(m_hr=pICmd2->GetDBSession(IID_IUnknown,&pIUnknown),S_OK));
if(COMPARE(ValidateSessionObject(pIUnknown),TRUE))
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pICmd2);
SAFE_RELEASE(pIRowsetInfo);
SAFE_RELEASE(pIUnknown);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc S_OK: Don't execute command, get same IUnknown
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CDBSession::Variation_2()
{
ICommand* pICmd1 = NULL;
IUnknown* pIUnknown = NULL;
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(!CHECK(m_hr=pICmd1->GetDBSession(IID_IUnknown,&pIUnknown),S_OK));
if(COMPARE(ValidateSessionObject(pIUnknown),TRUE))
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pIUnknown);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc E_NOINTERFACE: dso iid, valid ptr
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CDBSession::Variation_4()
{
ICommand* pICmd1 = NULL;
IDBInitialize* pIDBInitialize = INVALID(IDBInitialize *);
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(m_hr=pICmd1->GetDBSession(IID_IDBInitialize,PPI &pIDBInitialize),E_NOINTERFACE));
if(!pIDBInitialize)
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
if(pIDBInitialize != INVALID(IDBInitialize *))
SAFE_RELEASE(pIDBInitialize);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc E_NOINTERFACE: iid_null, valid ptr
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CDBSession::Variation_5()
{
ICommand* pICmd1 = NULL;
IDBCreateCommand* pIDBCreateCommand = INVALID(IDBCreateCommand *);
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(m_hr=pICmd1->GetDBSession(IID_NULL,PPI &pIDBCreateCommand),E_NOINTERFACE));
if(!pIDBCreateCommand)
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
if(pIDBCreateCommand != INVALID(IDBCreateCommand *))
SAFE_RELEASE(pIDBCreateCommand);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc E_INVALIDARG: valid session id, ptr==NULL
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CDBSession::Variation_6()
{
ICommand * pICmd1 = NULL;
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECKW(m_hr=pICmd1->GetDBSession(IID_IDBCreateCommand,NULL),E_INVALIDARG));
TPASS
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL CDBSession::Terminate()
{
// {{ TCW_TERM_BASECLASS_CHECK2
return(CCmd::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(Zombie)
//*-----------------------------------------------------------------------
//| Test Case: Zombie - Induce zombie states
//| Created: 02/02/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL Zombie::Init()
{
if(!CTransaction::Init())
return TEST_SKIPPED;
odtLog << L"CTransaction::Init succeeded\n";
//This is a mandatory interface, it should always succeed
return COMPARE(RegisterInterface(COMMAND_INTERFACE, IID_ICommand, 0, NULL), TRUE);
}
//*-----------------------------------------------------------------------
// @mfunc TestTxn
// Tests commit/abort with respect to IAccessor on commands
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Zombie::TestTxn
(
ETXN eTxn,
BOOL fRetaining
)
{
BOOL fSuccess = FALSE;
ULONG index=0;
ICommandText * pICommand=NULL;
IRowset * pIRowset=NULL;
IUnknown * pIDBSession=NULL;
if (!StartTransaction(SELECT_ALLFROMTBL, (IUnknown **)&pICommand,
0, NULL, NULL, ISOLATIONLEVEL_READUNCOMMITTED))
goto CLEANUP;
if (eTxn == ETXN_COMMIT)
{
//Commit the transaction, with retention as specified
if(!GetCommit(fRetaining))
goto CLEANUP;
}
else
{
//Abort the transaction, with retention as specified
if(!GetAbort(fRetaining))
goto CLEANUP;
}
//Make sure everything still works after commit or abort
if (!CHECK(pICommand->Execute(NULL,IID_IRowset,NULL,NULL,PPI &pIRowset),S_OK))
goto CLEANUP;
if(!CHECK(pICommand->Cancel(),S_OK))
goto CLEANUP;
fSuccess = CHECK(pICommand->GetDBSession(IID_IDBCreateCommand,&pIDBSession),S_OK);
CLEANUP:
SAFE_RELEASE(pIDBSession);
SAFE_RELEASE(pICommand);
SAFE_RELEASE(pIRowset);
//Return code of Commit/Abort will vary depending on whether
//or not we have an open txn, so adjust accordingly
if (fRetaining)
CleanUpTransaction(S_OK);
else
CleanUpTransaction(XACT_E_NOTRANSACTION);
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc State 1:Abort with fRetaining set to TRUE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Zombie::Variation_1()
{
return TestTxn(ETXN_ABORT, TRUE);
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc State 2:Abort with fRetaining set to FALSE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Zombie::Variation_2()
{
return TestTxn(ETXN_ABORT, FALSE);
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc State 3:Commit with fRetaining set to TRUE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Zombie::Variation_3()
{
return TestTxn(ETXN_COMMIT, TRUE);
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc State 4:Commit with fRetaining set to FALSE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int Zombie::Variation_4()
{
return TestTxn(ETXN_COMMIT, FALSE);
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL Zombie::Terminate()
{
// {{ TCW_TERM_BASECLASS_CHECK2
return(CTransaction::Terminate());
} // }}
// {{ TCW_TC_PROTOTYPE(CCancel)
//*-----------------------------------------------------------------------
//| Test Case: CCancel - general cases
//| Created: 04/08/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL CCancel::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(CCmd::Init())
// }}
{
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc S_OK,S_OK: 2 cmd obj (Select & Insert), cancel each during execution
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CCancel::Variation_1()
{
ICommand * pICmd1=NULL;
ICommand * pICmd2=NULL;
IRowset * pIRowset = NULL;
HRESULT hr = NOERROR;
ULONG iTime = 0;
// Make sure the threading model is correct for this variation. We only
// support Free threaded.
if (!VerifyThreadingModel(COINIT_MULTITHREADED))
return TEST_SKIPPED;
TESTBEGIN;
INIT_THRDS(FOUR_THRDS);
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd2,NULL));
// Set text in command object
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_COLLISTFROMTBL,NULL)))
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
hr = SetCommandText(m_pIMalloc,pICmd2,m_pTable,NULL,eSELECT,SELECT_COLLISTFROMTBL,NULL);
else
hr = SetCommandText(m_pIMalloc,pICmd2,m_pTable,NULL,eINSERT,NO_QUERY,NULL);
CLEANUP(FAILED(hr))
{
HRESULT hrExecute=DB_E_CANCELED;
HRESULT hrExecuteOr = S_OK; // Expect either hrExecute or hrExecuteOr result from Execute command.
HRESULT hrCancel=S_OK;
HRESULT hrCancelOr=DB_E_CANTCANCEL;
STATEMENTKIND eStatementKind1 = eSELECT;
STATEMENTKIND eStatementKind2 = eINSERT;
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
eStatementKind2 = eSELECT;
THRDARG ExecuteFirstCmd = { this, pICmd1,&hrExecute, &eStatementKind1, &hrExecuteOr};
THRDARG CancelFirstCmd = { this, pICmd1,&hrCancelOr, &eStatementKind1, &hrCancel};
THRDARG ExecuteSecondCmd ={ this, pICmd2,&hrExecute, &eStatementKind2, &hrExecuteOr};
THRDARG CancelSecondCmd = { this, pICmd2,&hrCancelOr, &eStatementKind2, &hrCancel};
// Try 100 times to see if thread timing impacts results.
for (iTime = 0; iTime < 100; iTime++)
{
// odtLog << L"Time # " << iTime+1 << L"\n";
//Create Thread
CREATE_THRD(THRD_ONE,Execute,&ExecuteFirstCmd);
CREATE_THRD(THRD_TWO,Cancel,&CancelFirstCmd);
CREATE_THRD(THRD_THREE,Execute,&ExecuteSecondCmd);
CREATE_THRD(THRD_FOUR,Cancel,&CancelSecondCmd);
//Start Thread
START_THRDS();
// End Thread
END_THRDS();
}
}
TPASS;
CLEANUP:
odtLog << L"Times: " << iTime << L"\n";
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pICmd2);
SAFE_RELEASE(pIRowset);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc S_OK,S_OK: 2 cmd obj (Select & Insert), cancel 1 during, cancel 1 after execution
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CCancel::Variation_2()
{
ICommand * pICmd1=NULL;
ICommand * pICmd2=NULL;
HRESULT hr = NOERROR;
// Make sure the threading model is correct for this variation. We only
// support Free threaded.
if (!VerifyThreadingModel(COINIT_MULTITHREADED))
return TEST_SKIPPED;
TESTBEGIN;
INIT_THRDS(TWO_THRDS);
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd2,NULL))
// Set text in command object
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_COLLISTFROMTBL,NULL)));
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
hr = SetCommandText(m_pIMalloc,pICmd2,m_pTable,NULL,eSELECT,SELECT_COLLISTFROMTBL,NULL);
else
hr = SetCommandText(m_pIMalloc,pICmd2,m_pTable,NULL,eINSERT,NO_QUERY,NULL);
CLEANUP(FAILED(hr))
{ // First cmd object
HRESULT hrExecute1=DB_E_CANCELED;
HRESULT hrExecuteOr = S_OK; // Expect either Canceled or S_OK
HRESULT hrCancel1=S_OK;
HRESULT hrCancel1Or=DB_E_CANTCANCEL;
STATEMENTKIND eStatementKind = eSELECT;
THRDARG ExecuteFirstCmd = { this, pICmd1,&hrExecute1, &eStatementKind, &hrExecuteOr};
THRDARG CancelFirstCmd = { this, pICmd1,&hrCancel1, &eStatementKind, &hrCancel1Or};
//Create Thread
CREATE_THRD(THRD_ONE,Execute,&ExecuteFirstCmd);
CREATE_THRD(THRD_TWO,Cancel,&CancelFirstCmd);
//Start Thread
START_THRDS();
// End Thread
END_THRDS();
}
// Second cmd object
// cRowsAffected is null on purpose
if(!CHECK(pICmd2->Execute(NULL,IID_NULL,NULL,NULL,NULL),S_OK))
goto CLEANUP;
hr = pICmd2->Cancel();
if(!(hr==S_OK)&&!(hr==DB_E_CANTCANCEL))
goto CLEANUP;
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pICmd2);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc S_OK,S_OK: 2 cmd obj (Select & Insert), cancel 1 before, cancel 1 during execution
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CCancel::Variation_3()
{
ICommand * pICmd1=NULL;
ICommand * pICmd2=NULL;
HRESULT hr = NOERROR;
// Make sure the threading model is correct for this variation. We only
// support Free threaded.
if (!VerifyThreadingModel(COINIT_MULTITHREADED))
return TEST_SKIPPED;
TESTBEGIN;
INIT_THRDS(TWO_THRDS);
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd2,NULL));
// Set text in command object
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_COLLISTFROMTBL,NULL)));
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
hr = SetCommandText(m_pIMalloc,pICmd2,m_pTable,NULL,eSELECT,SELECT_COLLISTFROMTBL,NULL);
else
hr = SetCommandText(m_pIMalloc,pICmd2,m_pTable,NULL,eINSERT,NO_QUERY,NULL);
CLEANUP(FAILED(hr));
// Second cmd object
// cRowsAffected is null on purpose
if(!CHECK(pICmd2->Execute(NULL,IID_NULL,NULL,NULL,NULL),S_OK))
goto CLEANUP;
hr = pICmd2->Cancel();
if(!(hr==S_OK)&&!(hr==DB_E_CANTCANCEL))
goto CLEANUP;
{ // First cmd object
HRESULT hrExecute1=DB_E_CANCELED;
HRESULT hrExecuteOr=S_OK; // Expect DB_E_CANCELED or S_OK.
HRESULT hrCancel1=S_OK;
HRESULT hrCancel1Or=DB_E_CANTCANCEL;
STATEMENTKIND eStatementKind1 = eSELECT;
THRDARG ExecuteFirstCmd = { this, pICmd1,&hrExecute1, &eStatementKind1, &hrExecuteOr};
THRDARG CancelFirstCmd = { this, pICmd1,&hrCancel1, &eStatementKind1, &hrCancel1Or};
//Create Thread
CREATE_THRD(THRD_ONE,Execute,&ExecuteFirstCmd);
CREATE_THRD(THRD_TWO,Cancel,&CancelFirstCmd);
//Start Thread
START_THRDS();
// End Thread
END_THRDS();
}
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pICmd2);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc S_OK,S_OK: 2 cmd obj, cancel 1 before, cancel 1 after
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CCancel::Variation_4()
{
ICommand * pICmd1=NULL;
ICommand * pICmd2=NULL;
HRESULT hr = NOERROR;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd2,NULL))
// Set text in command object
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_COLLISTFROMTBL,NULL)))
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
hr = SetCommandText(m_pIMalloc,pICmd2,m_pTable,NULL,eSELECT,SELECT_COLLISTFROMTBL,NULL);
else
hr = SetCommandText(m_pIMalloc,pICmd2,m_pTable,NULL,eINSERT,NO_QUERY,NULL);
CLEANUP(FAILED(hr));
if(!CHECK(pICmd1->Cancel(),S_OK))
goto CLEANUP;
// Second cmd object
// cRowsAffected is null on purpose
if(!CHECK(pICmd1->Execute(NULL,IID_NULL,NULL,NULL,NULL),S_OK))
goto CLEANUP;
// Second cmd object
// cRowsAffected is null on purpose
if(!CHECK(pICmd2->Execute(NULL,IID_NULL,NULL,NULL,NULL),S_OK))
goto CLEANUP;
hr = pICmd2->Cancel();
if(!(hr==S_OK)&&!(hr==DB_E_CANTCANCEL))
goto CLEANUP;
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pICmd2);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc S_OK: 1 cmd obj (Select), cancel before execution
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CCancel::Variation_5()
{
ICommand * pICmd1=NULL;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
// Set text in command object
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_COLLISTFROMTBL,NULL)))
if(!CHECK(pICmd1->Cancel(),S_OK))
goto CLEANUP;
// Second cmd object
// cRowsAffected is null on purpose
if(!CHECK(pICmd1->Execute(NULL,IID_NULL,NULL,NULL,NULL),S_OK))
goto CLEANUP;
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc S_OK: 1 cmd obj (Select), cancel after execution
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CCancel::Variation_6()
{
ICommand * pICmd1=NULL;
HRESULT hr;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
// Set text in command object
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_COLLISTFROMTBL,NULL)))
// Second cmd object
// cRowsAffected is null on purpose
if(!CHECK(pICmd1->Execute(NULL,IID_NULL,NULL,NULL,NULL),S_OK))
goto CLEANUP;
hr = pICmd1->Cancel();
if(!(hr==S_OK)&&!(hr==DB_E_CANTCANCEL))
goto CLEANUP;
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc S_OK: 1 cmd obj (Select), execute, cancel cancel
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CCancel::Variation_7()
{
ICommand * pICmd1=NULL;
// Make sure the threading model is correct for this variation. We only
// support Free threaded.
if (!VerifyThreadingModel(COINIT_MULTITHREADED))
return TEST_SKIPPED;
TESTBEGIN;
INIT_THRDS(THREE_THRDS);
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL))
// Set text in command object
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_COLLISTFROMTBL,NULL)))
{ // First cmd object
HRESULT hrExecute1=DB_E_CANCELED;
HRESULT hrExecuteOr=S_OK; // Expect S_OK or DB_E_CANCELED.
HRESULT hrCancel1=S_OK;
HRESULT hrCancel1Or=DB_E_CANTCANCEL;
HRESULT hrCancel2 = S_OK;
HRESULT hrCancel2Or=DB_E_CANTCANCEL;
STATEMENTKIND eStatementKind = eSELECT;
THRDARG ExecuteFirstCmd = { this, pICmd1,&hrExecute1, &eStatementKind, &hrExecuteOr};
THRDARG CancelFirstCmd = { this, pICmd1,&hrCancel1, &eStatementKind, &hrCancel1Or};
THRDARG CancelFirstCmd2 = { this, pICmd1,&hrCancel2, &eStatementKind, &hrCancel2Or};
//Create Thread
CREATE_THRD(THRD_ONE,Execute,&ExecuteFirstCmd);
CREATE_THRD(THRD_TWO,Cancel,&CancelFirstCmd);
CREATE_THRD(THRD_THREE,Cancel,&CancelFirstCmd2);
//Start Thread
START_THRDS();
// End Thread
END_THRDS();
}
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc S_OK: 1 cmd obj (Insert), cancel before execution
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CCancel::Variation_8()
{
ICommand * pICmd1=NULL;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
// Set text in command object
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
if(!CHECK(pICmd1->Cancel(),S_OK))
goto CLEANUP;
// Second cmd object
// cRowsAffected is null on purpose
if(!CHECK(pICmd1->Execute(NULL,IID_NULL,NULL,NULL,NULL),S_OK))
goto CLEANUP;
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc S_OK: 1 cmd obj (Insert), cancel after execution
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CCancel::Variation_9()
{
ICommand * pICmd1=NULL;
HRESULT hr;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
// Set text in command object
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
// Second cmd object
// cRowsAffected is null on purpose
if(!CHECK(pICmd1->Execute(NULL,IID_NULL,NULL,NULL,NULL),S_OK))
goto CLEANUP;
hr = pICmd1->Cancel();
if((hr!=S_OK) && (hr!=DB_E_CANTCANCEL))
{
// We need to post an error here
CHECK(hr, S_OK);
goto CLEANUP;
}
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc S_OK: 1 cmd obj (Insert), execute, cancel cancel
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CCancel::Variation_10()
{
ICommand * pICmd1=NULL;
//If the provider is read only or does not understand SQL, skip variation.
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
return TEST_SKIPPED;
// Make sure the threading model is correct for this variation. We only
// support Free threaded.
if (!VerifyThreadingModel(COINIT_MULTITHREADED))
return TEST_SKIPPED;
TESTBEGIN;
INIT_THRDS(THREE_THRDS);
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
// Set text in command object
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eINSERT,NO_QUERY,NULL)));
{ // First cmd object
HRESULT hrExecute1=DB_E_CANCELED;
HRESULT hrExecuteOr=S_OK;
HRESULT hrCancel1=S_OK;
HRESULT hrCancel2 = S_OK;
HRESULT hrCancel1Or = DB_E_CANTCANCEL;
HRESULT hrCancel2Or = DB_E_CANTCANCEL;
STATEMENTKIND eStatementKind = eINSERT;
THRDARG ExecuteFirstCmd = { this, pICmd1,&hrExecute1, &eStatementKind, &hrExecuteOr};
THRDARG CancelFirstCmd = { this, pICmd1,&hrCancel1, &eStatementKind, &hrCancel1Or};
THRDARG CancelFirstCmd2 = { this, pICmd1,&hrCancel2, &eStatementKind, &hrCancel2Or};
//Create Thread
CREATE_THRD(THRD_ONE,Execute,&ExecuteFirstCmd);
CREATE_THRD(THRD_TWO,Cancel,&CancelFirstCmd);
CREATE_THRD(THRD_THREE,Cancel,&CancelFirstCmd2);
//Start Thread
START_THRDS();
// End Thread
END_THRDS();
}
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN;
}
// }}
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc No Query Set, 1 Cancel per Thread, Before Execution
//
// @rdesc TEST_PASS or TEST_FAIL
//
int CCancel::Variation_11()
{
ICommand * pICmd1=NULL;
TESTBEGIN;
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
// Second cmd object
// cRowsAffected is null on purpose
if(!CHECK(pICmd1->Cancel(),S_OK))
goto CLEANUP;
if(!CHECK(pICmd1->Execute(NULL,IID_NULL,NULL,NULL,NULL),DB_E_NOCOMMAND))
goto CLEANUP;
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
TRETURN
}
// }}
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL CCancel::Terminate()
{
// {{ TCW_TERM_BASECLASS_CHECK2
return(CCmd::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(TCExtendedErrors)
//*-----------------------------------------------------------------------
//| Test Case: TCExtendedErrors - Extended Errors
//| Created: 08/04/96
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCExtendedErrors::Init()
{
ICommand *pICommand = NULL;
ISupportErrorInfo *pISupportErrorInfo = NULL;
HRESULT hr = NOERROR;
BOOL fResult = TEST_FAIL;
//Create an object for checking extended errors, which will use
//m_pError to increment the error count as needed.
m_pExtError = new CExtError(m_pThisTestModule->m_ProviderClsid, m_pError);
if (!m_pExtError)
return FALSE;
CLEANUP(!CCmd::Init());
CLEANUP(!GetCommand(IID_ICommand,PPI &pICommand,NULL));
CLEANUP(FAILED(hr=pICommand->QueryInterface(IID_ISupportErrorInfo, (void **)&pISupportErrorInfo) ));
fResult = TEST_PASS;
CLEANUP:
if(hr==E_NOINTERFACE)
{
odtLog<<L"ISupportErrorInfo is not supported."<<ENDL;
fResult = TEST_SKIPPED;
}
SAFE_RELEASE(pICommand);
SAFE_RELEASE(pISupportErrorInfo);
return fResult;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Valid ICommand call with previous error object existing.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCExtendedErrors::Variation_1()
{
BOOL fSuccess = FALSE;
//ULONG index=0;
ICommand * pICommand=NULL;
IRowset * pIRowset=NULL;
IUnknown * pIDBSession=NULL;
//For each method of the interface, first create an error object on
//the current thread, then try get S_OK from the ICommand method.
//We then check extended errors to verify nothing is set since an
//error object shouldn't exist following a successful call.
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICommand,NULL))
//create an error object
m_pExtError->CauseError();
// First session object's command
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICommand,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
CLEANUP(!CHECK(m_hr = pICommand->Execute(NULL,IID_IRowset,NULL,NULL,PPI &pIRowset),S_OK));
//Do extended check following Execute
fSuccess = XCHECK(pICommand, IID_ICommand, m_hr);
//create an error object
m_pExtError->CauseError();
if(CHECK(m_hr=pICommand->Cancel(),S_OK))
//Do extended check following Cancel
fSuccess &= XCHECK(pICommand, IID_ICommand, m_hr);
//create an error object
m_pExtError->CauseError();
if(CHECK(m_hr=pICommand->GetDBSession(IID_IDBCreateCommand,&pIDBSession),S_OK))
//Do extended check following GetDBSession
fSuccess &= XCHECK(pICommand, IID_ICommand, m_hr);
CLEANUP:
SAFE_RELEASE(pIDBSession);
SAFE_RELEASE(pICommand);
SAFE_RELEASE(pIRowset);
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Invalid Execute call with previous error object existing
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCExtendedErrors::Variation_2()
{
BOOL fSuccess=TEST_FAIL;
ICommand* pICommand=NULL;
IRowset * pRowset=NULL;
WCHAR wszSQL[]=L"Select * from";
//For each method of the interface, first create an error object on
//the current thread, then try get a failure from the ICommand method.
//We then check extended errors to verify the right extended error behavior.
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICommand,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICommand,m_pTable,NULL,eSQL,NO_QUERY,(WCHAR *) wszSQL)));
//create an error object
m_pExtError->CauseError();
//Command text contains error
if(CHECK(m_hr = pICommand->Execute(NULL,IID_IRowset,NULL,NULL,PPI &pRowset),DB_E_ERRORSINCOMMAND))
{
//Do extended check following Execute
fSuccess = XCHECK(pICommand, IID_ICommand, m_hr);
}
if(!pRowset)
fSuccess &= TRUE;
CLEANUP:
SAFE_RELEASE(pICommand);
SAFE_RELEASE(pRowset);
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Invalid GetDBSession calls with previous error object existing
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCExtendedErrors::Variation_3()
{
BOOL fSuccess=TEST_FAIL;
ICommand* pICommand=NULL;
IDBInitialize* pIDBInitialize=NULL;
//For each method of the interface, first create an error object on
//the current thread, then try get a failure from the ICommand method.
//We then check extended errors to verify the right extended error behavior.
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICommand,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICommand,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
//create an error object
m_pExtError->CauseError();
if(CHECK(m_hr=pICommand->GetDBSession(IID_IDBInitialize,PPI &pIDBInitialize),E_NOINTERFACE))
//Do extended check following GetDBSession
fSuccess = XCHECK(pICommand, IID_ICommand, m_hr);
if(!pIDBInitialize)
fSuccess &= TRUE;
CLEANUP:
SAFE_RELEASE(pICommand);
SAFE_RELEASE(pIDBInitialize);
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Invalid GetDBSession calls with no previous error object existing
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCExtendedErrors::Variation_4()
{
BOOL fSuccess=TEST_FAIL;
ICommand* pICommand=NULL;
//For each method of the interface, with no error object on
//the current thread, try get a failure from the ICommand method.
//We then check extended errors to verify the right extended error behavior.
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICommand,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICommand,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
if(CHECK(m_hr=pICommand->GetDBSession(IID_IDBCreateCommand,NULL),E_INVALIDARG))
//Do extended check following GetDBSession
fSuccess = XCHECK(pICommand, IID_ICommand, m_hr);
CLEANUP:
SAFE_RELEASE(pICommand);
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc E_NOINTERFACE Execute call with no previous error object existing
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCExtendedErrors::Variation_5()
{
BOOL fSuccess=TEST_FAIL;
ICommand* pICommand=NULL;
IRowset* pIRowset=NULL;
//For each method of the interface, with no error object on
//the current thread, try get a failure from the ICommand method.
//We then check extended errors to verify the right extended error behavior.
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICommand,NULL))
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICommand,m_pTable,NULL,eSELECT,SELECT_ALLFROMTBL,NULL)));
if(CHECK(m_hr = pICommand->Execute(NULL,IID_IDBInitialize,NULL,NULL,PPI &pIRowset),E_NOINTERFACE))
//Do extended check following Execute
fSuccess = XCHECK(pICommand, IID_ICommand, m_hr);
if(!pIRowset)
fSuccess &= TRUE;
CLEANUP:
SAFE_RELEASE(pICommand);
SAFE_RELEASE(pIRowset);
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc DB_E_NOCOMMAND Execute call with no previous error object existing
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCExtendedErrors::Variation_6()
{
BOOL fSuccess=TEST_FAIL;
ICommand* pICommand=NULL;
IRowset* pIRowset=NULL;
//For each method of the interface, with no error object on
//the current thread, try get a failure from the ICommand method.
//We then check extended errors to verify the right extended error behavior.
TESTBEGIN
CLEANUP(!GetCommand(IID_ICommand,PPI &pICommand,NULL))
// Second cmd object
// cRowsAffected is null on purpose
if(!CHECK(pICommand->Cancel(),S_OK))
goto CLEANUP;
if(CHECK(m_hr=pICommand->Execute(NULL,IID_NULL,NULL,NULL,NULL),DB_E_NOCOMMAND))
{
//Do extended check following Execute
fSuccess = XCHECK(pICommand, IID_ICommand, m_hr);
}
CLEANUP:
SAFE_RELEASE(pICommand);
if (fSuccess)
return TEST_PASS;
else
return TEST_FAIL;
}
//}}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc DB_E_CANCELED Check extended error info when Execute is canceled
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCExtendedErrors::Variation_7()
{
ICommand * pICmd1=NULL;
ICommand * pICmd2=NULL;
IRowset * pIRowset = NULL;
HRESULT hr = NOERROR;
// Make sure the threading model is correct for this variation. We only
// support Free threaded.
if (!VerifyThreadingModel(COINIT_MULTITHREADED))
return TEST_SKIPPED;
// In this variation we want to validate extended error information
m_fValidateExtended = TRUE;
TESTBEGIN;
INIT_THRDS(FOUR_THRDS);
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd1,NULL));
CLEANUP(!GetCommand(IID_ICommand,PPI &pICmd2,NULL));
// Set text in command object
CLEANUP(FAILED(SetCommandText(m_pIMalloc,pICmd1,m_pTable,NULL,eSELECT,SELECT_COLLISTFROMTBL,NULL)))
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
hr = SetCommandText(m_pIMalloc,pICmd2,m_pTable,NULL,eSELECT,SELECT_COLLISTFROMTBL,NULL);
else
hr = SetCommandText(m_pIMalloc,pICmd2,m_pTable,NULL,eINSERT,NO_QUERY,NULL);
CLEANUP(FAILED(hr))
{
HRESULT hrExecute=DB_E_CANCELED;
HRESULT hrExecuteOr = S_OK; // Expect either hrExecute or hrExecuteOr result from Execute command.
HRESULT hrCancel=S_OK;
HRESULT hrCancelOr=DB_E_CANTCANCEL;
STATEMENTKIND eStatementKind1 = eSELECT;
STATEMENTKIND eStatementKind2 = eINSERT;
if( g_fReadOnlyProvider || m_pTable->GetSQLSupport() == DBPROPVAL_SQL_NONE )
eStatementKind2 = eSELECT;
THRDARG ExecuteFirstCmd = { this, pICmd1,&hrExecute, &eStatementKind1, &hrExecuteOr};
THRDARG CancelFirstCmd = { this, pICmd1,&hrCancelOr, &eStatementKind1, &hrCancel};
THRDARG ExecuteSecondCmd ={ this, pICmd2,&hrExecute, &eStatementKind2, &hrExecuteOr};
THRDARG CancelSecondCmd = { this, pICmd2,&hrCancelOr, &eStatementKind2, &hrCancel};
//Create Thread
CREATE_THRD(THRD_ONE,Execute,&ExecuteFirstCmd);
CREATE_THRD(THRD_TWO,Cancel,&CancelFirstCmd);
CREATE_THRD(THRD_THREE,Execute,&ExecuteSecondCmd);
CREATE_THRD(THRD_FOUR,Cancel,&CancelSecondCmd);
//Start Thread
START_THRDS();
// End Thread
END_THRDS();
}
TPASS;
CLEANUP:
SAFE_RELEASE(pICmd1);
SAFE_RELEASE(pICmd2);
SAFE_RELEASE(pIRowset);
m_fValidateExtended = FALSE;
TRETURN;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCExtendedErrors::Terminate()
{
//free error object
if (m_pExtError)
delete m_pExtError;
m_pExtError = NULL;
return (CCmd::Terminate());
} // }}
// }}