//-------------------------------------------------------------------- // 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 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 <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; iExecute(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<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 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 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 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 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<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<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 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; iExecute(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; ulIndexSelect(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; ulColGetSQLSupport() == 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<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()); } // }} // }}