//-------------------------------------------------------------------- // Microsoft OLE DB Test // // Copyright (C) 1995-2000 Microsoft Corporation // // @doc // // @module IRUpdate.cpp | This module tests the OLEDB IRowsetUpdate interface // #include "MODStandard.hpp" // Standard headers #include "IRUpdate.h" // IRowsetUpdate header #include "msdasql.h" // KAGPROP_QUERYBASEDUPDATES #include "ExtraLib.h" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Module Values // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // {{ TCW_MODULE_GLOBALS DECLARE_MODULE_CLSID = { 0x0bb5a150, 0x8cce, 0x11cf, { 0xaa, 0x41, 0x00, 0xaa, 0x00, 0x3e, 0x77, 0x8a }}; DECLARE_MODULE_NAME("IRowsetUpdate"); DECLARE_MODULE_OWNER("Microsoft"); DECLARE_MODULE_DESCRIP("IRowsetUpdate interface test"); DECLARE_MODULE_VERSION(838070366); // }} //-------------------------------------------------------------------- // @func Module level initialization routine // // @rdesc Success or Failure // @flag TRUE | Successful initialization // @flag FALSE | Initialization problems // BOOL ModuleInit(CThisTestModule * pThisTestModule) { return CommonModuleInit(pThisTestModule, IID_IRowsetUpdate, FOURTEEN_ROWS); } //-------------------------------------------------------------------- // @func Module level termination routine // // @rdesc Success or Failure // @flag TRUE | Successful initialization // @flag FALSE | Initialization problems // BOOL ModuleTerminate(CThisTestModule * pThisTestModule) { return CommonModuleTerminate(pThisTestModule); } //////////////////////////////////////////////////////////////////////////// // TCIRowsetUpdate // //////////////////////////////////////////////////////////////////////////// class TCIRowsetUpdate : public CRowsetUpdate { public: //constructors TCIRowsetUpdate(WCHAR* pwszTestCaseName = INVALID(WCHAR*)); virtual ~TCIRowsetUpdate(); //methods virtual BOOL Init(); virtual BOOL Terminate(); virtual BOOL VerifyAddRefRows ( ULONG cRows, HROW* rghRows, ULONG ulRefCount = 0, DBROWSTATUS dwRowStatus = DBROWSTATUS_S_OK ); virtual BOOL VerifyReleaseRows ( ULONG cRows, HROW* rghRows, ULONG ulRefCount = 0, DBROWSTATUS dwRowStatus = DBROWSTATUS_S_OK ); //@mfunc: verify the reference counts for an array of RefCounts virtual BOOL VerifyRowStatus ( ULONG cRows, //[in] cRows DBROWSTATUS* rgRowStatus, //[in] rgRowStatus DBROWSTATUS dwRowStatus = DBROWSTATUS_S_OK //[in] Expected RowStatus ); }; //////////////////////////////////////////////////////////////////////////// // TCIRowsetUpdate::TCIRowsetUpdate // //////////////////////////////////////////////////////////////////////////// TCIRowsetUpdate::TCIRowsetUpdate(WCHAR * wstrTestCaseName) : CRowsetUpdate(wstrTestCaseName) { } //////////////////////////////////////////////////////////////////////////// // TCIRowsetUpdate::~TCIRowsetUpdate // //////////////////////////////////////////////////////////////////////////// TCIRowsetUpdate::~TCIRowsetUpdate() { } //////////////////////////////////////////////////////////////////////////// // TCIRowsetUpdate::Init // //////////////////////////////////////////////////////////////////////////// BOOL TCIRowsetUpdate::Init() { return CRowsetUpdate::Init(); } //////////////////////////////////////////////////////////////////////////// // TCIRowsetUpdate::Terminate // //////////////////////////////////////////////////////////////////////////// BOOL TCIRowsetUpdate::Terminate() { return CRowsetUpdate::Terminate(); } //////////////////////////////////////////////////////////////////////////// // TCIRowsetUpdate::VerifyReleaseRows // //////////////////////////////////////////////////////////////////////////// BOOL TCIRowsetUpdate::VerifyReleaseRows ( ULONG cRows, HROW* rghRows, ULONG ulRefCount, DBROWSTATUS dwRowStatus ) { TBEGIN ULONG* rgRefCounts = NULL; DBROWSTATUS* rgRowStatus = NULL; if(cRows && rghRows) { //Release the rows TESTC_(ReleaseRows(cRows, rghRows, &rgRefCounts, &rgRowStatus),S_OK); TESTC(rgRefCounts != NULL && rgRowStatus != NULL); //Verify the ref counts and status QTESTC(VerifyRefCounts(cRows, rgRefCounts, ulRefCount)); QTESTC(VerifyRowStatus(cRows, rgRowStatus, dwRowStatus)); } CLEANUP: PROVIDER_FREE(rgRefCounts); PROVIDER_FREE(rgRowStatus); TRETURN; } //////////////////////////////////////////////////////////////////////////// // TCIRowsetUpdate::VerifyAddRefRows // //////////////////////////////////////////////////////////////////////////// BOOL TCIRowsetUpdate::VerifyAddRefRows ( ULONG cRows, HROW* rghRows, ULONG ulRefCount, DBROWSTATUS dwRowStatus ) { TBEGIN ULONG* rgRefCounts = NULL; DBROWSTATUS* rgRowStatus = NULL; if(cRows && rghRows) { rgRefCounts = PROVIDER_ALLOC_(cRows, ULONG); rgRowStatus = PROVIDER_ALLOC_(cRows, DBROWSTATUS); TESTC(rgRefCounts != NULL); TESTC(rgRowStatus != NULL); //AddRef the rows TESTC_(pIRowset()->AddRefRows(cRows, rghRows, rgRefCounts, rgRowStatus),S_OK); //Verify the ref count / row status TESTC(VerifyRefCounts(cRows, rgRefCounts, ulRefCount)); TESTC(VerifyRowStatus(cRows, rgRowStatus, dwRowStatus)); } CLEANUP: PROVIDER_FREE(rgRefCounts); PROVIDER_FREE(rgRowStatus); TRETURN; } //////////////////////////////////////////////////////////////////////////// // TCIRowsetUpdate::VerifyRowStatus // //////////////////////////////////////////////////////////////////////////// BOOL TCIRowsetUpdate::VerifyRowStatus ( ULONG cRows, //[in] cRows DBROWSTATUS* rgRowStatus, //[in] rgRowStatus DBROWSTATUS dwRowStatus //[in] Expected RowStatus ) { //every element in the ref count array should be the same as cExpected for(ULONG i=0; iQueryI(IID_IRowsetUpdate, valid int Variation_10(); // @cmember General - Verify AddRef / Release int Variation_11(); // @cmember General - Verify RefCount or row handles int Variation_12(); // @cmember Boundary - [NULL Accessor] int Variation_13(); // @cmember Boundary - [PASSBYREF NULL Accessor] int Variation_14(); // @cmember Boundary - [valid, valid, NULL] int Variation_15(); // @cmember Boundary - [DB_INVALID_ROW, valid, valid] int Variation_16(); // @cmember Boundary - [valid, DB_NULL_HACCESSOR, valid] int Variation_17(); // @cmember Boundary - Call GetOriginalData before any other method int Variation_18(); // @cmember Empty int Variation_19(); // @cmember Parameters - Hard deleted row int Variation_20(); // @cmember Parameters - Soft Deleted row, No update int Variation_21(); // @cmember Parameters - Newly inserted row, No update int Variation_22(); // @cmember Parameters - Newly inserted row - NULL Accessor, No update int Variation_23(); // @cmember Parameters - A modified row, No update int Variation_24(); // @cmember Parameters - An inserted, modified row int Variation_25(); // @cmember Parameters - A newly inserted row, update int Variation_26(); // @cmember Parameters - A newly inserted row - NULL Accessor, update int Variation_27(); // @cmember Parameters - A modified row, update int Variation_28(); // @cmember Parameters - An inserted/modified row, update int Variation_29(); // @cmember Parameters - Insert/Modify/Delete all rows int Variation_30(); // @cmember Empty int Variation_31(); // @cmember Empty int Variation_32(); // @cmember Empty int Variation_33(); // @cmember Empty int Variation_34(); // @cmember Empty int Variation_35(); // @cmember Empty int Variation_36(); // @cmember Empty int Variation_37(); // @cmember Accessor - BLOB / Long columns - SetPos int Variation_38(); // @cmember Accessor - BLOB / Long columns - QBU int Variation_39(); // @cmember Empty int Variation_40(); // @cmember Parameters - DB_E_BADACCESSORTYPE int Variation_41(); // @cmember Parameters - DB_E_SEC_E_PERMISSIONDENIED int Variation_42(); // @cmember Parameters - DB_E_BADBINDINFO int Variation_43(); // @cmember Parameters - DB_E_COLUMNUNAVAILABLE int Variation_44(); // @cmember Empty int Variation_45(); // @cmember Sequence - Call GetOriginalData 3 times int Variation_46(); // }} }; // {{ TCW_TESTCASE(TCGetOriginalRows) #define THE_CLASS TCGetOriginalRows BEG_TEST_CASE(TCGetOriginalRows, CRowsetUpdate, L"IRowsetUpdate::GetOriginalRows test case") TEST_VARIATION(1, L"General - IID_IRowsetUpdate on a read-only rowset") TEST_VARIATION(2, L"General - IID_IRowsetUpdate on a read-only rowset, created with OuterJoin") TEST_VARIATION(3, L"General - IID_IRowsetChange implicitly set on IID_IRowsetUpdate") TEST_VARIATION(4, L"General - IID_IRowsetUpdate is not exposed on IRowsetChange") TEST_VARIATION(5, L"General - IID_IRowsetLocate exposed on IRowsetUpdate") TEST_VARIATION(6, L"General - QueryI(invalid, valid") TEST_VARIATION(7, L"General - QueryI(valid, NULL") TEST_VARIATION(8, L"General - QueryI(IID_IRowsetUpdate, valid") TEST_VARIATION(9, L"General - QueryI(IID_IRowsetChange, valid") TEST_VARIATION(10, L"General - IRowsetChange->QueryI(IID_IRowsetUpdate, valid") TEST_VARIATION(11, L"General - Verify AddRef / Release") TEST_VARIATION(12, L"General - Verify RefCount or row handles") TEST_VARIATION(13, L"Boundary - [NULL Accessor]") TEST_VARIATION(14, L"Boundary - [PASSBYREF NULL Accessor]") TEST_VARIATION(15, L"Boundary - [valid, valid, NULL]") TEST_VARIATION(16, L"Boundary - [DB_INVALID_ROW, valid, valid]") TEST_VARIATION(17, L"Boundary - [valid, DB_NULL_HACCESSOR, valid]") TEST_VARIATION(18, L"Boundary - Call GetOriginalData before any other method") TEST_VARIATION(19, L"Empty") TEST_VARIATION(20, L"Parameters - Hard deleted row") TEST_VARIATION(21, L"Parameters - Soft Deleted row, No update") TEST_VARIATION(22, L"Parameters - Newly inserted row, No update") TEST_VARIATION(23, L"Parameters - Newly inserted row - NULL Accessor, No update") TEST_VARIATION(24, L"Parameters - A modified row, No update") TEST_VARIATION(25, L"Parameters - An inserted, modified row") TEST_VARIATION(26, L"Parameters - A newly inserted row, update") TEST_VARIATION(27, L"Parameters - A newly inserted row - NULL Accessor, update") TEST_VARIATION(28, L"Parameters - A modified row, update") TEST_VARIATION(29, L"Parameters - An inserted/modified row, update") TEST_VARIATION(30, L"Parameters - Insert/Modify/Delete all rows") TEST_VARIATION(31, L"Empty") TEST_VARIATION(32, L"Empty") TEST_VARIATION(33, L"Empty") TEST_VARIATION(34, L"Empty") TEST_VARIATION(35, L"Empty") TEST_VARIATION(36, L"Empty") TEST_VARIATION(37, L"Empty") TEST_VARIATION(38, L"Accessor - BLOB / Long columns - SetPos") TEST_VARIATION(39, L"Accessor - BLOB / Long columns - QBU") TEST_VARIATION(40, L"Empty") TEST_VARIATION(41, L"Parameters - DB_E_BADACCESSORTYPE") TEST_VARIATION(42, L"Parameters - DB_E_SEC_E_PERMISSIONDENIED") TEST_VARIATION(43, L"Parameters - DB_E_BADBINDINFO") TEST_VARIATION(44, L"Parameters - DB_E_COLUMNUNAVAILABLE") TEST_VARIATION(45, L"Empty") TEST_VARIATION(46, L"Sequence - Call GetOriginalData 3 times") END_TEST_CASE() #undef THE_CLASS // }} // }} // {{ TCW_TEST_CASE_MAP(TCGetPendingRows) //-------------------------------------------------------------------- // @class IRowsetUpdate::GetPendingRows test case // class TCGetPendingRows : public CRowsetUpdate { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCGetPendingRows,CRowsetUpdate); // }} // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember General - Verify GetPendingRows alters row handles correctly int Variation_1(); // @cmember Boundary - N Changes [NULL, _ALL, NULL, NULL] int Variation_2(); // @cmember Boundary - N Changes [invalid, _ALL, NULL, invalid, invalid] int Variation_3(); // @cmember Boundary - N Changes [NULL, _ALL, valid, NULL, NULL] int Variation_4(); // @cmember Boundary - N Changes [NULL, _ALL, valid, NULL, valid] int Variation_5(); // @cmember Boundary - N Changes [NULL, _ALL, valid, valid, NULL] int Variation_6(); // @cmember Boundary - No Changes [NULL, _ALL, NULL, NULL, NULL] int Variation_7(); // @cmember Boundary - No Changes [NULL, _ALL, valid, NULL, NULL] int Variation_8(); // @cmember Boundary - No Changes [NULL, _ALL, valid, valid, NULL] int Variation_9(); // @cmember Boundary - No Changes [NULL, _ALL, valid, valid, valid] int Variation_10(); // @cmember Boundary - No Changes (NULL, _ALL, valid, NULL, valid int Variation_11(); // @cmember Boundary - Empty Rowset [NULL, _ALL, valid, valid, valid] int Variation_12(); // @cmember Empty int Variation_13(); // @cmember Parameters - DBROWSTATUS seperately, before any changes int Variation_14(); // @cmember Parameters - DBPENDINGSTATUS_INVALIDROW int Variation_15(); // @cmember Parameters - DBROWSTATUS _NEW | _CHANGED | _SOFTDELETED int Variation_16(); // @cmember Parameters - DBPENDINGSTATUS_NEW, w/ no new rows int Variation_17(); // @cmember Parameters - DBPENDINGSTATUS_CHANGED, w/ no changed rows int Variation_18(); // @cmember Parameters - DBPENDINGSTATUS_UNCHANGED, w/ all changed rows int Variation_19(); // @cmember Parameters - DBPENDINGSTATUS_DELETED, w/ no soft-deleted rows int Variation_20(); // @cmember Empty int Variation_21(); // @cmember Parameters - _NEW | _UNCHANGED int Variation_22(); // @cmember Parameters - _NEW | _SOFTDELETED int Variation_23(); // @cmember Empty int Variation_24(); // @cmember Parameters - Insert/Modify/Delete a single row int Variation_25(); // @cmember Empty int Variation_26(); // @cmember Sequence - Call GetPendingRows 3 times int Variation_27(); // @cmember Sequence - Modify the same row twice int Variation_28(); // @cmember Sequence - Modify the same row twice, undo, GetPendingRows int Variation_29(); // }} }; // {{ TCW_TESTCASE(TCGetPendingRows) #define THE_CLASS TCGetPendingRows BEG_TEST_CASE(TCGetPendingRows, CRowsetUpdate, L"IRowsetUpdate::GetPendingRows test case") TEST_VARIATION(1, L"General - Verify GetPendingRows alters row handles correctly") TEST_VARIATION(2, L"Boundary - N Changes [NULL, _ALL, NULL, NULL]") TEST_VARIATION(3, L"Boundary - N Changes [invalid, _ALL, NULL, invalid, invalid]") TEST_VARIATION(4, L"Boundary - N Changes [NULL, _ALL, valid, NULL, NULL]") TEST_VARIATION(5, L"Boundary - N Changes [NULL, _ALL, valid, NULL, valid]") TEST_VARIATION(6, L"Boundary - N Changes [NULL, _ALL, valid, valid, NULL]") TEST_VARIATION(7, L"Boundary - No Changes [NULL, _ALL, NULL, NULL, NULL]") TEST_VARIATION(8, L"Boundary - No Changes [NULL, _ALL, valid, NULL, NULL]") TEST_VARIATION(9, L"Boundary - No Changes [NULL, _ALL, valid, valid, NULL]") TEST_VARIATION(10, L"Boundary - No Changes [NULL, _ALL, valid, valid, valid]") TEST_VARIATION(11, L"Boundary - No Changes (NULL, _ALL, valid, NULL, valid") TEST_VARIATION(12, L"Boundary - Empty Rowset [NULL, _ALL, valid, valid, valid]") TEST_VARIATION(13, L"Empty") TEST_VARIATION(14, L"Parameters - DBROWSTATUS seperately, before any changes") TEST_VARIATION(15, L"Parameters - DBPENDINGSTATUS_INVALIDROW") TEST_VARIATION(16, L"Parameters - DBROWSTATUS _NEW | _CHANGED | _SOFTDELETED") TEST_VARIATION(17, L"Parameters - DBPENDINGSTATUS_NEW, w/ no new rows") TEST_VARIATION(18, L"Parameters - DBPENDINGSTATUS_CHANGED, w/ no changed rows") TEST_VARIATION(19, L"Parameters - DBPENDINGSTATUS_UNCHANGED, w/ all changed rows") TEST_VARIATION(20, L"Parameters - DBPENDINGSTATUS_DELETED, w/ no soft-deleted rows") TEST_VARIATION(21, L"Empty") TEST_VARIATION(22, L"Parameters - _NEW | _UNCHANGED") TEST_VARIATION(23, L"Parameters - _NEW | _SOFTDELETED") TEST_VARIATION(24, L"Empty") TEST_VARIATION(25, L"Parameters - Insert/Modify/Delete a single row") TEST_VARIATION(26, L"Empty") TEST_VARIATION(27, L"Sequence - Call GetPendingRows 3 times") TEST_VARIATION(28, L"Sequence - Modify the same row twice") TEST_VARIATION(29, L"Sequence - Modify the same row twice, undo, GetPendingRows") END_TEST_CASE() #undef THE_CLASS // }} // }} // {{ TCW_TEST_CASE_MAP(TCUndo) //-------------------------------------------------------------------- // @class IRowsetUpdate::Undo test case // class TCUndo : public CRowsetUpdate { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCUndo,CRowsetUpdate); // }} // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember Boundary - No Changes [NULL, 0, NULL, NULL, NULL] int Variation_1(); // @cmember Boundary - No Changes [NULL, N, valid, NULL, NULL] int Variation_2(); // @cmember Boundary - No Changes [NULL,0,NULL, valid, valid] int Variation_3(); // @cmember Boundary - No Changes [invalid, 1, NULL, valid, valid] int Variation_4(); // @cmember Boundary - N Changes [NULL, 0, NULL, NULL, valid] int Variation_5(); // @cmember Boundary - N Changes [NULL, 0, valid, valid, valid] int Variation_6(); // @cmember Boundary - N Changes [NULL, N, valid, NULL, NULL] int Variation_7(); // @cmember Boundary - N Changes [NULL, N, valid, valid, valid] int Variation_8(); // @cmember Boundary - N Changes [invalid, N, NULL, valid, valid] int Variation_9(); // @cmember Boundary - N Changes [invalid, N, valid, valid, NULL] int Variation_10(); // @cmember Empty int Variation_11(); // @cmember Parameters - 3 invalid / 2 modified int Variation_12(); // @cmember Parameters - 1 hard del / 1 invalid / 1 modified int Variation_13(); // @cmember Parameters - 1 hard del / 1 invalid int Variation_14(); // @cmember Parameters - 3 soft del / 2 orginal int Variation_15(); // @cmember Parameters - 3 new rows / 1 orginal int Variation_16(); // @cmember Parameters - 4 modified / 3 orginal int Variation_17(); // @cmember Parameters - 3 soft del / 2 orginal, update int Variation_18(); // @cmember Parameters - 3 new rows / 1 orginal, update int Variation_19(); // @cmember Parameters - 4 modified / 3 orginal, update int Variation_20(); // @cmember Parameters - 3 hard del / 2 modified int Variation_21(); // @cmember Parameters - Insert/Modify/Delete a single row int Variation_22(); // @cmember Parameters - Insert/Modify/Delete a single row, Update int Variation_23(); // @cmember Parameters - Duplicate entries in the array int Variation_24(); // @cmember Empty int Variation_25(); // @cmember Sequence - Fetch every other row, modify every even, undo all odd. int Variation_26(); // @cmember Sequence - Call Undo 3 times int Variation_27(); // @cmember Empty int Variation_28(); // @cmember Boundary - Empty Rowset [NULL, 0 ,NULL, valid, valid] int Variation_29(); // @cmember Empty int Variation_30(); // @cmember Accessor - BLOB / Long columns - SetPos int Variation_31(); // @cmember Accessor - BLOB / Long columns - QBU int Variation_32(); // @cmember Empty int Variation_33(); // @cmember General - Soft-Deleted/Undo verify valid row handle int Variation_34(); // @cmember General - Inserted/Undo verify invalid row handle int Variation_35(); // @cmember General - Modified/Undo verify valid row handle, and OriginalData int Variation_36(); // @cmember General - Verify Undo alters row handle refcount correctly int Variation_37(); // }} }; // {{ TCW_TESTCASE(TCUndo) #define THE_CLASS TCUndo BEG_TEST_CASE(TCUndo, CRowsetUpdate, L"IRowsetUpdate::Undo test case") TEST_VARIATION(1, L"Boundary - No Changes [NULL, 0, NULL, NULL, NULL]") TEST_VARIATION(2, L"Boundary - No Changes [NULL, N, valid, NULL, NULL]") TEST_VARIATION(3, L"Boundary - No Changes [NULL,0,NULL, valid, valid]") TEST_VARIATION(4, L"Boundary - No Changes [invalid, 1, NULL, valid, valid]") TEST_VARIATION(5, L"Boundary - N Changes [NULL, 0, NULL, NULL, valid]") TEST_VARIATION(6, L"Boundary - N Changes [NULL, 0, valid, valid, valid]") TEST_VARIATION(7, L"Boundary - N Changes [NULL, N, valid, NULL, NULL]") TEST_VARIATION(8, L"Boundary - N Changes [NULL, N, valid, valid, valid]") TEST_VARIATION(9, L"Boundary - N Changes [invalid, N, NULL, valid, valid]") TEST_VARIATION(10, L"Boundary - N Changes [invalid, N, valid, valid, NULL]") TEST_VARIATION(11, L"Empty") TEST_VARIATION(12, L"Parameters - 3 invalid / 2 modified") TEST_VARIATION(13, L"Parameters - 1 hard del / 1 invalid / 1 modified") TEST_VARIATION(14, L"Parameters - 1 hard del / 1 invalid") TEST_VARIATION(15, L"Parameters - 3 soft del / 2 orginal") TEST_VARIATION(16, L"Parameters - 3 new rows / 1 orginal") TEST_VARIATION(17, L"Parameters - 4 modified / 3 orginal") TEST_VARIATION(18, L"Parameters - 3 soft del / 2 orginal, update") TEST_VARIATION(19, L"Parameters - 3 new rows / 1 orginal, update") TEST_VARIATION(20, L"Parameters - 4 modified / 3 orginal, update") TEST_VARIATION(21, L"Parameters - 3 hard del / 2 modified") TEST_VARIATION(22, L"Parameters - Insert/Modify/Delete a single row") TEST_VARIATION(23, L"Parameters - Insert/Modify/Delete a single row, Update") TEST_VARIATION(24, L"Parameters - Duplicate entries in the array") TEST_VARIATION(25, L"Empty") TEST_VARIATION(26, L"Sequence - Fetch every other row, modify every even, undo all odd.") TEST_VARIATION(27, L"Sequence - Call Undo 3 times") TEST_VARIATION(28, L"Empty") TEST_VARIATION(29, L"Boundary - Empty Rowset [NULL, 0 ,NULL, valid, valid]") TEST_VARIATION(30, L"Empty") TEST_VARIATION(31, L"Accessor - BLOB / Long columns - SetPos") TEST_VARIATION(32, L"Accessor - BLOB / Long columns - QBU") TEST_VARIATION(33, L"Empty") TEST_VARIATION(34, L"General - Soft-Deleted/Undo verify valid row handle") TEST_VARIATION(35, L"General - Inserted/Undo verify invalid row handle") TEST_VARIATION(36, L"General - Modified/Undo verify valid row handle, and OriginalData") TEST_VARIATION(37, L"General - Verify Undo alters row handle refcount correctly") END_TEST_CASE() #undef THE_CLASS // }} // }} // {{ TCW_TEST_CASE_MAP(TCUpdate) //-------------------------------------------------------------------- // @class IRowsetUpdate::Update test case // class TCUpdate : public CRowsetUpdate { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCUpdate,CRowsetUpdate); // }} // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember Boundary - No Changes [NULL, 0, NULL,NULL,NULL,NULL,NULL] int Variation_1(); // @cmember Boundary - No Changes (NULL, 0, NULL, valid, valid, valid, valid int Variation_2(); // @cmember Boundary - N Changes (NULL, N, valid, NULL, NULL, valid, valid int Variation_3(); // @cmember Boundary - N Changes (invalid, N, NULL, valid, valid, valid, valid int Variation_4(); // @cmember Boundary - N Changes (invalid, N, valid, valid, NULL, valid, valid int Variation_5(); // @cmember Boundary - N Changes (NULL, 0, NULL, valid, valid, valid, NULL int Variation_6(); // @cmember Boundary - N Changes (NULL, 0, NULL, NULL, NULL, NULL, NULL int Variation_7(); // @cmember Boundary - N Changes (NULL, 0, NULL, valid, valid,valid,valid, int Variation_8(); // @cmember Boundary - Empty Rowset (NULL, 0, NULL, valid, valid,valid,valid, int Variation_9(); // @cmember Empty int Variation_10(); // @cmember Parameters - 3 hard deleted / 2 modified int Variation_11(); // @cmember Parameters - 3 invalid / 2 inserted int Variation_12(); // @cmember Parameters - 1 hard deleted / 1 invalid / 1 soft-del int Variation_13(); // @cmember Parameters - 1 hard deleted / 1 invalid int Variation_14(); // @cmember Parameters - 1 col with non-schema info int Variation_15(); // @cmember Parameters - 3 col with metacolumn non-schema info int Variation_16(); // @cmember Parameters - 2 inserted rows, no value specified / not nullable int Variation_17(); // @cmember Empty int Variation_18(); // @cmember Sequence - Update a non-updateable column int Variation_19(); // @cmember Sequence - Delete a non-updateable column int Variation_20(); // @cmember Sequence - Deferred only int Variation_21(); // @cmember Sequence - Cache-Deferred only int Variation_22(); // @cmember Sequence - Cache-Deferred / Deferred / Non-deferred col int Variation_23(); // @cmember Empty int Variation_24(); // @cmember Parameters - Duplicate hrow entries in the array int Variation_25(); // @cmember Parameters - Fetch/Modify/Release int Variation_26(); // @cmember Parameters - Fetch/Modify/don't Release int Variation_27(); // @cmember Empty int Variation_28(); // @cmember Accessor - BLOB / Long columns - SetPos int Variation_29(); // @cmember Accessor - BLOB / Long columns - QBU int Variation_30(); // @cmember Empty int Variation_31(); // @cmember Related - Resync / GetOriginalData same data int Variation_32(); // @cmember Related - ResynchRows int Variation_33(); // @cmember Related - Modify / Resync int Variation_34(); // @cmember Related - Modify / Resync / Undo int Variation_35(); // @cmember Empty int Variation_36(); // @cmember Properties - NONE int Variation_37(); // @cmember Properties - OWNINSERT int Variation_38(); // @cmember Properties - OWNINSERT & CANSCROLL int Variation_39(); // @cmember Properties - OWNUPDATEDELETE int Variation_40(); // @cmember Properties - OWNUPDATEDELETE & CANFETCH int Variation_41(); // @cmember Properties - OTHERINSERT int Variation_42(); // @cmember Properties - OTHERINSERT & CANSCROLL int Variation_43(); // @cmember Properties - OTHERUPDATEDELETE int Variation_44(); // @cmember Properties - OTHERUPDATEDELETE & CANSCROLL int Variation_45(); // @cmember Properties - OWNUPDATEDELETE & OTHERINSERT int Variation_46(); // @cmember Properties - OWNUPDATEDELETE & OTHERINSERT & CANFETCH int Variation_47(); // @cmember Properties - OTHERUPDATEDELETE & OWNINSERT int Variation_48(); // @cmember Properties - OTHERUPDATEDELETE & OWNINSERT & CANSCROLL int Variation_49(); // @cmember Properties - verify property dependencies int Variation_50(); // @cmember Empty int Variation_51(); // @cmember Related - Qualified Table Name int Variation_52(); // @cmember Empty int Variation_53(); // @cmember Properties - MAXPENDINGCHANGEROWS int Variation_54(); // @cmember Properties - CANHOLDROWS int Variation_55(); // @cmember Properties - ~CANHOLDROWS int Variation_56(); // @cmember Properties - BOOKMARKS int Variation_57(); // @cmember Empty int Variation_58(); // @cmember Transactions - Insert/Commit int Variation_59(); // @cmember Transactions - Insert/Commit/Update int Variation_60(); // @cmember Transactions - Modify/Update/Commit int Variation_61(); // @cmember Transactions - Modify/Update/Commit/Undo int Variation_62(); // @cmember Transactions - Delete/Update/Abort int Variation_63(); // @cmember Transactions - Delete/Update/Abort/Undo int Variation_64(); // @cmember Transactions - concurrency - DB_E_CONCURRENCYVILOATION int Variation_65(); // @cmember Transactions - ABORTRETAINING int Variation_66(); // @cmember Transactions - ~ABORTRETAINING int Variation_67(); // @cmember Transactions - COMMITRETAINING int Variation_68(); // @cmember Transactions - ~COMMITRETAINING int Variation_69(); // @cmember Transactions - NOTENTRANT int Variation_70(); // @cmember Empty int Variation_71(); // @cmember Sequence - Insert/Modify/Delete a single row int Variation_72(); // @cmember Sequence - Delete all rows/Undo 1/Modify 1/Update int Variation_73(); // @cmember Sequence - 1 Row rowset/Delete row/Undo/Delete/Update/Undo/Update int Variation_74(); // @cmember Sequence - Insert 3 rows/Undo all/Insert 4/Modify int Variation_75(); // @cmember Empty int Variation_76(); // @cmember Sequence - Call Update 3 times int Variation_77(); // @cmember Sequence - Call Update on seperate columns int Variation_78(); // @cmember Sequence - Update multilple rows, covering all types int Variation_79(); // @cmember Sequence - Multiple Table Update int Variation_80(); // }} }; // {{ TCW_TESTCASE(TCUpdate) #define THE_CLASS TCUpdate BEG_TEST_CASE(TCUpdate, CRowsetUpdate, L"IRowsetUpdate::Update test case") TEST_VARIATION(1, L"Boundary - No Changes [NULL, 0, NULL,NULL,NULL,NULL,NULL]") TEST_VARIATION(2, L"Boundary - No Changes (NULL, 0, NULL, valid, valid, valid, valid") TEST_VARIATION(3, L"Boundary - N Changes (NULL, N, valid, NULL, NULL, valid, valid") TEST_VARIATION(4, L"Boundary - N Changes (invalid, N, NULL, valid, valid, valid, valid") TEST_VARIATION(5, L"Boundary - N Changes (invalid, N, valid, valid, NULL, valid, valid") TEST_VARIATION(6, L"Boundary - N Changes (NULL, 0, NULL, valid, valid, valid, NULL") TEST_VARIATION(7, L"Boundary - N Changes (NULL, 0, NULL, NULL, NULL, NULL, NULL") TEST_VARIATION(8, L"Boundary - N Changes (NULL, 0, NULL, valid, valid,valid,valid,") TEST_VARIATION(9, L"Boundary - Empty Rowset (NULL, 0, NULL, valid, valid,valid,valid,") TEST_VARIATION(10, L"Empty") TEST_VARIATION(11, L"Parameters - 3 hard deleted / 2 modified") TEST_VARIATION(12, L"Parameters - 3 invalid / 2 inserted") TEST_VARIATION(13, L"Parameters - 1 hard deleted / 1 invalid / 1 soft-del") TEST_VARIATION(14, L"Parameters - 1 hard deleted / 1 invalid") TEST_VARIATION(15, L"Parameters - 1 col with non-schema info") TEST_VARIATION(16, L"Parameters - 3 col with metacolumn non-schema info") TEST_VARIATION(17, L"Parameters - 2 inserted rows, no value specified / not nullable") TEST_VARIATION(18, L"Empty") TEST_VARIATION(19, L"Sequence - Update a non-updateable column") TEST_VARIATION(20, L"Sequence - Delete a non-updateable column") TEST_VARIATION(21, L"Sequence - Deferred only") TEST_VARIATION(22, L"Sequence - Cache-Deferred only") TEST_VARIATION(23, L"Sequence - Cache-Deferred / Deferred / Non-deferred col") TEST_VARIATION(24, L"Empty") TEST_VARIATION(25, L"Parameters - Duplicate hrow entries in the array") TEST_VARIATION(26, L"Parameters - Fetch/Modify/Release") TEST_VARIATION(27, L"Parameters - Fetch/Modify/don't Release") TEST_VARIATION(28, L"Empty") TEST_VARIATION(29, L"Accessor - BLOB / Long columns - SetPos") TEST_VARIATION(30, L"Accessor - BLOB / Long columns - QBU") TEST_VARIATION(31, L"Empty") TEST_VARIATION(32, L"Related - Resync / GetOriginalData same data") TEST_VARIATION(33, L"Related - ResynchRows") TEST_VARIATION(34, L"Related - Modify / Resync ") TEST_VARIATION(35, L"Related - Modify / Resync / Undo") TEST_VARIATION(36, L"Empty") TEST_VARIATION(37, L"Properties - NONE") TEST_VARIATION(38, L"Properties - OWNINSERT") TEST_VARIATION(39, L"Properties - OWNINSERT & CANSCROLL") TEST_VARIATION(40, L"Properties - OWNUPDATEDELETE") TEST_VARIATION(41, L"Properties - OWNUPDATEDELETE & CANFETCH") TEST_VARIATION(42, L"Properties - OTHERINSERT") TEST_VARIATION(43, L"Properties - OTHERINSERT & CANSCROLL") TEST_VARIATION(44, L"Properties - OTHERUPDATEDELETE") TEST_VARIATION(45, L"Properties - OTHERUPDATEDELETE & CANSCROLL") TEST_VARIATION(46, L"Properties - OWNUPDATEDELETE & OTHERINSERT") TEST_VARIATION(47, L"Properties - OWNUPDATEDELETE & OTHERINSERT & CANFETCH") TEST_VARIATION(48, L"Properties - OTHERUPDATEDELETE & OWNINSERT") TEST_VARIATION(49, L"Properties - OTHERUPDATEDELETE & OWNINSERT & CANSCROLL") TEST_VARIATION(50, L"Properties - verify property dependencies") TEST_VARIATION(51, L"Empty") TEST_VARIATION(52, L"Related - Qualified Table Name") TEST_VARIATION(53, L"Empty") TEST_VARIATION(54, L"Properties - MAXPENDINGCHANGEROWS") TEST_VARIATION(55, L"Properties - CANHOLDROWS") TEST_VARIATION(56, L"Properties - ~CANHOLDROWS") TEST_VARIATION(57, L"Properties - BOOKMARKS") TEST_VARIATION(58, L"Empty") TEST_VARIATION(59, L"Transactions - Insert/Commit") TEST_VARIATION(60, L"Transactions - Insert/Commit/Update") TEST_VARIATION(61, L"Transactions - Modify/Update/Commit") TEST_VARIATION(62, L"Transactions - Modify/Update/Commit/Undo") TEST_VARIATION(63, L"Transactions - Delete/Update/Abort") TEST_VARIATION(64, L"Transactions - Delete/Update/Abort/Undo") TEST_VARIATION(65, L"Transactions - concurrency - DB_E_CONCURRENCYVILOATION") TEST_VARIATION(66, L"Transactions - ABORTRETAINING") TEST_VARIATION(67, L"Transactions - ~ABORTRETAINING") TEST_VARIATION(68, L"Transactions - COMMITRETAINING") TEST_VARIATION(69, L"Transactions - ~COMMITRETAINING") TEST_VARIATION(70, L"Transactions - NOTENTRANT") TEST_VARIATION(71, L"Empty") TEST_VARIATION(72, L"Sequence - Insert/Modify/Delete a single row") TEST_VARIATION(73, L"Sequence - Delete all rows/Undo 1/Modify 1/Update") TEST_VARIATION(74, L"Sequence - 1 Row rowset/Delete row/Undo/Delete/Update/Undo/Update") TEST_VARIATION(75, L"Sequence - Insert 3 rows/Undo all/Insert 4/Modify") TEST_VARIATION(76, L"Empty") TEST_VARIATION(77, L"Sequence - Call Update 3 times") TEST_VARIATION(78, L"Sequence - Call Update on seperate columns") TEST_VARIATION(79, L"Sequence - Update multilple rows, covering all types") TEST_VARIATION(80, L"Sequence - Multiple Table Update") END_TEST_CASE() #undef THE_CLASS // }} // }} // {{ TCW_TEST_CASE_MAP(TCGetRowStatus) //-------------------------------------------------------------------- // @class IRowsetUpdate::GetRowStatus // class TCGetRowStatus : public CRowsetUpdate { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCGetRowStatus,CRowsetUpdate); // }} // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember General - Verify GetRowStatus alters row handles RefCount correctly int Variation_1(); // @cmember Boundary - No Changes [invalid, 0, NULL, valid] int Variation_2(); // @cmember Boundary - No Changes [NULL, 1, valid, NULL] int Variation_3(); // @cmember Boundary - No Changes [NULL, 1, NULL, valid] int Variation_4(); // @cmember Empty int Variation_5(); // @cmember Empty int Variation_6(); // @cmember Boundary - N Changes [NULL, 0, NULL, NULL] int Variation_7(); // @cmember Boundary - N Changes [NULL, N, NULL, NULL] int Variation_8(); // @cmember Boundary - N Changes [NULL, N, valid, valid] int Variation_9(); // @cmember Boundary - Empty Rowset [NULL, N, valid, valid] int Variation_10(); // @cmember Empty int Variation_11(); // @cmember Empty int Variation_12(); // @cmember Parameters - 3 hard deleted 2 modified int Variation_13(); // @cmember Parameters - 3 invalid int Variation_14(); // @cmember Parameters - 1 hard deleted 1 invalid 1 modified int Variation_15(); // @cmember Empty int Variation_16(); // @cmember Parameters - All types int Variation_17(); // @cmember Parameters - All Unchanged int Variation_18(); // @cmember Parameters - All Inserted int Variation_19(); // @cmember Parameters - All Soft-Deleted int Variation_20(); // @cmember Parameters - Insert/Modify int Variation_21(); // @cmember Parameters - Modify Delete int Variation_22(); // @cmember Parameters - Insert/Modify/Delete int Variation_23(); // @cmember Empty int Variation_24(); // @cmember Sequence - Insert/Delete/Modify - Update int Variation_25(); // @cmember Sequence - Make all type changes - Undo half - Update int Variation_26(); // @cmember Sequence - Change N rows, GetPendingRows, GetRowStatus int Variation_27(); // @cmember Sequence - Call GetRowStatus 3 times int Variation_28(); // }} }; // {{ TCW_TESTCASE(TCGetRowStatus) #define THE_CLASS TCGetRowStatus BEG_TEST_CASE(TCGetRowStatus, CRowsetUpdate, L"IRowsetUpdate::GetRowStatus") TEST_VARIATION(1, L"General - Verify GetRowStatus alters row handles RefCount correctly") TEST_VARIATION(2, L"Boundary - No Changes [invalid, 0, NULL, valid]") TEST_VARIATION(3, L"Boundary - No Changes [NULL, 1, valid, NULL]") TEST_VARIATION(4, L"Boundary - No Changes [NULL, 1, NULL, valid]") TEST_VARIATION(5, L"Empty") TEST_VARIATION(6, L"Empty") TEST_VARIATION(7, L"Boundary - N Changes [NULL, 0, NULL, NULL]") TEST_VARIATION(8, L"Boundary - N Changes [NULL, N, NULL, NULL]") TEST_VARIATION(9, L"Boundary - N Changes [NULL, N, valid, valid]") TEST_VARIATION(10, L"Boundary - Empty Rowset [NULL, N, valid, valid]") TEST_VARIATION(11, L"Empty") TEST_VARIATION(12, L"Empty") TEST_VARIATION(13, L"Parameters - 3 hard deleted 2 modified") TEST_VARIATION(14, L"Parameters - 3 invalid") TEST_VARIATION(15, L"Parameters - 1 hard deleted 1 invalid 1 modified") TEST_VARIATION(16, L"Empty") TEST_VARIATION(17, L"Parameters - All types") TEST_VARIATION(18, L"Parameters - All Unchanged") TEST_VARIATION(19, L"Parameters - All Inserted") TEST_VARIATION(20, L"Parameters - All Soft-Deleted") TEST_VARIATION(21, L"Parameters - Insert/Modify") TEST_VARIATION(22, L"Parameters - Modify Delete") TEST_VARIATION(23, L"Parameters - Insert/Modify/Delete") TEST_VARIATION(24, L"Empty") TEST_VARIATION(25, L"Sequence - Insert/Delete/Modify - Update") TEST_VARIATION(26, L"Sequence - Make all type changes - Undo half - Update") TEST_VARIATION(27, L"Sequence - Change N rows, GetPendingRows, GetRowStatus") TEST_VARIATION(28, L"Sequence - Call GetRowStatus 3 times") END_TEST_CASE() #undef THE_CLASS // }} // }} // {{ TCW_TEST_CASE_MAP(TCExtendedErrors) //-------------------------------------------------------------------- // @class Extended Errors // class TCExtendedErrors : public CRowsetUpdate { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCExtendedErrors,CRowsetUpdate); // }} // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember Valid GetOriginalData calls with previous error object existing. int Variation_1(); // @cmember Invalid GetOriginalData calls with previous error object existing int Variation_2(); // @cmember Invalid GetOriginalData calls with no previous error object existing int Variation_3(); // @cmember Valid GetPendingRows calls with previous error object existing. int Variation_4(); // @cmember Invalid GetPendingRows calls with previous error object existing int Variation_5(); // @cmember Invalid GetPendingRows calls with no previous error object existing int Variation_6(); // @cmember Valid GetRowStatus calls with previous error object existing. int Variation_7(); // @cmember Invalid GetRowStatus calls with previous error object existing int Variation_8(); // @cmember Invalid GetRowStatus calls with no previous error object existing int Variation_9(); // @cmember Valid Undo calls with previous error object existing. int Variation_10(); // @cmember Invalid Undo calls with previous error object existing int Variation_11(); // @cmember Invalid Undo calls with no previous error object existing int Variation_12(); // @cmember Valid Update calls with previous error object existing. int Variation_13(); // @cmember Invalid Update calls with previous error object existing int Variation_14(); // @cmember Invalid Update calls with no previous error object existing int Variation_15(); // @cmember S_FALSE GetPendingRows call with no previous error object existing int Variation_16(); // @cmember DB_E_DELETEDROW GetOriginalData call with no previous error object existing int Variation_17(); // @cmember DB_E_BADACCESSORTYPE GetOriginal call with no previous error object existing int Variation_18(); // }} }; // {{ TCW_TESTCASE(TCExtendedErrors) #define THE_CLASS TCExtendedErrors BEG_TEST_CASE(TCExtendedErrors, CRowsetUpdate, L"Extended Errors") TEST_VARIATION(1, L"Valid GetOriginalData calls with previous error object existing.") TEST_VARIATION(2, L"Invalid GetOriginalData calls with previous error object existing") TEST_VARIATION(3, L"Invalid GetOriginalData calls with no previous error object existing") TEST_VARIATION(4, L"Valid GetPendingRows calls with previous error object existing.") TEST_VARIATION(5, L"Invalid GetPendingRows calls with previous error object existing") TEST_VARIATION(6, L"Invalid GetPendingRows calls with no previous error object existing") TEST_VARIATION(7, L"Valid GetRowStatus calls with previous error object existing.") TEST_VARIATION(8, L"Invalid GetRowStatus calls with previous error object existing") TEST_VARIATION(9, L"Invalid GetRowStatus calls with no previous error object existing") TEST_VARIATION(10, L"Valid Undo calls with previous error object existing.") TEST_VARIATION(11, L"Invalid Undo calls with previous error object existing") TEST_VARIATION(12, L"Invalid Undo calls with no previous error object existing") TEST_VARIATION(13, L"Valid Update calls with previous error object existing.") TEST_VARIATION(14, L"Invalid Update calls with previous error object existing") TEST_VARIATION(15, L"Invalid Update calls with no previous error object existing") TEST_VARIATION(16, L"S_FALSE GetPendingRows call with no previous error object existing") TEST_VARIATION(17, L"DB_E_DELETEDROW GetOriginalData call with no previous error object existing") TEST_VARIATION(18, L"DB_E_BADACCESSORTYPE GetOriginal call with no previous error object existing") END_TEST_CASE() #undef THE_CLASS // }} // }} // {{ TCW_TEST_CASE_MAP(TCZombie) //-------------------------------------------------------------------- // @class Zombie testing of IRowsetUpdate // class TCZombie : public CTransaction { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCZombie,CTransaction); // }} ULONG m_cPropSets; DBPROPSET* m_rgPropSets; // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember Zombie - ABORT with fRetaining == TRUE int Variation_1(); // @cmember Zombie - ABORT with fRetaining == FALSE int Variation_2(); // @cmember Zombie - COMMIT with fRetaining == TRUE int Variation_3(); // @cmember Zombie - COMMIT with fRetaining == TRUE int Variation_4(); // }} }; // {{ TCW_TESTCASE(TCZombie) #define THE_CLASS TCZombie BEG_TEST_CASE(TCZombie, CTransaction, L"Zombie testing of IRowsetUpdate") TEST_VARIATION(1, L"Zombie - ABORT with fRetaining == TRUE") TEST_VARIATION(2, L"Zombie - ABORT with fRetaining == FALSE") TEST_VARIATION(3, L"Zombie - COMMIT with fRetaining == TRUE") TEST_VARIATION(4, L"Zombie - COMMIT with fRetaining == TRUE") END_TEST_CASE() #undef THE_CLASS // }} // }} // }} END_DECLARE_TEST_CASES(); // {{ TCW_TESTMODULE(ThisModule) TEST_MODULE(7, ThisModule, gwszModuleDescrip) TEST_CASE(1, TCGetOriginalRows) TEST_CASE(2, TCGetPendingRows) TEST_CASE(3, TCUndo) TEST_CASE(4, TCUpdate) TEST_CASE(5, TCGetRowStatus) TEST_CASE(6, TCExtendedErrors) TEST_CASE(7, TCZombie) END_TEST_MODULE() // }} // {{ TCW_TC_PROTOTYPE(TCGetOriginalRows) //*----------------------------------------------------------------------- //| Test Case: TCGetOriginalRows - IRowsetUpdate::GetOriginalRows test case //| Created: 03/29/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCGetOriginalRows::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CRowsetUpdate::Init()) // }} { return TEST_PASS; } return TEST_FAIL; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc General - IID_IRowsetUpdate on a read-only rowset // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_1() { TBEGIN HROW hRow = NULL; DBROWSTATUS* rgRowStatus = NULL; CRowsetUpdate ReadOnlyRowset; //Try to ask for IID_IRowsetUpdate on a readonly rowset TESTC_PROVIDER(ReadOnlyRowset.CreateRowset(SELECT_COUNT)==S_OK); //Now that IRowsetUpdate is allowed on a read-only rowset, verify //DBPROP_COLUMNRESTICT is VARIANT_TRUE TESTC_PROVIDER(ReadOnlyRowset.GetProperty(DBPROP_COLUMNRESTRICT)); //Also Verify that we can't make any changes to this rowset TESTC_(ReadOnlyRowset.GetRow(FIRST_ROW,&hRow),S_OK); TESTC_(ReadOnlyRowset.DeleteRow(hRow),S_OK); TESTC_(ReadOnlyRowset.UpdateRow(ONE_ROW,&hRow,NULL,NULL,&rgRowStatus),DB_E_ERRORSOCCURRED); //Verify not updatable TESTC(rgRowStatus != NULL); //PERMISSIONDENIED should only be returned if ROWRESTRICT is on if(ReadOnlyRowset.GetProperty(DBPROP_ROWRESTRICT)) { TESTC(rgRowStatus[0] == DBROWSTATUS_E_PERMISSIONDENIED); } else { TESTC(rgRowStatus[0] == DBROWSTATUS_E_INTEGRITYVIOLATION); } CLEANUP: ReadOnlyRowset.ReleaseRows(hRow); PROVIDER_FREE(rgRowStatus); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc General - IID_IRowsetUpdate on a read-only rowset, created with OuterJoin // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_2() { TBEGIN IDBSchemaRowset* pIDBSchemaRowset = NULL; IUnknown* pIUnknown = NULL; CRowset Rowset1; Rowset1.SetProperty(DBPROP_IRowsetChange); CRowset Rowset2; Rowset2.SetProperty(DBPROP_IRowsetUpdate); //Obtain IDBSchemaRowset interface HRESULT hr = QI(pISession(), IID_IDBSchemaRowset,(void**)&pIDBSchemaRowset); //Not all providers will support IDBSchemaRowset TESTC_PROVIDER(hr==S_OK); //Try to ask for DBPROP_IRowsetChange on a read-only schema rowset TESTC_(pIDBSchemaRowset->GetRowset(NULL,DBSCHEMA_TABLES,0,NULL,IID_IRowset,Rowset1.m_cPropSets,Rowset1.m_rgPropSets,&pIUnknown),DB_E_ERRORSOCCURRED); TESTC_(pIDBSchemaRowset->GetRowset(NULL,DBSCHEMA_TABLES,0,NULL,IID_IRowsetChange,0,NULL,&pIUnknown),E_NOINTERFACE); //Try to ask for DBPROP_IRowsetUpdate on a read-only schema rowset TESTC_(pIDBSchemaRowset->GetRowset(NULL,DBSCHEMA_TABLES,0,NULL,IID_IRowset,Rowset2.m_cPropSets,Rowset2.m_rgPropSets,&pIUnknown),DB_E_ERRORSOCCURRED); TESTC_(pIDBSchemaRowset->GetRowset(NULL,DBSCHEMA_TABLES,0,NULL,IID_IRowsetUpdate,0,NULL,&pIUnknown),E_NOINTERFACE); CLEANUP: SAFE_RELEASE(pIDBSchemaRowset); SAFE_RELEASE(pIUnknown); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc General - IID_IRowsetChange implicitly set on IID_IRowsetUpdate // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_3() { TBEGIN CRowset RowsetA; //Set Properties RowsetA.SetProperty(DBPROP_IRowsetUpdate); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Just as a sanity check, make sure IID_IRowseUpdate is still set TESTC_PROVIDER(RowsetA.GetProperty(DBPROP_IRowsetUpdate)); //Verify IID_IRowsetChange is implicitly set TESTC_PROVIDER(RowsetA.GetProperty(DBPROP_IRowsetChange)); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc General - IID_IRowsetUpdate is not exposed on IRowsetChange // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_4() { TBEGIN CRowsetChange RowsetChange; TESTC_PROVIDER(RowsetChange.CreateRowset()==S_OK); //Just as a sanity check, make sure IID_IRowseChange is still set TESTC_PROVIDER(RowsetChange.GetProperty(DBPROP_IRowsetChange)); //Verify IID_IRowsetUpdate is not implicitly set TESTC_PROVIDER(!(RowsetChange.GetProperty(DBPROP_IRowsetUpdate))); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc General - IID_IRowsetLocate exposed on IRowsetUpdate // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_5() { TBEGIN CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_IRowsetLocate)==S_OK); //Just as a sanity check, make sure properties are still set TESTC_PROVIDER(RowsetA.GetProperty(DBPROP_IRowsetUpdate)); //Verify IID_IRowsetLocate is implicitly set if(SupportedProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET)) TESTC(RowsetA.GetProperty(DBPROP_IRowsetLocate)); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc General - QueryI(invalid, valid // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_6() { TBEGIN CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //QI for a non-rowset Interface TESTC_(QI(RowsetA.pIRowsetUpdate(),IID_IConnectionPoint),E_NOINTERFACE); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc General - QueryI(valid, NULL // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_7() { TBEGIN CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); TESTC_(RowsetA.pIRowsetUpdate()->QueryInterface(IID_IRowsetUpdate, NULL),E_INVALIDARG); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc General - QueryI(IID_IRowsetUpdate, valid // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_8() { TBEGIN CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); TESTC_(QI(RowsetA.pIRowsetUpdate(),IID_IRowsetUpdate),S_OK); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc General - QueryI(IID_IRowsetChange, valid // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_9() { TBEGIN CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); TESTC_(QI(RowsetA.pIRowsetUpdate(),IID_IRowsetChange),S_OK); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(10) //*----------------------------------------------------------------------- // @mfunc General - IRowsetChange->QueryI(IID_IRowsetUpdate, valid // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_10() { TBEGIN //Create a IRowsetChange CRowsetChange RowsetChange; TESTC_PROVIDER(RowsetChange.CreateRowset(DBPROP_IRowsetChange)==S_OK); // IRowsetChange->QI(IID_IRowsetUpdate) TESTC_(QI(RowsetChange.pIRowsetChange(),IID_IRowsetUpdate),E_NOINTERFACE); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(11) //*----------------------------------------------------------------------- // @mfunc General - Verify AddRef / Release // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_11() { TBEGIN ULONG cOrgRefCount; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the current reference count cOrgRefCount = GetRefCount(RowsetA.pIRowsetUpdate()); //Increment ref count a few times RowsetA.pIRowsetUpdate()->AddRef(); RowsetA.pIRowsetUpdate()->AddRef(); RowsetA.pIRowsetUpdate()->AddRef(); //Release a couple of times RowsetA.pIRowsetUpdate()->Release(); RowsetA.pIRowsetUpdate()->Release(); //Addref RowsetA.pIRowsetUpdate()->AddRef(); //Release RowsetA.pIRowsetUpdate()->Release(); RowsetA.pIRowsetUpdate()->Release(); TESTC(GetRefCount(RowsetA.pIRowsetUpdate())==cOrgRefCount); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(12) //*----------------------------------------------------------------------- // @mfunc General - Verify RefCount or row handles // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_12() { TBEGIN const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; void* rgpOriginalData[NROWS] = {NULL,NULL,NULL}; ULONG i; ULONG rgBeforeRefCounts[NROWS] = {0,0,0}; ULONG rgAfterRefCounts[NROWS] = {0,0,0}; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Get the current ref count for all row handles, before the call TESTC_(RowsetA()->AddRefRows(NROWS,rghRow,rgBeforeRefCounts,NULL),S_OK); TESTC_(RowsetA.ReleaseRows(NROWS,rghRow),S_OK); //Call GetOriginalData on the above rows TESTC_(RowsetA.GetOriginalData(NROWS, rghRow, rgpOriginalData),S_OK); //Get the current ref count for all row handles, after the call TESTC_(RowsetA()->AddRefRows(NROWS,rghRow,rgAfterRefCounts,NULL),S_OK); TESTC_(RowsetA.ReleaseRows(NROWS,rghRow),S_OK); //Verify the refcount of the row handles have not increased for(i=0; iCreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,&hNullAccessor,NULL),S_OK); //Obtain the first row TESTC_(RowsetA.GetRow(FIRST_ROW, &hRow),S_OK); TESTC_(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,hNullAccessor,pData),S_OK); TESTC(pData==INVALID(void*)); TESTC_(RowsetA.pIAccessor()->ReleaseAccessor(INVALID(HACCESSOR),NULL),DB_E_BADACCESSORHANDLE); TESTC_(RowsetA.pIAccessor()->ReleaseAccessor(DB_NULL_HACCESSOR,NULL),DB_E_BADACCESSORHANDLE); CLEANUP: RowsetA.ReleaseAccessor(hNullAccessor); RowsetA.ReleaseAccessor(hAccessor); RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(14) //*----------------------------------------------------------------------- // @mfunc Boundary - [PASSBYREF NULL Accessor] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_14() { TBEGIN HACCESSOR hNullAccessor = DB_NULL_HACCESSOR; HACCESSOR hAccessor = DB_NULL_HACCESSOR; HROW hRow = DB_NULL_HROW; void* pData = INVALID(void*); BOOL fByrefAccessorSupported = FALSE; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Create a NULL BYREF Accessor (if supported) if(RowsetA.GetProperty(DBPROP_BYREFACCESSORS)) { TESTC_(RowsetA.pIAccessor()->CreateAccessor(DBACCESSOR_ROWDATA | DBACCESSOR_PASSBYREF ,0,NULL,0,&hNullAccessor,NULL),S_OK); } //Otherwsie just a NULL Accessor is fine else { TESTC_(RowsetA.pIAccessor()->CreateAccessor(DBACCESSOR_ROWDATA ,0,NULL,0,&hNullAccessor,NULL),S_OK); } //Obtain the first row TESTC_(RowsetA.GetRow(FIRST_ROW, &hRow),S_OK); TESTC_(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,hNullAccessor,pData),S_OK); TESTC(pData==INVALID(void*)); TESTC_(RowsetA.pIAccessor()->ReleaseAccessor(hNullAccessor,NULL),S_OK); TESTC_(RowsetA.pIAccessor()->ReleaseAccessor(hAccessor,NULL),DB_E_BADACCESSORHANDLE); TESTC_(RowsetA.pIAccessor()->ReleaseAccessor(INVALID(HACCESSOR),NULL),DB_E_BADACCESSORHANDLE); TESTC_(RowsetA.pIAccessor()->ReleaseAccessor(DB_NULL_HACCESSOR,NULL),DB_E_BADACCESSORHANDLE); CLEANUP: RowsetA.ReleaseAccessor(hAccessor); RowsetA.ReleaseAccessor(hNullAccessor); RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(15) //*----------------------------------------------------------------------- // @mfunc Boundary - [valid, valid, NULL] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_15() { TBEGIN HROW hRow = DB_NULL_HROW; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Get the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //Call GetOriginalData with NULL pDdata TESTC_(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,RowsetA.m_hAccessor,NULL),E_INVALIDARG); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(16) //*----------------------------------------------------------------------- // @mfunc Boundary - [DB_INVALID_ROW, valid, valid] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_16() { CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Call GetOriginalData with invalid row - should fail gracefully TESTC_(RowsetA.pIRowsetUpdate()->GetOriginalData(DB_NULL_HROW,RowsetA.m_hAccessor,RowsetA.m_pData),DB_E_BADROWHANDLE); TESTC(RowsetA.m_pData!=NULL) //provider shouldn't touch my alloced buffer; CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(17) //*----------------------------------------------------------------------- // @mfunc Boundary - [valid, DB_NULL_HACCESSOR, valid] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_17() { HROW hRow = DB_NULL_HROW; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Should be able to pass DB_NUL_HROW to release rows TESTC_(RowsetA.ReleaseRows(ONE_ROW,&hRow),DB_E_ERRORSOCCURRED); //Get the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //Call GetOriginalData with a NULL Accessor TESTC_(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,DB_NULL_HACCESSOR,RowsetA.m_pData),DB_E_BADACCESSORHANDLE); TESTC(RowsetA.m_pData!=NULL) //provider shouldn't touch my alloced buffer; CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(18) //*----------------------------------------------------------------------- // @mfunc Boundary - Call GetOriginalData before any other method // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_18() { HROW hRow = DB_NULL_HROW; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Get the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //GetOriginalData, before any other modifying methods TESTC_(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,RowsetA.m_hAccessor,RowsetA.m_pData),S_OK); TESTC(RowsetA.m_pData!=NULL) //provider shouldn't touch my alloced buffer; CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(19) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_19() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(20) //*----------------------------------------------------------------------- // @mfunc Parameters - Hard deleted row // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_20() { HROW hRow = DB_NULL_HROW; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //Hard-delete the row TESTC_(RowsetA.HardDeleteRow(hRow),S_OK); //Call GetOriginalData on the hard deleted row TESTC_(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,RowsetA.m_hAccessor,RowsetA.m_pData),DB_E_DELETEDROW); TESTC(RowsetA.m_pData!=NULL) //provider shouldn't touch my alloced buffer; CLEANUP: RowsetA.ReleaseRows(hRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(21) //*----------------------------------------------------------------------- // @mfunc Parameters - Soft Deleted row, No update // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_21() { void* pOriginalData = NULL; HROW hRow = DB_NULL_HROW; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //Save the orginal row data TESTC_(RowsetA.GetRowData(hRow, &pOriginalData),S_OK); //Soft-delete the row TESTC_(RowsetA.DeleteRow(hRow),S_OK); //Call GetOriginalData on the soft deleted row TESTC_(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,RowsetA.m_hAccessor,RowsetA.m_pData),S_OK); //Compare with the orginal data, should match TESTC(RowsetA.CompareRowData(pOriginalData,RowsetA.m_pData)); CLEANUP: RowsetA.ReleaseRows(hRow); PROVIDER_FREE(pOriginalData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(22) //*----------------------------------------------------------------------- // @mfunc Parameters - Newly inserted row, No update // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_22() { HROW hRow = DB_NULL_HROW; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Soft-Insert the row TESTC_(RowsetA.InsertRow(&hRow),S_OK); //Call GetOriginalData on the soft inserted row //This may produce DB_S_ERRORSOCCURRED since if the driver has non-NULL //columns, Some providers cannot return ISNULL, and has no idea what valid //defaults would be, so DBSTATUS_E_UNAVAILABLE will be returned for those //columns TEST3C_(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,RowsetA.m_hAccessor,RowsetA.m_pData),S_OK,DB_S_ERRORSOCCURRED,DB_E_ERRORSOCCURRED); //GetOriginalData should return defaults, therefore it should not match TESTC(!RowsetA.CompareRowData(hRow,RowsetA.m_pData)); //Compare with defaults TESTC(RowsetA.CompareWithDefaults(RowsetA.m_pData)); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(23) //-------------------------------------------------------------------- // @mfunc Parameters - Newly inserted row - NULL Accessor, No update // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_23() { HROW hRow = DB_NULL_HROW; HACCESSOR hAccessor = NULL; void* pData = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Create NULL Accessor TESTC_(RowsetA.pIAccessor()->CreateAccessor(DBACCESSOR_ROWDATA, 0, NULL, 0, &hAccessor, NULL),S_OK); //Soft-Insert the row (using NULL Accessor) TESTC_(RowsetA.pIRowsetUpdate()->InsertRow(NULL, hAccessor, NULL, &hRow),S_OK); //Call GetOriginalData on the soft inserted row //This may produce DB_S_ERRORSOCCURRED since if the driver has non-NULL //columns, Some providers cannot return ISNULL, and has no idea what valid //defaults would be, so DBSTATUS_E_UNAVAILABLE will be returned for those //columns TEST3C_(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,RowsetA.m_hAccessor,RowsetA.m_pData),S_OK,DB_S_ERRORSOCCURRED,DB_E_ERRORSOCCURRED); //Get the Data TEST3C_(RowsetA.GetRowData(hRow, &pData),S_OK,DB_S_ERRORSOCCURRED,DB_E_ERRORSOCCURRED); //Compare with defaults TESTC(RowsetA.CompareWithDefaults(RowsetA.m_pData)); CLEANUP: RowsetA.ReleaseRows(hRow); PROVIDER_FREE(pData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(24) //*----------------------------------------------------------------------- // @mfunc Parameters - A modified row, No update // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_24() { void* pOriginalData = NULL; HROW hRow = DB_NULL_HROW; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //Save the orginal data TESTC_(RowsetA.GetRowData(hRow, &pOriginalData),S_OK); //Modify the row TESTC_(RowsetA.ModifyRow(hRow),S_OK); //Call GetOriginalData on the modified row TESTC_(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,RowsetA.m_hAccessor,RowsetA.m_pData),S_OK); //Compare data with orginal data, should match TESTC(RowsetA.CompareRowData(pOriginalData,RowsetA.m_pData)); //Compare data with modified data, should not match TESTC(!RowsetA.CompareRowData(hRow,RowsetA.m_pData)); CLEANUP: RowsetA.ReleaseRows(hRow); PROVIDER_FREE(pOriginalData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(25) //*----------------------------------------------------------------------- // @mfunc Parameters - An inserted, modified row // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_25() { void* pModifiedData = NULL; HROW hRow = DB_NULL_HROW; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the first row TESTC_(RowsetA.InsertRow(&hRow),S_OK); //Modify the row TESTC_(RowsetA.ModifyRow(hRow),S_OK); //Save the modified data TESTC_(RowsetA.GetRowData(hRow, &pModifiedData),S_OK); //Call GetOriginalData on the modified row TEST3C_(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,RowsetA.m_hAccessor,RowsetA.m_pData),S_OK,DB_S_ERRORSOCCURRED,DB_E_ERRORSOCCURRED); //Compare data with modified data, should not match TESTC(!RowsetA.CompareRowData(pModifiedData,RowsetA.m_pData)); //Compare data with defaults, should match TESTC(RowsetA.CompareWithDefaults(RowsetA.m_pData)); CLEANUP: RowsetA.ReleaseRows(hRow); PROVIDER_FREE(pModifiedData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(26) //*----------------------------------------------------------------------- // @mfunc Parameters - A newly inserted row, update // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_26() { TBEGIN HROW hRow = DB_NULL_HROW; HACCESSOR hAccessor = NULL; void* pOriginalData = NULL; void* pData = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Soft-Insert the row TESTC_(RowsetA.InsertRow(&hRow),S_OK); //Save the OriginalData TEST3C_(RowsetA.GetOriginalData(hRow, &pOriginalData),S_OK,DB_S_ERRORSOCCURRED,DB_E_ERRORSOCCURRED); //Save the Data TESTC_(RowsetA.GetRowData(hRow, &pData),S_OK); //Update the row - (Hard Insert) TESTC_(RowsetA.UpdateRow(hRow),S_OK); //Call GetOriginalData on the updated row TESTC_(RowsetA.GetOriginalData(hRow, &RowsetA.m_pData),S_OK); //Compare data with original data, should not match (updated) TESTC(!RowsetA.CompareRowData(pOriginalData, RowsetA.m_pData)); //Compare data with row data, should match (updated) TESTC(RowsetA.CompareRowData(pData, RowsetA.m_pData)); CLEANUP: RowsetA.ReleaseRows(hRow); PROVIDER_FREE(pOriginalData); PROVIDER_FREE(pData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(27) //-------------------------------------------------------------------- // @mfunc Parameters - A newly inserted row - NULL Accessor, update // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_27() { TBEGIN HRESULT hr; HROW hRow = DB_NULL_HROW; HACCESSOR hAccessor = NULL; void* pData = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_SERVERDATAONINSERT); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); pData = PROVIDER_ALLOC(RowsetA.m_cRowSize*sizeof(void*)); //Create NULL Accessor TESTC_(RowsetA.pIAccessor()->CreateAccessor(DBACCESSOR_ROWDATA, 0, NULL, 0, &hAccessor, NULL),S_OK); //Soft-Insert the row (using NULL Accessor) TESTC_(RowsetA.pIRowsetUpdate()->InsertRow(NULL, hAccessor, NULL, &hRow),S_OK); //This may produce DB_E_ERRORSOCCURRED since if the table has non-NULL //columns, the driver may fail to insert the row, since I have bound no values hr = RowsetA.UpdateRow(hRow); TESTC(hr==S_OK || hr==DB_E_ERRORSOCCURRED); //Call GetOriginalData on the soft inserted row //Since there really is no "OrginalData" on a newly inserted row //that hasn't been updated yet, the provider should return defaults if(hr == S_OK) { //Note: Since the update succeeded, the provider used NULLs for nullable columns //and Defaults for all columns that were non-nullable that had defaults. Weither they return //the defaults (ie: make a roundtrip to obtain the defaults inserted), is dependent upon the //DBPROP_SERVERDATAONINSERT property. If this is not supported, then we have to allow //errors returned since the defaults may not have been brought back from the server... if(SettableProperty(DBPROP_SERVERDATAONINSERT, DBPROPSET_ROWSET)) { TESTC_(hr = RowsetA.GetOriginalData(hRow, &RowsetA.m_pData),S_OK); } else { TEST3C_(hr = RowsetA.GetOriginalData(hRow, &RowsetA.m_pData),S_OK,DB_S_ERRORSOCCURRED,DB_E_ERRORSOCCURRED); } //GetData for row in the rowset (should return the same result as GetOriginalData) TESTC_(RowsetA.pIRowset()->GetData(hRow,RowsetA.m_hAccessor,pData), hr); //Both GetOriginalData and GetData should match... //The row was successfully inserted, so now there is no pending insert TESTC(RowsetA.CompareRowData(RowsetA.m_pData, pData)); } else { //This may produce DB_S_ERRORSOCCURRED since if the driver has non-NULL //columns, some providers cannot return ISNULL, and has no idea what valid //defaults would be, so DBSTATUS_E_UNAVAILABLE will be returned for those columns TEST3C_(RowsetA.GetOriginalData(hRow, &RowsetA.m_pData),S_OK,DB_S_ERRORSOCCURRED,DB_E_ERRORSOCCURRED); //GetData for row in the rowset TEST3C_(RowsetA.pIRowset()->GetData(hRow,RowsetA.m_hAccessor,pData),S_OK,DB_S_ERRORSOCCURRED,DB_E_ERRORSOCCURRED); //Compare data with defaults, should match TESTC(RowsetA.CompareWithDefaults(RowsetA.m_pData)); } CLEANUP: RowsetA.ReleaseRows(hRow); PROVIDER_FREE(pData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(28) //*----------------------------------------------------------------------- // @mfunc Parameters - A modified row, update // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_28() { void* pOriginalData = NULL; HROW hRow = DB_NULL_HROW; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERINSERT); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //Save the orginal row data TESTC_(RowsetA.GetRowData(hRow, &pOriginalData),S_OK); //Hard-Modify the row TESTC_(RowsetA.ModifyRow(hRow),S_OK); TESTC_(RowsetA.UpdateRow(hRow),S_OK); //Call GetOriginalData on the modified row TESTC_(RowsetA.GetOriginalData(hRow, &RowsetA.m_pData),S_OK); //Compare data with orginal data, should not equal, updated was performed TESTC(!RowsetA.CompareRowData(pOriginalData,RowsetA.m_pData)); //Compare data with modified data, should be equal, update was performed TESTC(RowsetA.CompareRowData(hRow,RowsetA.m_pData)); CLEANUP: RowsetA.ReleaseRows(hRow); PROVIDER_FREE(pOriginalData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(29) //*----------------------------------------------------------------------- // @mfunc Parameters - An inserted/modified row, update // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_29() { void* pOriginalData = NULL; void* pModifiedData = NULL; HROW hRow = DB_NULL_HROW; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the first row TESTC_(RowsetA.InsertRow(&hRow),S_OK); //Save the OriginalData TESTC_(RowsetA.GetRowData(hRow, &pOriginalData),S_OK); //Modify the row TESTC_(RowsetA.ModifyRow(hRow),S_OK); //Save the modified data TESTC_(RowsetA.GetRowData(hRow, &pModifiedData),S_OK); //Update the row TESTC_(RowsetA.UpdateRow(hRow),S_OK); //Call GetOriginalData on the updated row TESTC_(RowsetA.GetOriginalData(hRow, &RowsetA.m_pData),S_OK); //Compare data with modified data, should match, (updated) TESTC(RowsetA.CompareRowData(pModifiedData,RowsetA.m_pData)); //Compare data with original data, should not match (updated) TESTC(!RowsetA.CompareRowData(pOriginalData,RowsetA.m_pData)); CLEANUP: RowsetA.ReleaseRows(hRow); PROVIDER_FREE(pModifiedData); PROVIDER_FREE(pOriginalData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(30) //*----------------------------------------------------------------------- // @mfunc Parameters - Insert/Modify/Delete all rows // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_30() { TBEGIN const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; DBCOUNTITEM i,cRows = NROWS; //Create a rowset with no rows CRowsetUpdate RowsetA; RowsetA.SetProperty(DBPROP_CANHOLDROWS); TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_ALLFROMTBL, IID_IRowset, g_p1RowTable)==S_OK); cRows = RowsetA.GetMaxPendingRows(); if(cRows==0 || cRows>NROWS) cRows = NROWS; //Now insert all rows TESTC_(RowsetA.InsertRow(cRows, rghRow),S_OK); //Now modify all rows TESTC_(RowsetA.ModifyRow(cRows, rghRow),S_OK); //Now delete all rows TESTC_(RowsetA.DeleteRow(cRows, rghRow),S_OK); //Now call GetOriginalData for(i=0; iGetData(rghRow[ROW_ONE], hAccessor, pData1),S_OK); //Insert a row (BLOB data) TESTC_(RowsetA.pIRowsetChange()->InsertRow(NULL,hAccessor, pInsertData, &hNewRow),S_OK); //Modify a row (BLOB data) TESTC_(RowsetA.pIRowsetChange()->SetData(rghRow[ROW_ONE],hAccessor, pModifyData),S_OK); //Delete a row (BLOB data) TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK); //GetOrginalData should produce the orginal results TESTC_(RowsetA.pIRowsetUpdate()->GetOriginalData(rghRow[ROW_ONE], hAccessor, pData2),S_OK); TESTC(RowsetA.CompareRowData(pData1, pData2, hAccessor)); CLEANUP: //Free Data RowsetA.ReleaseRowData(pInsertData,hAccessor); RowsetA.ReleaseRowData(pModifyData,hAccessor); //Release the Accesssor RowsetA.ReleaseAccessor(hAccessor); RowsetA.ReleaseRows(hNewRow); RowsetA.ReleaseRows(NROWS, rghRow); PROVIDER_FREE(pData1); PROVIDER_FREE(pData2); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(39) //*----------------------------------------------------------------------- // @mfunc Accessor - BLOB / Long columns - QBU // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_39() { TBEGIN TRETURN //TODO need to work on blob support once supported HACCESSOR hAccessor = DB_NULL_HACCESSOR; const int NROWS = TWO_ROWS; HROW rghRow[NROWS] = {NULL,NULL}; HROW hNewRow = DB_NULL_HROW; DBLENGTH cRowSize = 0; void* pInsertData = NULL; void* pModifyData = NULL; void* pData1 = NULL; void* pData2 = NULL; CRowsetUpdate RowsetA; RowsetA.SetProperty(DBPROP_IRowsetLocate); RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Create Accessor binding BLOB/Long data (last param TRUE) TESTC_(GetAccessorAndBindings(RowsetA(),DBACCESSOR_ROWDATA,&hAccessor, NULL,NULL,&cRowSize,DBPART_ALL,UPDATEABLE_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); //Alloc buffers TESTC(RowsetA.MakeRowData(&pInsertData,hAccessor)); TESTC(RowsetA.MakeRowData(&pModifyData,hAccessor)); pData1 = PROVIDER_ALLOC(sizeof(pInsertData)); pData2 = PROVIDER_ALLOC(sizeof(pInsertData)); //Get Rows TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_ONE]),S_OK); TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_TWO]),S_OK); //Get the Data TESTC_(RowsetA.pIRowset()->GetData(rghRow[ROW_ONE], hAccessor, pData1),S_OK); //Insert a row (BLOB data) TESTC_(RowsetA.pIRowsetChange()->InsertRow(NULL,hAccessor, pInsertData, &hNewRow),S_OK); //Modify a row (BLOB data) TESTC_(RowsetA.pIRowsetChange()->SetData(rghRow[ROW_ONE],hAccessor, pModifyData),S_OK); //Delete a row (BLOB data) TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK); //GetOrginalData should produce the orginal results TESTC_(RowsetA.pIRowsetUpdate()->GetOriginalData(rghRow[ROW_ONE], hAccessor, pData2),S_OK); TESTC(RowsetA.CompareRowData(pData1, pData2, hAccessor)); CLEANUP: //Free Data RowsetA.ReleaseRowData(pInsertData,hAccessor); RowsetA.ReleaseRowData(pModifyData,hAccessor); //Release the Accesssor RowsetA.ReleaseAccessor(hAccessor); RowsetA.ReleaseRows(hNewRow); RowsetA.ReleaseRows(NROWS, rghRow); PROVIDER_FREE(pData1); PROVIDER_FREE(pData2); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(40) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_40() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(41) //*----------------------------------------------------------------------- // @mfunc Parameters - DB_E_BADACCESSORTYPE // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_41() { HACCESSOR hAccessor = DB_NULL_HACCESSOR; HROW hRow = DB_NULL_HROW; HRESULT hr = S_OK; //Create the rowset CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateCommand()==S_OK); //Create an invalid Accessor for use with GetOriginalData //Must be done on the CommandObject, ParameterAccessors are not allowed //to be created on the RowsetObject TEST2C_(hr = GetAccessorAndBindings(RowsetA.pICommand(),DBACCESSOR_PARAMETERDATA,&hAccessor, NULL,NULL,NULL,DBPART_ALL,ALL_COLS_BOUND,FORWARD, NO_COLS_BY_REF,NULL,NULL,NULL,DBTYPE_EMPTY,0,NULL,NULL, NO_COLS_OWNED_BY_PROV, DBPARAMIO_INPUT), S_OK, DB_E_BADACCESSORFLAGS); if(hr == S_OK) { //Now that we have the Accessor Created, now create the rowset //Must be a command query, since the accessor was created on the command TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_REVCOLLIST)==S_OK); //Obtain the first row TESTC_(RowsetA.GetRow(FIRST_ROW, &hRow),S_OK); //Call GetOriginalData with an invalid accessor type TESTC_(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,hAccessor,RowsetA.m_pData),DB_E_BADACCESSORTYPE); TESTC(RowsetA.m_pData!=NULL); } else { //Make sure the provider doesn't support parameters (validated immediately) TESTC_(QI(RowsetA.pICommand(), IID_ICommandWithParameters), E_NOINTERFACE); } CLEANUP: RowsetA.ReleaseAccessor(hAccessor); RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(42) //*----------------------------------------------------------------------- // @mfunc Parameters - DB_E_SEC_E_PERMISSIONDENIED // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_42() { HACCESSOR hAccessor = DB_NULL_HACCESSOR; HROW hRow = DB_NULL_HROW; HRESULT hr = S_OK; //Create the rowset CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateCommand()==S_OK); //Create an invalid Accessor for use with GetOriginalData //Must be done on the CommandObject, ParameterAccessors are not allowed //to be created on the RowsetObject TEST2C_(hr = GetAccessorAndBindings(RowsetA.pICommand(),DBACCESSOR_PARAMETERDATA,&hAccessor, NULL,NULL,NULL,DBPART_ALL,ALL_COLS_BOUND,FORWARD, NO_COLS_BY_REF,NULL,NULL,NULL,DBTYPE_EMPTY,0,NULL,NULL, NO_COLS_OWNED_BY_PROV, DBPARAMIO_INPUT), S_OK, DB_E_BADACCESSORFLAGS); if(hr == S_OK) { //Now that we have the Accessor Created, now create the rowset //Must be a command query, since the accessor was created on the command TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_REVCOLLIST)==S_OK); //Obtain the first row TESTC_(RowsetA.GetRow(FIRST_ROW, &hRow),S_OK); //Call GetOriginalData with an invalid accessor type TESTC_(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,hAccessor,RowsetA.m_pData),DB_E_BADACCESSORTYPE); TESTC(RowsetA.m_pData!=NULL); } else { //Make sure the provider doesn't support parameters (validated immediately) TESTC_(QI(RowsetA.pICommand(), IID_ICommandWithParameters), E_NOINTERFACE); } CLEANUP: RowsetA.ReleaseAccessor(hAccessor); RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(43) //*----------------------------------------------------------------------- // @mfunc Parameters - DB_E_BADBINDINFO // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_43() { HACCESSOR hAccessor = DB_NULL_HACCESSOR; HROW hRow = DB_NULL_HROW; HRESULT hr = S_OK; //Create the rowset CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateCommand()==S_OK); //Create an invalid Accessor for use with GetOriginalData //Must be done on the CommandObject, ParameterAccessors are not allowed //to be created on the RowsetObject TEST2C_(hr = GetAccessorAndBindings(RowsetA.pICommand(),DBACCESSOR_PARAMETERDATA,&hAccessor, NULL,NULL,NULL,DBPART_ALL,ALL_COLS_BOUND,FORWARD, NO_COLS_BY_REF,NULL,NULL,NULL,DBTYPE_EMPTY,0,NULL,NULL, NO_COLS_OWNED_BY_PROV, DBPARAMIO_INPUT), S_OK, DB_E_BADACCESSORFLAGS); if(hr == S_OK) { //Now that we have the Accessor Created, now create the rowset //Must be a command query, since the accessor was created on the command TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_REVCOLLIST)==S_OK); //Obtain the first row TESTC_(RowsetA.GetRow(FIRST_ROW, &hRow),S_OK); //Call GetOriginalData with an invalid accessor type TESTC_(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,hAccessor,RowsetA.m_pData),DB_E_BADACCESSORTYPE) ; TESTC(RowsetA.m_pData!=NULL); } else { //Make sure the provider doesn't support parameters (validated immediately) TESTC_(QI(RowsetA.pICommand(), IID_ICommandWithParameters), E_NOINTERFACE); } CLEANUP: RowsetA.ReleaseAccessor(hAccessor); RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(44) //*----------------------------------------------------------------------- // @mfunc Parameters - DB_E_COLUMNUNAVAILABLE // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_44() { HACCESSOR hAccessor = DB_NULL_HACCESSOR; HROW hRow = DB_NULL_HROW; HRESULT hr = S_OK; //Create the rowset CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateCommand()==S_OK); //Create an invalid Accessor for use with GetOriginalData //Must be done on the CommandObject, ParameterAccessors are not allowed //to be created on the RowsetObject TEST2C_(hr = GetAccessorAndBindings(RowsetA.pICommand(),DBACCESSOR_PARAMETERDATA,&hAccessor, NULL,NULL,NULL,DBPART_ALL,ALL_COLS_BOUND,FORWARD, NO_COLS_BY_REF,NULL,NULL,NULL,DBTYPE_EMPTY,0,NULL,NULL, NO_COLS_OWNED_BY_PROV, DBPARAMIO_INPUT), S_OK, DB_E_BADACCESSORFLAGS); if(hr == S_OK) { //Now that we have the Accessor Created, now create the rowset //Must be a command query, since the accessor was created on the command TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_REVCOLLIST)==S_OK); //Obtain the first row TESTC_(RowsetA.GetRow(FIRST_ROW, &hRow),S_OK); //Call GetOriginalData with an invalid accessor type TESTC_(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,hAccessor,RowsetA.m_pData),DB_E_BADACCESSORTYPE); TESTC(RowsetA.m_pData!=NULL); } else { //Make sure the provider doesn't support parameters (validated immediately) TESTC_(QI(RowsetA.pICommand(), IID_ICommandWithParameters), E_NOINTERFACE); } CLEANUP: RowsetA.ReleaseAccessor(hAccessor); RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(45) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_45() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(46) //*----------------------------------------------------------------------- // @mfunc Sequence - Call GetOriginalData 3 times // // @rdesc TEST_PASS or TEST_FAIL // int TCGetOriginalRows::Variation_46() { void* pOriginalData = NULL; void* pModifiedData = NULL; void* pFirstCall = NULL; void* pSecondCall = NULL; void* pThirdCall = NULL; HROW hRow = DB_NULL_HROW; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); pFirstCall = PROVIDER_ALLOC(sizeof(void*)*RowsetA.m_cRowSize); pSecondCall = PROVIDER_ALLOC(sizeof(void*)*RowsetA.m_cRowSize); pThirdCall = PROVIDER_ALLOC(sizeof(void*)*RowsetA.m_cRowSize); //Obtain the row handle(s); TESTC_(RowsetA.GetRow(FIRST_ROW, &hRow),S_OK); //Save the OriginalData TESTC_(RowsetA.GetRowData(hRow, &pOriginalData),S_OK); //Modify the row TESTC_(RowsetA.ModifyRow(hRow),S_OK); //Save the modified data TESTC_(RowsetA.GetRowData(hRow, &pModifiedData),S_OK); //Call GetOriginalData the first time TESTC_(RowsetA.GetOriginalData(hRow, &pFirstCall),S_OK); //Compare data with modified data, should not match TESTC(!RowsetA.CompareRowData(pModifiedData,pFirstCall)); //Compare data with original data, should match TESTC(RowsetA.CompareRowData(pOriginalData,pFirstCall)); //Modify the row again TESTC_(RowsetA.ModifyRow(hRow),S_OK); //Call GetOriginalData the Second time TESTC_(RowsetA.GetOriginalData(hRow, &pSecondCall),S_OK); //Modify the row again TESTC_(RowsetA.ModifyRow(hRow),S_OK); //Call GetOriginalData the Third time TESTC_(RowsetA.GetOriginalData(hRow, &pThirdCall),S_OK); //All three GetOriginalData calls should match, no update was performed TESTC(RowsetA.CompareRowData(pFirstCall, pSecondCall)); TESTC(RowsetA.CompareRowData(pSecondCall, pThirdCall)); CLEANUP: //Release the row handle RowsetA.ReleaseRows(hRow); PROVIDER_FREE(pModifiedData); PROVIDER_FREE(pOriginalData); PROVIDER_FREE(pFirstCall); PROVIDER_FREE(pSecondCall); PROVIDER_FREE(pThirdCall); TRETURN } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCGetOriginalRows::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CRowsetUpdate::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCGetPendingRows) //*----------------------------------------------------------------------- //| Test Case: TCGetPendingRows - IRowsetUpdate::GetPendingRows test case //| Created: 03/29/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCGetPendingRows::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CRowsetUpdate::Init()) // }} { return TEST_PASS; } return TEST_FAIL; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc General - Verify GetPendingRows alters row handles correctly // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_1() { DBCOUNTITEM cRowsObtained = 0; HROW rghRow[THREE_ROWS] = {NULL,NULL,NULL}; DBCOUNTITEM cPendingRows = 0; HROW* rgPendingRows = NULL; ULONG* rgRefCounts = NULL; DBROWSTATUS* rgRowStatus = NULL; ULONG ulRefCount = 0; DBSTATUS dwRowStatus = 0; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, THREE_ROWS, &cRowsObtained, rghRow),S_OK); //Make change(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; //Release row handles //DB_S_ERRORSOCCURRED - PendingChanges TESTC_(RowsetA.ReleaseRows(cRowsObtained, rghRow, &rgRefCounts, &rgRowStatus),S_OK); TESTC(rgRowStatus[ROW_ONE] == DBROWSTATUS_S_PENDINGCHANGES); //Verify now invalid row handles TESTC_(RowsetA.ReleaseRows(ONE_ROW, rghRow, &ulRefCount, &dwRowStatus), rgRefCounts[ROW_ONE] == 0 ? DB_E_ERRORSOCCURRED : S_OK); TESTC_(RowsetA.ReleaseRows(ONE_ROW, rghRow, &ulRefCount, &dwRowStatus), ulRefCount == 0 ? DB_E_ERRORSOCCURRED : S_OK); //Call GetPendingRows, and have row handles retuned TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,&rgPendingRows,NULL),S_OK); TESTC(cPendingRows==ONE_ROW); TESTC(rgPendingRows[0]==rghRow[ROW_ONE]); //verify row handles have been refcounted, should be valid TESTC_(RowsetA.ReleaseRows(cPendingRows, rgPendingRows, &ulRefCount, &dwRowStatus),S_OK); TESTC_(RowsetA.ReleaseRows(cPendingRows, rgPendingRows), ulRefCount == 0 ? DB_E_ERRORSOCCURRED : S_OK); CLEANUP: RowsetA.ReleaseRows(cPendingRows, rgPendingRows); PROVIDER_FREE(rgRefCounts); PROVIDER_FREE(rgRowStatus); PROVIDER_FREE(rgPendingRows); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes [NULL, _ALL, NULL, NULL] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_2() { TBEGIN DBCOUNTITEM cRowsObtained = 0; HROW* rghRows = NULL; HRESULT hr = S_OK; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 //Grab all the rows in the rowset, provider alloced array hr = RowsetA()->GetNextRows(NULL, 0, LONG_MAX, &cRowsObtained, &rghRows); TESTC(hr==DB_S_ENDOFROWSET || hr==DB_S_ROWLIMITEXCEEDED || hr==E_OUTOFMEMORY); if(hr==E_OUTOFMEMORY) { TESTC(cRowsObtained == 0); TESTC(rghRows == NULL); goto CLEANUP; } if(hr==DB_S_ROWLIMITEXCEEDED) { TESTC(RowsetA.GetMaxOpenRows() != 0); TESTC(cRowsObtained && cRowsObtained= 3); TESTC(rghRows!=NULL); } //Modify Row 1 TESTC_(RowsetA.ModifyRow(rghRows[ROW_ONE]),S_OK) TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,NULL,NULL,NULL),S_OK); //Delete Row 2 TESTC_PROVIDER(cRowsObtained >=2); if(!RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.UpdateAll(),S_OK); TESTC_(RowsetA.DeleteRow(rghRows[ROW_TWO]),S_OK) TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,NULL,NULL,NULL),S_OK); //Insert Row3 TESTC_PROVIDER(cRowsObtained >=3); if(!RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.UpdateAll(),S_OK); TESTC_(RowsetA.InsertRow(&rghRows[ROW_THREE]),S_OK) TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,NULL,NULL,NULL),S_OK); CLEANUP: RowsetA.ReleaseRows(cRowsObtained,rghRows); PROVIDER_FREE(rghRows); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes [invalid, _ALL, NULL, invalid, invalid] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_3() { TBEGIN HROW rghRow[THREE_ROWS] = {NULL,NULL,NULL}; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //NOTE: We pass Invalid pointers to prgPendingRows and prgPendingStauts on input, since the //spec states prgPendingRows and prgPendingStatus are ignored if pcPendingRows is NULL on input. //insert row 1; TESTC_(RowsetA.InsertRow(&rghRow[ROW_ONE]),S_OK) TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(INVALID(HCHAPTER),DBPENDINGSTATUS_ALL,NULL,INVALID(HROW**),INVALID(ULONG**)),S_OK); //insert row 2; if(!RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.UpdateAll(),S_OK); TESTC_(RowsetA.InsertRow(&rghRow[ROW_TWO]),S_OK) TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(INVALID(HCHAPTER),DBPENDINGSTATUS_ALL,NULL,INVALID(HROW**),INVALID(ULONG**)),S_OK); //insert row 3; if(!RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.UpdateAll(),S_OK); TESTC_(RowsetA.InsertRow(&rghRow[ROW_THREE]),S_OK) TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(INVALID(HCHAPTER),DBPENDINGSTATUS_ALL,NULL,INVALID(HROW**),INVALID(ULONG**)),S_OK); CLEANUP: RowsetA.ReleaseRows(THREE_ROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes [NULL, _ALL, valid, NULL, NULL] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_4() { TBEGIN HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; DBCOUNTITEM cPendingRows = 0; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW, TWO_ROWS, rghRow),S_OK); //Make change(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1 TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,NULL,NULL),S_OK); COMPC(cPendingRows,ONE_ROW); TESTC_PROVIDER(RowsetA.AllowPendingRows(2)); TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK) //delete row 2 TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,NULL,NULL),S_OK); COMPC(cPendingRows,TWO_ROWS); TESTC_PROVIDER(RowsetA.AllowPendingRows(3)); TESTC_(RowsetA.InsertRow(&rghRow[ROW_THREE]),S_OK) //Insert row 3 TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 3 TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,NULL,NULL),S_OK); COMPC(cPendingRows,THREE_ROWS); TESTC_PROVIDER(RowsetA.AllowPendingRows(4)); TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //insert row 4 TESTC_(RowsetA.ModifyRow(rghRow[ROW_FOUR]),S_OK) //modify row 4 TESTC_(RowsetA.DeleteRow(rghRow[ROW_FOUR]),S_OK) //delete row 4 TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,NULL,NULL),S_OK); COMPC(cPendingRows,THREE_ROWS); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes [NULL, _ALL, valid, NULL, valid] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_5() { TBEGIN const int NROWS = SEVEN_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL}; DBCOUNTITEM cPendingRows = 0; DBPENDINGSTATUS* rgPendingStatus = NULL; DBCOUNTITEM cModifiedRows = 0; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK); //Make change(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; cModifiedRows++; if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 3; cModifiedRows++; } else { //Otherwise make sure the Data is unchanged... TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),DB_E_MAXPENDCHANGESEXCEEDED); TESTC(RowsetA.CompareOrgRowData(rghRow[ROW_THREE])); } if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //modify row 4; TESTC_(RowsetA.DeleteRow(rghRow[ROW_FOUR]),S_OK) //delete row 4; } if(RowsetA.AllowPendingRows(4)) { TESTC_(RowsetA.InsertRow(&rghRow[ROW_SIX]),S_OK) //insert row 6; TESTC_(RowsetA.ModifyRow(rghRow[ROW_SIX]),S_OK) //modify row 6; TESTC_(RowsetA.DeleteRow(rghRow[ROW_SIX]),S_OK) //delete row 6; } if(RowsetA.AllowPendingRows(5)) { TESTC_(RowsetA.InsertRow(&rghRow[ROW_SEVEN]),S_OK) //insert row 7; cModifiedRows++; } TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,NULL,&rgPendingStatus),S_OK); COMPC(cPendingRows, cModifiedRows) COMPC(rgPendingStatus[0], DBPENDINGSTATUS_CHANGED) if(cModifiedRows >= 2) COMPC(rgPendingStatus[1], DBPENDINGSTATUS_CHANGED) if(cModifiedRows >= 3) COMPC(rgPendingStatus[2], DBPENDINGSTATUS_NEW) CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(rgPendingStatus); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes [NULL, _ALL, valid, valid, NULL] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_6() { TBEGIN const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; DBCOUNTITEM cPendingRows = 0; HROW* rgPendingRows = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Make change(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1 TESTC_PROVIDER(RowsetA.AllowPendingRows(2)); TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK) //delete row 2 TESTC_PROVIDER(RowsetA.AllowPendingRows(3)); TESTC_(RowsetA.InsertRow(&rghRow[ROW_THREE]),S_OK) //insert row 3 TESTC_(RowsetA.DeleteRow(rghRow[ROW_THREE]),S_OK) //delete row 3 TESTC_PROVIDER(RowsetA.AllowPendingRows(4)); TESTC_(RowsetA.ModifyRow(rghRow[ROW_FOUR]),S_OK) //modify row 4 TESTC_(RowsetA.DeleteRow(rghRow[ROW_FOUR]),S_OK) //delete row 4 TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,&rgPendingRows,NULL),S_OK); RowsetA.ReleaseRows(cPendingRows,rgPendingRows); //GetPendingRows refcounts COMPC(cPendingRows,THREE_ROWS) TESTC(rgPendingRows!=NULL); COMPC(rgPendingRows[0],rghRow[ROW_ONE]) COMPC(rgPendingRows[1],rghRow[ROW_TWO]) COMPC(rgPendingRows[2],rghRow[ROW_FOUR]) CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(rgPendingRows); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc Boundary - No Changes [NULL, _ALL, NULL, NULL, NULL] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_7() { CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,NULL,NULL,NULL),S_FALSE); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc Boundary - No Changes [NULL, _ALL, valid, NULL, NULL] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_8() { DBCOUNTITEM cPendingRows = 1; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,NULL,NULL),S_FALSE); COMP(cPendingRows,NO_ROWS); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc Boundary - No Changes [NULL, _ALL, valid, valid, NULL] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_9() { DBCOUNTITEM cPendingRows = 1; HROW* rgPendingRows = NULL; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,&rgPendingRows,NULL),S_FALSE); COMPC(cPendingRows,NO_ROWS) TESTC(rgPendingRows==NULL) ; CLEANUP: PROVIDER_FREE(rgPendingRows); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(10) //*----------------------------------------------------------------------- // @mfunc Boundary - No Changes [NULL, _ALL, valid, valid, valid] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_10() { DBCOUNTITEM cPendingRows = 1; HROW* rgPendingRows = NULL; DBPENDINGSTATUS* rgPendingStatus = NULL; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,&rgPendingRows,&rgPendingStatus),S_FALSE); COMPC(cPendingRows,NO_ROWS) TESTC(rgPendingRows==NULL && rgPendingStatus==NULL); CLEANUP: PROVIDER_FREE(rgPendingRows) PROVIDER_FREE(rgPendingStatus) TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(11) //*----------------------------------------------------------------------- // @mfunc Boundary - No Changes (NULL, _ALL, valid, NULL, valid // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_11() { DBCOUNTITEM cPendingRows = 1; DBPENDINGSTATUS* rgPendingStatus = NULL; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,NULL,&rgPendingStatus),S_FALSE); TESTC(cPendingRows==NO_ROWS && rgPendingStatus==NULL); CLEANUP: PROVIDER_FREE(rgPendingStatus) TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(12) //*----------------------------------------------------------------------- // @mfunc Boundary - Empty Rowset [NULL, _ALL, valid, valid, valid] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_12() { DBCOUNTITEM cPendingRows = 1; HROW* rgPendingRows = NULL; DBPENDINGSTATUS* rgPendingStatus = NULL; CRowsetUpdate EmptyRowset; TESTC_PROVIDER(EmptyRowset.CreateRowset(SELECT_EMPTYROWSET)==S_OK); TESTC_(EmptyRowset.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,&rgPendingRows,&rgPendingStatus),S_FALSE); COMPC(cPendingRows,NO_ROWS) TESTC(rgPendingRows==NULL && rgPendingStatus==NULL); CLEANUP: PROVIDER_FREE(rgPendingRows) PROVIDER_FREE(rgPendingStatus) TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(13) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_13() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(14) //*----------------------------------------------------------------------- // @mfunc Parameters - DBPENDINGSTATUS seperately, before any changes // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_14() { TBEGIN const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; HROW hNewRow = NULL; ULONG cModifiedRows = 0; ULONG cDeletedRows = 0; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain the row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //BEFORE CHANGES //GetPendingRows DBPENDINGSTATUS_NEW TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_NEW, NO_ROWS),S_FALSE); //GetPendingRows DBPENDINGSTATUS_CHANGED TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_CHANGED, NO_ROWS),S_FALSE); //GetPendingRows DBPENDINGSTATUS_DELETED TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_DELETED, NO_ROWS),S_FALSE); //GetPendingRows DBPENDINGSTATUS_ALL TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_ALL, NO_ROWS),S_FALSE); //AFTER CHANGES //Insert a row TESTC_(RowsetA.InsertRow(&hNewRow),S_OK) //Insert row; //Modify a row if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; cModifiedRows++; } if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 3; cModifiedRows++; } //Delete a row if(RowsetA.AllowPendingRows(4)) { TESTC_(RowsetA.DeleteRow(rghRow[ROW_FOUR]),S_OK) //delete row 4; cDeletedRows++; } //GetPendingRows DBPENDINGSTATUS_NEW TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_NEW, ONE_ROW, DBPENDINGSTATUS_NEW),S_OK); //GetPendingRows DBPENDINGSTATUS_CHANGED TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_CHANGED, cModifiedRows, DBPENDINGSTATUS_CHANGED),cModifiedRows ? S_OK : S_FALSE); //GetPendingRows DBPENDINGSTATUS_DELETED TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_DELETED, cDeletedRows, DBPENDINGSTATUS_DELETED), cDeletedRows ? S_OK : S_FALSE); //GetPendingRows DBPENDINGSTATUS_ALL TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_ALL, 1 + cModifiedRows + cDeletedRows), S_OK); //GetPendingRows DBPENDINGSTATUS_UNCHANGED TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_UNCHANGED,NULL,NULL,NULL),E_INVALIDARG); //GetPendingRows DBPENDINGSTATUS_INVALIDROW TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_INVALIDROW,NULL,NULL,NULL),E_INVALIDARG); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); RowsetA.ReleaseRows(hNewRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(15) //*----------------------------------------------------------------------- // @mfunc Parameters - DBPENDINGSTATUS_INVALIDROW // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_15() { const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; DBCOUNTITEM cPendingRows; HROW* rgPendingRows = NULL; DBPENDINGSTATUS* rgPendingStatus = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Modify row(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; //GetPendingRows DBPENDINGSTATUS_INVALIDROW TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_INVALIDROW,&cPendingRows,&rgPendingRows,&rgPendingStatus),E_INVALIDARG); COMPC(cPendingRows, NO_ROWS); TESTC(rgPendingRows==NULL && rgPendingStatus==NULL); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); PROVIDER_FREE(rgPendingRows) PROVIDER_FREE(rgPendingStatus) TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(16) //*----------------------------------------------------------------------- // @mfunc Parameters - DBPENDINGSTATUS _NEW | _CHANGED | _SOFTDELETED // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_16() { const int NROWS = TWO_ROWS; HROW rghRow[NROWS] = {NULL,NULL}; DBCOUNTITEM cPendingRows; HROW* rgPendingRows = NULL; DBPENDINGSTATUS* rgPendingStatus = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Modify row(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWO]),S_OK) //modify row 2; //GetPendingRows NEW | CHANGED | SOFTDELETED TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_NEW |DBPENDINGSTATUS_CHANGED |DBPENDINGSTATUS_DELETED,&cPendingRows,&rgPendingRows,&rgPendingStatus),S_OK); RowsetA.ReleaseRows(cPendingRows,rgPendingRows); //GetPendingRows refcounts COMPC(cPendingRows,ONE_ROW) COMPC(rgPendingRows[0],rghRow[ROW_TWO]) COMPC(rgPendingStatus[0],DBPENDINGSTATUS_CHANGED) PROVIDER_FREE(rgPendingRows); PROVIDER_FREE(rgPendingStatus); //GetPendingRows NEW | CHANGED | SOFTDELETED | UNCHANGED TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_NEW |DBPENDINGSTATUS_CHANGED |DBPENDINGSTATUS_DELETED|DBPENDINGSTATUS_UNCHANGED,&cPendingRows,&rgPendingRows,&rgPendingStatus),E_INVALIDARG); COMPC(cPendingRows,NO_ROWS) TESTC(rgPendingRows==NULL && rgPendingStatus==NULL); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(rgPendingRows); PROVIDER_FREE(rgPendingStatus); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(17) //*----------------------------------------------------------------------- // @mfunc Parameters - DBPENDINGSTATUS_NEW, w/ no new rows // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_17() { const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; DBCOUNTITEM cPendingRows; HROW* rgPendingRows = NULL; DBPENDINGSTATUS* rgPendingStatus = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Delete row(s) TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK) //modify row 2; //GetPendingRows NEW, with no new rows TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_NEW,&cPendingRows,&rgPendingRows,&rgPendingStatus),S_FALSE); COMPC(cPendingRows, NO_ROWS) //No NEW rows TESTC(rgPendingRows==NULL && rgPendingStatus==NULL); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); PROVIDER_FREE(rgPendingRows) PROVIDER_FREE(rgPendingStatus) TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(18) //*----------------------------------------------------------------------- // @mfunc Parameters - DBPENDINGSTATUS_CHANGED, w/ no changed rows // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_18() { TBEGIN const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; HROW hNewRow = NULL; DBCOUNTITEM cPendingRows; HROW* rgPendingRows = NULL; DBPENDINGSTATUS* rgPendingStatus = NULL; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain the row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Insert row(s) TESTC_(RowsetA.InsertRow(&hNewRow),S_OK) //insert row; //GetPendingRows CHANGED, with no modified rows TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_CHANGED,&cPendingRows,&rgPendingRows,&rgPendingStatus),S_FALSE); COMPC(cPendingRows,NO_ROWS) //No changed rows TESTC(rgPendingRows==NULL && rgPendingStatus==NULL); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); RowsetA.ReleaseRows(hNewRow); PROVIDER_FREE(rgPendingRows) PROVIDER_FREE(rgPendingStatus) TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(19) //*----------------------------------------------------------------------- // @mfunc Parameters - DBPENDINGSTATUS_UNCHANGED, w/ all changed rows // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_19() { const int NROWS = SEVEN_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL}; DBCOUNTITEM cPendingRows; HROW* rgPendingRows = NULL; DBPENDINGSTATUS* rgPendingStatus = NULL; DBCOUNTITEM cModifiedRows = 0; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERINSERT); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Modify row(s) cModifiedRows = RowsetA.GetMaxPendingRows(); if(cModifiedRows==0 || cModifiedRows > NROWS) cModifiedRows = NROWS; TESTC_(RowsetA.ModifyRow(cModifiedRows, rghRow),S_OK) //modify all rows; //GetPendingRows DBPENDINGSTATUS_UNCHANGED TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_UNCHANGED,&cPendingRows,&rgPendingRows,&rgPendingStatus),E_INVALIDARG); COMPC(cPendingRows,NO_ROWS) TESTC(rgPendingRows==NULL && rgPendingStatus==NULL); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); PROVIDER_FREE(rgPendingRows) PROVIDER_FREE(rgPendingStatus) TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(20) //*----------------------------------------------------------------------- // @mfunc Parameters - DBPENDINGSTATUS_DELETED, w/ no soft-deleted rows // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_20() { HROW hNewRow = NULL; DBCOUNTITEM cPendingRows; HROW* rgPendingRows = NULL; DBPENDINGSTATUS* rgPendingStatus = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Insert row(s) TESTC_(RowsetA.InsertRow(&hNewRow),S_OK); //Modify row(s) TESTC_(RowsetA.ModifyRow(hNewRow),S_OK); //GetPendingRows SOFTDELETED, with no deleted rows TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_DELETED,&cPendingRows,&rgPendingRows,&rgPendingStatus),S_FALSE); COMPC(cPendingRows,NO_ROWS) //No soft-Deleted rows TESTC(rgPendingRows==NULL && rgPendingStatus==NULL); //According to the 2.0 spec, InsertRow - SetData counts as NEW row not CHANGED TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_NEW, ONE_ROW),S_OK); TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_CHANGED, NO_ROWS),S_FALSE); CLEANUP: RowsetA.ReleaseRows(hNewRow); PROVIDER_FREE(rgPendingRows) PROVIDER_FREE(rgPendingStatus) TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(21) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_21() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(22) //*----------------------------------------------------------------------- // @mfunc Parameters - _NEW | _UNCHANGED // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_22() { TBEGIN const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; HROW hNewRow = NULL; DBCOUNTITEM cPendingRows; HROW* rgPendingRows = NULL; DBPENDINGSTATUS* rgPendingStatus = NULL; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain the row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Insert row(s) TESTC_(RowsetA.InsertRow(&hNewRow),S_OK); //GetPendingRows TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_NEW | DBPENDINGSTATUS_UNCHANGED,&cPendingRows,&rgPendingRows,&rgPendingStatus),E_INVALIDARG); COMPC(cPendingRows,NO_ROWS) TESTC(rgPendingRows==NULL && rgPendingStatus==NULL); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); RowsetA.ReleaseRows(hNewRow); PROVIDER_FREE(rgPendingRows) PROVIDER_FREE(rgPendingStatus) TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(23) //*----------------------------------------------------------------------- // @mfunc Parameters - _NEW | _SOFTDELETED // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_23() { TBEGIN const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; HROW hNewRow = NULL; DBCOUNTITEM cPendingRows; HROW* rgPendingRows = NULL; DBPENDINGSTATUS* rgPendingStatus = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain the row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Insert row(s) TESTC_(RowsetA.InsertRow(&hNewRow),S_OK); //Modify row(s) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWO]),S_OK); if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK); //GetPendingRows TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_NEW | DBPENDINGSTATUS_DELETED,&cPendingRows,&rgPendingRows,&rgPendingStatus),S_OK); RowsetA.ReleaseRows(cPendingRows,rgPendingRows); //GetPendingRows refcounts TESTC(cPendingRows == ONE_ROW); TESTC(rgPendingRows!=NULL && rgPendingStatus!=NULL); TESTC(rgPendingRows[0]==hNewRow); TESTC(rgPendingStatus[0]==DBPENDINGSTATUS_NEW); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); RowsetA.ReleaseRows(hNewRow); PROVIDER_FREE(rgPendingRows) PROVIDER_FREE(rgPendingStatus) TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(24) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_24() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(25) //*----------------------------------------------------------------------- // @mfunc Parameters - Insert/Modify/Delete a single row // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_25() { HROW hRow = DB_NULL_HROW; DBCOUNTITEM cPendingRows; HROW* rgPendingRows = NULL; DBPENDINGSTATUS* rgPendingStatus = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Insert row(s) TESTC_(RowsetA.InsertRow(&hRow),S_OK); //Modify row(s) TESTC_(RowsetA.ModifyRow(hRow),S_OK); //Delete row(s) TESTC_(RowsetA.DeleteRow(hRow),S_OK); //GetPendingRows TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,&rgPendingRows,&rgPendingStatus),S_FALSE); COMPC(cPendingRows,NO_ROWS) TESTC(rgPendingRows==NULL && rgPendingStatus==NULL); CLEANUP: RowsetA.ReleaseRows(hRow); PROVIDER_FREE(rgPendingRows) PROVIDER_FREE(rgPendingStatus) TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(26) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_26() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(27) //*----------------------------------------------------------------------- // @mfunc Sequence - Call GetPendingRows 3 times // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_27() { TBEGIN const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; HROW hNewRow = NULL; ULONG cModifiedRows = 0; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain the row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Insert row(s) TESTC_(RowsetA.InsertRow(&hNewRow),S_OK); cModifiedRows++; //Modify row(s) if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWO]),S_OK); cModifiedRows++; } if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK); cModifiedRows++; } //GetPendingRows #1 TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_ALL, cModifiedRows),S_OK); //GetPendingRows #2 TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_ALL, cModifiedRows),S_OK); //Update TESTC_(RowsetA.UpdateAll(),S_OK); //GetPendingRows #3 TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_ALL, NO_ROWS),S_FALSE); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); RowsetA.ReleaseRows(hNewRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(28) //*----------------------------------------------------------------------- // @mfunc Sequence - Modify the same row twice // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_28() { const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; DBCOUNTITEM cPendingRows; HROW* rgPendingRows = NULL; DBPENDINGSTATUS* rgPendingStatus = NULL; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, TWO_ROWS, rghRow),S_OK); //Make a duplicate HROW, HROW3 == HROW1 rghRow[ROW_THREE] = rghRow[ROW_ONE]; //Modify row(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 1, duplicate; //GetPendingRows TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,&rgPendingRows,&rgPendingStatus),S_OK); RowsetA.ReleaseRows(cPendingRows,rgPendingRows); //GetPendingRows refcounts COMPC(cPendingRows,ONE_ROW) COMPC(rgPendingRows[0],rghRow[ROW_ONE]) COMPC(rgPendingStatus[0],DBPENDINGSTATUS_CHANGED) CLEANUP: RowsetA.ReleaseRows(TWO_ROWS,rghRow); PROVIDER_FREE(rgPendingRows) PROVIDER_FREE(rgPendingStatus) TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(29) //*----------------------------------------------------------------------- // @mfunc Sequence - Modify the same row twice, undo, GetPendingRows // // @rdesc TEST_PASS or TEST_FAIL // int TCGetPendingRows::Variation_29() { const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; DBCOUNTITEM cPendingRows; HROW* rgPendingRows = NULL; DBPENDINGSTATUS* rgPendingStatus = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, TWO_ROWS, rghRow),S_OK); //Make a duplicate HROW, HROW3 == HROW1 rghRow[ROW_THREE] = rghRow[ROW_ONE]; //Modify row(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; TESTC_(RowsetA.DeleteRow(rghRow[ROW_THREE]),S_OK) //delete row 1, duplicate; //GetPendingRows TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,&rgPendingRows,&rgPendingStatus),S_OK); RowsetA.ReleaseRows(cPendingRows,rgPendingRows); //GetPendingRows refcounts COMPC(cPendingRows,ONE_ROW) COMPC(rgPendingRows[0],rghRow[ROW_ONE]) COMPC(rgPendingStatus[0],DBPENDINGSTATUS_DELETED) PROVIDER_FREE(rgPendingRows); PROVIDER_FREE(rgPendingStatus); //Undo all TESTC_(RowsetA.UndoAll(),S_OK); //GetPendingRows TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,&rgPendingRows,&rgPendingStatus),S_FALSE); COMPC(cPendingRows,NO_ROWS) TESTC(rgPendingRows==NULL && rgPendingStatus==NULL); CLEANUP: RowsetA.ReleaseRows(TWO_ROWS,rghRow); PROVIDER_FREE(rgPendingRows) PROVIDER_FREE(rgPendingStatus) TRETURN } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCGetPendingRows::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CRowsetUpdate::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCUndo) //*----------------------------------------------------------------------- //| Test Case: TCUndo - IRowsetUpdate::Undo test case //| Created: 03/29/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCUndo::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CRowsetUpdate::Init()) // }} { return TEST_PASS; } return TEST_FAIL; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc Boundary - No Changes [NULL, 0, NULL, NULL, NULL] // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_1() { CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); TESTC_(RowsetA.pIRowsetUpdate()->Undo(NULL,0,NULL,NULL,NULL,NULL),S_OK); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Boundary - No Changes [NULL, N, valid, NULL, NULL] // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_2() { HROW hInvalidRow = INVALID(HROW); CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); TESTC_(RowsetA.pIRowsetUpdate()->Undo(NULL,0,&hInvalidRow,NULL,NULL,NULL),S_OK); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc Boundary - No Changes [NULL,0,NULL, valid, valid] // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_3() { DBCOUNTITEM cRowsUndone = 1; //should be 0 on error HROW* rgRowsUndone; //should be NULL on error DBROWSTATUS* rgRowStatus; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); TESTC_(RowsetA.pIRowsetUpdate()->Undo(NULL,0,NULL,&cRowsUndone,&rgRowsUndone,&rgRowStatus),S_OK); COMPC(cRowsUndone,NO_ROWS) TESTC(rgRowsUndone==NULL && rgRowStatus==NULL); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc Boundary - No Changes [invalid, 1, NULL, valid, valid] // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_4() { DBCOUNTITEM cRowsUndone = 1; HROW* rgRowsUndone; DBROWSTATUS* rgRowStatus; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); TESTC_(RowsetA.pIRowsetUpdate()->Undo(INVALID(HCHAPTER),ONE_ROW,NULL,&cRowsUndone,&rgRowsUndone,&rgRowStatus),E_INVALIDARG); COMPC(cRowsUndone,NO_ROWS) TESTC(rgRowsUndone==NULL && rgRowStatus==NULL); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes [NULL, 0, NULL, NULL, valid] // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_5() { TBEGIN const int NROWS = SEVEN_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL}; HROW* rgRowsUndone = INVALID(HROW*); DBROWSTATUS* rgRowStatus = INVALID(DBROWSTATUS*); CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_FOUR]),S_OK); TESTC_(RowsetA.GetNextRows(&rghRow[ROW_FIVE]),S_OK); //Make change(s) TESTC_(RowsetA.InsertRow(&rghRow[ROW_THREE]),S_OK) //insert row 3; TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 3; //Undo (0,NULL) TESTC_(RowsetA.pIRowsetUpdate()->Undo(NULL,0,NULL,NULL,&rgRowsUndone,&rgRowStatus),S_OK); //Since pcRowsUndone==NULL, there can be no out arrays //Should just ingore rgRowsUndone / rgRowStatus TESTC(rgRowsUndone==INVALID(HROW*) && rgRowStatus==INVALID(DBROWSTATUS*)); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes [NULL, 0, valid, valid, valid] // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_6() { TBEGIN const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_ONE]),S_OK) ; TESTC_(RowsetA.GetNextRows(&rghRow[ROW_TWO]),S_OK) ; TESTC_(RowsetA.GetNextRows(&rghRow[ROW_FOUR]),S_OK) ; //Make 2 changes TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK) //delete row 2; } if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.InsertRow(&rghRow[ROW_THREE]),S_OK) //insert row 3; TESTC_(RowsetA.DeleteRow(rghRow[ROW_THREE]),S_OK) //delete row 3; } //Call Undo, (all) TESTC_(RowsetA.UndoRow(0,rghRow),S_OK); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes [NULL, N, valid, NULL, NULL] // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_7() { TBEGIN const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; DBROWSTATUS* rgRowStatus = NULL; void* pOriginalData[NROWS] = {NULL,NULL,NULL}; void* pModifiedData[NROWS] = {NULL,NULL,NULL}; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_ONE]),S_OK) ; TESTC_(RowsetA.GetNextRows(SECOND_ROW,&rghRow[ROW_TWO]),S_OK); rghRow[ROW_THREE] = rghRow[ROW_TWO]; //2 instances of the same hrow with changes //Save Orginal Data TESTC_(RowsetA.GetRowData(NROWS, rghRow, pOriginalData),S_OK); //Make 2 changes TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWO]),S_OK) //modify row 2; if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.DeleteRow(rghRow[ROW_THREE]),S_OK) //delete row 3; //Save Modified Data TESTC_(RowsetA.GetRowData(rghRow[ROW_ONE],&pModifiedData[0]),S_OK); TESTC_(RowsetA.pIRowsetUpdate()->Undo(NULL,NROWS,rghRow,NULL,NULL,&rgRowStatus),S_OK); //rgRowStatus should be filled in TESTC(rgRowStatus!=NULL); TESTC(VerifyArray(NROWS,rgRowStatus,DBROWSTATUS_S_OK)); //Verify undo matched orginal data TESTC(RowsetA.CompareRowData(NROWS, rghRow,pOriginalData)); //Verify undo does not match modified data TESTC(!RowsetA.CompareRowData(rghRow[ROW_ONE],pModifiedData[0])); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE2(NROWS, pOriginalData); PROVIDER_FREE2(NROWS, pModifiedData); PROVIDER_FREE(rgRowStatus); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes [NULL, N, valid, valid, valid] // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_8() { TBEGIN const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; DBROWSTATUS* rgRowStatus = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_ONE]),S_OK) ; TESTC_(RowsetA.GetNextRows(&rghRow[ROW_TWO]),S_OK) ; rghRow[ROW_FOUR] = rghRow[ROW_TWO]; //2 instances of the same hrow with changes //Make changes TESTC_(RowsetA.InsertRow(&rghRow[ROW_THREE]),S_OK) //insert row 3; TESTC_(RowsetA.DeleteRow(rghRow[ROW_THREE]),S_OK) //delete row 3; if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK) //delete row 2; //Undo NROWS TESTC_(RowsetA.pIRowsetUpdate()->Undo(NULL,NROWS,rghRow,NULL,NULL,&rgRowStatus),DB_S_ERRORSOCCURRED); TESTC(rgRowStatus!=NULL); TESTC(rgRowStatus[0]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[1]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[2]==DBROWSTATUS_E_DELETED); TESTC(rgRowStatus[3]==DBROWSTATUS_S_OK); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(rgRowStatus); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes [invalid, N, NULL, valid, valid] // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_9() { TBEGIN DBCOUNTITEM cRowsUndone = 1; //should be 0 on error HROW* rgRowsUndone; //should be NULL on error DBROWSTATUS* rgRowStatus; //should be NULL on error const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_ONE]),S_OK); //Make 2 changes TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; TESTC_(RowsetA.pIRowsetUpdate()->Undo(INVALID(HCHAPTER),NROWS,NULL,&cRowsUndone,&rgRowsUndone,&rgRowStatus),E_INVALIDARG); COMPC(cRowsUndone,NO_ROWS) TESTC(rgRowsUndone==NULL && rgRowStatus==NULL); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(10) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes [invalid, N, valid, valid, NULL] // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_10() { TBEGIN const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; DBCOUNTITEM cRowsUndone = 1; DBROWSTATUS* rgRowStatus = INVALID(DBROWSTATUS*); CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_ONE]),S_OK) ; //Make 2 changes TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; TESTC_(RowsetA.pIRowsetUpdate()->Undo(NULL,0,NULL,&cRowsUndone,NULL,&rgRowStatus),E_INVALIDARG); COMPC(cRowsUndone,NO_ROWS); TESTC(rgRowStatus==NULL); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(11) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_11() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(12) //*----------------------------------------------------------------------- // @mfunc Parameters - 3 invalid / 2 modified // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_12() { void* pOriginalData = NULL; void* pModifiedData = NULL; const int NROWS = FIVE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL}; DBROWSTATUS* rgRowStatus = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s), starting at row 1, get 5 handles rghRow[ROW_ONE] = DB_NULL_HROW; //invalid TESTC_(RowsetA.GetRow(FIRST_ROW,TWO_ROWS,&rghRow[ROW_TWO]),S_OK) ; rghRow[ROW_FOUR] = INVALID(HROW); //invalid rghRow[ROW_FIVE] = DB_NULL_HROW; //invalid //Save the orginal row data TESTC_(RowsetA.GetRowData(rghRow[ROW_THREE], &pOriginalData),S_OK); //Delete/Modify the row(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 3; //Save the modified row data TESTC_(RowsetA.GetRowData(rghRow[ROW_THREE], &pModifiedData),S_OK); //Call Undo on the modified/invlaid row(s) TESTC_(RowsetA.pIRowsetUpdate()->Undo(NULL,NROWS,rghRow,NULL,NULL,&rgRowStatus),DB_S_ERRORSOCCURRED); TESTC(rgRowStatus!=NULL); TESTC(rgRowStatus[0]==DBROWSTATUS_E_INVALID); TESTC(rgRowStatus[1]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[2]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[3]==DBROWSTATUS_E_INVALID); TESTC(rgRowStatus[4]==DBROWSTATUS_E_INVALID); //Compare data with orginal data, should be equal, undo was called TESTC(RowsetA.CompareRowData(rghRow[ROW_THREE], pOriginalData)); //Compare data with modified data, should not be equal, undo was called TESTC(!RowsetA.CompareRowData(rghRow[ROW_THREE], pModifiedData)); CLEANUP: //Release the row handles RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(pOriginalData); PROVIDER_FREE(pModifiedData); PROVIDER_FREE(rgRowStatus); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(13) //*----------------------------------------------------------------------- // @mfunc Parameters - 1 hard del / 1 invalid / 1 modified // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_13() { TBEGIN void* pOriginalData = NULL; void* pModifiedData = NULL; const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; DBROWSTATUS* rgRowStatus = NULL; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1, get 5 handles rghRow[ROW_ONE] = DB_NULL_HROW; TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_TWO]),S_OK) ; TESTC_(RowsetA.GetNextRows(&rghRow[ROW_THREE]),S_OK); //Save the orginal modified row data TESTC_(RowsetA.GetRowData(rghRow[ROW_TWO], &pOriginalData),S_OK); //Hard delete the row TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_THREE]),S_OK) //hard-delete row 3; //Modify/delete row(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWO]),S_OK) //modify row 2; TESTC_(RowsetA.GetRowData(rghRow[ROW_TWO], &pModifiedData),S_OK); //Call Undo on the modified/invlaid row(s) TESTC_(RowsetA.pIRowsetUpdate()->Undo(NULL,NROWS,rghRow,NULL,NULL,&rgRowStatus),DB_S_ERRORSOCCURRED); TESTC(rgRowStatus!=NULL); TESTC(rgRowStatus[0]==DBROWSTATUS_E_INVALID); TESTC(rgRowStatus[1]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[2]==DBROWSTATUS_E_DELETED); //Compare data with orginal data, should be equal, undo was called TESTC(RowsetA.CompareRowData(rghRow[ROW_TWO],pOriginalData)); //Compare data with modified data, should not be equal, undo was called TESTC(!RowsetA.CompareRowData(rghRow[ROW_TWO],pModifiedData)); CLEANUP: //Release the row handle RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(pOriginalData); PROVIDER_FREE(pModifiedData); PROVIDER_FREE(rgRowStatus); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(14) //*----------------------------------------------------------------------- // @mfunc Parameters - 1 hard del / 1 invalid // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_14() { const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; DBROWSTATUS* rgRowStatus = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s), starting at row 1, get 5 handles rghRow[ROW_ONE] = DB_NULL_HROW; TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_TWO]),S_OK) ; rghRow[ROW_THREE] = rghRow[ROW_TWO]; //row 3 == row 2 duplicate //Hard-Delete row(s) TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_TWO]),S_OK) //hard-delete row 2; //Call Undo on the modified/invlaid row(s) TESTC_(RowsetA.pIRowsetUpdate()->Undo(NULL,NROWS,rghRow,NULL,NULL,&rgRowStatus),DB_E_ERRORSOCCURRED); TESTC(rgRowStatus!=NULL); TESTC(rgRowStatus[0]==DBROWSTATUS_E_INVALID); TESTC(rgRowStatus[1]==DBROWSTATUS_E_DELETED); TESTC(rgRowStatus[2]==DBROWSTATUS_E_DELETED); CLEANUP: //Release the row handle RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(rgRowStatus); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(15) //*----------------------------------------------------------------------- // @mfunc Parameters - 3 soft del / 2 orginal // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_15() { const int NROWS = FIVE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL}; void* pOriginalData[NROWS] = {NULL,NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERINSERT); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s), starting at row 1, get 5 handles TESTC_(RowsetA.GetRow(FIRST_ROW,NROWS,rghRow),S_OK) ; //Save the orginal row data TESTC_(RowsetA.GetRowData(NROWS, rghRow, pOriginalData),S_OK); //Delete the row(s) TESTC_(RowsetA.DeleteRow(rghRow[ROW_ONE]),S_OK) //delete row 1; if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.DeleteRow(rghRow[ROW_THREE]),S_OK) //delete row 3; if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.DeleteRow(rghRow[ROW_FIVE]),S_OK) //delete row 5; //Call Undo on the deleted/orginal row(s) TESTC_(RowsetA.UndoRow(NROWS,rghRow),S_OK); //Compare data with orginal data, should be equal, undo was called TESTC(RowsetA.CompareRowData(NROWS, rghRow, pOriginalData)); CLEANUP: //Release the row handle RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE2(NROWS, pOriginalData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(16) //*----------------------------------------------------------------------- // @mfunc Parameters - 3 new rows / 1 orginal // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_16() { TBEGIN void* pOriginalData = NULL; void* pData = NULL; const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); pData = PROVIDER_ALLOC(sizeof(void*)*RowsetA.m_cRowSize); //Obtain handle(s), starting at row 1, get 5 handles TESTC_(RowsetA.GetRow(SECOND_ROW, &rghRow[ROW_THREE]),S_OK) //get row 3; TESTC_(RowsetA.InsertRow(&rghRow[ROW_ONE]),S_OK) //insert row 1; if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_TWO]),S_OK) //insert row 2; if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //insert row 4; //Save the orginal row data TESTC_(RowsetA.GetRowData(rghRow[ROW_THREE], &pOriginalData),S_OK) //orginal; //Call Undo on the inserted/orginal row(s) TESTC_(RowsetA.UndoRow(NROWS,rghRow),RowsetA.AllowPendingRows(3) ? S_OK : DB_S_ERRORSOCCURRED); //Compare data with orginal data, should be equal, undo was called TESTC(RowsetA.CompareRowData(rghRow[ROW_THREE], pOriginalData)); //Inserted rows should no longer exists... //TESTC(!ValidRow(rghRow[ROW_ONE])); //TESTC(!ValidRow(rghRow[ROW_TWO])); //TESTC(!ValidRow(rghRow[ROW_FOUR])); CLEANUP: //Release the row handle RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(pOriginalData); PROVIDER_FREE(pData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(17) //*----------------------------------------------------------------------- // @mfunc Parameters - 4 modified / 3 orginal // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_17() { const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; void* pOriginalData[NROWS] = {NULL,NULL,NULL,NULL}; void* pModifiedData = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s), starting at row 1, get 5 handles TESTC_(RowsetA.GetRow(FIRST_ROW,NROWS,rghRow),S_OK) ; //Save the orginal row data TESTC_(RowsetA.GetRowData(NROWS, rghRow, pOriginalData),S_OK); //Modify row(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 3; //Save the modified row data TESTC_(RowsetA.GetRowData(rghRow[ROW_THREE], &pModifiedData),S_OK); //Call Undo on the deleted/orginal row(s) TESTC_(RowsetA.UndoRow(NROWS,rghRow),S_OK); //Compare data with orginal data, should be equal, undo was called TESTC(RowsetA.CompareRowData(NROWS, rghRow, pOriginalData)); //Compare data with modified data, should not be equal, undo was called TESTC(!RowsetA.CompareRowData(rghRow[ROW_THREE], pModifiedData)); CLEANUP: //Release the row handle RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE2(NROWS, pOriginalData); PROVIDER_FREE(pModifiedData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(18) //*----------------------------------------------------------------------- // @mfunc Parameters - 3 soft del / 2 orginal, update // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_18() { const int NROWS = FIVE_ROWS; void* pOriginalData[NROWS] = {NULL,NULL,NULL,NULL}; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL}; ULONG cDeletedRows = 0; DBROWSTATUS* rgRowStatus = NULL; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s), starting at row 1, get 5 handles TESTC_(RowsetA.GetRow(FIRST_ROW,NROWS,rghRow),S_OK) ; //Save the orginal row data TESTC_(RowsetA.GetRowData(NROWS, rghRow, pOriginalData),S_OK); //Delete the row(s) TESTC_(RowsetA.DeleteRow(rghRow[ROW_ONE]),S_OK) //delete row 1; cDeletedRows++; if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.DeleteRow(rghRow[ROW_THREE]),S_OK) //delete row 3; cDeletedRows++; } if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.DeleteRow(rghRow[ROW_FIVE]),S_OK) //delete row 5; cDeletedRows++; } //Update TESTC_(RowsetA.UpdateRow(NROWS,rghRow),S_OK); //Call Undo on the deleted/orginal row(s) //I could just Undo all, but since I want to pound on the array that is //holding the pending rows, try undoing every other row in the array //deleted TESTC_(RowsetA.UndoRow(NROWS,rghRow,NULL,NULL,&rgRowStatus),DB_S_ERRORSOCCURRED); TESTC(rgRowStatus != NULL); COMPC(rgRowStatus[0], DBROWSTATUS_E_DELETED); COMPC(rgRowStatus[1], DBROWSTATUS_S_OK); COMPC(rgRowStatus[2], (DBROWSTATUS)((cDeletedRows >= 2) ? DBROWSTATUS_E_DELETED : DBROWSTATUS_S_OK)); COMPC(rgRowStatus[3], DBROWSTATUS_S_OK); COMPC(rgRowStatus[4], (DBROWSTATUS)((cDeletedRows >= 3) ? DBROWSTATUS_E_DELETED : DBROWSTATUS_S_OK)); //Compare orginal rows with orginal data, should be equal, no change TESTC(RowsetA.CompareRowData(rghRow[ROW_TWO], pOriginalData[1])); TESTC(RowsetA.CompareRowData(rghRow[ROW_FOUR], pOriginalData[3])); CLEANUP: //Release the row handle RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE2(NROWS, pOriginalData); PROVIDER_FREE(rgRowStatus); TableInsert(THREE_ROWS); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(19) //*----------------------------------------------------------------------- // @mfunc Parameters - 3 new rows / 1 orginal, update // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_19() { TBEGIN const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; ULONG cRows = 0; void* pOriginalData[NROWS] = {NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1, get 5 handles TESTC_(RowsetA.GetRow(SECOND_ROW, &rghRow[ROW_ONE]),S_OK); cRows++; TESTC_(RowsetA.InsertRow(&rghRow[ROW_TWO]),S_OK); cRows++; if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.InsertRow(&rghRow[ROW_THREE]),S_OK); cRows++; } if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK); cRows++; } //Save the orginal row data TESTC_(RowsetA.GetRowData(cRows, rghRow, pOriginalData),S_OK); //Update all row(s) TESTC_(RowsetA.UpdateRow(cRows, rghRow),S_OK); //Call Undo on the inserted/orginal row(s) TESTC_(RowsetA.UndoRow(cRows, rghRow),S_OK); //Compare data with orginal data, should be equal, undo was called //Inserted rows should exists, since update was called TESTC(RowsetA.CompareRowData(cRows, rghRow, pOriginalData)); CLEANUP: //Release the row handle RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE2(NROWS, pOriginalData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(20) //*----------------------------------------------------------------------- // @mfunc Parameters - 4 modified / 3 orginal, update // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_20() { const int NROWS = FOUR_ROWS; void* pOriginalData[NROWS] = {NULL,NULL,NULL,NULL}; void* pModifiedData = NULL; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; DBCOUNTITEM cRowsUndone = 1; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s), starting at row 1, get 5 handles TESTC_(RowsetA.GetRow(FIRST_ROW,NROWS,rghRow),S_OK) ; //Save the orginal row(s) data TESTC_(RowsetA.GetRowData(NROWS, rghRow, pOriginalData),S_OK); //Modify row(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 3; //Save the modified row data TESTC_(RowsetA.GetRowData(rghRow[ROW_THREE], &pModifiedData),S_OK); //Update TESTC_(RowsetA.UpdateRow(NROWS,rghRow),S_OK); //Call Undo TESTC_(RowsetA.UndoRow(0,NULL,&cRowsUndone),S_OK); TESTC(cRowsUndone==NO_ROWS); //Compare with orginal data, should not be equal, update was called TESTC(!RowsetA.CompareRowData(rghRow[ROW_THREE], pOriginalData[2])); //Compare with modified data, should be equal, update was called TESTC(RowsetA.CompareRowData(rghRow[ROW_THREE], pModifiedData)); //Compare orginal rows, should be equal to prginal data, no change TESTC(RowsetA.CompareRowData(rghRow[ROW_ONE], pOriginalData[0])); TESTC(RowsetA.CompareRowData(rghRow[ROW_TWO], pOriginalData[1])); TESTC(RowsetA.CompareRowData(rghRow[ROW_FOUR], pOriginalData[3])); CLEANUP: //Release the row handle RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE2(NROWS,pOriginalData); PROVIDER_FREE(pModifiedData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(21) //*----------------------------------------------------------------------- // @mfunc Parameters - 3 hard del / 2 modified // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_21() { void* pOriginalData = NULL; void* pModifiedData = NULL; const int NROWS = FIVE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL}; DBROWSTATUS* rgRowStatus = NULL; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s), starting at row 1, get 5 handles TESTC_(RowsetA.GetRow(FIRST_ROW,NROWS,rghRow),S_OK); //Save the orginal row data TESTC_(RowsetA.GetRowData(rghRow[ROW_TWO], &pOriginalData),S_OK); //Hard-Delete the row(s) TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_ONE]),S_OK); TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_THREE]),S_OK); TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_FIVE]),S_OK); //Modify the row(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWO]),S_OK) //modified; //Save the modified row data TESTC_(RowsetA.GetRowData(rghRow[ROW_TWO], &pModifiedData),S_OK); //Call Undo on the modified/deleted row(s) //I could just Undo all, but since I want to pound on the array that is //holding the pending rows, try undoing every other row in the array //deleted TESTC_(RowsetA.pIRowsetUpdate()->Undo(NULL,NROWS,rghRow,NULL,NULL,&rgRowStatus),DB_S_ERRORSOCCURRED); //Verify output TESTC(rgRowStatus!=NULL); TESTC(rgRowStatus[0]==DBROWSTATUS_E_DELETED); TESTC(rgRowStatus[1]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[2]==DBROWSTATUS_E_DELETED); TESTC(rgRowStatus[3]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[4]==DBROWSTATUS_E_DELETED); //Compare data with orginal data, should be equal, undo was called TESTC(RowsetA.CompareRowData(rghRow[ROW_TWO],pOriginalData)); //Compare data with modified data, should not be equal, undo was called TESTC(!RowsetA.CompareRowData(rghRow[ROW_TWO],pModifiedData)); CLEANUP: //Release the row handle RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(pOriginalData); PROVIDER_FREE(pModifiedData); PROVIDER_FREE(rgRowStatus); TableInsert(THREE_ROWS); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(22) //*----------------------------------------------------------------------- // @mfunc Parameters - Insert/Modify/Delete a single row // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_22() { HROW hRow = DB_NULL_HROW; DBCOUNTITEM cRowsUndone = 1; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Insert row TESTC_(RowsetA.InsertRow(&hRow),S_OK); //Modify row TESTC_(RowsetA.ModifyRow(hRow),S_OK); //Delete row TESTC_(RowsetA.DeleteRow(hRow),S_OK); //Call Undo //An inserted row has been deleted. This row is now an invalid state, and is no //no longer pending (see GetPendingRows), and IRowsetUpdate::Undo with (0,NULL) //only undoes pending rows, thus there are no pending rows to undo, thus S_OK... TESTC_(RowsetA.UndoRow(0,NULL,&cRowsUndone),S_OK); TESTC(cRowsUndone==NO_ROWS); //Row should no longer exists TESTC_(RowsetA.GetOriginalData(hRow, &RowsetA.m_pData),DB_E_DELETEDROW); CLEANUP: //Release the row handle RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(23) //*----------------------------------------------------------------------- // @mfunc Parameters - Insert/Modify/Delete a single row, Update // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_23() { HROW hRow = DB_NULL_HROW; DBCOUNTITEM cRowsUndone = 1; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Insert row TESTC_(RowsetA.InsertRow(&hRow),S_OK); //Modify row TESTC_(RowsetA.ModifyRow(hRow),S_OK); //Delete row TESTC_(RowsetA.DeleteRow(hRow),S_OK); //Update TESTC_(RowsetA.UpdateAll(),S_OK); //Call Undo TESTC_(RowsetA.UndoRow(0,NULL,&cRowsUndone),S_OK); TESTC(cRowsUndone==NO_ROWS); //Row should not exists, update was called TESTC_(RowsetA.GetOriginalData(hRow, &RowsetA.m_pData),DB_E_DELETEDROW); CLEANUP: //Release the row handle RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(24) //*----------------------------------------------------------------------- // @mfunc Parameters - Duplicate entries in the array // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_24() { const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; ULONG cRowsUndone = 1; HROW* rgRowsUndone = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, TWO_ROWS, rghRow),S_OK); //Make a duplicate HROW, rghRow[ROW_THREE] = rghRow[ROW_ONE]; // HROW3 == HROW1 rghRow[ROW_FOUR] = rghRow[ROW_TWO]; // HROW4 == HROW2 //Modify row(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 1, duplicate; //Call Undo TESTC_(RowsetA.UndoRow(NROWS,rghRow),S_OK); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); PROVIDER_FREE(rgRowsUndone); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(25) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_25() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(26) //*----------------------------------------------------------------------- // @mfunc Sequence - Fetch every other row, modify every even, undo all odd. // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_26() { TBEGIN const int NROWS = SIX_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL,NULL}; HROW hNewRow = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Modify every even row TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWO]),S_OK); if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_FOUR]),S_OK); if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_SIX]),S_OK); //Now internally there should be an array of every other row //Just to pound on that array, will insert delete a couple of rows from the middle if(RowsetA.AllowPendingRows(4)) TESTC_(RowsetA.InsertRow(&hNewRow),S_OK); if(RowsetA.AllowPendingRows(5)) TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_FOUR]),S_OK); //Now Undo every even TESTC_(RowsetA.UndoRow(rghRow[ROW_TWO]),S_OK); TESTC_(RowsetA.UndoRow(rghRow[ROW_FOUR]), RowsetA.AllowPendingRows(5) ? DB_E_ERRORSOCCURRED : S_OK); TESTC_(RowsetA.UndoRow(rghRow[ROW_SIX]),S_OK); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); RowsetA.ReleaseRows(hNewRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(27) //*----------------------------------------------------------------------- // @mfunc Sequence - Call Undo 3 times // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_27() { TBEGIN const int NROWS = SIX_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL,NULL}; HROW hNewRow = NULL; DBCOUNTITEM cModifiedRows = 0; DBCOUNTITEM cRowsUndone = 0; HROW* rgRowsUndone = NULL; DBROWSTATUS* rgRowStatus = PROVIDER_ALLOC_(1,DBROWSTATUS); ULONG ulRefCount = 0; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Insert row(s) TESTC_(RowsetA.InsertRow(&hNewRow),S_OK) //insert row 7; cModifiedRows++; //Release some of the Rows, just to make sure that the changes //are not lost, and that internally the provider doesn't have a problem //trying to undo pending changes where the row refount is released... TESTC_(RowsetA.ReleaseRows(1, &hNewRow, &ulRefCount),S_OK); RowsetA.ReleaseRows(1, &hNewRow, &ulRefCount); //Modify row(s) if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; cModifiedRows++; } if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWO]),S_OK) //modify row 2; TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK) //delete row 2; cModifiedRows++; } if(RowsetA.AllowPendingRows(4)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_SIX]),S_OK) //modify row 6; TESTC_(RowsetA.ReleaseRows(rghRow[ROW_SIX]),S_OK); cModifiedRows++; } //Call Undo #1 TESTC_(RowsetA.UndoRow(0,NULL,&cRowsUndone,&rgRowsUndone),S_OK); TESTC(cRowsUndone==cModifiedRows && rgRowsUndone!=NULL); //Since 0, NULL was passed the returned array is not required to be ordered //In the same order of the changes. TESTC(FindValue(hNewRow, cRowsUndone, rgRowsUndone)); if(cModifiedRows >= 2) TESTC(FindValue(rghRow[ROW_ONE], cRowsUndone, rgRowsUndone)); if(cModifiedRows >= 3) TESTC(FindValue(rghRow[ROW_TWO], cRowsUndone, rgRowsUndone)); if(cModifiedRows >= 4) TESTC(FindValue(rghRow[ROW_SIX], cRowsUndone, rgRowsUndone)); //Call Undo #2 TESTC_(RowsetA.UndoRow(0,NULL,&cRowsUndone),S_OK); TESTC(cRowsUndone==NO_ROWS); //Delete row(s) (row was already released) TESTC_(RowsetA.pIRowsetUpdate()->DeleteRows(NULL,ONE_ROW,&hNewRow,rgRowStatus),DB_E_ERRORSOCCURRED); TESTC(rgRowStatus != NULL); TESTC(rgRowStatus[0] == (DBROWSTATUS)(ulRefCount ? DBROWSTATUS_E_DELETED : DBROWSTATUS_E_INVALID)); //Call Undo #3 TESTC_(RowsetA.UndoRow(0,NULL,&cRowsUndone),S_OK); TESTC(cRowsUndone==NO_ROWS); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); RowsetA.ReleaseRows(hNewRow); PROVIDER_FREE(rgRowStatus); PROVIDER_FREE(rgRowsUndone); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(28) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_28() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(29) //*----------------------------------------------------------------------- // @mfunc Boundary - Empty Rowset [NULL, 0 ,NULL, valid, valid] // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_29() { DBCOUNTITEM cRowsUndone = 1; CRowsetUpdate EmptyRowset; TESTC_PROVIDER(EmptyRowset.CreateRowset(SELECT_EMPTYROWSET)==S_OK); TESTC_(EmptyRowset.UndoRow(0,NULL,&cRowsUndone),S_OK); TESTC(cRowsUndone==NO_ROWS); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(30) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_30() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(31) //*----------------------------------------------------------------------- // @mfunc Accessor - BLOB / Long columns - SetPos // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_31() { TBEGIN TRETURN //TODO need to work on blob support once supported HACCESSOR hAccessor = DB_NULL_HACCESSOR; const int NROWS = TWO_ROWS; HROW rghRow[NROWS] = {NULL,NULL}; HROW hNewRow = DB_NULL_HROW; DBLENGTH cRowSize = 0; void* pInsertData = NULL; void* pModifyData = NULL; void* pData1 = NULL; void* pData2 = NULL; CRowsetUpdate RowsetA; RowsetA.SetProperty(DBPROP_IRowsetLocate); RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Create Accessor binding BLOB/Long data (last param TRUE) TESTC_(GetAccessorAndBindings(RowsetA(),DBACCESSOR_ROWDATA,&hAccessor, NULL,NULL,&cRowSize,DBPART_ALL,UPDATEABLE_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); //Alloc buffers TESTC(RowsetA.MakeRowData(&pInsertData,hAccessor)); TESTC(RowsetA.MakeRowData(&pModifyData,hAccessor)); pData1 = PROVIDER_ALLOC(sizeof(pInsertData)); pData2 = PROVIDER_ALLOC(sizeof(pInsertData)); //Get Rows TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_ONE]),S_OK); TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_TWO]),S_OK); //Get the Data TESTC_(RowsetA.pIRowset()->GetData(rghRow[ROW_ONE], hAccessor, pData1),S_OK); //Modify a row (BLOB data) TESTC_(RowsetA.pIRowsetChange()->SetData(rghRow[ROW_ONE],hAccessor, pModifyData),S_OK); //Insert a row (BLOB data) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.pIRowsetChange()->InsertRow(NULL,hAccessor, pInsertData, &hNewRow),S_OK); //Delete a row (BLOB data) if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK); //Before undo, should be equal TESTC_(RowsetA.pIRowset()->GetData(rghRow[ROW_ONE], hAccessor, pData2),S_OK); TESTC(RowsetA.CompareRowData(pData2, pModifyData, hAccessor)); //Now call Undo TESTC_(RowsetA.UndoAll(),S_OK); //After undo, should not be equal TESTC_(RowsetA.pIRowset()->GetData(rghRow[ROW_ONE], hAccessor, pData2),S_OK); TESTC(!RowsetA.CompareRowData(pData2, pModifyData, hAccessor)); CLEANUP: //Free Data RowsetA.ReleaseRowData(pInsertData,hAccessor); RowsetA.ReleaseRowData(pModifyData,hAccessor); //Release the Accesssor RowsetA.ReleaseAccessor(hAccessor); RowsetA.ReleaseRows(hNewRow); RowsetA.ReleaseRows(NROWS, rghRow); PROVIDER_FREE(pData1); PROVIDER_FREE(pData2); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(32) //*----------------------------------------------------------------------- // @mfunc Accessor - BLOB / Long columns - QBU // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_32() { TBEGIN TRETURN //TODO need to work on blob support once supported HACCESSOR hAccessor = DB_NULL_HACCESSOR; const int NROWS = TWO_ROWS; HROW rghRow[NROWS] = {NULL,NULL}; HROW hNewRow = DB_NULL_HROW; DBLENGTH cRowSize = 0; void* pInsertData = NULL; void* pModifyData = NULL; void* pData1 = NULL; void* pData2 = NULL; CRowsetUpdate RowsetA; RowsetA.SetProperty(DBPROP_IRowsetLocate); RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Create Accessor binding BLOB/Long data (last param TRUE) TESTC_(GetAccessorAndBindings(RowsetA(),DBACCESSOR_ROWDATA,&hAccessor, NULL,NULL,&cRowSize,DBPART_ALL,UPDATEABLE_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); //Alloc buffers TESTC(RowsetA.MakeRowData(&pInsertData,hAccessor)); TESTC(RowsetA.MakeRowData(&pModifyData,hAccessor)); pData1 = PROVIDER_ALLOC(sizeof(pInsertData)); pData2 = PROVIDER_ALLOC(sizeof(pInsertData)); //Get Rows TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_ONE]),S_OK); TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_TWO]),S_OK); //Get the Data TESTC_(RowsetA.pIRowset()->GetData(rghRow[ROW_ONE], hAccessor, pData1),S_OK); //Modify a row (BLOB data) TESTC_(RowsetA.pIRowsetChange()->SetData(rghRow[ROW_ONE],hAccessor, pModifyData),S_OK); //Insert a row (BLOB data) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.pIRowsetChange()->InsertRow(NULL,hAccessor, pInsertData, &hNewRow),S_OK); //Delete a row (BLOB data) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK); //Before undo, should be equal TESTC_(RowsetA.pIRowset()->GetData(rghRow[ROW_ONE], hAccessor, pData2),S_OK); TESTC(RowsetA.CompareRowData(pData2, pModifyData, hAccessor)); //Now call Undo TESTC_(RowsetA.UndoAll(),S_OK); //After undo, should not be equal TESTC_(RowsetA.pIRowset()->GetData(rghRow[ROW_ONE], hAccessor, pData2),S_OK); TESTC(!RowsetA.CompareRowData(pData2, pModifyData, hAccessor)); CLEANUP: //Free Data RowsetA.ReleaseRowData(pInsertData,hAccessor); RowsetA.ReleaseRowData(pModifyData,hAccessor); //Release the Accesssor RowsetA.ReleaseAccessor(hAccessor); RowsetA.ReleaseRows(hNewRow); RowsetA.ReleaseRows(NROWS, rghRow); PROVIDER_FREE(pData1); PROVIDER_FREE(pData2); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(33) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_33() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(34) //*----------------------------------------------------------------------- // @mfunc General - Soft-Deleted/Undo verify valid row handle // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_34() { TBEGIN const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; HROW hNewRow = NULL; DBCOUNTITEM cModifiedRows = 0; DBCOUNTITEM cRowsUndone = 1; HROW* rgRowsUndone = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Delete row(s) TESTC_(RowsetA.DeleteRow(rghRow[ROW_THREE]),S_OK); cModifiedRows++; //Insert row(s) if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.InsertRow(&hNewRow),S_OK); cModifiedRows++; } //Modify row(s) if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK); cModifiedRows++; } //Call Undo TESTC_(RowsetA.UndoRow(0,NULL,&cRowsUndone,&rgRowsUndone),S_OK); COMPC(cRowsUndone, cModifiedRows); //Since 0, NULL was passed the returned array is not required to be ordered //In the same order of the changes. TESTC(FindValue(rghRow[ROW_THREE], cRowsUndone, rgRowsUndone)); TESTC_(RowsetA.GetOriginalData(rghRow[ROW_THREE], &RowsetA.m_pData),S_OK); if(cModifiedRows >= 2) { TESTC(FindValue(hNewRow, cRowsUndone, rgRowsUndone)); TESTC_(RowsetA.GetOriginalData(hNewRow, &RowsetA.m_pData),DB_E_DELETEDROW); } if(cModifiedRows >= 3) { TESTC(FindValue(rghRow[ROW_ONE], cRowsUndone, rgRowsUndone)); TESTC_(RowsetA.GetOriginalData(rghRow[ROW_ONE], &RowsetA.m_pData),S_OK); } CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); RowsetA.ReleaseRows(hNewRow); PROVIDER_FREE(rgRowsUndone); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(35) //*----------------------------------------------------------------------- // @mfunc General - Inserted/Undo verify invalid row handle // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_35() { TBEGIN const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; HROW hNewRow = NULL; DBCOUNTITEM cModifiedRows = 0; DBCOUNTITEM cRowsUndone = 1; HROW* rgRowsUndone = NULL; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Insert row(s) TESTC_(RowsetA.InsertRow(&hNewRow),S_OK); cModifiedRows++; //Modify row(s) if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK); cModifiedRows++; } //Delete row(s) if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.DeleteRow(rghRow[ROW_THREE]),S_OK); cModifiedRows++; } //Call Undo TESTC_(RowsetA.UndoRow(0,NULL,&cRowsUndone,&rgRowsUndone),S_OK); COMPC(cRowsUndone, cModifiedRows) //Since 0, NULL was passed the returned array is not required to be ordered //In the same order of the changes. TESTC(FindValue(hNewRow, cRowsUndone, rgRowsUndone)); TESTC_(RowsetA.GetOriginalData(hNewRow, &RowsetA.m_pData),DB_E_DELETEDROW); if(cModifiedRows >= 2) { TESTC(FindValue(rghRow[ROW_ONE], cRowsUndone, rgRowsUndone)); TESTC_(RowsetA.GetOriginalData(rghRow[ROW_ONE], &RowsetA.m_pData),S_OK); } if(cModifiedRows >= 3) { TESTC(FindValue(rghRow[ROW_THREE], cRowsUndone, rgRowsUndone)); TESTC_(RowsetA.GetOriginalData(rghRow[ROW_THREE], &RowsetA.m_pData),S_OK); } CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); RowsetA.ReleaseRows(hNewRow); PROVIDER_FREE(rgRowsUndone); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(36) //*----------------------------------------------------------------------- // @mfunc General - Modified/Undo verify valid row handle, and OriginalData // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_36() { TBEGIN const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; HROW hNewRow = NULL; DBCOUNTITEM cRowsUndone = 1; HROW* rgRowsUndone = NULL; DBCOUNTITEM cModifiedRows = 0; void* pOriginalData = NULL; void* pModifiedData = NULL; void* pData = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); pData = PROVIDER_ALLOC(sizeof(void*)*RowsetA.m_cRowSize); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Save OriginalData TESTC_(RowsetA.GetRowData(rghRow[ROW_ONE],&pOriginalData),S_OK); //Modify row(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK); cModifiedRows++; //Insert row(s) if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.InsertRow(&hNewRow),S_OK); cModifiedRows++; } //Delete row(s) if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.DeleteRow(rghRow[ROW_THREE]),S_OK); cModifiedRows++; } //Save ModifiedData TESTC_(RowsetA.GetRowData(rghRow[ROW_ONE],&pModifiedData),S_OK); //Call Undo TESTC_(RowsetA.UndoRow(0,NULL,&cRowsUndone,&rgRowsUndone),S_OK); COMPC(cRowsUndone, cModifiedRows) //Since 0, NULL was passed the returned array is not required to be ordered //In the same order of the changes. TESTC(FindValue(rghRow[ROW_ONE], cRowsUndone, rgRowsUndone)); TESTC_(RowsetA.GetOriginalData(rghRow[ROW_ONE], &pData),S_OK); if(cModifiedRows >= 2) { TESTC(FindValue(hNewRow, cRowsUndone, rgRowsUndone)); TESTC_(RowsetA.GetOriginalData(hNewRow, &pData),DB_E_DELETEDROW); } if(cModifiedRows >= 3) { TESTC(FindValue(rghRow[ROW_THREE], cRowsUndone, rgRowsUndone)); TESTC_(RowsetA.GetOriginalData(rghRow[ROW_THREE], &pData),S_OK); } //Verify modified/undo data TESTC(RowsetA.CompareRowData(rghRow[ROW_ONE],pOriginalData)); TESTC(!RowsetA.CompareRowData(rghRow[ROW_ONE],pModifiedData)); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); RowsetA.ReleaseRows(hNewRow); PROVIDER_FREE(pData); PROVIDER_FREE(pOriginalData); PROVIDER_FREE(pModifiedData); PROVIDER_FREE(rgRowsUndone); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(37) //*----------------------------------------------------------------------- // @mfunc General - Verify Undo alters row handle refcount correctly // // @rdesc TEST_PASS or TEST_FAIL // int TCUndo::Variation_37() { TBEGIN const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; HROW hNewRow = NULL; DBCOUNTITEM cRowsUndone = 1; HROW* rgRowsUndone = NULL; DBROWSTATUS* rgRowStatus = NULL; DBCOUNTITEM cModifiedRows = 0; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Delete row(s) TESTC_(RowsetA.DeleteRow(rghRow[ROW_THREE]),S_OK); cModifiedRows++; //Insert row(s) if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.InsertRow(&hNewRow),S_OK); cModifiedRows++; } //Modify row(s) if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK); cModifiedRows++; } //Release all the rows TESTC_(RowsetA.ReleaseRows(NROWS, rghRow, NULL, &rgRowStatus),S_OK) //Will return DBROWSTATUS_S_PENDINGCHANGES; TESTC(rgRowStatus != NULL); TESTC(rgRowStatus[ROW_ONE] == (DBROWSTATUS)(cModifiedRows>=3 ? DBROWSTATUS_S_PENDINGCHANGES : DBROWSTATUS_S_OK)); TESTC(rgRowStatus[ROW_TWO] == DBROWSTATUS_S_OK); TESTC(rgRowStatus[ROW_THREE] == DBROWSTATUS_S_PENDINGCHANGES); if(hNewRow) { PROVIDER_FREE(rgRowStatus); TESTC_(RowsetA.ReleaseRows(ONE_ROW, &hNewRow, NULL, &rgRowStatus),S_OK) //Will return DBROWSTATUS_S_PENDINGCHANGES; TESTC(rgRowStatus != NULL); TESTC(rgRowStatus[0] == DBROWSTATUS_S_PENDINGCHANGES); } //Call Undo PROVIDER_FREE(rgRowStatus); TESTC_(RowsetA.pIRowsetUpdate()->Undo(NULL,0,NULL,&cRowsUndone,&rgRowsUndone,&rgRowStatus),S_OK); COMPC(cRowsUndone, cModifiedRows) //Since 0, NULL was passed the returned array is not required to be ordered //In the same order of the changes. TESTC(FindValue(rghRow[ROW_THREE], cRowsUndone, rgRowsUndone)); VerifyArray(cRowsUndone, rgRowStatus, DBROWSTATUS_S_OK); if(cModifiedRows >= 2) TESTC(FindValue(hNewRow, cRowsUndone, rgRowsUndone)); if(cModifiedRows >= 3) TESTC(FindValue(rghRow[ROW_ONE], cRowsUndone, rgRowsUndone)); //Release again, should be fine TESTC_(RowsetA.ReleaseRows(cRowsUndone,rgRowsUndone),S_OK); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); RowsetA.ReleaseRows(hNewRow); PROVIDER_FREE(rgRowsUndone); PROVIDER_FREE(rgRowStatus); TRETURN } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCUndo::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CRowsetUpdate::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCUpdate) //*----------------------------------------------------------------------- //| Test Case: TCUpdate - IRowsetUpdate::Update test case //| Created: 03/29/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCUpdate::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CRowsetUpdate::Init()) // }} { return TEST_PASS; } return TEST_FAIL; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc Boundary - No Changes [NULL, 0, NULL,NULL,NULL,NULL,NULL] // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_1() { CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); TESTC_(RowsetA.pIRowsetUpdate()->Update(NULL,0,NULL,NULL,NULL,NULL),S_OK); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Boundary - No Changes (NULL, 0, NULL, valid, valid, valid, valid // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_2() { CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); TESTC_(RowsetA.UpdateRow(0,NULL),S_OK); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes (NULL, N, valid, NULL, NULL, valid, valid // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_3() { DBROWSTATUS* rgRowStatus = NULL; const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,NROWS,rghRow),S_OK); //Make changes TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK) //delete row 2; if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_FOUR]),S_OK) //modify row 4; if(RowsetA.AllowPendingRows(4)) TESTC_(RowsetA.DeleteRow(rghRow[ROW_FOUR]),S_OK) //delete row 4; TESTC_(RowsetA.pIRowsetUpdate()->Update(NULL,NROWS,rghRow,NULL,NULL,&rgRowStatus),S_OK); TESTC(rgRowStatus != NULL); TESTC(VerifyArray(NROWS,rgRowStatus,DBROWSTATUS_S_OK)); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(rgRowStatus); TableInsert(TWO_ROWS); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes (invalid, N, NULL, valid, valid, valid, valid // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_4() { TBEGIN DBCOUNTITEM cUpdatedRows = 1; HROW* rgUpdatedRows = NULL; DBROWSTATUS* rgRowStatus = NULL; const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS,rghRow),S_OK); //Make changes(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; TESTC_(RowsetA.pIRowsetUpdate()->Update(INVALID(HCHAPTER),NROWS,NULL,&cUpdatedRows,&rgUpdatedRows,&rgRowStatus),E_INVALIDARG); TESTC(cUpdatedRows==0 && rgUpdatedRows==NULL && rgRowStatus==NULL); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(rgUpdatedRows); PROVIDER_FREE(rgRowStatus); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes (invalid, N, valid, valid, NULL, valid, valid // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_5() { TBEGIN HROW* rgUpdatedRows = INVALID(HROW*); DBROWSTATUS* rgRowStatus = INVALID(DBROWSTATUS*); const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS,rghRow),S_OK); //Make changes(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK) //delete row 2; if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.InsertRow(&rghRow[ROW_THREE]),S_OK) //insert row 3; TESTC_(RowsetA.DeleteRow(rghRow[ROW_THREE]),S_OK) //delete row 3; } TESTC_(RowsetA.pIRowsetUpdate()->Update(NULL,0,NULL,NULL,&rgUpdatedRows,&rgRowStatus),S_OK); //rgUpdatedRows / rgRowStatus should just be ignored since, pcUpdaedRows==NULL TESTC(rgUpdatedRows==INVALID(HROW*) && rgRowStatus==INVALID(DBROWSTATUS*)); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); TableInsert(TWO_ROWS); //Adjust the table TRETURN; } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes (NULL, 0, NULL, valid, valid, valid, NULL // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_6() { TBEGIN DBCOUNTITEM cUpdatedRows = 1; DBROWSTATUS* rgRowStatus = NULL; const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS,rghRow),S_OK); //Make changes(s) TESTC_(RowsetA.InsertRow(&rghRow[ROW_THREE]),S_OK) //insert row 3; TESTC_(RowsetA.pIRowsetUpdate()->Update(NULL,0,NULL,&cUpdatedRows,NULL,&rgRowStatus),E_INVALIDARG); TESTC(cUpdatedRows==0 && rgRowStatus==NULL); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(rgRowStatus); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes (NULL, 0, NULL, NULL, NULL, NULL, NULL // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_7() { HROW hNewRow = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Make changes(s) TESTC_(RowsetA.InsertRow(&hNewRow),S_OK) //insert row; TESTC_(RowsetA.UpdateRow(hNewRow),S_OK); CLEANUP: RowsetA.ReleaseRows(hNewRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes (NULL, 0, NULL, valid, valid,valid,valid, // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_8() { TBEGIN DBCOUNTITEM cUpdatedRows = 1; HROW* rgUpdatedRows = NULL; DBCOUNTITEM cModifiedRows = 0; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,TWO_ROWS,rghRow),S_OK); //Make changes(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; cModifiedRows++; //Release some of the rows, so we know that the provider doesn't have a //problem trying to update pending rows, that have been released... TESTC_(RowsetA.ReleaseRows(rghRow[ROW_ONE]),S_OK); RowsetA.ReleaseRows(rghRow[ROW_ONE]); if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK) //delete row 2; TESTC_(RowsetA.ReleaseRows(rghRow[ROW_TWO]),S_OK); cModifiedRows++; } if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //insert row 4; TESTC_(RowsetA.DeleteRow(rghRow[ROW_FOUR]),S_OK) //delete row 4; } //Update (0,NULL) TESTC_(RowsetA.UpdateRow(0,NULL,&cUpdatedRows,&rgUpdatedRows),S_OK); TESTC(cUpdatedRows==cModifiedRows); COMPC(rgUpdatedRows[0],rghRow[ROW_ONE]) if(cModifiedRows >= 2) COMPC(rgUpdatedRows[1],rghRow[ROW_TWO]) CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS,rghRow); PROVIDER_FREE(rgUpdatedRows); TableInsert(TWO_ROWS); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc Boundary - Empty Rowset (NULL, 0, NULL, valid, valid,valid,valid, // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_9() { DBCOUNTITEM cRowsUndone = 1; HROW* rgRowsUndone = NULL; CRowsetUpdate EmptyRowset; TESTC_PROVIDER(EmptyRowset.CreateRowset(SELECT_EMPTYROWSET)==S_OK); TESTC_(EmptyRowset.UpdateRow(0,NULL,&cRowsUndone,&rgRowsUndone),S_OK); TESTC(cRowsUndone==0 && rgRowsUndone==NULL); CLEANUP: PROVIDER_FREE(rgRowsUndone) TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(10) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_10() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(11) //*----------------------------------------------------------------------- // @mfunc Parameters - 3 hard deleted / 2 modified // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_11() { const int NROWS = FIVE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL}; DBROWSTATUS* rgRowStatus = NULL; void* pOriginalData = NULL; void* pModifiedData = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,NROWS,rghRow),S_OK) ; //Save orginal data TESTC_(RowsetA.GetRowData(rghRow[ROW_ONE],&pOriginalData),S_OK) //save row 1 old data; TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_TWO]),S_OK) //delete row 2; TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_FOUR]),S_OK)//delete row 4; TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_FIVE]),S_OK)//delete row 5; //Make changes(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 3; //Save modified data TESTC_(RowsetA.GetRowData(rghRow[ROW_ONE], &pModifiedData),S_OK) //save row 1 new data; TESTC_(RowsetA.UpdateRow(NROWS,rghRow,NULL,NULL,&rgRowStatus),DB_S_ERRORSOCCURRED); TESTC(rgRowStatus != NULL); TESTC(rgRowStatus[0]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[1]==DBROWSTATUS_E_DELETED); TESTC(rgRowStatus[2]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[3]==DBROWSTATUS_E_DELETED); TESTC(rgRowStatus[4]==DBROWSTATUS_E_DELETED); //Verify Update did update the data at the backend // TESTC(RowsetA.CompareTableData(FIRST_ROW, rghRow[ROW_ONE])); // TESTC(RowsetA.CompareTableData(THIRD_ROW, rghRow[ROW_THREE])); //Verify Update did update the data in the rowset TESTC(RowsetA.CompareRowData(rghRow[ROW_ONE],pModifiedData)); //Verify Updated data does not equal orginal data TESTC(!RowsetA.CompareRowData(rghRow[ROW_ONE],pOriginalData)); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(rgRowStatus); PROVIDER_FREE(pOriginalData); PROVIDER_FREE(pModifiedData); TableInsert(THREE_ROWS); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(12) //*----------------------------------------------------------------------- // @mfunc Parameters - 3 invalid / 2 inserted // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_12() { const int NROWS = FIVE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL}; DBROWSTATUS* rgRowStatus = NULL; void* pOriginalData = NULL; void* pModifiedData = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,NROWS,rghRow),S_OK) ; //Save orginal data TESTC_(RowsetA.GetRowData(rghRow[ROW_THREE],&pOriginalData),S_OK) //save row 3 old data; //Make changes(s) TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_FIVE]),S_OK)//delete row 5; TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 3; if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; //Save modified data TESTC_(RowsetA.GetRowData(rghRow[ROW_THREE],&pModifiedData),S_OK) //save row 3 new data; //Update TESTC_(RowsetA.UpdateRow(NROWS,rghRow,NULL,NULL,&rgRowStatus),DB_S_ERRORSOCCURRED); TESTC(rgRowStatus != NULL); TESTC(rgRowStatus[0]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[1]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[2]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[3]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[4]==DBROWSTATUS_E_DELETED); //Verify Update did update the data at the backend // TESTC(RowsetA.CompareTableData(FIRST_ROW, rghRow[ROW_ONE])); // TESTC(RowsetA.CompareTableData(THIRD_ROW, rghRow[ROW_THREE])); //Verify Update did update the data in the rowset TESTC(RowsetA.CompareRowData(rghRow[ROW_THREE],pModifiedData)); //Verify Updated data does not equal orginal data TESTC(!RowsetA.CompareRowData(rghRow[ROW_THREE],pOriginalData)); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(rgRowStatus); PROVIDER_FREE(pOriginalData); PROVIDER_FREE(pModifiedData); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(13) //*----------------------------------------------------------------------- // @mfunc Parameters - 1 hard deleted / 1 invalid / 1 soft-del // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_13() { DBROWSTATUS* rgRowStatus = NULL; const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s) TESTC_(RowsetA.GetRow(SECOND_ROW, TWO_ROWS, rghRow),S_OK); //Make changes(s) TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_ONE]),S_OK) //hard-delete row 1; TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK) //soft-delete row 2; rghRow[ROW_THREE] = DB_NULL_HROW; //invalid row 3 rghRow[ROW_FOUR] = rghRow[ROW_ONE]; //duplicate row 4 == row 1 TESTC_(RowsetA.UpdateRow(NROWS,rghRow,NULL,NULL,&rgRowStatus),DB_S_ERRORSOCCURRED); TESTC(rgRowStatus != NULL); TESTC(rgRowStatus[0]==DBROWSTATUS_E_DELETED); TESTC(rgRowStatus[1]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[2]==DBROWSTATUS_E_INVALID); TESTC(rgRowStatus[3]==DBROWSTATUS_E_DELETED); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(rgRowStatus); TableInsert(TWO_ROWS); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(14) //*----------------------------------------------------------------------- // @mfunc Parameters - 1 hard deleted / 1 invalid // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_14() { DBROWSTATUS* rgRowStatus = NULL; const int NROWS = TWO_ROWS; HROW rghRow[NROWS] = {NULL,NULL}; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s) TESTC_(RowsetA.GetRow(SECOND_ROW, &rghRow[ROW_ONE]),S_OK); rghRow[ROW_TWO] = DB_NULL_HROW; //invalid row 2 //Make changes(s) TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_ONE]),S_OK) //hard-delete row 1; TESTC_(RowsetA.UpdateRow(NROWS,rghRow,NULL,NULL,&rgRowStatus),DB_E_ERRORSOCCURRED); TESTC(rgRowStatus != NULL); TESTC(rgRowStatus[0]==DBROWSTATUS_E_DELETED); TESTC(rgRowStatus[1]==DBROWSTATUS_E_INVALID); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(rgRowStatus); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(15) //*----------------------------------------------------------------------- // @mfunc Parameters - 1 col with non-schema info // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_15() { DBROWSTATUS* rgRowStatus = NULL; const int NROWS = ONE_ROW; HROW rghRow[NROWS] = {NULL}; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s) TESTC_(RowsetA.GetRow(SECOND_ROW, &rghRow[ROW_ONE]),S_OK); //Make changes(s) TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_ONE]),S_OK) //hard-delete row 1; TESTC_(RowsetA.UpdateRow(NROWS,rghRow,NULL,NULL,&rgRowStatus),DB_E_ERRORSOCCURRED); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(rgRowStatus); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(16) //*----------------------------------------------------------------------- // @mfunc Parameters - 3 col with metacolumn non-schema info // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_16() { const int NROWS = ONE_ROW; HROW rghRow[NROWS] = {NULL}; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, &rghRow[ROW_ONE]),S_OK); //Make changes(s) TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_ONE]),S_OK) //hard-delete row 1; TESTC_(RowsetA.UpdateRow(NROWS,rghRow,NULL,NULL,NULL),DB_E_ERRORSOCCURRED); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(17) //*----------------------------------------------------------------------- // @mfunc Parameters - 2 inserted rows, no value specified / not nullable // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_17() { TBEGIN DBCOUNTITEM cUpdatedRows = 1; HROW* rgUpdatedRows = NULL; DBCOUNTITEM cInsertedRows = 0; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s) TESTC_(RowsetA.InsertRow(&rghRow[ROW_ONE]),S_OK); cInsertedRows++; if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.InsertRow(&rghRow[ROW_THREE]),S_OK); cInsertedRows++; } //These are valid inserted rows, with defaults if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.InsertRow(&rghRow[ROW_TWO]),S_OK); cInsertedRows++; } if(RowsetA.AllowPendingRows(4)) { TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK); cInsertedRows++; } TESTC_(RowsetA.UpdateRow(0,NULL,&cUpdatedRows,&rgUpdatedRows),S_OK); TESTC(cUpdatedRows==cInsertedRows); TESTC(rgUpdatedRows[0]==rghRow[ROW_ONE]); if(cInsertedRows >= 2) TESTC(rgUpdatedRows[1]==rghRow[ROW_THREE]); if(cInsertedRows >= 3) TESTC(rgUpdatedRows[2]==rghRow[ROW_TWO]); if(cInsertedRows >= 4) TESTC(rgUpdatedRows[3]==rghRow[ROW_FOUR]); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS,rghRow); PROVIDER_FREE(rgUpdatedRows); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(18) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_18() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(19) //*----------------------------------------------------------------------- // @mfunc Sequence - Update a non-updateable column // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_19() { HACCESSOR hAccessorAllCol = NULL; DBLENGTH cRowSize = 0; DBORDINAL cAllBindings = 0; DBORDINAL cUpdBindings = 0; HRESULT hr = S_OK; HROW hRow = NULL; DBROWSTATUS* rgRowStatus = NULL; void* pData = NULL; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the hAccessor bindings for all col, even non-updateable columns TESTC_(GetAccessorAndBindings(RowsetA(), DBACCESSOR_ROWDATA, &hAccessorAllCol, NULL, &cAllBindings, &cRowSize, DBPART_ALL, ALL_COLS_BOUND),S_OK); //Obtain the hAccessor bindings for all updateable columns TESTC_(GetAccessorAndBindings(RowsetA(), DBACCESSOR_ROWDATA, NULL, NULL, &cUpdBindings, NULL, DBPART_ALL, UPDATEABLE_COLS_BOUND),S_OK); //If all columns are updateable, there is nothing to test for this variation if(cUpdBindings == cAllBindings) goto CLEANUP; //Alloc buffer large enough for all columns pData = PROVIDER_ALLOC(sizeof(void*)*cRowSize); //Get row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //Get Data TESTC_(RowsetA()->GetData(hRow,hAccessorAllCol,pData),S_OK); //Release the row handle TESTC_(RowsetA.ReleaseRows(hRow),S_OK); //Insert a new row, containing non-updateable columns //Its provider specific wither can can insert any other the other columns hRow = NULL; hr = RowsetA.pIRowsetUpdate()->InsertRow(NULL,hAccessorAllCol,pData,&hRow); TEST2C_(hr, DB_S_ERRORSOCCURRED, DB_E_ERRORSOCCURRED); //Try Updating the row, containing non-updateable columns TESTC_(RowsetA.UpdateRow(ONE_ROW,&hRow,NULL,NULL,&rgRowStatus),DB_E_ERRORSOCCURRED); TESTC(rgRowStatus != NULL); if(hr==DB_S_ERRORSOCCURRED) { //If we got a success code from InsertRow, then the hRow returned should be valid //And passing a valid hRow to Update should fail since not all are updatable TESTC(hRow != NULL); TESTC(rgRowStatus[0]==DBROWSTATUS_E_INTEGRITYVIOLATION); } else { //If we got a failure code from InsertRow, then the hRow returned should be NULL //And passing a NULL hRow to Update should fail TESTC(hRow == NULL); TESTC(rgRowStatus[0]==DBROWSTATUS_E_INVALID); } CLEANUP: RowsetA.ReleaseRows(hRow); PROVIDER_FREE(rgRowStatus); PROVIDER_FREE(pData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(20) //*----------------------------------------------------------------------- // @mfunc Sequence - Delete a non-updateable column // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_20() { HACCESSOR hAccessorAllCol = NULL; DBLENGTH cRowSize = 0; DBORDINAL cAllBindings = 0; DBORDINAL cUpdBindings = 0; HRESULT hr = S_OK; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; DBROWSTATUS* rgRowStatus = NULL; void* pData = NULL; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain the hAccessor bindings for all col, even non-updateable columns TESTC_(GetAccessorAndBindings(RowsetA(), DBACCESSOR_ROWDATA, &hAccessorAllCol, NULL, &cAllBindings, &cRowSize, DBPART_ALL, ALL_COLS_BOUND),S_OK); //Obtain the hAccessor bindings for all updateable columns TESTC_(GetAccessorAndBindings(RowsetA(), DBACCESSOR_ROWDATA, NULL, NULL, &cUpdBindings, NULL, DBPART_ALL, UPDATEABLE_COLS_BOUND),S_OK); //Depending upon the DataSource all columns might be updateable //If all columns are updateable, there is nothing to test for this variation if(cUpdBindings == cAllBindings) goto CLEANUP; //Alloc buffer large enough for all columns pData = PROVIDER_ALLOC(sizeof(void*)*cRowSize); //Get row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW,THREE_ROWS,rghRow),S_OK); //Get Data TESTC_(RowsetA()->GetData(rghRow[ROW_TWO],hAccessorAllCol,pData),S_OK); //Insert a new row, containing non-updateable columns //Its provider specific wither can can insert any other the other columns hr = RowsetA.pIRowsetUpdate()->InsertRow(NULL,hAccessorAllCol,pData,&rghRow[ROW_FOUR]); TEST2C_(hr, DB_S_ERRORSOCCURRED, DB_E_ERRORSOCCURRED); //Now update backend TESTC_(RowsetA.UpdateRow(rghRow[ROW_FOUR]),DB_E_ERRORSOCCURRED); //Try deleting non-updateable row TESTC_(RowsetA.pIRowsetUpdate()->DeleteRows(NULL,ONE_ROW,&rghRow[ROW_FOUR],NULL), hr==DB_S_ERRORSOCCURRED ? S_OK : DB_E_ERRORSOCCURRED); //Now Try Updating the rows, containing non-updateable columns TESTC_(RowsetA.UpdateRow(FOUR_ROWS,rghRow,NULL,NULL,&rgRowStatus),DB_S_ERRORSOCCURRED); TESTC(rgRowStatus != NULL); TESTC(rgRowStatus[0]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[1]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[2]==DBROWSTATUS_S_OK); TESTC(rgRowStatus[3]==(DBROWSTATUS)(hr==DB_S_ERRORSOCCURRED ? DBROWSTATUS_E_DELETED : DBROWSTATUS_E_INVALID)); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS, rghRow); RowsetA.ReleaseAccessor(hAccessorAllCol); PROVIDER_FREE(pData); PROVIDER_FREE(rgRowStatus); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(21) //*----------------------------------------------------------------------- // @mfunc Sequence - Deferred only // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_21() { const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; void* pOriginalData = NULL; void* pBackEndData = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_DEFERRED); RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Make changes to the backend //TODO //Obtain handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Verify Seen with GetOriginalData TESTC_(RowsetA.GetOriginalData(rghRow[ROW_ONE], &pOriginalData),S_OK); //TESTC(RowsetA.CompareRowData(&pOriginalData, &pBackEndData)); //Make changes to the backend again //TODO //Verify Not Seen with GetOriginalData TESTC_(RowsetA.GetOriginalData(rghRow[ROW_ONE], &pOriginalData),S_OK); //TESTC(!RowsetA.CompareRowData(&pOriginalData, &pBackEndData)); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(pOriginalData); PROVIDER_FREE(pBackEndData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(22) //*----------------------------------------------------------------------- // @mfunc Sequence - Cache-Deferred only // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_22() { const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; void* pOriginalData = NULL; void* pBackEndData = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_CACHEDEFERRED); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Make changes to the backend //TODO //Obtain handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Verify Seen with GetOriginalData TESTC_(RowsetA.GetOriginalData(rghRow[ROW_ONE], &pOriginalData),S_OK); //TESTC(RowsetA.CompareRowData(&pOriginalData, &pBackEndData)); //Make changes to the backend again //TODO //Verify Not Seen with GetOriginalData TESTC_(RowsetA.GetOriginalData(rghRow[ROW_ONE], &pOriginalData),S_OK); //TESTC(!RowsetA.CompareRowData(&pOriginalData, &pBackEndData)); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(pOriginalData); PROVIDER_FREE(pBackEndData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(23) //*----------------------------------------------------------------------- // @mfunc Sequence - Cache-Deferred / Deferred / Non-deferred col // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_23() { const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; void* pOriginalData = NULL; void* pBackEndData = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_DEFERRED); RowsetA.SetSettableProperty(DBPROP_CACHEDEFERRED); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Make changes to the backend //TODO //Obtain handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Verify Seen with GetOriginalData TESTC_(RowsetA.GetOriginalData(rghRow[ROW_ONE], &pOriginalData),S_OK); //TESTC(RowsetA.CompareRowData(&pOriginalData, &pBackEndData)); //Make changes to the backend again //TODO //Verify Not Seen with GetOriginalData TESTC_(RowsetA.GetOriginalData(rghRow[ROW_ONE], &pOriginalData),S_OK); //TESTC(!RowsetA.CompareRowData(&pOriginalData, &pBackEndData)); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(pOriginalData); PROVIDER_FREE(pBackEndData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(24) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_24() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(25) //*----------------------------------------------------------------------- // @mfunc Parameters - Duplicate hrow entries in the array // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_25() { TBEGIN HROW rghRow[FIVE_ROWS] = {NULL,NULL,NULL,NULL,NULL}; ULONG cUpdatedRows = 1; HROW* rgUpdatedRows = NULL; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, TWO_ROWS, rghRow),S_OK); rghRow[ROW_THREE] = rghRow[ROW_ONE]; // Duplicate hRow, hRow1 == hRow3 rghRow[ROW_FOUR] = rghRow[ROW_TWO]; // Duplicate hRow, hRow2 == hRow4 //Now make some changes TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //delete row 1; if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //delete row 1 //Duplicate...; if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWO]),S_OK) //delete row 3; if(RowsetA.AllowPendingRows(4)) TESTC_(RowsetA.DeleteRow(rghRow[ROW_FOUR]),S_OK) //delete row 3 //Duplicate...; if(RowsetA.AllowPendingRows(5)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FIVE]),S_OK) //insert row 5; TESTC_(RowsetA.UpdateRow(FIVE_ROWS,rghRow), RowsetA.AllowPendingRows(5) ? S_OK : DB_S_ERRORSOCCURRED); CLEANUP: RowsetA.ReleaseRows(FIVE_ROWS,rghRow); PROVIDER_FREE(rgUpdatedRows); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(26) //*----------------------------------------------------------------------- // @mfunc Parameters - Fetch/Modify/Release // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_26() { TBEGIN DBCOUNTITEM cUpdatedRows = 1; HROW* rgUpdatedRows = NULL; DBCOUNTITEM cModifiedRows = 0; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, THREE_ROWS, rghRow),S_OK); //Now make some changes TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; cModifiedRows++; if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK) //delete row 2; cModifiedRows++; } if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //insert row 4; cModifiedRows++; } //Now release handles RowsetA.ReleaseRows(FOUR_ROWS, rghRow); TESTC_(RowsetA.UpdateRow(0,NULL,&cUpdatedRows,&rgUpdatedRows),S_OK); TESTC(cUpdatedRows==cModifiedRows && rgUpdatedRows!=NULL); COMPC(rgUpdatedRows[0],rghRow[ROW_ONE]) if(cModifiedRows >=2 ) COMPC(rgUpdatedRows[1],rghRow[ROW_TWO]) if(cModifiedRows >=3 ) COMPC(rgUpdatedRows[2],rghRow[ROW_FOUR]) CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS,rghRow); PROVIDER_FREE(rgUpdatedRows); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(27) //*----------------------------------------------------------------------- // @mfunc Parameters - Fetch/Modify/don't Release // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_27() { TBEGIN DBCOUNTITEM cUpdatedRows = 1; HROW* rgUpdatedRows = NULL; HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, THREE_ROWS, rghRow),S_OK); //Now make some changes TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //insert row 4; //Don't release handles TESTC_(RowsetA.UpdateRow(0,NULL,&cUpdatedRows,&rgUpdatedRows),S_OK); TESTC(cUpdatedRows==ONE_ROW); COMPC(rgUpdatedRows[0],rghRow[ROW_FOUR]) CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS,rghRow); PROVIDER_FREE(rgUpdatedRows); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(28) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_28() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(29) //*----------------------------------------------------------------------- // @mfunc Accessor - BLOB / Long columns - SetPos // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_29() { TBEGIN TRETURN //TODO need to work on blob support once supported HACCESSOR hAccessor = DB_NULL_HACCESSOR; const int NROWS = TWO_ROWS; HROW rghRow[NROWS] = {NULL,NULL}; HROW hNewRow = DB_NULL_HROW; DBLENGTH cRowSize = 0; void* pInsertData = NULL; void* pModifyData = NULL; void* pData1 = NULL; void* pData2 = NULL; CRowsetUpdate RowsetA; RowsetA.SetProperty(DBPROP_IRowsetLocate); RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Create Accessor binding BLOB/Long data (last param TRUE) TESTC_(GetAccessorAndBindings(RowsetA(),DBACCESSOR_ROWDATA,&hAccessor, NULL,NULL,&cRowSize,DBPART_ALL,UPDATEABLE_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); //Alloc buffers TESTC(RowsetA.MakeRowData(&pInsertData,hAccessor)); TESTC(RowsetA.MakeRowData(&pModifyData,hAccessor)); pData1 = PROVIDER_ALLOC(sizeof(pInsertData)); pData2 = PROVIDER_ALLOC(sizeof(pInsertData)); //Get Rows TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_ONE]),S_OK); TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_TWO]),S_OK); //Get the Data TESTC_(RowsetA.pIRowset()->GetData(rghRow[ROW_ONE], hAccessor, pData1),S_OK); //Modify a row (BLOB data) TESTC_(RowsetA.pIRowsetChange()->SetData(rghRow[ROW_ONE],hAccessor, pModifyData),S_OK); //Delete a row (BLOB data) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK); //Before update, should not be equal TESTC(!RowsetA.CompareRowData(pData1, pModifyData, hAccessor)); //Now call Update TESTC_(RowsetA.UpdateAll(),S_OK); //After update, should be equal TESTC_(RowsetA.pIRowset()->GetData(rghRow[ROW_ONE], hAccessor, pData2),S_OK); TESTC(RowsetA.CompareRowData(pData2, pModifyData, hAccessor)); CLEANUP: //Free Data RowsetA.ReleaseRowData(pInsertData,hAccessor); RowsetA.ReleaseRowData(pModifyData,hAccessor); //Release the Accesssor RowsetA.ReleaseAccessor(hAccessor); RowsetA.ReleaseRows(hNewRow); RowsetA.ReleaseRows(NROWS, rghRow); PROVIDER_FREE(pData1); PROVIDER_FREE(pData2); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(30) //*----------------------------------------------------------------------- // @mfunc Accessor - BLOB / Long columns - QBU // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_30() { TBEGIN TRETURN //TODO need to work on blob support once supported HACCESSOR hAccessor = DB_NULL_HACCESSOR; const int NROWS = TWO_ROWS; HROW rghRow[NROWS] = {NULL,NULL}; HROW hNewRow = DB_NULL_HROW; DBLENGTH cRowSize = 0; void* pInsertData = NULL; void* pModifyData = NULL; void* pData1 = NULL; void* pData2 = NULL; CRowsetUpdate RowsetA; RowsetA.SetProperty(DBPROP_IRowsetLocate); RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Create Accessor binding BLOB/Long data (last param TRUE) TESTC_(GetAccessorAndBindings(RowsetA(),DBACCESSOR_ROWDATA,&hAccessor, NULL,NULL,&cRowSize,DBPART_ALL,UPDATEABLE_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); //Alloc buffers TESTC(RowsetA.MakeRowData(&pInsertData,hAccessor)); TESTC(RowsetA.MakeRowData(&pModifyData,hAccessor)); pData1 = PROVIDER_ALLOC(sizeof(pInsertData)); pData2 = PROVIDER_ALLOC(sizeof(pInsertData)); //Get Rows TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_ONE]),S_OK); TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_TWO]),S_OK); //Get the Data TESTC_(RowsetA.pIRowset()->GetData(rghRow[ROW_ONE], hAccessor, pData1),S_OK); //Modify a row (BLOB data) TESTC_(RowsetA.pIRowsetChange()->SetData(rghRow[ROW_ONE],hAccessor, pModifyData),S_OK); //Delete a row (BLOB data) if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK); //Insert a row (BLOB data) if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.pIRowsetChange()->InsertRow(NULL,hAccessor, pInsertData, &hNewRow),S_OK); //Before update, should not be equal TESTC(!RowsetA.CompareRowData(pData1, pModifyData, hAccessor)); //Now call Update TESTC_(RowsetA.UpdateAll(),S_OK); //After update, should be equal TESTC_(RowsetA.pIRowset()->GetData(rghRow[ROW_ONE], hAccessor, pData2),S_OK); TESTC(RowsetA.CompareRowData(pData2, pModifyData, hAccessor)); CLEANUP: //Free Data RowsetA.ReleaseRowData(pInsertData,hAccessor); RowsetA.ReleaseRowData(pModifyData,hAccessor); //Release the Accesssor RowsetA.ReleaseAccessor(hAccessor); RowsetA.ReleaseRows(hNewRow); RowsetA.ReleaseRows(NROWS, rghRow); PROVIDER_FREE(pData1); PROVIDER_FREE(pData2); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(31) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_31() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(32) //*----------------------------------------------------------------------- // @mfunc Related - Resync / GetOriginalData same data // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_32() { TBEGIN HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; void* pOriginalData = NULL; void* pResynchData = NULL; IRowsetResynch* pIRowsetResynch = NULL; CRowsetUpdate RowsetA; RowsetA.SetProperty(DBPROP_IRowsetResynch);//Requires RESYNCH TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Alloc pData pResynchData = PROVIDER_ALLOC(sizeof(void*)*RowsetA.m_cRowSize); //Obtain handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, THREE_ROWS, rghRow),S_OK); //Now make some changes TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 3; if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //insert row 4; //Call GetOriginalData for row 3 TESTC_(RowsetA.GetOriginalData(rghRow[ROW_THREE], &pOriginalData),S_OK); //Obtain the Resynch Interface TESTC_(QI(RowsetA(),IID_IRowsetResynch,(void**)&pIRowsetResynch),S_OK); //Call Resynch::GetVisisableData for Row 3 TESTC_(pIRowsetResynch->GetVisibleData(rghRow[ROW_THREE],RowsetA.m_hAccessor,pResynchData),S_OK); //Verify GetOriginalData == GetVisibleData TESTC(RowsetA.CompareRowData(pOriginalData, pResynchData)); //Call Update TESTC_(RowsetA.UpdateAll(),S_OK); //Verify GetOriginalData == GetVisibleData after update if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.GetOriginalData(rghRow[ROW_TWO], &pOriginalData),S_OK); TESTC_(pIRowsetResynch->GetVisibleData(rghRow[ROW_TWO],RowsetA.m_hAccessor,pResynchData),S_OK); TESTC(RowsetA.CompareRowData(pOriginalData, pResynchData)); } CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS,rghRow); SAFE_RELEASE(pIRowsetResynch); PROVIDER_FREE(pResynchData); PROVIDER_FREE(pOriginalData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(33) //*----------------------------------------------------------------------- // @mfunc Related - ResynchRows // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_33() { TBEGIN const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; void* pOriginalData = NULL; IRowsetResynch* pIRowsetResynch = NULL; CRowsetUpdate RowsetA; RowsetA.SetProperty(DBPROP_IRowsetResynch);//Requires RESYNCH RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, THREE_ROWS, rghRow),S_OK); //Now make some changes TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 3; if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //insert row 4; //Call GetOriginalData for row 3 TESTC_(RowsetA.GetOriginalData(rghRow[ROW_THREE], &pOriginalData),S_OK); //Verify GetOriginalData != Rowset after changes TESTC(!RowsetA.CompareRowData(rghRow[ROW_THREE], pOriginalData)); //Obtain the Resynch Interface TESTC_(QI(RowsetA(),IID_IRowsetResynch,(void**)&pIRowsetResynch),S_OK); //Call Resynch::ResynchRows for all rows TESTC_(pIRowsetResynch->ResynchRows(0,NULL,NULL,NULL,NULL),DB_S_ERRORSOCCURRED); //Verify GetOriginalData == GetVisibleData TESTC(RowsetA.CompareRowData(rghRow[ROW_THREE], pOriginalData)); //Call Update TESTC_(RowsetA.UpdateAll(),S_OK); //Verify GetOriginalData == GetVisibleData after update TESTC(RowsetA.CompareRowData(rghRow[ROW_THREE], pOriginalData)); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS,rghRow); SAFE_RELEASE(pIRowsetResynch); PROVIDER_FREE(pOriginalData); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(34) //*----------------------------------------------------------------------- // @mfunc Related - Modify / Resync // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_34() { TBEGIN const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; void* pOriginalData = NULL; IRowsetResynch* pIRowsetResynch = NULL; DBCOUNTITEM cRowsResynched = 1; HROW* rgRowsResynched = NULL; DBROWSTATUS* rgRowStatus = NULL; DBCOUNTITEM cModifiedRows = 0; CRowsetUpdate RowsetA; RowsetA.SetProperty(DBPROP_IRowsetResynch); //Requires RESYNCH RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, THREE_ROWS, rghRow),S_OK); //Now make some changes TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //insert row 4; cModifiedRows++; if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 3; cModifiedRows++; } if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; cModifiedRows++; } //GetPendingRows == 3 TESTC_(RowsetA.GetPendingRows(cModifiedRows),S_OK); //Obtain the Resynch Interface TESTC_(QI(RowsetA(),IID_IRowsetResynch,(void**)&pIRowsetResynch),S_OK); //Call Resynch::ResynchRows for all rows //Should return DB_S for newly inserted rows TESTC_(pIRowsetResynch->ResynchRows(0,NULL,&cRowsResynched,&rgRowsResynched,&rgRowStatus),DB_S_ERRORSOCCURRED); //Verify Resynch output params TESTC(cRowsResynched==FOUR_ROWS) //All "Active" rows; TESTC(rgRowsResynched!=NULL && rgRowStatus!=NULL); //ResynchRows resycnhs all active rows, so any retrieved or intered row is game //Thats why even though only 3 rows have been changed, 4 are returned... TESTC(rgRowsResynched[3] == rghRow[ROW_FOUR]); TESTC(rgRowStatus[3] == DBROWSTATUS_E_PENDINGINSERT); if(cModifiedRows >= 2) { TESTC(rgRowsResynched[1] == rghRow[ROW_TWO]); TESTC(rgRowStatus[1] == DBROWSTATUS_S_OK); } if(cModifiedRows >= 3) { TESTC(rgRowsResynched[2] == rghRow[ROW_THREE]); TESTC(rgRowStatus[2] == DBROWSTATUS_S_OK); } if(cModifiedRows >= 4) { TESTC(rgRowsResynched[0] == rghRow[ROW_ONE]); TESTC(rgRowStatus[0] == DBROWSTATUS_S_OK); } //GetPendingRows, should be ONE after resync, there was a newly inserted row TESTC_(RowsetA.GetPendingRows(ONE_ROW),S_OK); //Update All, no updates TESTC_(RowsetA.UpdateAll(),S_OK); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); RowsetA.ReleaseRows(cRowsResynched,rgRowsResynched); SAFE_RELEASE(pIRowsetResynch); PROVIDER_FREE(pOriginalData); PROVIDER_FREE(rgRowsResynched); PROVIDER_FREE(rgRowStatus); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(35) //*----------------------------------------------------------------------- // @mfunc Related - Modify / Resync / Undo // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_35() { TBEGIN const int NROWS = ONE_ROW; HROW rghRow[NROWS] = {NULL}; IRowsetResynch* pIRowsetResynch = NULL; CRowsetUpdate RowsetA; RowsetA.SetProperty(DBPROP_IRowsetResynch);//Requires RESYNCH TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, ONE_ROW, rghRow),S_OK); //Now make some changes TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK) //insert row 4; //GetPendingRows == 1 TESTC_(RowsetA.GetPendingRows(ONE_ROW),S_OK); //Obtain the Resynch Interface TESTC_(QI(RowsetA(),IID_IRowsetResynch,(void**)&pIRowsetResynch),S_OK); //Call Resynch::ResynchRows for all rows //Should return DB_S for newly inserted rows TESTC_(pIRowsetResynch->ResynchRows(0,NULL,NULL,NULL,NULL),DB_S_ERRORSOCCURRED); //GetPendingRows, should be ONE after resync, there was a newly inserted row TESTC_(RowsetA.GetPendingRows(ONE_ROW),S_OK); //Undo all TESTC_(RowsetA.UndoAll(),S_OK); //GetPendingRows TESTC_(RowsetA.GetPendingRows(NO_ROWS),S_FALSE); //Update All TESTC_(RowsetA.UpdateAll(),S_OK); //GetPendingRows TESTC_(RowsetA.GetPendingRows(NO_ROWS),S_FALSE); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); SAFE_RELEASE(pIRowsetResynch); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(36) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_36() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(37) //*----------------------------------------------------------------------- // @mfunc Properties - NONE // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_37() { TBEGIN HROW hNewRowA = NULL; HROW hFirstRowA= NULL; HROW hNewRowB = NULL; HROW hFirstRowB= NULL; CRowsetUpdate RowsetA, RowsetB; //Set no OWN/OTHER properties TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); RowsetB.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetB.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //2 Rowsets, A and B //A fetches/deletes the first row //B modifies last row //A inserts a new row //B inserts a new row, Updates //A Updates //A fetches and deletes the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hFirstRowA),S_OK); TESTC_(RowsetA.DeleteRow(hFirstRowA),S_OK); TESTC_(RowsetA.ReleaseRows(hFirstRowA),S_OK); //Will Return DBROWSTATUS_S_PENDINGCHANGES; //B modifies the first row, make sure no conflict between A's row TESTC_(RowsetB.GetRow(FIRST_ROW,&hFirstRowB),S_OK); TESTC_(RowsetB.DeleteRow(hFirstRowB),S_OK); //A inserts a new row if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&hNewRowA),S_OK); //B inserts a new row, Updates if(RowsetB.AllowPendingRows(2)) TESTC_(RowsetB.InsertRow(&hNewRowB),S_OK); TESTC_(RowsetB.UndoRow(hFirstRowB),S_OK); TESTC_(RowsetB.UpdateAll(),S_OK); //A Updates, row should already been deleted TESTC_(RowsetA.UpdateAll(),S_OK); CLEANUP: RowsetA.ReleaseRows(hNewRowA); RowsetA.ReleaseRows(hFirstRowA); RowsetB.ReleaseRows(hNewRowB); RowsetB.ReleaseRows(hFirstRowB); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(38) //*----------------------------------------------------------------------- // @mfunc Properties - OWNINSERT // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_38() { TBEGIN HROW hNewRowA = NULL; HROW hFirstRowA= NULL; HROW hNewRowB = NULL; HROW hFirstRowB= NULL; CRowsetUpdate RowsetA, RowsetB; //Set OWNINSERT properties if(!MSDASQL) RowsetA.SetSettableProperty(DBPROP_OTHERINSERT); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); if(!MSDASQL) RowsetB.SetSettableProperty(DBPROP_OTHERINSERT); TESTC_PROVIDER(RowsetB.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //2 Rowsets, A and B //A fetches/deletes the first row //B modifies last row //A inserts a new row //B inserts a new row, Updates //A Updates //A fetches and deletes the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hFirstRowA),S_OK); TESTC_(RowsetA.DeleteRow(hFirstRowA),S_OK); TESTC_(RowsetA.ReleaseRows(hFirstRowA),S_OK); //Will Return DBROWSTATUS_S_PENDINGCHANGES; //B modifies the first row, make sure no conflict between A's row TESTC_(RowsetB.GetRow(FIRST_ROW,&hFirstRowB),S_OK); TESTC_(RowsetB.DeleteRow(hFirstRowB),S_OK); //A inserts a new row if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&hNewRowA),S_OK); //B inserts a new row, Updates if(RowsetB.AllowPendingRows(2)) TESTC_(RowsetB.InsertRow(&hNewRowB),S_OK); TESTC_(RowsetB.UndoRow(hFirstRowB),S_OK); TESTC_(RowsetB.UpdateAll(),S_OK); //A Updates, row should already been deleted TESTC_(RowsetA.UpdateAll(),S_OK); CLEANUP: RowsetA.ReleaseRows(hNewRowA); RowsetA.ReleaseRows(hFirstRowA); RowsetB.ReleaseRows(hNewRowB); RowsetB.ReleaseRows(hFirstRowB); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(39) //*----------------------------------------------------------------------- // @mfunc Properties - OWNINSERT & CANSCROLL // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_39() { TBEGIN HROW hNewRowA = NULL; HROW hFirstRowA= NULL; HROW hNewRowB = NULL; HROW hFirstRowB= NULL; CRowsetUpdate RowsetA, RowsetB; //Set OWNINSERTT & CANSCROLL properties if(!MSDASQL) RowsetA.SetSettableProperty(DBPROP_OTHERINSERT); RowsetA.SetSettableProperty(DBPROP_CANSCROLLBACKWARDS); RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); if(!MSDASQL) RowsetB.SetSettableProperty(DBPROP_OTHERINSERT); RowsetB.SetSettableProperty(DBPROP_CANSCROLLBACKWARDS); TESTC_PROVIDER(RowsetB.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //2 Rowsets, A and B //A fetches/deletes the first row //B modifies last row //A inserts a new row //B inserts a new row, Updates //A Updates //A fetches and deletes the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hFirstRowA),S_OK); TESTC_(RowsetA.DeleteRow(hFirstRowA),S_OK); TESTC_(RowsetA.ReleaseRows(hFirstRowA),S_OK); //Will Return DBROWSTATUS_S_PENDINGCHANGES; //B modifies the first row, make sure no conflict between A's row TESTC_(RowsetB.GetRow(FIRST_ROW,&hFirstRowB),S_OK); TESTC_(RowsetB.DeleteRow(hFirstRowB),S_OK); //A inserts a new row if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&hNewRowA),S_OK); //B inserts a new row, Updates if(RowsetB.AllowPendingRows(2)) TESTC_(RowsetB.InsertRow(&hNewRowB),S_OK); TESTC_(RowsetB.UndoRow(hFirstRowB),S_OK); TESTC_(RowsetB.UpdateAll(),S_OK); //A Updates, row should already been deleted TESTC_(RowsetA.UpdateAll(),S_OK); CLEANUP: RowsetA.ReleaseRows(hNewRowA); RowsetA.ReleaseRows(hFirstRowA); RowsetB.ReleaseRows(hNewRowB); RowsetB.ReleaseRows(hFirstRowB); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(40) //*----------------------------------------------------------------------- // @mfunc Properties - OWNUPDATEDELETE // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_40() { TBEGIN HROW hNewRowA = NULL; HROW hFirstRowA= NULL; HROW hNewRowB = NULL; HROW hFirstRowB= NULL; CRowsetUpdate RowsetA, RowsetB; //Set OWNUPDATEDELETE properties RowsetA.SetSettableProperty(DBPROP_OWNUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); RowsetB.SetSettableProperty(DBPROP_OWNUPDATEDELETE); TESTC_PROVIDER(RowsetB.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //2 Rowsets, A and B //A fetches/deletes the first row //B modifies last row //A inserts a new row //B inserts a new row, Updates //A Updates //A fetches and deletes the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hFirstRowA),S_OK); TESTC_(RowsetA.DeleteRow(hFirstRowA),S_OK); TESTC_(RowsetA.ReleaseRows(hFirstRowA),S_OK); //Will Return DBROWSTATUS_S_PENDINGCHANGES; //B modifies the first row, make sure no conflict between A's row TESTC_(RowsetB.GetRow(FIRST_ROW,&hFirstRowB),S_OK); TESTC_(RowsetB.DeleteRow(hFirstRowB),S_OK); //A inserts a new row if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&hNewRowA),S_OK); //B inserts a new row, Updates if(RowsetB.AllowPendingRows(2)) TESTC_(RowsetB.InsertRow(&hNewRowB),S_OK); TESTC_(RowsetB.UndoRow(hFirstRowB),S_OK); TESTC_(RowsetB.UpdateAll(),S_OK); //A Updates, row should already been deleted TESTC_(RowsetA.UpdateAll(),S_OK); CLEANUP: RowsetA.ReleaseRows(hNewRowA); RowsetA.ReleaseRows(hFirstRowA); RowsetB.ReleaseRows(hNewRowB); RowsetB.ReleaseRows(hFirstRowB); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(41) //*----------------------------------------------------------------------- // @mfunc Properties - OWNUPDATEDELETE & CANFETCH // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_41() { TBEGIN HROW hNewRowA = NULL; HROW hFirstRowA= NULL; HROW hNewRowB = NULL; HROW hFirstRowB= NULL; CRowsetUpdate RowsetA, RowsetB; //Set OWNUPDATEDELETE & CANFETCH properties RowsetA.SetSettableProperty(DBPROP_OWNUPDATEDELETE); RowsetA.SetSettableProperty(DBPROP_CANFETCHBACKWARDS); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); RowsetB.SetSettableProperty(DBPROP_OWNUPDATEDELETE); RowsetB.SetSettableProperty(DBPROP_CANFETCHBACKWARDS); TESTC_PROVIDER(RowsetB.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //2 Rowsets, A and B //A fetches/deletes the first row //B modifies last row //A inserts a new row //B inserts a new row, Updates //A Updates //A fetches and deletes the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hFirstRowA),S_OK); TESTC_(RowsetA.DeleteRow(hFirstRowA),S_OK); TESTC_(RowsetA.ReleaseRows(hFirstRowA),S_OK); //Will Return DBROWSTATUS_S_PENDINGCHANGES; //B modifies the first row, make sure no conflict between A's row TESTC_(RowsetB.GetRow(FIRST_ROW,&hFirstRowB),S_OK); TESTC_(RowsetB.DeleteRow(hFirstRowB),S_OK); //A inserts a new row if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&hNewRowA),S_OK); //B inserts a new row, Updates if(RowsetB.AllowPendingRows(2)) TESTC_(RowsetB.InsertRow(&hNewRowB),S_OK); TESTC_(RowsetB.UndoRow(hFirstRowB),S_OK); TESTC_(RowsetB.UpdateAll(),S_OK); //A Updates, row should already been deleted TESTC_(RowsetA.UpdateAll(),S_OK); CLEANUP: RowsetA.ReleaseRows(hNewRowA); RowsetA.ReleaseRows(hFirstRowA); RowsetB.ReleaseRows(hNewRowB); RowsetB.ReleaseRows(hFirstRowB); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(42) //*----------------------------------------------------------------------- // @mfunc Properties - OTHERINSERT // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_42() { TBEGIN HROW hNewRowA = NULL; HROW hFirstRowA= NULL; HROW hNewRowB = NULL; HROW hFirstRowB= NULL; CRowsetUpdate RowsetA, RowsetB; //Set OTHERINSERT properties if(!MSDASQL) RowsetA.SetSettableProperty(DBPROP_OTHERINSERT); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); if(!MSDASQL) RowsetB.SetSettableProperty(DBPROP_OTHERINSERT); TESTC_PROVIDER(RowsetB.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //2 Rowsets, A and B //A fetches/deletes the first row //B modifies last row //A inserts a new row //B inserts a new row, Updates //A Updates //A fetches and deletes the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hFirstRowA),S_OK); TESTC_(RowsetA.DeleteRow(hFirstRowA),S_OK); TESTC_(RowsetA.ReleaseRows(hFirstRowA),S_OK); //Will Return DBROWSTATUS_S_PENDINGCHANGES; //B modifies the first row, make sure no conflict between A's row TESTC_(RowsetB.GetRow(FIRST_ROW,&hFirstRowB),S_OK); TESTC_(RowsetB.DeleteRow(hFirstRowB),S_OK); //A inserts a new row if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&hNewRowA),S_OK); //B inserts a new row, Updates if(RowsetB.AllowPendingRows(2)) TESTC_(RowsetB.InsertRow(&hNewRowB),S_OK); TESTC_(RowsetB.UndoRow(hFirstRowB),S_OK); TESTC_(RowsetB.UpdateAll(),S_OK); //A Updates, row should already been deleted TESTC_(RowsetA.UpdateAll(),S_OK); CLEANUP: RowsetA.ReleaseRows(hNewRowA); RowsetA.ReleaseRows(hFirstRowA); RowsetB.ReleaseRows(hNewRowB); RowsetB.ReleaseRows(hFirstRowB); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(43) //*----------------------------------------------------------------------- // @mfunc Properties - OTHERINSERT & CANSCROLL // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_43() { TBEGIN HROW hNewRowA = NULL; HROW hFirstRowA= NULL; HROW hNewRowB = NULL; HROW hFirstRowB= NULL; CRowsetUpdate RowsetA, RowsetB; //Set OTHERINSERT & CANSCROLL properties if(!MSDASQL) RowsetA.SetSettableProperty(DBPROP_OTHERINSERT); RowsetA.SetSettableProperty(DBPROP_CANSCROLLBACKWARDS); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); if(!MSDASQL) RowsetB.SetSettableProperty(DBPROP_OTHERINSERT); RowsetB.SetSettableProperty(DBPROP_CANSCROLLBACKWARDS); RowsetB.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetB.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //2 Rowsets, A and B //A fetches/deletes the first row //B modifies last row //A inserts a new row //B inserts a new row, Updates //A Updates //A fetches and deletes the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hFirstRowA),S_OK); TESTC_(RowsetA.DeleteRow(hFirstRowA),S_OK); TESTC_(RowsetA.ReleaseRows(hFirstRowA),S_OK); //Will Return DBROWSTATUS_S_PENDINGCHANGES; //B modifies the first row, make sure no conflict between A's row TESTC_(RowsetB.GetRow(FIRST_ROW,&hFirstRowB),S_OK); TESTC_(RowsetB.DeleteRow(hFirstRowB),S_OK); //A inserts a new row if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&hNewRowA),S_OK); //B inserts a new row, Updates if(RowsetB.AllowPendingRows(2)) TESTC_(RowsetB.InsertRow(&hNewRowB),S_OK); TESTC_(RowsetB.UndoRow(hFirstRowB),S_OK); TESTC_(RowsetB.UpdateAll(),S_OK); //A Updates, row should already been deleted TESTC_(RowsetA.UpdateAll(),S_OK); CLEANUP: RowsetA.ReleaseRows(hNewRowA); RowsetA.ReleaseRows(hFirstRowA); RowsetB.ReleaseRows(hNewRowB); RowsetB.ReleaseRows(hFirstRowB); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(44) //*----------------------------------------------------------------------- // @mfunc Properties - OTHERUPDATEDELETE // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_44() { TBEGIN HROW hNewRowA = NULL; HROW hFirstRowA= NULL; HROW hNewRowB = NULL; HROW hFirstRowB= NULL; CRowsetUpdate RowsetA, RowsetB; //Set OTHERUPDATEDELETE properties RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); RowsetB.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetB.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //2 Rowsets, A and B //A fetches/deletes the first row //B modifies last row //A inserts a new row //B inserts a new row, Updates //A Updates //A fetches and deletes the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hFirstRowA),S_OK); TESTC_(RowsetA.DeleteRow(hFirstRowA),S_OK); TESTC_(RowsetA.ReleaseRows(hFirstRowA),S_OK); //Will Return DBROWSTATUS_S_PENDINGCHANGES; //B modifies the first row, make sure no conflict between A's row TESTC_(RowsetB.GetRow(FIRST_ROW,&hFirstRowB),S_OK); TESTC_(RowsetB.DeleteRow(hFirstRowB),S_OK); //A inserts a new row if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&hNewRowA),S_OK); //B inserts a new row, Updates if(RowsetB.AllowPendingRows(2)) TESTC_(RowsetB.InsertRow(&hNewRowB),S_OK); TESTC_(RowsetB.UndoRow(hFirstRowB),S_OK); TESTC_(RowsetB.UpdateAll(),S_OK); //A Updates, row should already been deleted TESTC_(RowsetA.UpdateAll(),S_OK); CLEANUP: RowsetA.ReleaseRows(hNewRowA); RowsetA.ReleaseRows(hFirstRowA); RowsetB.ReleaseRows(hNewRowB); RowsetB.ReleaseRows(hFirstRowB); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(45) //*----------------------------------------------------------------------- // @mfunc Properties - OTHERUPDATEDELETE & CANSCROLL // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_45() { TBEGIN HROW hNewRowA = NULL; HROW hFirstRowA= NULL; HROW hNewRowB = NULL; HROW hFirstRowB= NULL; CRowsetUpdate RowsetA, RowsetB; //Set OTHERUPDATEDELETE & CANSCROLL properties RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); RowsetA.SetSettableProperty(DBPROP_CANSCROLLBACKWARDS); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); RowsetB.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); RowsetB.SetSettableProperty(DBPROP_CANSCROLLBACKWARDS); RowsetB.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetB.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //2 Rowsets, A and B //A fetches/deletes the first row //B modifies last row //A inserts a new row //B inserts a new row, Updates //A Updates //A fetches and deletes the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hFirstRowA),S_OK); TESTC_(RowsetA.DeleteRow(hFirstRowA),S_OK); TESTC_(RowsetA.ReleaseRows(hFirstRowA),S_OK); //Will Return DBROWSTATUS_S_PENDINGCHANGES; //B modifies the first row, make sure no conflict between A's row TESTC_(RowsetB.GetRow(FIRST_ROW,&hFirstRowB),S_OK); TESTC_(RowsetB.DeleteRow(hFirstRowB),S_OK); //A inserts a new row if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&hNewRowA),S_OK); //B inserts a new row, Updates if(RowsetB.AllowPendingRows(2)) TESTC_(RowsetB.InsertRow(&hNewRowB),S_OK); TESTC_(RowsetB.UndoRow(hFirstRowB),S_OK); TESTC_(RowsetB.UpdateAll(),S_OK); //A Updates, row should already been deleted TESTC_(RowsetA.UpdateAll(),S_OK); CLEANUP: RowsetA.ReleaseRows(hNewRowA); RowsetA.ReleaseRows(hFirstRowA); RowsetB.ReleaseRows(hNewRowB); RowsetB.ReleaseRows(hFirstRowB); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(46) //*----------------------------------------------------------------------- // @mfunc Properties - OWNUPDATEDELETE & OTHERINSERT // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_46() { TBEGIN HROW hNewRowA = NULL; HROW hFirstRowA= NULL; HROW hNewRowB = NULL; HROW hFirstRowB= NULL; CRowsetUpdate RowsetA, RowsetB; //Set OTHERUPDATEDELETE & OTHRINSERT properties RowsetA.SetSettableProperty(DBPROP_OWNUPDATEDELETE); if(!MSDASQL) RowsetA.SetSettableProperty(DBPROP_OTHERINSERT); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); RowsetB.SetSettableProperty(DBPROP_OWNUPDATEDELETE); if(!MSDASQL) RowsetB.SetSettableProperty(DBPROP_OTHERINSERT); TESTC_PROVIDER(RowsetB.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //2 Rowsets, A and B //A fetches/deletes the first row //B modifies last row //A inserts a new row //B inserts a new row, Updates //A Updates //A fetches and deletes the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hFirstRowA),S_OK); TESTC_(RowsetA.DeleteRow(hFirstRowA),S_OK); TESTC_(RowsetA.ReleaseRows(hFirstRowA),S_OK); //Will Return DBROWSTATUS_S_PENDINGCHANGES; //B modifies the first row, make sure no conflict between A's row TESTC_(RowsetB.GetRow(FIRST_ROW,&hFirstRowB),S_OK); TESTC_(RowsetB.DeleteRow(hFirstRowB),S_OK); //A inserts a new row if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&hNewRowA),S_OK); //B inserts a new row, Updates if(RowsetB.AllowPendingRows(2)) TESTC_(RowsetB.InsertRow(&hNewRowB),S_OK); TESTC_(RowsetB.UndoRow(hFirstRowB),S_OK); TESTC_(RowsetB.UpdateAll(),S_OK); //A Updates, row should already been deleted TESTC_(RowsetA.UpdateAll(),S_OK); CLEANUP: RowsetA.ReleaseRows(hNewRowA); RowsetA.ReleaseRows(hFirstRowA); RowsetB.ReleaseRows(hNewRowB); RowsetB.ReleaseRows(hFirstRowB); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(47) //*----------------------------------------------------------------------- // @mfunc Properties - OWNUPDATEDELETE & OTHERINSERT & CANFETCH // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_47() { TBEGIN HROW hNewRowA = NULL; HROW hFirstRowA= NULL; HROW hNewRowB = NULL; HROW hFirstRowB= NULL; CRowsetUpdate RowsetA, RowsetB; //Set OWNUPDATEDELETE & OTHRINSERT & CANFETCH properties RowsetA.SetSettableProperty(DBPROP_OWNUPDATEDELETE); if(!MSDASQL) RowsetA.SetSettableProperty(DBPROP_OTHERINSERT); RowsetA.SetSettableProperty(DBPROP_CANFETCHBACKWARDS); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); RowsetB.SetSettableProperty(DBPROP_OWNUPDATEDELETE); if(!MSDASQL) RowsetB.SetSettableProperty(DBPROP_OTHERINSERT); RowsetB.SetSettableProperty(DBPROP_CANFETCHBACKWARDS); TESTC_PROVIDER(RowsetB.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //2 Rowsets, A and B //A fetches/deletes the first row //B modifies last row //A inserts a new row //B inserts a new row, Updates //A Updates //A fetches and deletes the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hFirstRowA),S_OK); TESTC_(RowsetA.DeleteRow(hFirstRowA),S_OK); TESTC_(RowsetA.ReleaseRows(hFirstRowA),S_OK); //Will Return DBROWSTATUS_S_PENDINGCHANGES; //B modifies the first row, make sure no conflict between A's row TESTC_(RowsetB.GetRow(FIRST_ROW,&hFirstRowB),S_OK); TESTC_(RowsetB.DeleteRow(hFirstRowB),S_OK); //A inserts a new row if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&hNewRowA),S_OK); //B inserts a new row, Updates if(RowsetB.AllowPendingRows(2)) TESTC_(RowsetB.InsertRow(&hNewRowB),S_OK); TESTC_(RowsetB.UndoRow(hFirstRowB),S_OK); TESTC_(RowsetB.UpdateAll(),S_OK); //A Updates, row should already been deleted TESTC_(RowsetA.UpdateAll(),S_OK); CLEANUP: RowsetA.ReleaseRows(hNewRowA); RowsetA.ReleaseRows(hFirstRowA); RowsetB.ReleaseRows(hNewRowB); RowsetB.ReleaseRows(hFirstRowB); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(48) //*----------------------------------------------------------------------- // @mfunc Properties - OTHERUPDATEDELETE & OWNINSERT // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_48() { TBEGIN HROW hNewRowA = NULL; HROW hFirstRowA= NULL; HROW hNewRowB = NULL; HROW hFirstRowB= NULL; CRowsetUpdate RowsetA, RowsetB; //Set OTHERUPDATEDELETE & OWNINSERT properties RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); if(!MSDASQL) RowsetA.SetSettableProperty(DBPROP_OTHERINSERT); RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); RowsetB.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); if(!MSDASQL) RowsetB.SetSettableProperty(DBPROP_OTHERINSERT); TESTC_PROVIDER(RowsetB.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //2 Rowsets, A and B //A fetches/deletes the first row //B modifies last row //A inserts a new row //B inserts a new row, Updates //A Updates //A fetches and deletes the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hFirstRowA),S_OK); TESTC_(RowsetA.DeleteRow(hFirstRowA),S_OK); TESTC_(RowsetA.ReleaseRows(hFirstRowA),S_OK); //Will Return DBROWSTATUS_S_PENDINGCHANGES; //B modifies the first row, make sure no conflict between A's row TESTC_(RowsetB.GetRow(FIRST_ROW,&hFirstRowB),S_OK); TESTC_(RowsetB.DeleteRow(hFirstRowB),S_OK); //A inserts a new row if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&hNewRowA),S_OK); //B inserts a new row, Updates if(RowsetB.AllowPendingRows(2)) TESTC_(RowsetB.InsertRow(&hNewRowB),S_OK); TESTC_(RowsetB.UndoRow(hFirstRowB),S_OK); TESTC_(RowsetB.UpdateAll(),S_OK); //A Updates, row should already been deleted TESTC_(RowsetA.UpdateAll(),S_OK); CLEANUP: RowsetA.ReleaseRows(hNewRowA); RowsetA.ReleaseRows(hFirstRowA); RowsetB.ReleaseRows(hNewRowB); RowsetB.ReleaseRows(hFirstRowB); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(49) //*----------------------------------------------------------------------- // @mfunc Properties - OTHERUPDATEDELETE & OWNINSERT & CANSCROLL // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_49() { TBEGIN HROW hNewRowA = NULL; HROW hFirstRowA= NULL; HROW hNewRowB = NULL; HROW hFirstRowB= NULL; CRowsetUpdate RowsetA, RowsetB; //Set OTHERUPDATEDELETE & OWNINSERT & CANSCROLL properties RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); if(!MSDASQL) RowsetA.SetSettableProperty(DBPROP_OTHERINSERT); RowsetA.SetSettableProperty(DBPROP_CANSCROLLBACKWARDS); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); RowsetB.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); if(!MSDASQL) RowsetB.SetSettableProperty(DBPROP_OTHERINSERT); RowsetB.SetSettableProperty(DBPROP_CANSCROLLBACKWARDS); RowsetB.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetB.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //2 Rowsets, A and B //A fetches/deletes the first row //B modifies last row //A inserts a new row //B inserts a new row, Updates //A Updates //A fetches and deletes the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hFirstRowA),S_OK); TESTC_(RowsetA.DeleteRow(hFirstRowA),S_OK); TESTC_(RowsetA.ReleaseRows(hFirstRowA),S_OK); //Will Return DBROWSTATUS_S_PENDINGCHANGES; //B modifies the first row, make sure no conflict between A's row TESTC_(RowsetB.GetRow(FIRST_ROW,&hFirstRowB),S_OK); TESTC_(RowsetB.DeleteRow(hFirstRowB),S_OK); //A inserts a new row if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.InsertRow(&hNewRowA),S_OK); //B inserts a new row, Updates if(RowsetB.AllowPendingRows(2)) TESTC_(RowsetB.InsertRow(&hNewRowB),S_OK); TESTC_(RowsetB.UndoRow(hFirstRowB),S_OK); TESTC_(RowsetB.UpdateAll(),S_OK); //A Updates, row should already been deleted TESTC_(RowsetA.UpdateAll(),S_OK); CLEANUP: RowsetA.ReleaseRows(hNewRowA); RowsetA.ReleaseRows(hFirstRowA); RowsetB.ReleaseRows(hNewRowB); RowsetB.ReleaseRows(hFirstRowB); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(50) //*----------------------------------------------------------------------- // @mfunc Properties - verify property dependencies // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_50() { TBEGIN CRowset RowsetA; //Set Properties RowsetA.SetProperty(DBPROP_IRowsetUpdate); RowsetA.SetProperty(DBPROP_OTHERUPDATEDELETE); RowsetA.SetProperty(DBPROP_OWNUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Just as a sanity check, make sure IID_IRowseUpdate is still set TESTC(RowsetA.GetProperty(DBPROP_IRowsetUpdate)); //Verify IID_IRowsetChange is implicitly set TESTC_PROVIDER(RowsetA.GetProperty(DBPROP_IRowsetChange)); //Just as a sanity check, make sure still set TESTC(RowsetA.GetProperty(DBPROP_OTHERUPDATEDELETE)); //Just as a sanity check, make sure still set TESTC(RowsetA.GetProperty(DBPROP_OWNUPDATEDELETE)); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(51) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_51() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(52) //*----------------------------------------------------------------------- // @mfunc Related - Qualified Table Name // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_52() { CRowsetUpdate RowsetA; HROW hRow = DB_NULL_HROW; //Use the Qualified table name, TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the row handle TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //Make change(s) TESTC_(RowsetA.DeleteRow(hRow),S_OK); //Update the row TESTC_(RowsetA.UpdateRow(hRow),S_OK); CLEANUP: RowsetA.ReleaseRows(hRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(53) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_53() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(54) //*----------------------------------------------------------------------- // @mfunc Properties - MAXPENDINGCHANGEROWS // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_54() { TBEGIN const ULONG NROWS = 7; HROW rghRow[NROWS]; HROW rghNewRow[NROWS]; ULONG_PTR ulMaxPendingRows = 0; ULONG_PTR i, ulMaxOpenRows = 0; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); RowsetA.GetProperty(DBPROP_MAXPENDINGROWS, DBPROPSET_ROWSET, &ulMaxPendingRows); RowsetA.GetProperty(DBPROP_MAXOPENROWS, DBPROPSET_ROWSET, &ulMaxOpenRows); TESTC_PROVIDER(RowsetA.AllowPendingRows(NROWS)); //Besides just stress testing the number of pendingrows and open rows, //I'm also going to stress test the internal imp of the update array. //Their keeping an internal array of the modified rows, and upon deleting //some they will compact the array. So this should be stress tested here... //Grab all the rows of the table, starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Modify every even row for(i=0; iGetNextRows(NULL, SECOND_ROW, ONE_ROW, &cRowsObtained, &rgRowsObtained), S_OK, DB_S_ROWLIMITEXCEEDED, DB_E_ROWSNOTRELEASED); if(hr == S_OK) { //Able to hold row when CANHOLDROWS = FALSE TESTC(cRowsObtained==1 && rgRowsObtained!=NULL && rgRowsObtained[0]!=NULL); } else if(hr == DB_S_ROWLIMITEXCEEDED) { //Unable to have more than 1 row open TESTC(cRowsObtained==0 && rgRowsObtained==NULL); TESTC(RowsetA.m_ulMaxOpenRows == 1); } else { //Unable to hold rows when CANHOLDROWS = FALSE TESTC(cRowsObtained==0 && rgRowsObtained==NULL); } CLEANUP: RowsetA.ReleaseRows(hFirstRow); RowsetA.ReleaseRows(hLastRow); RowsetA.ReleaseRows(cRowsObtained, rgRowsObtained); PROVIDER_FREE(rgRowsObtained); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(57) //*----------------------------------------------------------------------- // @mfunc Properties - BOOKMARKS // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_57() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(58) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_58() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(59) //*----------------------------------------------------------------------- // @mfunc Transactions - Insert/Commit // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_59() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(60) //*----------------------------------------------------------------------- // @mfunc Transactions - Insert/Commit/Update // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_60() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(61) //*----------------------------------------------------------------------- // @mfunc Transactions - Modify/Update/Commit // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_61() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(62) //*----------------------------------------------------------------------- // @mfunc Transactions - Modify/Update/Commit/Undo // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_62() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(63) //*----------------------------------------------------------------------- // @mfunc Transactions - Delete/Update/Abort // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_63() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(64) //*----------------------------------------------------------------------- // @mfunc Transactions - Delete/Update/Abort/Undo // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_64() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(65) //*----------------------------------------------------------------------- // @mfunc Transactions - concurrency - DB_E_CONCURRENCYVILOATION // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_65() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(66) //*----------------------------------------------------------------------- // @mfunc Transactions - ABORTRETAINING // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_66() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(67) //*----------------------------------------------------------------------- // @mfunc Transactions - ~ABORTRETAINING // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_67() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(68) //*----------------------------------------------------------------------- // @mfunc Transactions - COMMITRETAINING // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_68() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(69) //*----------------------------------------------------------------------- // @mfunc Transactions - ~COMMITRETAINING // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_69() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(70) //*----------------------------------------------------------------------- // @mfunc Transactions - NOTENTRANT // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_70() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(71) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_71() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(72) //*----------------------------------------------------------------------- // @mfunc Sequence - Insert/Modify/Delete a single row // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_72() { HROW hRow = DB_NULL_HROW; DBCOUNTITEM cPendingRows = 1; HROW* rgPendingRows; DBROWSTATUS* rgPendingStatus = NULL; DBROWSTATUS* rgRowStatus = NULL; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Make changes(s) TESTC_(RowsetA.InsertRow(&hRow),S_OK) //insert row X; TESTC_(RowsetA.ModifyRow(hRow),S_OK) //modify row X; TESTC_(RowsetA.DeleteRow(hRow),S_OK) //delete row X; //inv: Should be no changes that need updating. TESTC_(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,&rgPendingRows,&rgPendingStatus),S_FALSE); COMPC(cPendingRows,NO_ROWS) TESTC(rgPendingRows==NULL && rgPendingStatus==NULL); //inv: Should not be any updates to the backend TESTC_(RowsetA.UpdateRow(ONE_ROW, &hRow, NULL, NULL, &rgRowStatus),DB_E_ERRORSOCCURRED); TESTC(rgRowStatus != NULL); TESTC(rgRowStatus[0] == DBROWSTATUS_E_DELETED); CLEANUP: RowsetA.ReleaseRows(hRow); PROVIDER_FREE(rgPendingStatus); PROVIDER_FREE(rgRowStatus); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(73) //*----------------------------------------------------------------------- // @mfunc Sequence - Delete all rows/Undo 1/Modify 1/Update // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_73() { const ULONG NROWS = 7; HROW rghRow[NROWS]; DBCOUNTITEM cModifiedRows = 0; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Grab all the rows in the table, starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); cModifiedRows = RowsetA.GetMaxPendingRows(); if(cModifiedRows==0 || cModifiedRows>NROWS) cModifiedRows = NROWS; //Delete all the rows in the table TESTC_(RowsetA.DeleteRow(cModifiedRows,rghRow),S_OK); //GetPendingRows, all rows should have pending changes TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_DELETED,cModifiedRows),S_OK); //Now undo last row TESTC_(RowsetA.UndoRow(rghRow[cModifiedRows-1]),S_OK); TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_DELETED,cModifiedRows-1), (cModifiedRows-1) ? S_OK : S_FALSE); //Now Delete that row TESTC_(RowsetA.DeleteRow(rghRow[cModifiedRows-1]),S_OK); TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_DELETED,cModifiedRows), S_OK); //Call update TESTC_(RowsetA.UpdateRow(cModifiedRows,rghRow),S_OK); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); TableInsert(NROWS); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(74) //*----------------------------------------------------------------------- // @mfunc Sequence - 1 Row rowset/Delete row/Undo/Delete/Update/Undo/Update // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_74() { HROW hRow = DB_NULL_HROW; CRowsetUpdate RowsetA; //Create a rowset from a 1 row table TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_ALLFROMTBL, IID_IRowset, g_p1RowTable)==S_OK); //Grab the only row in the table, row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //Delete the row in the table TESTC_(RowsetA.DeleteRow(hRow),S_OK); //GetPendingRows, all rows should have pending changes TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_DELETED,ONE_ROW),S_OK); //Now undo last row TESTC_(RowsetA.UndoRow(hRow),S_OK); TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_DELETED,NO_ROWS),S_FALSE); //Now Delete that row TESTC_(RowsetA.DeleteRow(hRow),S_OK); TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_DELETED,ONE_ROW),S_OK); //Call update TESTC_(RowsetA.UpdateRow(hRow),S_OK); CLEANUP: RowsetA.ReleaseRows(hRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(75) //*----------------------------------------------------------------------- // @mfunc Sequence - Insert 3 rows/Undo all/Insert 4/Modify // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_75() { TBEGIN const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; DBROWSTATUS* rgRowStatus = NULL; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); TESTC_PROVIDER(RowsetA.AllowPendingRows(NROWS)); //Insert 3 rows into the table TESTC_(RowsetA.InsertRow(THREE_ROWS, rghRow),S_OK); //Undo all of them TESTC_(RowsetA.UndoRow(THREE_ROWS, rghRow),S_OK); //Insert 4 rows into the table TESTC_(RowsetA.InsertRow(FOUR_ROWS, rghRow),S_OK); //Modify those rows TESTC_(RowsetA.ModifyRow(FOUR_ROWS, rghRow),S_OK); //Update 2 of them TESTC_(RowsetA.UpdateRow(rghRow[ROW_ONE]),S_OK); TESTC_(RowsetA.UpdateRow(rghRow[ROW_TWO]),S_OK); //InsertRow->SetData - is still considered a NEW Row according to the spec TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_NEW,TWO_ROWS),S_OK); TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_CHANGED, NO_ROWS),S_FALSE); TESTC_(RowsetA.GetPendingRows(DBPENDINGSTATUS_DELETED, NO_ROWS),S_FALSE); //Undo the other two TESTC_(RowsetA.UndoRow(rghRow[ROW_THREE]),S_OK); TESTC_(RowsetA.UndoRow(rghRow[ROW_FOUR]),S_OK); TESTC_(RowsetA.GetPendingRows(NO_ROWS),S_FALSE); //Update All, shouldn't be any updates, row 3, row 4 are invalid TESTC_(RowsetA.UpdateRow(FOUR_ROWS,rghRow,NULL,NULL,&rgRowStatus),DB_S_ERRORSOCCURRED); TESTC(rgRowStatus != NULL); TESTC(rgRowStatus[0] == DBROWSTATUS_S_OK); TESTC(rgRowStatus[1] == DBROWSTATUS_S_OK); TESTC(rgRowStatus[2] == DBROWSTATUS_E_DELETED); TESTC(rgRowStatus[3] == DBROWSTATUS_E_DELETED); TESTC_(RowsetA.GetPendingRows(NO_ROWS),S_FALSE); CLEANUP: PROVIDER_FREE(rgRowStatus); RowsetA.ReleaseRows(FOUR_ROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(76) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_76() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(77) //*----------------------------------------------------------------------- // @mfunc Sequence - Call Update 3 times // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_77() { TBEGIN const int NROWS = SIX_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL,NULL}; DBCOUNTITEM cModifiedRows = 0; DBCOUNTITEM cUpdatedRows = 0; HROW* rgUpdatedRows = NULL; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //NOTE: //With this variation (mutliple Updates) it is important that //we don't modify the same row twice in different updates //Since I have bound the index column, modifiying the data will cause //the row to be repositioned, (SQLServer) will be unable to reposition on //that row... //Obtain row handle(s) TESTC_(RowsetA.GetRow(SECOND_ROW, &rghRow[ROW_ONE]),S_OK); TESTC_(RowsetA.GetNextRows(&rghRow[ROW_TWO]),S_OK); TESTC_(RowsetA.GetNextRows(&rghRow[ROW_THREE]),S_OK); TESTC_(RowsetA.GetNextRows(&rghRow[ROW_FOUR]),S_OK); TESTC_(RowsetA.InsertRow(&rghRow[ROW_FIVE]),S_OK); cModifiedRows++; //Make change(s) if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWO]),S_OK); cModifiedRows++; } if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.DeleteRow(rghRow[ROW_FOUR]),S_OK); cModifiedRows++; } //Update #1 TESTC_(RowsetA.UpdateRow(0,NULL,&cUpdatedRows,&rgUpdatedRows),S_OK); TESTC(cUpdatedRows==cModifiedRows); //Since 0,NULL was passed in, you can't assume the rows returned // Are in the same order as modifed... TESTC(FindValue(rghRow[ROW_FIVE], cUpdatedRows, rgUpdatedRows)); if(cModifiedRows >=2) TESTC(FindValue(rghRow[ROW_TWO], cUpdatedRows, rgUpdatedRows)); if(cModifiedRows >=3) TESTC(FindValue(rghRow[ROW_FOUR], cUpdatedRows, rgUpdatedRows)); PROVIDER_FREE(rgUpdatedRows); //Update #2 TESTC_(RowsetA.UpdateRow(0,NULL,&cUpdatedRows,&rgUpdatedRows),S_OK); TESTC(cUpdatedRows==NO_ROWS); //Make a few of changes, to the previously updated rows TESTC_(RowsetA.InsertRow(&rghRow[ROW_SIX]),S_OK); cModifiedRows = 1; if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK); TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK); cModifiedRows++; } if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.DeleteRow(rghRow[ROW_THREE]),S_OK); cModifiedRows++; } //Update #3 TESTC_(RowsetA.UpdateRow(0,NULL,&cUpdatedRows,&rgUpdatedRows),S_OK); TESTC(cUpdatedRows==cModifiedRows); //Since 0,NULL was passed in, you can't assume the rows returned //Are in the same order as modifed... TESTC(FindValue(rghRow[ROW_SIX], cUpdatedRows, rgUpdatedRows)); if(RowsetA.AllowPendingRows(2)) TESTC(FindValue(rghRow[ROW_ONE], cUpdatedRows, rgUpdatedRows)); if(RowsetA.AllowPendingRows(3)) TESTC(FindValue(rghRow[ROW_THREE], cUpdatedRows, rgUpdatedRows)); CLEANUP: RowsetA.ReleaseRows(SIX_ROWS, rghRow); PROVIDER_FREE(rgUpdatedRows); TableInsert(TWO_ROWS); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(78) //*----------------------------------------------------------------------- // @mfunc Sequence - Call Update on seperate columns // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_78() { TBEGIN TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(79) //*----------------------------------------------------------------------- // @mfunc Sequence - Update multilple rows, covering all types // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_79() { TBEGIN const int NROWS = FOURTEEN_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; DBCOUNTITEM cUpdatedRows = 1; HROW* rgUpdatedRows = NULL; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); TESTC_PROVIDER(RowsetA.AllowPendingRows(NROWS)); //Row types // 1. DELETEDROW (hard-deleted) g e // 2. SOFT-DELETED g u // 3. MODIFIED g u // 4. MODIFIED/DELETED g u // 5. MODIFIED/MODIFIED g u // 6. UNDONE ROW g // 7. BADROWHANDLE (invalid) e // 8. INSERTED i u // 9. INSERTED/MODIFIED i u //10. INSERTED/MODIFIED/DELETED i u //11. INSERTED/DELETED i u //12. INSERTED/MODFIFIED/MODIFIED i u //13. INSERTED/MODFIFIED/MODIFIED/DELETED i u //14. UNCHANGED g //g - indicates which rows require fetching/getting //i - indicates which rows require inserting //e - indicates which rows will produce an error //u - indicates which rows should be reported as updated //Obtain handle(s) of fetched rows TESTC_(RowsetA.GetRow(FIRST_ROW, SIX_ROWS, rghRow),S_OK) //rows 1-6; //Now obtain other handles rghRow[ROW_SEVEN] = DB_NULL_HROW; //row 7 //Now obtain the inserted row handles TESTC_(RowsetA.InsertRow(&rghRow[ROW_EIGHT]),S_OK) //row 8; TESTC_(RowsetA.InsertRow(&rghRow[ROW_NINE]),S_OK) //row 9; TESTC_(RowsetA.InsertRow(&rghRow[ROW_TEN]),S_OK) //row 10; TESTC_(RowsetA.InsertRow(&rghRow[ROW_ELEVEN]),S_OK) //row 11; TESTC_(RowsetA.InsertRow(&rghRow[ROW_TWELVE]),S_OK) //row 12; TESTC_(RowsetA.InsertRow(&rghRow[ROW_THIRTEEN]),S_OK) //row 13; //Now modify to get the above descriptions TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_ONE]),S_OK) //hard-delete row 1; TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK) //soft-delete row 2; TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 3; TESTC_(RowsetA.ModifyRow(rghRow[ROW_FOUR]),S_OK) //modify row 4; TESTC_(RowsetA.DeleteRow(rghRow[ROW_FOUR]),S_OK) //delete row 4; TESTC_(RowsetA.ModifyRow(rghRow[ROW_FIVE]),S_OK) //modify row 5; TESTC_(RowsetA.DeleteRow(rghRow[ROW_FIVE]),S_OK) //modify row 5; TESTC_(RowsetA.ModifyRow(rghRow[ROW_SIX]),S_OK) //modify row 6; TESTC_(RowsetA.UndoRow(rghRow[ROW_SIX]),S_OK) //undo row 6; // row 7 is already bad // row 8 is already inserted TESTC_(RowsetA.ModifyRow(rghRow[ROW_NINE]),S_OK) //modify row 9; TESTC_(RowsetA.ModifyRow(rghRow[ROW_TEN]),S_OK) //modify row 10; TESTC_(RowsetA.DeleteRow(rghRow[ROW_TEN]),S_OK) //delete row 10; TESTC_(RowsetA.DeleteRow(rghRow[ROW_ELEVEN]),S_OK) //delete row 11; TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWELVE]),S_OK) //modify row 12; TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWELVE]),S_OK) //modify row 12; TESTC_(RowsetA.ModifyRow(rghRow[ROW_THIRTEEN]),S_OK) //modify row 13; TESTC_(RowsetA.ModifyRow(rghRow[ROW_THIRTEEN]),S_OK) //modify row 13; TESTC_(RowsetA.DeleteRow(rghRow[ROW_THIRTEEN]),S_OK) //delete row 13; //Now update the beast... TESTC_(RowsetA.UpdateRow(0,NULL,&cUpdatedRows,&rgUpdatedRows),S_OK); TESTC_(RowsetA.ReleaseRows(cUpdatedRows,rgUpdatedRows),S_OK); //Verify array TESTC(cUpdatedRows==SEVEN_ROWS); //Since 0,NULL was passed in, you can't assume the rows returned //Are in the same order as modifed... TESTC(FindValue(rghRow[ROW_EIGHT], cUpdatedRows, rgUpdatedRows)); TESTC(FindValue(rghRow[ROW_NINE], cUpdatedRows, rgUpdatedRows)); TESTC(FindValue(rghRow[ROW_TWELVE], cUpdatedRows, rgUpdatedRows)); TESTC(FindValue(rghRow[ROW_TWO], cUpdatedRows, rgUpdatedRows)); TESTC(FindValue(rghRow[ROW_THREE], cUpdatedRows, rgUpdatedRows)); TESTC(FindValue(rghRow[ROW_FOUR], cUpdatedRows, rgUpdatedRows)); TESTC(FindValue(rghRow[ROW_FIVE], cUpdatedRows, rgUpdatedRows)); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(rgUpdatedRows); TableInsert(SIX_ROWS); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(80) //*----------------------------------------------------------------------- // @mfunc Sequence - Multiple Table Update // // @rdesc TEST_PASS or TEST_FAIL // int TCUpdate::Variation_80() { TBEGIN TRETURN } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCUpdate::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CRowsetUpdate::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCGetRowStatus) //*----------------------------------------------------------------------- //| Test Case: TCGetRowStatus - IRowsetUpdate::GetRowStatus //| Created: 04/16/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCGetRowStatus::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CRowsetUpdate::Init()) // }} { return TEST_PASS; } return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc General - Verify GetRowStatus alters row handles RefCount correctly // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_1() { HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; DBROWSTATUS rgPendingStatus[1] = {ULONG_MAX}; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Fetch rows TESTC_(RowsetA.GetRow(FIRST_ROW, FOUR_ROWS, rghRow),S_OK); //Release rows TESTC_(RowsetA.ReleaseRows(FOUR_ROWS,rghRow),S_OK); //GetRowStatus [invalid, 0, NULL, valid], should no nothing TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(INVALID(HCHAPTER),0,NULL,rgPendingStatus),S_OK); TESTC(rgPendingStatus[0] == ULONG_MAX); //Release again, should cause error TESTC_(RowsetA.ReleaseRows(FOUR_ROWS,rghRow),DB_E_ERRORSOCCURRED); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS, rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Boundary - No Changes [invalid, 0, NULL, valid] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_2() { HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; DBROWSTATUS rgPendingStatus[1] = {ULONG_MAX}; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Fetch rows TESTC_(RowsetA.GetRow(FIRST_ROW, FOUR_ROWS, rghRow),S_OK); //GetRowStatus [invalid, 0, NULL, NULL], do nothing TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(INVALID(HCHAPTER), 0, NULL, NULL),S_OK); //GetRowStatus [invalid, 0, NULL, valid], should ignore rgPendingStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(INVALID(HCHAPTER), 0, NULL, rgPendingStatus),S_OK); TESTC(rgPendingStatus[0] == ULONG_MAX); //GetRowStatus [invalid, 0, NULL, valid], should ignore rghRows and do nothing TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(INVALID(HCHAPTER), 0, rghRow, NULL), S_OK); //GetRowStatus [invalid, 0, valid, valid], should ignore rgPendingStatus rgPendingStatus[0] = ULONG_MAX; TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(INVALID(HCHAPTER), 0, rghRow, rgPendingStatus), S_OK); TESTC(rgPendingStatus[0] == ULONG_MAX); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS, rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc Boundary - No Changes [NULL, 1, valid, NULL] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_3() { HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Fetch rows TESTC_(RowsetA.GetRow(FIRST_ROW, FOUR_ROWS, rghRow),S_OK); //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL, ONE_ROW, rghRow, NULL),E_INVALIDARG); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS, rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc Boundary - No Changes [NULL, 1, NULL, valid] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_4() { HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; DBROWSTATUS rgPendingStatus[1] = {ULONG_MAX}; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Fetch rows TESTC_(RowsetA.GetRow(FIRST_ROW, FOUR_ROWS, rghRow),S_OK); //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL, ONE_ROW, NULL, rgPendingStatus),E_INVALIDARG); TESTC(rgPendingStatus[0] == ULONG_MAX); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS, rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_5() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_6() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes [NULL, 0, NULL, NULL] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_7() { HROW rghRow[SIX_ROWS] = {NULL,NULL,NULL,NULL,NULL,NULL}; DBROWSTATUS rgPendingStatus[1] = {ULONG_MAX}; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Fetch rows TESTC_(RowsetA.GetRow(FIRST_ROW, FOUR_ROWS, rghRow),S_OK); //Modify row(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWO]),S_OK); if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_FOUR]),S_OK); //Insert row(s) if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_SIX]),S_OK); if(RowsetA.AllowPendingRows(4)) TESTC_(RowsetA.InsertRow(&rghRow[ROW_FIVE]),S_OK); //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,0,NULL,NULL),S_OK); CLEANUP: RowsetA.ReleaseRows(SIX_ROWS, rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes [NULL, N, NULL, NULL] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_8() { HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; DBPENDINGSTATUS rgPendingStatus[FOUR_ROWS] = {ULONG_MAX,ULONG_MAX,ULONG_MAX,ULONG_MAX}; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Fetch rows TESTC_(RowsetA.GetRow(FIRST_ROW, FOUR_ROWS, rghRow),S_OK); //Modify row(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWO]),S_OK); if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_FOUR]),S_OK); //Delete row(s) if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.DeleteRow(rghRow[ROW_ONE]),S_OK); //GetRowStatus (N, NULL, NULL) - E_INVALIDARG TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL, FOUR_ROWS, NULL, NULL), E_INVALIDARG); //GetRowStatus (N, NULL, valid) - E_INVALIDARG TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL, FOUR_ROWS, NULL, rgPendingStatus), E_INVALIDARG); TESTC(VerifyArray(FOUR_ROWS, rgPendingStatus, ULONG_MAX)); //GetRowStatus (N, valid, NULL) - E_INVALIDARG TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL, FOUR_ROWS, rghRow, NULL), E_INVALIDARG); //GetRowStatus (N, valid, valid) - S_OK TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL, FOUR_ROWS, rghRow, rgPendingStatus), S_OK); COMPC(rgPendingStatus[ROW_ONE], (DBPENDINGSTATUS)(RowsetA.AllowPendingRows(3) ? DBPENDINGSTATUS_DELETED : DBPENDINGSTATUS_UNCHANGED)); COMPC(rgPendingStatus[ROW_TWO], DBPENDINGSTATUS_CHANGED); COMPC(rgPendingStatus[ROW_THREE], DBPENDINGSTATUS_UNCHANGED); COMPC(rgPendingStatus[ROW_FOUR], (DBPENDINGSTATUS)(RowsetA.AllowPendingRows(2) ? DBPENDINGSTATUS_CHANGED : DBPENDINGSTATUS_UNCHANGED)); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS, rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc Boundary - N Changes [NULL, N, valid, valid] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_9() { const int NROWS = SIX_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL,NULL}; DBPENDINGSTATUS rgPendingStatus[NROWS]; ULONG cModifiedRows = 0; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Fetch rows TESTC_(RowsetA.GetRow(FIRST_ROW, THREE_ROWS, rghRow),S_OK); //Modify row(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWO]),S_OK); //modify row 2 cModifiedRows = 1; if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK); //modify row 3 cModifiedRows++; } //Delete row(s) if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.InsertRow(&rghRow[ROW_FIVE]),S_OK); //insert row 5 cModifiedRows++; } if(RowsetA.AllowPendingRows(4)) { TESTC_(RowsetA.InsertRow(&rghRow[ROW_SIX]),S_OK); //insert row 6 cModifiedRows++; } //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,NROWS,rghRow,rgPendingStatus),DB_S_ERRORSOCCURRED); COMPC(rgPendingStatus[0],DBPENDINGSTATUS_UNCHANGED); COMPC(rgPendingStatus[1],DBPENDINGSTATUS_CHANGED); COMPC(rgPendingStatus[3],DBPENDINGSTATUS_INVALIDROW); if(cModifiedRows >=2) COMPC(rgPendingStatus[2],DBPENDINGSTATUS_CHANGED); if(cModifiedRows >=3) COMPC(rgPendingStatus[4],DBPENDINGSTATUS_NEW); if(cModifiedRows >=4) COMPC(rgPendingStatus[5],DBPENDINGSTATUS_NEW); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(10) //*----------------------------------------------------------------------- // @mfunc Boundary - Empty Rowset [NULL, N, valid, valid] // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_10() { const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; DBPENDINGSTATUS rgPendingStatus[NROWS]; CRowsetUpdate EmptyRowsetA; TESTC_PROVIDER(EmptyRowsetA.CreateRowset(SELECT_EMPTYROWSET)==S_OK); //Can't fetch any rows, but is useful, since we can guarentee no other //row modidifying methods have been called... rghRow[ROW_ONE] = DB_NULL_HROW; rghRow[ROW_TWO] = DB_NULL_HROW; rghRow[ROW_THREE] = INVALID(HROW); rghRow[ROW_FOUR] = DB_NULL_HROW; //GetRowStatus TESTC_(EmptyRowsetA.pIRowsetUpdate()->GetRowStatus(NULL,NROWS,rghRow,rgPendingStatus),DB_E_ERRORSOCCURRED); COMPC(rgPendingStatus[0],DBPENDINGSTATUS_INVALIDROW); COMPC(rgPendingStatus[1],DBPENDINGSTATUS_INVALIDROW); COMPC(rgPendingStatus[2],DBPENDINGSTATUS_INVALIDROW); COMPC(rgPendingStatus[3],DBPENDINGSTATUS_INVALIDROW); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(11) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_11() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(12) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_12() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(13) //*----------------------------------------------------------------------- // @mfunc Parameters - 3 hard deleted 2 modified // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_13() { const int NROWS = FIVE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL}; DBPENDINGSTATUS rgPendingStatus[NROWS]; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,NROWS,rghRow),S_OK) ; TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_TWO]),S_OK) //hard-delete row 2; TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_FOUR]),S_OK) //hard-delete row 4; TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_FIVE]),S_OK) //hard-delete row 5; //Make changes(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 3; //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,NROWS,rghRow,rgPendingStatus),DB_S_ERRORSOCCURRED); TESTC(rgPendingStatus!=NULL); TESTC(rgPendingStatus[ROW_ONE] == DBPENDINGSTATUS_CHANGED); TESTC(rgPendingStatus[ROW_TWO] == DBPENDINGSTATUS_INVALIDROW); TESTC(rgPendingStatus[ROW_THREE] == (DBPENDINGSTATUS)(RowsetA.AllowPendingRows(2) ? DBPENDINGSTATUS_CHANGED : DBPENDINGSTATUS_UNCHANGED)); TESTC(rgPendingStatus[ROW_FOUR] == DBPENDINGSTATUS_INVALIDROW); TESTC(rgPendingStatus[ROW_FIVE] == DBPENDINGSTATUS_INVALIDROW); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); TableInsert(THREE_ROWS); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(14) //*----------------------------------------------------------------------- // @mfunc Parameters - 3 invalid // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_14() { const int NROWS = FIVE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL}; DBPENDINGSTATUS rgPendingStatus[NROWS]; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,TWO_ROWS,rghRow),S_OK) ; //Rest are invalid rghRow[ROW_THREE] = DB_NULL_HROW; rghRow[ROW_FOUR] = INVALID(HROW); rghRow[ROW_FIVE] = DB_NULL_HROW; //Make changes(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,NROWS,rghRow,rgPendingStatus),DB_S_ERRORSOCCURRED); TESTC(rgPendingStatus!=NULL); TESTC(rgPendingStatus[ROW_ONE] == DBPENDINGSTATUS_CHANGED); TESTC(rgPendingStatus[ROW_TWO] == DBPENDINGSTATUS_UNCHANGED); TESTC(rgPendingStatus[ROW_THREE] == DBPENDINGSTATUS_INVALIDROW); TESTC(rgPendingStatus[ROW_FOUR] == DBPENDINGSTATUS_INVALIDROW); TESTC(rgPendingStatus[ROW_FIVE] == DBPENDINGSTATUS_INVALIDROW); CLEANUP: RowsetA.ReleaseRows(TWO_ROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(15) //*----------------------------------------------------------------------- // @mfunc Parameters - 1 hard deleted 1 invalid 1 modified // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_15() { const int NROWS = FIVE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL}; DBPENDINGSTATUS rgPendingStatus[NROWS]; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,TWO_ROWS,rghRow),S_OK) ; //Rest are invalid rghRow[ROW_THREE] = DB_NULL_HROW; //Make changes(s) TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_ONE]),S_OK) //delete row 1; TESTC_(RowsetA.ModifyRow(rghRow[ROW_TWO]),S_OK) //modify row 2; //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,NROWS,rghRow,rgPendingStatus),DB_S_ERRORSOCCURRED); TESTC(rgPendingStatus!=NULL); TESTC(rgPendingStatus[ROW_ONE] == DBPENDINGSTATUS_INVALIDROW); TESTC(rgPendingStatus[ROW_TWO] == DBPENDINGSTATUS_CHANGED); TESTC(rgPendingStatus[ROW_THREE] == DBPENDINGSTATUS_INVALIDROW); CLEANUP: RowsetA.ReleaseRows(TWO_ROWS,rghRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(16) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_16() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(17) //*----------------------------------------------------------------------- // @mfunc Parameters - All types // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_17() { TBEGIN const int NROWS = SIX_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL,NULL,NULL}; DBPENDINGSTATUS rgPendingStatus[NROWS]; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,FOUR_ROWS,rghRow),S_OK) ; TESTC_(RowsetA.InsertRow(&rghRow[ROW_FIVE]),S_OK) //1 inserted; rghRow[ROW_SIX] = DB_NULL_HROW; //1 invalid TESTC_(RowsetA.HardDeleteRow(rghRow[ROW_THREE]),S_OK)//1 hard-deleted; TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK) //1 deleted; if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //1 modified; //[ROW_FOUR] //1 unchanged //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,NROWS,rghRow,rgPendingStatus),DB_S_ERRORSOCCURRED); TESTC(rgPendingStatus!=NULL); TESTC(rgPendingStatus[ROW_ONE] == (DBPENDINGSTATUS)(RowsetA.AllowPendingRows(2) ? DBPENDINGSTATUS_CHANGED : DBPENDINGSTATUS_UNCHANGED)); TESTC(rgPendingStatus[ROW_TWO] == DBPENDINGSTATUS_DELETED); TESTC(rgPendingStatus[ROW_THREE] == DBPENDINGSTATUS_INVALIDROW); TESTC(rgPendingStatus[ROW_FOUR] == DBPENDINGSTATUS_UNCHANGED); TESTC(rgPendingStatus[ROW_FIVE] == DBPENDINGSTATUS_NEW); TESTC(rgPendingStatus[ROW_SIX] == DBPENDINGSTATUS_INVALIDROW); CLEANUP: RowsetA.ReleaseRows(FIVE_ROWS,rghRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(18) //*----------------------------------------------------------------------- // @mfunc Parameters - All Unchanged // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_18() { const int NROWS = TWO_ROWS; HROW rghRow[NROWS] = {NULL,NULL}; DBPENDINGSTATUS rgPendingStatus[NROWS]; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,NROWS,rghRow),S_OK) ; //Make no changes //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,NROWS,rghRow,rgPendingStatus),S_OK); TESTC(rgPendingStatus!=NULL); TESTC(VerifyArray(NROWS,rgPendingStatus,DBPENDINGSTATUS_UNCHANGED)); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(19) //*----------------------------------------------------------------------- // @mfunc Parameters - All Inserted // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_19() { TBEGIN const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; DBPENDINGSTATUS rgPendingStatus[NROWS]; DBCOUNTITEM cModifiedRows = 0; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); cModifiedRows = RowsetA.GetMaxPendingRows(); if(cModifiedRows==0 || cModifiedRows>NROWS) cModifiedRows = NROWS; //Insert row handle(s) TESTC_(RowsetA.InsertRow(cModifiedRows,rghRow),S_OK); //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,cModifiedRows,rghRow,rgPendingStatus),S_OK); TESTC(rgPendingStatus!=NULL); TESTC(VerifyArray(cModifiedRows,rgPendingStatus,DBPENDINGSTATUS_NEW)); //Update all TESTC_(RowsetA.UpdateAll(),S_OK) ; CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(20) //*----------------------------------------------------------------------- // @mfunc Parameters - All Soft-Deleted // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_20() { const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; DBPENDINGSTATUS rgPendingStatus[NROWS]; DBCOUNTITEM cModifiedRows = 0; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK) ; cModifiedRows = RowsetA.GetMaxPendingRows(); if(cModifiedRows==0 || cModifiedRows>NROWS) cModifiedRows = NROWS; //Delete row(s) TESTC_(RowsetA.DeleteRow(cModifiedRows,rghRow),S_OK) ; //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,cModifiedRows,rghRow,rgPendingStatus),S_OK); TESTC(rgPendingStatus!=NULL); TESTC(VerifyArray(cModifiedRows,rgPendingStatus,DBPENDINGSTATUS_DELETED)); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(21) //*----------------------------------------------------------------------- // @mfunc Parameters - Insert/Modify // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_21() { HROW hRow = DB_NULL_HROW; DBPENDINGSTATUS rgPendingStatus[ONE_ROW]; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Insert row TESTC_(RowsetA.InsertRow(&hRow),S_OK); TESTC_(RowsetA.ModifyRow(hRow),S_OK); //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,ONE_ROW,&hRow,rgPendingStatus),S_OK); TESTC(rgPendingStatus!=NULL); TESTC(rgPendingStatus[ROW_ONE] == DBPENDINGSTATUS_NEW); //An insertion followed by a modification counts as an insertion //Update all TESTC_(RowsetA.UpdateAll(),S_OK) ; CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(22) //*----------------------------------------------------------------------- // @mfunc Parameters - Modify Delete // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_22() { HROW hRow = DB_NULL_HROW; DBPENDINGSTATUS rgPendingStatus[ONE_ROW]; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain handle TESTC_(RowsetA.GetRow(FIRST_ROW, &hRow),S_OK); //Modify row TESTC_(RowsetA.ModifyRow(hRow),S_OK); //Delete row TESTC_(RowsetA.DeleteRow(hRow),S_OK); //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,ONE_ROW,&hRow,rgPendingStatus),S_OK); TESTC(rgPendingStatus!=NULL); COMPC(rgPendingStatus[ROW_ONE],DBPENDINGSTATUS_DELETED) CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(23) //*----------------------------------------------------------------------- // @mfunc Parameters - Insert/Modify/Delete // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_23() { HROW hRow = DB_NULL_HROW; DBPENDINGSTATUS rgPendingStatus[ONE_ROW]; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Insert row TESTC_(RowsetA.InsertRow(&hRow),S_OK); TESTC_(RowsetA.ModifyRow(hRow),S_OK); TESTC_(RowsetA.DeleteRow(hRow),S_OK); //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,ONE_ROW,&hRow,rgPendingStatus),DB_E_ERRORSOCCURRED); TESTC(rgPendingStatus!=NULL); TESTC(rgPendingStatus[0]==DBPENDINGSTATUS_INVALIDROW); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(24) //*----------------------------------------------------------------------- // @mfunc Empty // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_24() { return TEST_PASS; } // }} // {{ TCW_VAR_PROTOTYPE(25) //*----------------------------------------------------------------------- // @mfunc Sequence - Insert/Delete/Modify - Update // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_25() { TBEGIN const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; DBPENDINGSTATUS rgPendingStatus[NROWS]; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handles TESTC_(RowsetA.GetRow(FIRST_ROW, TWO_ROWS, rghRow),S_OK); //Insert row TESTC_(RowsetA.InsertRow(&rghRow[ROW_THREE]),S_OK); TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK); TESTC_(RowsetA.DeleteRow(rghRow[ROW_THREE]),S_OK); //Update TESTC_(RowsetA.UpdateAll(),S_OK); //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,NROWS,rghRow,rgPendingStatus),DB_S_ERRORSOCCURRED); TESTC(rgPendingStatus!=NULL); TESTC(rgPendingStatus[ROW_ONE] == DBPENDINGSTATUS_UNCHANGED); TESTC(rgPendingStatus[ROW_TWO] == DBPENDINGSTATUS_UNCHANGED); TESTC(rgPendingStatus[ROW_THREE] == DBPENDINGSTATUS_INVALIDROW); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(26) //*----------------------------------------------------------------------- // @mfunc Sequence - Make all type changes - Undo half - Update // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_26() { TBEGIN const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; DBPENDINGSTATUS rgPendingStatus[NROWS]; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handles TESTC_(RowsetA.GetRow(FIRST_ROW, TWO_ROWS, rghRow),S_OK); TESTC_(RowsetA.InsertRow(&rghRow[ROW_THREE]),S_OK); if(RowsetA.AllowPendingRows(2)) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK); if(RowsetA.AllowPendingRows(3)) TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK); //Undo TESTC_(RowsetA.UndoRow(rghRow[ROW_TWO]),S_OK); //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,NROWS,rghRow,rgPendingStatus),S_OK); TESTC(rgPendingStatus!=NULL); TESTC(rgPendingStatus[ROW_ONE] == (DBPENDINGSTATUS)(RowsetA.AllowPendingRows(2) ? DBPENDINGSTATUS_CHANGED : DBPENDINGSTATUS_UNCHANGED)); TESTC(rgPendingStatus[ROW_TWO] == DBPENDINGSTATUS_UNCHANGED); TESTC(rgPendingStatus[ROW_THREE] == DBPENDINGSTATUS_NEW); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(27) //*----------------------------------------------------------------------- // @mfunc Sequence - Change N rows, GetPendingRows, GetRowStatus // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_27() { TBEGIN const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; DBPENDINGSTATUS rgPendingStatus[NROWS]; ULONG cModifiedRows = 0; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain row handles TESTC_(RowsetA.GetRow(FIRST_ROW, THREE_ROWS, rghRow),S_OK); //Make N changes TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK); cModifiedRows++; if(RowsetA.AllowPendingRows(2)) { TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK); cModifiedRows++; } if(RowsetA.AllowPendingRows(3)) { TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK); cModifiedRows++; } //GetPendingRows = N TESTC_(RowsetA.GetPendingRows(cModifiedRows),S_OK); //GetRowStatus TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,NROWS,rghRow,rgPendingStatus),S_OK); TESTC(rgPendingStatus!=NULL); TESTC(rgPendingStatus[ROW_ONE] == (DBPENDINGSTATUS)(RowsetA.AllowPendingRows(2) ? DBPENDINGSTATUS_CHANGED : DBPENDINGSTATUS_UNCHANGED)); TESTC(rgPendingStatus[ROW_TWO] == (DBPENDINGSTATUS)(RowsetA.AllowPendingRows(3) ? DBPENDINGSTATUS_DELETED : DBPENDINGSTATUS_UNCHANGED)); TESTC(rgPendingStatus[ROW_THREE] == DBPENDINGSTATUS_UNCHANGED); TESTC(rgPendingStatus[ROW_FOUR] == DBPENDINGSTATUS_NEW); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(28) //*----------------------------------------------------------------------- // @mfunc Sequence - Call GetRowStatus 3 times // // @rdesc TEST_PASS or TEST_FAIL // int TCGetRowStatus::Variation_28() { TBEGIN const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; DBPENDINGSTATUS rgPendingStatus[NROWS]; CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); TESTC_PROVIDER(RowsetA.AllowPendingRows(NROWS)); //Make sure we have QBU turned on if(SupportedProperty(KAGPROP_QUERYBASEDUPDATES,DBPROPSET_PROVIDERROWSET)) TESTC(RowsetA.GetProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET)); //Obtain row handles TESTC_(RowsetA.GetRow(FIRST_ROW, THREE_ROWS, rghRow),S_OK); //Make N changes TESTC_(RowsetA.InsertRow(&rghRow[ROW_FOUR]),S_OK); TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK); TESTC_(RowsetA.DeleteRow(rghRow[ROW_TWO]),S_OK); //GetRowStatus #1 TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,NROWS,rghRow,rgPendingStatus),S_OK); TESTC(rgPendingStatus!=NULL); TESTC(rgPendingStatus[ROW_ONE] == DBPENDINGSTATUS_CHANGED); TESTC(rgPendingStatus[ROW_TWO] == DBPENDINGSTATUS_DELETED); TESTC(rgPendingStatus[ROW_THREE] == DBPENDINGSTATUS_UNCHANGED); TESTC(rgPendingStatus[ROW_FOUR] == DBPENDINGSTATUS_NEW); //GetRowStatus #2 TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,NROWS,rghRow,rgPendingStatus),S_OK); TESTC(rgPendingStatus!=NULL); TESTC(rgPendingStatus[ROW_ONE] == DBPENDINGSTATUS_CHANGED); TESTC(rgPendingStatus[ROW_TWO] == DBPENDINGSTATUS_DELETED); TESTC(rgPendingStatus[ROW_THREE] == DBPENDINGSTATUS_UNCHANGED); TESTC(rgPendingStatus[ROW_FOUR] == DBPENDINGSTATUS_NEW); //Update TESTC_(RowsetA.UpdateAll(),S_OK); //GetRowStatus #3 TESTC_(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,NROWS,rghRow,rgPendingStatus),DB_S_ERRORSOCCURRED); TESTC(rgPendingStatus!=NULL); TESTC(rgPendingStatus[ROW_ONE] == DBPENDINGSTATUS_UNCHANGED); TESTC(rgPendingStatus[ROW_TWO] == DBPENDINGSTATUS_INVALIDROW); TESTC(rgPendingStatus[ROW_THREE] == DBPENDINGSTATUS_UNCHANGED); TESTC(rgPendingStatus[ROW_FOUR] == DBPENDINGSTATUS_UNCHANGED); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCGetRowStatus::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CRowsetUpdate::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCExtendedErrors) //*----------------------------------------------------------------------- //| Test Case: TCExtendedErrors - Extended Errors //| Created: 07/25/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCExtendedErrors::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(CRowsetUpdate::Init()) // }} { return TEST_PASS; } return TEST_FAIL; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc Valid GetOriginalData calls with previous error object existing. // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_1() { HACCESSOR hNullAccessor = DB_NULL_HACCESSOR; HACCESSOR hAccessor = DB_NULL_HACCESSOR; HROW hRow = DB_NULL_HROW; void* pData = INVALID(void*); CRowsetUpdate RowsetA; //For each method of the interface, first create an error object on //the current thread, then try get S_OK from the IRowsetUpdate method. //We then check extended errors to verify nothing is set since an //error object shouldn't exist following a successful call. TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Create a NULL Accessor TESTC_(RowsetA.pIAccessor()->CreateAccessor(DBACCESSOR_ROWDATA,0,NULL,0,&hNullAccessor,NULL),S_OK); //Obtain the first row TESTC_(RowsetA.GetRow(FIRST_ROW, &hRow),S_OK); //create an error object TESTC(m_pExtError->CauseError()); TESTC_(m_hr=(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,hNullAccessor,pData)),S_OK); //Do extended check following GetOriginalData TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); TESTC(pData==INVALID(void*)); TESTC_(RowsetA.pIAccessor()->ReleaseAccessor(hNullAccessor ,NULL),S_OK); TESTC_(RowsetA.pIAccessor()->ReleaseAccessor(hAccessor ,NULL),DB_E_BADACCESSORHANDLE); TESTC_(RowsetA.pIAccessor()->ReleaseAccessor(INVALID(HACCESSOR),NULL),DB_E_BADACCESSORHANDLE); TESTC_(RowsetA.pIAccessor()->ReleaseAccessor(DB_NULL_HACCESSOR ,NULL),DB_E_BADACCESSORHANDLE); CLEANUP: //Release the Accesssor RowsetA.ReleaseAccessor(hNullAccessor); RowsetA.ReleaseAccessor(hAccessor); //Release the row handle RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Invalid GetOriginalData calls with previous error object existing // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_2() { //HACCESSOR hAccessor = DB_NULL_HACCESSOR; HROW hRow = DB_NULL_HROW; CRowsetUpdate RowsetA; //For each method of the interface, first create an error object on //the current thread, then try get a failure from the IRowsetUpdate method. //We then check extended errors to verify the right extended error behavior. //The work arround is to create a new rowset in this variation, which //will guarentee we don't have to call restart poisiton. TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Get the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //create an error object TESTC(m_pExtError->CauseError()); //Call GetOriginalData with NULL pDdata TESTC_(m_hr=(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,RowsetA.m_hAccessor,NULL)),E_INVALIDARG); //Do extended check following GetOriginalData TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc Invalid GetOriginalData calls with no previous error object existing // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_3() { //HACCESSOR hAccessor = DB_NULL_HACCESSOR; HROW hRow = DB_NULL_HROW; CRowsetUpdate RowsetA; //For each method of the interface, with no error object on //the current thread, try get a failure from the IRowsetUpdate method. //We then check extended errors to verify the right extended error behavior. //The work arround is to create a new rowset in this variation, which //will guarentee we don't have to call restart poisiton. TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Get the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //Call GetOriginalData with NULL pDdata TESTC_(m_hr=(RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,RowsetA.m_hAccessor,NULL)),E_INVALIDARG); //Do extended check following GetOriginalData TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); CLEANUP: RowsetA.ReleaseRows(hRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc Valid GetPendingRows calls with previous error object existing. // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_4() { TBEGIN const int NROWS = THREE_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL}; //For each method of the interface, first create an error object on //the current thread, then try get S_OK from the IRowsetUpdate method. //We then check extended errors to verify nothing is set since an //error object shouldn't exist following a successful call. CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW,&rghRow[ROW_ONE]),S_OK) ; TESTC_(RowsetA.GetNextRows(&rghRow[ROW_TWO]),S_OK) ; //Make 3 changes TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; //create an error object TESTC(m_pExtError->CauseError()); TESTC_(m_hr=(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,NULL,NULL,NULL)),S_OK); //Do extended check following GetPendingRows TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc Invalid GetPendingRows calls with previous error object existing // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_5() { const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; DBCOUNTITEM cPendingRows; HROW* rgPendingRows = NULL; DBPENDINGSTATUS* rgPendingStatus = NULL; CRowsetUpdate RowsetA; //For each method of the interface, first create an error object on //the current thread, then try get a failure from the IRowsetUpdate method. //We then check extended errors to verify the right extended error behavior. RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Modify row(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; //create an error object TESTC(m_pExtError->CauseError()); //GetPendingRows DBPENDINGSTATUS_INVALIDROW TESTC_(m_hr=(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_INVALIDROW,&cPendingRows,&rgPendingRows,&rgPendingStatus)),E_INVALIDARG); //Do extended check following GetPendingRows TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); COMPC(cPendingRows,NO_ROWS) TESTC(rgPendingRows==NULL && rgPendingStatus==NULL); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); PROVIDER_FREE(rgPendingRows) PROVIDER_FREE(rgPendingStatus) TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc Invalid GetPendingRows calls with no previous error object existing // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_6() { const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; DBCOUNTITEM cPendingRows; HROW* rgPendingRows = NULL; DBPENDINGSTATUS* rgPendingStatus = NULL; CRowsetUpdate RowsetA; //For each method of the interface, with no error object on //the current thread, then try get a failure from the IRowsetUpdate method. //We then check extended errors to verify the right extended error behavior. RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the row handle(s) TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS, rghRow),S_OK); //Modify row(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_THREE]),S_OK) //modify row 3; //GetPendingRows DBPENDINGSTATUS_INVALIDROW TESTC_(m_hr=(RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_INVALIDROW,&cPendingRows,&rgPendingRows,&rgPendingStatus)),E_INVALIDARG); //Do extended check following GetPendingRows TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); COMPC(cPendingRows,NO_ROWS) TESTC(rgPendingRows==NULL && rgPendingStatus==NULL); CLEANUP: RowsetA.ReleaseRows(NROWS, rghRow); PROVIDER_FREE(rgPendingRows) PROVIDER_FREE(rgPendingStatus) TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc Valid GetRowStatus calls with previous error object existing. // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_7() { HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; DBPENDINGSTATUS rgPendingStatus[1] = {ULONG_MAX}; CRowsetUpdate RowsetA; //For each method of the interface, first create an error object on //the current thread, then try get S_OK from the IRowsetUpdate method. //We then check extended errors to verify nothing is set since an //error object shouldn't exist following a successful call. TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Fetch rows TESTC_(RowsetA.GetRow(FIRST_ROW, FOUR_ROWS, rghRow),S_OK); //create an error object TESTC(m_pExtError->CauseError()); //GetRowStatus [invalid, 0, NULL, valid], should no nothing TESTC_(m_hr=(RowsetA.pIRowsetUpdate()->GetRowStatus(INVALID(HCHAPTER),0,NULL,rgPendingStatus)),S_OK); //Do extended check following GetRowStatus TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); TESTC(rgPendingStatus[0] == ULONG_MAX); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS, rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc Invalid GetRowStatus calls with previous error object existing // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_8() { HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; //For each method of the interface, first create an error object on //the current thread, then try get a failure from the IRowsetUpdate method. //We then check extended errors to verify the right extended error behavior. TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Fetch rows TESTC_(RowsetA.GetRow(FIRST_ROW, FOUR_ROWS, rghRow),S_OK); //create an error object TESTC(m_pExtError->CauseError()); //GetRowStatus TESTC_(m_hr=(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,ONE_ROW,rghRow,NULL)),E_INVALIDARG); //Do extended check following GetRowStatus TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS, rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc Invalid GetRowStatus calls with no previous error object existing // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_9() { HROW rghRow[FOUR_ROWS] = {NULL,NULL,NULL,NULL}; CRowsetUpdate RowsetA; //For each method of the interface, with no error object on //the current thread, then try get a failure from the IRowsetUpdate method. //We then check extended errors to verify the right extended error behavior. TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Fetch rows TESTC_(RowsetA.GetRow(FIRST_ROW, FOUR_ROWS, rghRow),S_OK); //GetRowStatus TESTC_(m_hr=(RowsetA.pIRowsetUpdate()->GetRowStatus(NULL,ONE_ROW,rghRow,NULL)),E_INVALIDARG); //Do extended check following GetRowStatus TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); CLEANUP: RowsetA.ReleaseRows(FOUR_ROWS, rghRow); TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(10) //*----------------------------------------------------------------------- // @mfunc Valid Undo calls with previous error object existing. // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_10() { CRowsetUpdate RowsetA; //For each method of the interface, first create an error object on //the current thread, then try get S_OK from the IRowsetUpdate method. //We then check extended errors to verify nothing is set since an //error object shouldn't exist following a successful call. TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //create an error object TESTC(m_pExtError->CauseError()); TESTC_(m_hr=(RowsetA.pIRowsetUpdate()->Undo(NULL,0,NULL,NULL,NULL,NULL)),S_OK); //Do extended check following Undo TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(11) //*----------------------------------------------------------------------- // @mfunc Invalid Undo calls with previous error object existing // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_11() { DBCOUNTITEM cRowsUndone = 1; HROW* rgRowsUndone; DBROWSTATUS* rgRowStatus; CRowsetUpdate RowsetA; //For each method of the interface, first create an error object on //the current thread, then try get a failure from the IRowsetUpdate method. //We then check extended errors to verify the right extended error behavior. TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //create an error object TESTC(m_pExtError->CauseError()); TESTC_(m_hr=(RowsetA.pIRowsetUpdate()->Undo(INVALID(HCHAPTER),ONE_ROW,NULL,&cRowsUndone,&rgRowsUndone,&rgRowStatus)),E_INVALIDARG); //Do extended check following Undo TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); COMPC(cRowsUndone,NO_ROWS) TESTC(rgRowsUndone==NULL && rgRowStatus==NULL); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(12) //*----------------------------------------------------------------------- // @mfunc Invalid Undo calls with no previous error object existing // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_12() { DBCOUNTITEM cRowsUndone = 1; HROW* rgRowsUndone; DBROWSTATUS* rgRowStatus; CRowsetUpdate RowsetA; //For each method of the interface, with no error object on //the current thread, then try get a failure from the IRowsetUpdate method. //We then check extended errors to verify the right extended error behavior. TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); TESTC_(m_hr=(RowsetA.pIRowsetUpdate()->Undo(INVALID(HCHAPTER),ONE_ROW,NULL,&cRowsUndone,&rgRowsUndone,&rgRowStatus)),E_INVALIDARG); //Do extended check following Undo TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); COMPC(cRowsUndone,NO_ROWS) TESTC(rgRowsUndone==NULL && rgRowStatus==NULL); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(13) //*----------------------------------------------------------------------- // @mfunc Valid Update calls with previous error object existing. // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_13() { CRowsetUpdate RowsetA; //For each method of the interface, first create an error object on //the current thread, then try get S_OK from the IRowsetUpdate method. //We then check extended errors to verify nothing is set since an //error object shouldn't exist following a successful call. RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //create an error object TESTC(m_pExtError->CauseError()); TESTC_(m_hr=(RowsetA.pIRowsetUpdate()->Update(NULL,0,NULL,NULL,NULL,NULL)),S_OK); //Do extended check following Update TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); CLEANUP: TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(14) //*----------------------------------------------------------------------- // @mfunc Invalid Update calls with previous error object existing // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_14() { TBEGIN DBCOUNTITEM cUpdatedRows = 1; HROW* rgUpdatedRows = NULL; DBROWSTATUS* rgRowStatus = NULL; const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; //For each method of the interface, first create an error object on //the current thread, then try get a failure from the IRowsetUpdate method. //We then check extended errors to verify the right extended error behavior. CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS,rghRow),S_OK); //Make changes(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; //create an error object TESTC(m_pExtError->CauseError()); TESTC_(m_hr=(RowsetA.pIRowsetUpdate()->Update(INVALID(HCHAPTER),NROWS,NULL,&cUpdatedRows,&rgUpdatedRows,&rgRowStatus)),E_INVALIDARG); //Do extended check following Update TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); TESTC(cUpdatedRows==0 && rgUpdatedRows==NULL && rgRowStatus==NULL); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(rgUpdatedRows); PROVIDER_FREE(rgRowStatus); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(15) //*----------------------------------------------------------------------- // @mfunc Invalid Update calls with no previous error object existing // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_15() { TBEGIN DBCOUNTITEM cUpdatedRows = 1; HROW* rgUpdatedRows = NULL; DBROWSTATUS* rgRowStatus = NULL; const int NROWS = FOUR_ROWS; HROW rghRow[NROWS] = {NULL,NULL,NULL,NULL}; //For each method of the interface, with no error object on //the current thread, then try get a failure from the IRowsetUpdate method. //We then check extended errors to verify the right extended error behavior. CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateRowset(DBPROP_CANHOLDROWS)==S_OK); //Obtain handle(s), starting at row 1 TESTC_(RowsetA.GetRow(FIRST_ROW, NROWS,rghRow),S_OK); //Make changes(s) TESTC_(RowsetA.ModifyRow(rghRow[ROW_ONE]),S_OK) //modify row 1; TESTC_(m_hr=(RowsetA.pIRowsetUpdate()->Update(INVALID(HCHAPTER),NROWS,NULL,&cUpdatedRows,&rgUpdatedRows,&rgRowStatus)),E_INVALIDARG); //Do extended check following Update TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); TESTC(cUpdatedRows==0 && rgUpdatedRows==NULL && rgRowStatus==NULL); CLEANUP: RowsetA.ReleaseRows(NROWS,rghRow); PROVIDER_FREE(rgUpdatedRows); PROVIDER_FREE(rgRowStatus); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(16) //*----------------------------------------------------------------------- // @mfunc S_FALSE GetPendingRows call with no previous error object existing // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_16() { DBCOUNTITEM cPendingRows = 1; CRowsetUpdate RowsetA; TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //For each method of the interface, with no error object on //the current thread, then try get a failure from the IRowsetUpdate method. //We then check extended errors to verify the right extended error behavior. TESTC_(m_hr=RowsetA.pIRowsetUpdate()->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,&cPendingRows,NULL,NULL),S_FALSE); //Do extended check following Update TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); COMPC(cPendingRows,NO_ROWS); CLEANUP: TRETURN } //}} // {{ TCW_VAR_PROTOTYPE(17) //*----------------------------------------------------------------------- // @mfunc DB_E_DELETEDROW GetOriginalData call with no previous error object existing // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_17() { HROW hRow = DB_NULL_HROW; CRowsetUpdate RowsetA; //For each method of the interface, with no error object on //the current thread, then try get a failure from the IRowsetUpdate method. //We then check extended errors to verify the right extended error behavior. RowsetA.SetSettableProperty(KAGPROP_QUERYBASEDUPDATES, DBPROPSET_PROVIDERROWSET); TESTC_PROVIDER(RowsetA.CreateRowset()==S_OK); //Obtain the first row TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //Hard-delete the row TESTC_(RowsetA.HardDeleteRow(hRow),S_OK); //Call GetOriginalData on the hard deleted row TESTC_(m_hr=RowsetA.GetOriginalData(hRow, &RowsetA.m_pData),DB_E_DELETEDROW); //Do extended check following Update TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); TESTC(RowsetA.m_pData!=NULL) //provider shouldn't touch my alloced buffer; CLEANUP: RowsetA.ReleaseRows(hRow); TableInsert(ONE_ROW); //Adjust the table TRETURN } //}} // {{ TCW_VAR_PROTOTYPE(18) //*----------------------------------------------------------------------- // @mfunc DB_E_BADACCESSORTYPE GetOriginal call with no previous error object existing // // @rdesc TEST_PASS or TEST_FAIL // int TCExtendedErrors::Variation_18() { HACCESSOR hAccessor = DB_NULL_HACCESSOR; HROW hRow = DB_NULL_HROW; HRESULT hr = S_OK; //For each method of the interface, with no error object on //the current thread, then try get a failure from the IRowsetUpdate method. //We then check extended errors to verify the right extended error behavior. //Create the rowset CRowsetUpdate RowsetA; RowsetA.SetSettableProperty(DBPROP_OTHERUPDATEDELETE); TESTC_PROVIDER(RowsetA.CreateCommand()==S_OK); //Create an invalid Accessor for use with GetOriginalData //Must be done on the CommandObject, ParameterAccessors are not allowed //to be created on the RowsetObject TEST2C_(hr = GetAccessorAndBindings(RowsetA.pICommand(),DBACCESSOR_PARAMETERDATA,&hAccessor, NULL,NULL,NULL,DBPART_ALL,UPDATEABLE_COLS_BOUND,FORWARD, NO_COLS_BY_REF,NULL,NULL,NULL,DBTYPE_BYREF,0,NULL,NULL, NO_COLS_OWNED_BY_PROV, DBPARAMIO_INPUT), S_OK, DB_E_BADACCESSORFLAGS); if(hr == S_OK) { //Now that we have the Accessor Created, now create the rowset //Must be a command query, since the accessor was created on the command TESTC_PROVIDER(RowsetA.CreateRowset(SELECT_REVCOLLIST)==S_OK); //Obtain the first row TESTC_(RowsetA.GetRow(FIRST_ROW, &hRow),S_OK); //Call GetOriginalData with an invalid accessor type TESTC_(m_hr=RowsetA.pIRowsetUpdate()->GetOriginalData(hRow,hAccessor,RowsetA.m_pData),DB_E_BADACCESSORTYPE); //Do extended check following Update TESTC(m_pExtError->ValidateExtended(m_hr, RowsetA.pIRowsetUpdate(), IID_IRowsetUpdate, LONGSTRING(__FILE__), __LINE__)); TESTC(RowsetA.m_pData!=NULL); } else { //Make sure the provider doesn't support parameters (validated immediately) TESTC_(QI(RowsetA.pICommand(), IID_ICommandWithParameters), E_NOINTERFACE); } CLEANUP: RowsetA.ReleaseAccessor(hAccessor); RowsetA.ReleaseRows(hRow); TRETURN } //}} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCExtendedErrors::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CRowsetUpdate::Terminate()); } // }} // }} // }} // {{ TCW_TC_PROTOTYPE(TCZombie) //*----------------------------------------------------------------------- //| Test Case: TCZombie - Zombie testing of IRowsetUpdate //| Created: 07/22/96 //*----------------------------------------------------------------------- //-------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCZombie::Init() { TBEGIN m_cPropSets = 0; m_rgPropSets = NULL; // {{ TCW_INIT_BASECLASS_CHECK if(CTransaction::Init()) // }} { //Set Properties SetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets, (void*)DBPROPVAL_UP_ALL,DBTYPE_I4); //register interface to be tested if(RegisterInterface(ROWSET_INTERFACE,IID_IRowsetUpdate)) return TRUE; } //Not all providers have to support transactions //If a required interface, an error would have been posted by VerifyInterface TEST_PROVIDER(m_pITransactionLocal != NULL); return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc Zombie - ABORT with fRetaining == TRUE // // @rdesc TEST_PASS or TEST_FAIL // int TCZombie::Variation_1() { IRowsetUpdate* pIRowsetUpdate = NULL; CRowsetUpdate RowsetA; HROW hRow = NULL; DBROWSTATUS rgRowStatus[ONE_ROW]; HRESULT ExpectedHr = E_UNEXPECTED; //Start the Transaction //And obtain the IOpenRowset interface TESTC_PROVIDER(StartTransaction(USE_SUPPORTED_SELECT_ALLFROMTBL,(IUnknown**)&pIRowsetUpdate,m_cPropSets,m_rgPropSets)); TESTC(pIRowsetUpdate!=NULL); TESTC(m_pIRowset!=NULL) //Rowset interface from CTransAction; //Obtain the first row TESTC_PROVIDER(RowsetA.CreateRowset(m_pIRowset)==S_OK); TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //Make a change, (delete it) TESTC_(RowsetA.DeleteRow(hRow),S_OK); //Abort the Transaction with fRetaining==TRUE TESTC(GetAbort(TRUE)); //Obtain the ABORTPRESERVE flag and adjust ExpectedHr if(m_fAbortPreserve) ExpectedHr = S_OK; //Verify we still can use GetOriginalData after an ABORT TESTC_(pIRowsetUpdate->GetOriginalData(hRow,RowsetA.m_hAccessor,RowsetA.m_pData),ExpectedHr); //Verify we still can use GetRowStatus after an ABORT TESTC_(pIRowsetUpdate->GetRowStatus(NULL,ONE_ROW,&hRow,rgRowStatus),ExpectedHr); //Verify we still can use GetPendingRows after an ABORT TESTC_(pIRowsetUpdate->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,NULL,NULL,NULL),ExpectedHr); //Verify we still can use Update (all) after an ABORT TESTC_(pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),ExpectedHr); //Verify we still can use Undo (all) after an ABORT TESTC_(pIRowsetUpdate->Undo(NULL,0,NULL,NULL,NULL,NULL),ExpectedHr); CLEANUP: SAFE_RELEASE(pIRowsetUpdate); RowsetA.ReleaseRows(hRow); CleanUpTransaction(S_OK); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Zombie - ABORT with fRetaining == FALSE // // @rdesc TEST_PASS or TEST_FAIL // int TCZombie::Variation_2() { IRowsetUpdate* pIRowsetUpdate = NULL; CRowsetUpdate RowsetA; HROW hRow = NULL; DBROWSTATUS rgRowStatus[ONE_ROW]; HRESULT ExpectedHr = E_UNEXPECTED; //Start the Transaction //And obtain the IOpenRowset interface TESTC_PROVIDER(StartTransaction(USE_SUPPORTED_SELECT_ALLFROMTBL,(IUnknown**)&pIRowsetUpdate,m_cPropSets,m_rgPropSets)); TESTC(pIRowsetUpdate!=NULL); TESTC(m_pIRowset!=NULL) //Rowset interface from CTransAction; //Obtain the first row TESTC_PROVIDER(RowsetA.CreateRowset(m_pIRowset)==S_OK); TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //Make a change, (delete it) TESTC_(RowsetA.DeleteRow(hRow),S_OK); //Abort the Transaction with fRetaining==FALSE TESTC(GetAbort(FALSE)); //Obtain the ABORTPRESERVE flag and adjust ExpectedHr if(m_fAbortPreserve) ExpectedHr = S_OK; //Verify we still can use GetOriginalData after an ABORT TESTC_(pIRowsetUpdate->GetOriginalData(hRow,RowsetA.m_hAccessor,RowsetA.m_pData),ExpectedHr); //Verify we still can use GetRowStatus after an ABORT TESTC_(pIRowsetUpdate->GetRowStatus(NULL,ONE_ROW,&hRow,rgRowStatus),ExpectedHr); //Verify we still can use GetPendingRows after an ABORT TESTC_(pIRowsetUpdate->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,NULL,NULL,NULL),ExpectedHr); //Verify we still can use Update (all) after an ABORT TESTC_(pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),ExpectedHr); //Verify we still can use Undo (all) after an ABORT TESTC_(pIRowsetUpdate->Undo(NULL,0,NULL,NULL,NULL,NULL),ExpectedHr); CLEANUP: SAFE_RELEASE(pIRowsetUpdate); RowsetA.ReleaseRows(hRow); CleanUpTransaction(XACT_E_NOTRANSACTION); //No longer in a transaction TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc Zombie - COMMIT with fRetaining == TRUE // // @rdesc TEST_PASS or TEST_FAIL // int TCZombie::Variation_3() { IRowsetUpdate* pIRowsetUpdate = NULL; CRowsetUpdate RowsetA; HROW hRow = NULL; DBROWSTATUS rgRowStatus[ONE_ROW]; HRESULT ExpectedHr = E_UNEXPECTED; //Start the Transaction //And obtain the IOpenRowset interface TESTC_PROVIDER(StartTransaction(USE_SUPPORTED_SELECT_ALLFROMTBL,(IUnknown**)&pIRowsetUpdate,m_cPropSets,m_rgPropSets)); TESTC(pIRowsetUpdate!=NULL); TESTC(m_pIRowset!=NULL) //Rowset interface from CTransAction; //Obtain the first row TESTC_PROVIDER(RowsetA.CreateRowset(m_pIRowset)==S_OK); TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //Make a change, (delete it) TESTC_(RowsetA.DeleteRow(hRow),S_OK); //Commit the Transaction with fRetaining==TRUE TESTC(GetCommit(TRUE)); //Obtain the COMMITPRESERVE flag and adjust ExpectedHr if(m_fCommitPreserve) ExpectedHr = S_OK; //Verify we still can use GetOriginalData after an COMMIT TESTC_(pIRowsetUpdate->GetOriginalData(hRow,RowsetA.m_hAccessor,RowsetA.m_pData),ExpectedHr); //Verify we still can use GetRowStatus after an COMMIT TESTC_(pIRowsetUpdate->GetRowStatus(NULL,ONE_ROW,&hRow,rgRowStatus),ExpectedHr); //Verify we still can use GetPendingRows after an COMMIT TESTC_(pIRowsetUpdate->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,NULL,NULL,NULL),ExpectedHr); //Verify we still can use Update (all) after an COMMIT TESTC_(pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),ExpectedHr); //Verify we still can use Undo (all) after an COMMIT TESTC_(pIRowsetUpdate->Undo(NULL,0,NULL,NULL,NULL,NULL),ExpectedHr); CLEANUP: SAFE_RELEASE(pIRowsetUpdate); RowsetA.ReleaseRows(hRow); CleanUpTransaction(S_OK); TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc Zombie - COMMIT with fRetaining == TRUE // // @rdesc TEST_PASS or TEST_FAIL // int TCZombie::Variation_4() { IRowsetUpdate* pIRowsetUpdate = NULL; CRowsetUpdate RowsetA; HROW hRow = NULL; DBROWSTATUS rgRowStatus[ONE_ROW]; HRESULT ExpectedHr = E_UNEXPECTED; //Start the Transaction //And obtain the IOpenRowset interface TESTC_PROVIDER(StartTransaction(USE_SUPPORTED_SELECT_ALLFROMTBL,(IUnknown**)&pIRowsetUpdate,m_cPropSets,m_rgPropSets)); TESTC(pIRowsetUpdate!=NULL); TESTC(m_pIRowset!=NULL) //Rowset interface from CTransAction; //Obtain the first row TESTC_PROVIDER(RowsetA.CreateRowset(m_pIRowset)==S_OK); TESTC_(RowsetA.GetRow(FIRST_ROW,&hRow),S_OK); //Make a change, (delete it) TESTC_(RowsetA.DeleteRow(hRow),S_OK); //Commit the Transaction with fRetaining==FALSE TESTC(GetCommit(FALSE)); //Obtain the COMMITPRESERVE flag and adjust ExpectedHr if(m_fCommitPreserve) ExpectedHr = S_OK; //Verify we still can use GetOriginalData after an COMMIT TESTC_(pIRowsetUpdate->GetOriginalData(hRow,RowsetA.m_hAccessor,RowsetA.m_pData),ExpectedHr); //Verify we still can use GetRowStatus after an COMMIT TESTC_(pIRowsetUpdate->GetRowStatus(NULL,ONE_ROW,&hRow,rgRowStatus),ExpectedHr); //Verify we still can use GetPendingRows after an COMMIT TESTC_(pIRowsetUpdate->GetPendingRows(NULL,DBPENDINGSTATUS_ALL,NULL,NULL,NULL),ExpectedHr); //Verify we still can use Update (all) after an COMMIT TESTC_(pIRowsetUpdate->Update(NULL,0,NULL,NULL,NULL,NULL),ExpectedHr); //Verify we still can use Undo (all) after an COMMIT TESTC_(pIRowsetUpdate->Undo(NULL,0,NULL,NULL,NULL,NULL),ExpectedHr); CLEANUP: SAFE_RELEASE(pIRowsetUpdate); RowsetA.ReleaseRows(hRow); CleanUpTransaction(XACT_E_NOTRANSACTION); //No longer in a transaction TableInsert(ONE_ROW); //Adjust the table TRETURN } // }} // {{ TCW_TERMINATE_METHOD //-------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TRUE or FALSE // BOOL TCZombie::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(CTransaction::Terminate()); //FreeProperties FreeProperties(&m_cPropSets,&m_rgPropSets); return(CTransaction::Terminate()); } // }} // }} // }}