//-------------------------------------------------------------------- // Microsoft OLE DB Test // // Copyright 1995-2000 Microsoft Corporation. // // @doc // // @module IIndexDefinition.CPP // #define DBINITCONSTANTS // Must be defined to initialize constants in OLEDB.H #define INITGUID #include "modstandard.hpp" #include "IIndxDef.h" #include "Extralib.h" class TCIIndexDefinition; #include #ifndef DB_E_BADINDEXID #define DB_E_BADINDEXID DB_E_BADID #endif extern IDBInitialize *g_pIDBInitialize; static BOOL fProperRangeForFillFactor = TRUE; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Module Values // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // {{ TCW_MODULE_GLOBALS DECLARE_MODULE_CLSID = { 0x406ceeb, 0x3b9d, 0x11d2, { 0xb0, 0x25, 0x0, 0xc0, 0x4f, 0xc2, 0x27, 0x93 } }; DECLARE_MODULE_NAME("IIndexDefinition"); DECLARE_MODULE_OWNER("Microsoft"); DECLARE_MODULE_DESCRIP("Testcase for IIndexDefinition"); DECLARE_MODULE_VERSION(795921705); // TCW_WizardVersion(2) // TCW_Automation(True) // }} TCW_MODULE_GLOBALS_END GUID guidModule = { 0x406ceeb, 0x3b9d, 0x11d2, { 0xb0, 0x25, 0x0, 0xc0, 0x4f, 0xc2, 0x27, 0x93 } }; #define FILL_PROP_SET(RGPROPSET_EL, NPROP, RGPROP, PROP_GUID) \ RGPROPSET_EL.cProperties = NPROP; \ RGPROPSET_EL.rgProperties = RGPROP; \ RGPROPSET_EL.guidPropertySet = PROP_GUID; \ memset(RGPROP, 0, NPROP*sizeof(DBPROP)); #define FILL_PROP(PROP, PROPID, VAR_TYPE, VAR_MACRO, VAR_VALUE, OPTION) \ PROP.dwPropertyID = PROPID; \ PROP.vValue.vt = VAR_TYPE; \ VAR_MACRO(&PROP.vValue) = VAR_VALUE; \ PROP.dwOptions = OPTION; typedef struct inparam{ ULONG i; TCIIndexDefinition *pObject; } CInParam; const ULONG nThreads=5; unsigned WINAPI ThreadProc(LPVOID lpvThreadParam); //*----------------------------------------------------------------------- // @class // class TCIIndexDefinition : public CSessionObject{ private: HRESULT GetLiteralInfo(); protected: // @cmember ptr to IIndexInterface CIIndexDefinition *m_pCIIndexDefinition; // IIndexDefinition *m_pIIndexDefinition; DBCOLUMNDESC *m_rgColumnDesc; DBORDINAL m_cColumnDesc; CTable *m_pPopulatedTable; DBORDINAL m_nIndex; ULONG m_cIndexCols; // the number of columns that support indexes DBORDINAL *m_rgIndexCols; // array of ordinals for columns that support indexes IDBSchemaRowset *m_pIDBSchemaRowset; // info to decide whether opening indexes are supported through IOpenRowset::OpenRowset // BOOL m_fIRowsetIndex; BOOL m_fSupportORS; BOOL m_fORSIndex; BOOL m_fORSIntegratedIndex; CList m_ColList; size_t m_cMaxTableName, m_cMaxIndexName, m_cMaxColumnName; LPOLESTR m_pwszInvalidTableChars; LPOLESTR m_pwszInvalidIndexChars; LPOLESTR m_pwszInvalidColumnChars; HRESULT m_rgResult[nThreads]; LPWSTR m_rgIndexName[nThreads]; // @cmember Display the index columns and orders BOOL DisplayIndex( DBINDEXCOLUMNDESC *rgIndexColumnDesc, // columns and order in index DBORDINAL nIndexSize // index size ); // Sets/Resets the nullibility of each column in the table. BOOL MakeColsNullable( CTable *pTable, BOOL bNullable ); /* //-------------------------------------------------------------------------- // // @cmember Read the value of a column in the indexe schema rowset // // RETURNS FALSE if the value was read and differ than the original one //-------------------------------------------------------------------------- BOOL GetIndexValue( LPVOID pVariable, // [OUT] value read BOOL *pfSet, // [OUT] if the value is set DBBINDING *rgDBBINDING, // [IN] binding array ULONG cColumn, // [IN] column to be read ULONG ulDBTYPE, // [IN] type of property variant BYTE *pData, // [IN] pointer to read DATA stru WCHAR *lpwszMesaj // [IN] message text for error ); */ //-------------------------------------------------------------------------- // // @cmember Check the result and property status //-------------------------------------------------------------------------- BOOL CheckProperty(const GUID guidPropSet, DBPROP *rgProp, HRESULT hr); //-------------------------------------------------------------------------- // // @cmember Read the value of a column in the indexe schema rowset // // RETURNS FALSE if the value was read and differ than the original one //-------------------------------------------------------------------------- BOOL GetIndexValueFromFirstRow( LPVOID pVariable, // [OUT] value read BOOL *pfSet, // [OUT] if the value is set DBBINDING *rgDBBINDING, // [IN] binding array ULONG cColumn, // [IN] column to be read ULONG ulDBTYPE, // [IN] type of property variant BYTE *pData, // [IN] pointer to read DATA stru DBPROPID PropID, // [IN] property that is being read ULONG cPropSets, // [IN] number of property sets DBPROPSET *rgPropSets, // [IN] array of property sets WCHAR *lpwszMesaj // [IN] message text for error ); //------------------------------------------------------------------------- // // @cmember Set a property in the property sets of a DBCOLUMNDESC //------------------------------------------------------------------------- BOOL SetProperty ( DBPROPSET **prgPropertySets, // [in/out] array of property sets ULONG *pcPropertySets, // [in/out] number of property sets DBPROPID propID, // [in] property ID DBTYPE wType, // [in] value type LPVOID value, // [in] property value DBPROPOPTIONS dwOption, // [in] prop options DBID colid, // [in] col id GUID guidPropertySet, // [in] the GUID of the propset ULONG *pcPropSet=NULL, // [out] index of property set where the prop was set ULONG *pcProp=NULL // [out] index in the rgProperties array ); // @cmember Build a valid table name of a certain length, from a certain pattern WCHAR *BuildValidName(size_t length, WCHAR* pattern); // @cmember Build an invalid table name of a certain length // the pattern is supposed to be shorter than the string to be build WCHAR *BuildInvalidName(size_t length, WCHAR* pattern, WCHAR* invchars); // @cmember Drops the index and releases its DBID // BOOL DropIndexAndReleaseID(DBID *pTableID, DBID **ppIndexID); // @cmember Sets an index with 1 column // tries all the columns if necessary // table ID is given by m_pTable->m_TableID // HRESULT SetIndex( // DBID *pIndexID, // [in] index ID // ULONG *nIndex, // [out] index column // DBID **ppIndexID // [out] index ID created by IIndexDefinition::CreateIndex() // ); // @cmember Sets an index with 1 column // tries all the columns if necessary, until succeeds HRESULT SetIndex( DBID *pTableID, // [in] table to which to attach the index DBID *pIndexID, // [in] index ID ULONG *nIndex, // [out] index column DBID **ppIndexID // [out] index ID created by IIndexDefinition::CreateIndex() ); /* // @cmember Check whether all the columns specified appear in index // if a IRowsetIndex could be open on the index, it goes for CheckIndex2 // otherwise tries to use IDBSchemaRowset BOOL CheckIndex( DBID *pTableID, // the index of the table DBID *pIndexDBID, // the index to be checked DBORDINAL cIndexColumnDesc, // how many elements DBINDEXCOLUMNDESC *rgIndexColumnDesc, // array with index original descriprion ULONG cPropertySets = 0, // number of property sets DBPROPSET *rgPropertySets = NULL // the array of property sets ); // @cmember Check whether all the columns specified appear in index // opens an IRowsetIndex and checks everything BOOL CheckIndex2( DBID *pTableID, // the index of the table DBID *pIndexDBID, // the index to be checked DBORDINAL cIndexColumnDesc, // how many elements DBINDEXCOLUMNDESC *rgIndexColumnDesc, // array with index original descriprion ULONG cPropertySets = 0, // number of property sets DBPROPSET *rgPropertySets = NULL // the array of property sets ); BOOL CheckReturnedDBID( DBID *pIndexID, // passed to CreateIndex DBID **ppIndexID // returned by CreateIndex ); */ // @cmember Check whether the property sets asked for rowset was preserved // all the data should be inside, the only thing that is allowed to be modified // is the property status BOOL IsPropSetPreserved ( DBPROPSET *rgInPropertySets, // the array passed to ITableDefinition::CreateTable DBPROPSET *rgOutPropertySets, // the aray returned by ITableDefinition::CreateTable ULONG cPropertySets // the size of the arrays ); /* //------------------------------------------------------------------------- // // @cmember create an index out of index column descriptors // // RETURNS: // E_FAIL if there is a consistency error // hr of the IIndexDefinition::CreateIndex() otherwise //------------------------------------------------------------------------- HRESULT CreateAndCheckIndex( DBID *pTableID, // [in] the ID of the table DBID *pIndexID, // [in] the ID of the index DBID **ppIndexID, // [in/out] stores output ptr to IndexID DBORDINAL nIndexSize, // [in] index size (no of columns) DBINDEXCOLUMNDESC *rgIndexColumnDesc, // [in] columns to be part of index ULONG cPropSets=0, // [in] count of property sets DBPROPSET *rgPropSets=NULL // [in] array of property sets ); //------------------------------------------------------------------------- // // @cmember create an index out of index column descriptors // Drops the index and returns just the result of the operation // // RETURNS: // E_FAIL if there is a consistency error // hr of the IIndexDefinition::CreateIndex() otherwise //------------------------------------------------------------------------- HRESULT CreateCheckAndDropIndex( DBID *pTableID, // [in] the ID of the table DBID *pIndexID, // [in] the ID of the index DBORDINAL nIndexSize, // [in] index size (no of columns) DBINDEXCOLUMNDESC *rgIndexColumnDesc, // [in] columns to be part of index ULONG cPropSets=0, // [in] count of property sets DBPROPSET *rgPropSets=NULL // [in] array of property sets ); */ //------------------------------------------------------------------------- // // @cmember create an index out of column ordinals // Drops the index afterwards // // // RETURNS: // E_FAIL if there is a consistency error // S_OK hr of the IIndexDefinition::CreateIndex() otherwise //------------------------------------------------------------------------- HRESULT CCNDropIndexFromOrdinals( CTable *pTable, // [in] the ID of the table DBID *pIndexID, // [in] the ID of the index DBCOLUMNDESC *rgColumnDesc, // [in] array of column descriptors DBORDINAL cColumnDesc, // [in] number of column desc DBORDINAL nIndexSize, // [in] index size (no of columns) DBORDINAL *rgIndexColumns, // [in] columns to be part of index DBINDEX_COL_ORDER *rgOrder, // [in] order on index columns ULONG cPropSets=0, // [in] count of property sets DBPROPSET *rgPropSets=NULL // [in] array of property sets ); //------------------------------------------------------------------------- // // @cmember create an index out of column ordinals // returns the ID of the created index // // // RETURNS: // E_FAIL if there is a consistency error // S_OK if function completes ok //------------------------------------------------------------------------- HRESULT CNCIndexFromOrdinals( CTable *pTable, // [in] the ID of the table DBID *pIndexID, // [in] the ID of the index DBID **ppIndexID, // [in/out] index ID of the created index DBCOLUMNDESC *rgColumnDesc, // [in] array of column descriptors DBORDINAL cColumnDesc, // [in] number of column desc DBORDINAL nIndexSize, // [in] index size (no of columns) DBORDINAL *rgIndexColumns, // [in] columns to be part of index DBINDEX_COL_ORDER *rgOrder, // [in] order on index columns ULONG cPropSets=0, // [in] count of property sets DBPROPSET *rgPropSets=NULL // [in] array of property sets ); // @cmember create an index out of column numbers // creates, checks it and then drops it // index size == 1 BOOL CreateIndexWithOneProperty( ULONG nValues, // [in] elements in the array VARIANT *rgValues, // [in] the values to be checked DBPROPID dwPropID, // [in] prop id GUID guidPropertySet=DBPROPSET_INDEX // [in] ); // @cmember create an index out of column numbers // creates, checks it and then drops it // index size == 1 BOOL CreateIndexWithOneLogicalProperty( DBPROPID dwPropID, // [in] prop id GUID guidPropertySet=DBPROPSET_INDEX // [in] ); // @cmember Iterator on indexes (as col no) int GetNextIndex( DBORDINAL *rgIndexColumns, // array containing the column numbers of the index BOOL *rgColumnPresent, // array of flags for membership to the index DBORDINAL nIndexsize, // index size DBORDINAL nCols // number of columns ); // @cmember Iterator on order (ascending/descending) int GetNextOrder( DBINDEX_COL_ORDER *rgIndexColumns, // array containing the column numbers of the index DBORDINAL k // index size ); // @cmember Builds and tries all indexes on a table HRESULT DoAllIndexes( CTable *pTable, // pointer to a CTable DBORDINAL nCols // number of columns in the table ); // @cmember Builds and tries all indexes on a table HRESULT DoAllIndexes( CTable *pTable, // pointer to a CTable DBORDINAL nCols, // number of columns in the table DBORDINAL nMaxIndexSize // maximum index size ); // @cmember Builds and tries all indexes of a given size defined upon a table HRESULT DoAllKIndexes( CTable *pTable, // pointer to a CTable DBORDINAL nIndexSize, // index size DBORDINAL nCols // number of columns in the table ); // @cmember Find the list of the indexable columns BOOL FindIndexableColumns( DBCOLUMNDESC *rgColumnDesc, // [IN] array of column desc on the new table DBORDINAL cColumnDesc, // [IN] number of column desc DBORDINAL **rgIndexCols, // [OUT] array of indexable columns DBORDINAL *cIndexCols // [OUT] number of indexable columns ); //------------------------------------------------------------------------- // // @cmember Prepare DBINDEXCOLUMNDESC array // RETURN // TRUE - function executed ok and memory was properly allocated // FALSE - otherwise //------------------------------------------------------------------------- BOOL MakeIndexColumnDesc( DBCOLUMNDESC *rgColumnDesc, // [IN] the array of column desc DBORDINAL cColumnDesc, // [IN] the number of columns in the table DBORDINAL *rgIndexCol, // [IN] the array of the column in the index DBINDEX_COL_ORDER *rgOrder, // [IN] the array of column order DBORDINAL nIndexSize, // [IN] index size DBINDEXCOLUMNDESC **rgIndexColumnDesc // [OUT] the desc of the index cols ); //------------------------------------------------------------------------- // // @cmember Releases the memomry allocated for the structure // RETURN: // TRUE - everything OK // FALSE - bad argument //------------------------------------------------------------------------- BOOL ReleaseIndexColumnDesc( DBINDEXCOLUMNDESC *rgIndexColumnDesc, // [IN] the desc of the index cols DBORDINAL nIndexSize // [IN] index size ); //------------------------------------------------------------------------- // // @cmember release the property of all columns // RETURNS: // TRUE - function executed correctly // FALSE - parameters look strange //------------------------------------------------------------------------- BOOL ReleaseAllColumnPropSets( DBORDINAL cColumnDesc, // [in] number of columns DBCOLUMNDESC *rgColumnDesc // [in] column descriptor array ); public: TCIIndexDefinition(WCHAR *wstrTestCaseName); virtual ~TCIIndexDefinition() {;} // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); /* //--------------------------------------------------------------------------- // TCIIndexDefinition::DoesIndexExist // // TCIIndexDefinition | // DoesIndexExist | // If this index is on this table return true If function runs correctly // but doesn't find the table name, function will return S_OK, but fExists // will be FALSE. If strIndexName is empty, returns E_FAIL. // // @mfunc DoesIndexExist // @rdesc HRESULT indicating success or failure // @flag S_OK | Function ran without problem // @flag E_FAIL | Function ran with problems // //--------------------------------------------------------------------------- HRESULT DoesIndexExist( DBID *pTableID, // @parm [IN] Table ID DBID *pIndexID, // @parm [IN] Index ID BOOL *fExists, // @parm [OUT] TRUE if index exists BOOL fAnyIndex = FALSE // @parm [IN] TRUE if search for all indexes ); //--------------------------------------------------------------------------- // TCIIndexDefinition::DoesIndexExistInIndexSchemaRowset // // TCIIndexDefinition | // DoesIndexExist | // If this index is on this table return true. If function runs correctly // but doesn't find the table name, function will return S_OK, but fExists // will be FALSE. If strIndexName is empty, returns E_FAIL. The index is sought in // index schema rowset. // // @mfunc DoesIndexExist // @rdesc HRESULT indicating success or failure // @flag S_OK | Function ran without problem // @flag E_FAIL | Function ran with problems // //--------------------------------------------------------------------------- HRESULT DoesIndexExistInIndexSchemaRowset( DBID *pTableID, // @parm [IN] Table ID DBID *pIndexID, // @parm [IN] Index ID BOOL *fExists, // @parm [OUT] TRUE if index exists BOOL fAnyIndex = FALSE // @parm [IN] TRUE if search for all indexes ); //--------------------------------------------------------------------------- // TCIIndexDefinition::DoesIndexExistRowsetIndex // // TCIIndexDefinition | // DoesIndexExist | // If this index is on this table return true. If function runs correctly // but doesn't find the table name, function will return S_OK, but fExists // will be FALSE. If strIndexName is empty, returns E_FAIL. The index is sought in // index schema rowset. // // @mfunc DoesIndexExist // @rdesc HRESULT indicating success or failure // @flag S_OK | Function ran without problem // @flag E_FAIL | Function ran with problems // //--------------------------------------------------------------------------- HRESULT DoesIndexExistRowsetIndex( DBID *pTableID, // @parm [IN] Table ID DBID *IndexID, // @parm [IN] Index ID BOOL *fExists // @parm [OUT] TRUE if index exists ); */ virtual unsigned MyThreadProc(ULONG i) {return i;} } ; // {{ TCW_TEST_CASE_MAP(TCCreateIndex) //*----------------------------------------------------------------------- // @class tests IIndexDefinition::CreateIndex() method // class TCCreateIndex : public TCIIndexDefinition { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCCreateIndex,TCIIndexDefinition); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); unsigned MyThreadProc(ULONG); friend unsigned WINAPI ThreadProc(LPVOID lpvThreadParam); // {{ TCW_TESTVARS() // @cmember Check the session object int Variation_1(); // @cmember create an index on a a non-empty table => S_OK int Variation_2(); // @cmember create an index on an empty table => S_OK int Variation_3(); // @cmember create an index on a table created with a SQL command => S_OK int Variation_4(); // @cmember create an index and get an IRowsetIndex interface on it => S_OK int Variation_5(); // @cmember create an index on a table generated with ITableDefinition => S_OK int Variation_6(); // @cmember create an index on a table that has a rowset open on it => S_OK int Variation_7(); // @cmember create an index on a table using column names and colID's read from IColumnsInfo int Variation_8(); // @cmember include a column twice in an index int Variation_9(); // @cmember create an index on an autoincrement column => S_OK int Variation_10(); // @cmember create an index on a column, drop the column int Variation_11(); // @cmember create an index on a view int Variation_12(); // @cmember create multiple indexes on the same table int Variation_13(); // @cmember create an index on a table, drop the table and check if the index is dropped as well) int Variation_14(); // @cmember create an index on a table; drop a column from index and readd it with another type int Variation_15(); // @cmember NULL pointer for pTableID => E_INVALIDARG int Variation_16(); // @cmember *pTableID == DB_NULLID => DB_E_NOTABLE int Variation_17(); // @cmember pTableID->uName.pwszName is NULL => DB_E_NOTABLE int Variation_18(); // @cmember pTableID->uName.pwszName is empty => DB_E_NOTABLE int Variation_19(); // @cmember table name is invalid => DB_E_NOTABLE int Variation_20(); // @cmember table name has maximum length => S_OK int Variation_21(); // @cmember table name exceeds maximum table name => DB_E_NOTABLE int Variation_22(); // @cmember NULL pointer for pIndexID and not NULL ppIndexID => S_OK int Variation_23(); // @cmember not NULL pointer for pIndexID and NULL ppIndexID =>S_OK int Variation_24(); // @cmember NULL pointer for pIndexID and NULL ppIndexID => E_INVALIDARG int Variation_25(); // @cmember *pIndexID == DB_NULLID => DB_E_BADINDEXID int Variation_26(); // @cmember pIndexID->uName.pwszName is NULL => DB_E_BADINDEXID int Variation_27(); // @cmember pIndexID->uName.pwszName is empty => DB_E_BADINDEXID int Variation_28(); // @cmember index name is invalid => DB_E_BADINDEXID int Variation_29(); // @cmember index name has maximum length => S_OK int Variation_30(); // @cmember index name exceeds maximum length name => DB_E_BADINDEXID int Variation_31(); // @cmember cIndexColumnDesc == 0 => E_INVALIDARG int Variation_32(); // @cmember rgIndexColumnDesc == NULL => E_INVALIDARG int Variation_33(); // @cmember cPropSets != 0 and rgPropSets == NULL => E_INVALIDARG int Variation_34(); // @cmember cPropSets == 0 and rgPropSets == NULL =>S_OK int Variation_35(); // @cmember cProperties == 0 and rgProperties != NULL in a rgPropertySets element => S_OK int Variation_36(); // @cmember cProperties == 0 and rgProperties == NULL in an rgPropertySets element => S_OK int Variation_37(); // @cmember cProperties != 0 and rgProperties == NULL in an element of rgPropertySets => E_INVALIDARG int Variation_38(); // @cmember eIndexColumnDesc invalid for at least one column => E_INVALIDARG int Variation_39(); // @cmember the index is made of all columns int Variation_40(); // @cmember Try to create a duplicate index => DB_E_DUPLICATEINDEX int Variation_41(); // @cmember Create an index on a single column table int Variation_42(); // @cmember all indexes on a 2 columns table int Variation_43(); // @cmember pIndexID and ppIndexID both not NULL => S_OK int Variation_44(); // @cmember valid, yet inexistent table name => DB_E_NOTABLE int Variation_45(); // @cmember inexistent column name => DB_E_NOCOLUMN int Variation_46(); // @cmember all DBKIND on pTableID int Variation_47(); // @cmember all DBKIND on pColumnID int Variation_48(); // @cmember all DBKIND on pIndexID int Variation_49(); // @cmember NULL pColumnID in an element of rgIndexColumnDesc => DB_E_NOCOLUMN int Variation_50(); // @cmember DB_NULLID pColumnID in an element of rgIndexColumnDesc => DB_E_NOCOLUMN int Variation_51(); // @cmember empty name for a column in an element of rgIndexColumnDesc => DB_E_NOCOLUMN int Variation_52(); // @cmember NULL column name in an element of rgIndexColumnDesc => DB_E_NOCOLUMN int Variation_53(); // @cmember Set DBPROP_INDEX_AUTOUPDATE int Variation_54(); // @cmember Set DBPROP_INDEX_CLUSTERED int Variation_55(); // @cmember Set DBPROP_INDEX_NULLS int Variation_56(); // @cmember Set DBPROP_INDEX_PRIMARYKEY int Variation_57(); // @cmember Set DBPROP_INDEX_SORTBOOKMARKS int Variation_58(); // @cmember Set DBPROP_INDEX_TEMPINDEX int Variation_59(); // @cmember Set DBPROP_INDEX_TYPE int Variation_60(); // @cmember Set DBPROP_INDEX_UNIQUE int Variation_61(); // @cmember Set DBPROP_INDEX_FILLFACTOR int Variation_62(); // @cmember Set DBPROP_INDEX_INITIALSIZE int Variation_63(); // @cmember Set DBPROP_INDEX_NULLCOLLATION int Variation_64(); // @cmember Set DBPROP_INDEX_SORTBOOKMARKS and DBPROP_INDEX_UNIQUE int Variation_65(); // @cmember Set DBPROP_INDEX_UNIQUE and DBPROP_INDEX_PRIMARYKEY int Variation_66(); // @cmember Set DBPROP_INDEX_UNIQUE and DBPROP_INDEX_NULLS int Variation_67(); // @cmember CONFLICTING properties (set both DBPROP_INDEX_NULLS and DBPROP_INDEX_PRIMARYKEY) int Variation_68(); // @cmember Non index dwPropertyID int Variation_69(); // @cmember Non index guidPropertySet int Variation_70(); // @cmember invalid value type for property int Variation_71(); // @cmember invalid value for a property int Variation_72(); // @cmember specifying a property twice int Variation_73(); // @cmember all the properties int Variation_74(); // @cmember column name is invalid => DB_E_NOCOLUMN int Variation_75(); // @cmember maximum length column name => S_OK int Variation_76(); // @cmember too long column name => DB_E_NOCOLUMN int Variation_77(); // @cmember multithreading int Variation_78(); // @cmember 2 threads, the same index int Variation_79(); // @cmember Primary and clustered index properties int Variation_80(); // @cmember bogus colid in a non column specific index property int Variation_81(); // @cmember DB_NULLID passed as colid in a column specific index property int Variation_82(); // @cmember valid, non DB_NULLID colid in a column specific index property int Variation_83(); // @cmember bogus colid in a column specific index property => error int Variation_84(); // }} TCW_TESTVARS_END } ; // {{ TCW_TESTCASE(TCCreateIndex) #define THE_CLASS TCCreateIndex BEG_TEST_CASE(TCCreateIndex, TCIIndexDefinition, L"tests IIndexDefinition::CreateIndex() method") TEST_VARIATION(1, L"Check the session object") TEST_VARIATION(2, L"create an index on a a non-empty table => S_OK") TEST_VARIATION(3, L"create an index on an empty table => S_OK") TEST_VARIATION(4, L"create an index on a table created with a SQL command => S_OK") TEST_VARIATION(5, L"create an index and get an IRowsetIndex interface on it => S_OK") TEST_VARIATION(6, L"create an index on a table generated with ITableDefinition => S_OK") TEST_VARIATION(7, L"create an index on a table that has a rowset open on it => S_OK") TEST_VARIATION(8, L"create an index on a table using column names and colID's read from IColumnsInfo") TEST_VARIATION(9, L"include a column twice in an index") TEST_VARIATION(10, L"create an index on an autoincrement column => S_OK") TEST_VARIATION(11, L"create an index on a column, drop the column") TEST_VARIATION(12, L"create an index on a view") TEST_VARIATION(13, L"create multiple indexes on the same table") TEST_VARIATION(14, L"create an index on a table, drop the table and check if the index is dropped as well)") TEST_VARIATION(15, L"create an index on a table; drop a column from index and readd it with another type") TEST_VARIATION(16, L"NULL pointer for pTableID => E_INVALIDARG") TEST_VARIATION(17, L"*pTableID == DB_NULLID => DB_E_NOTABLE") TEST_VARIATION(18, L"pTableID->uName.pwszName is NULL => DB_E_NOTABLE") TEST_VARIATION(19, L"pTableID->uName.pwszName is empty => DB_E_NOTABLE") TEST_VARIATION(20, L"table name is invalid => DB_E_NOTABLE") TEST_VARIATION(21, L"table name has maximum length => S_OK") TEST_VARIATION(22, L"table name exceeds maximum table name => DB_E_NOTABLE") TEST_VARIATION(23, L"NULL pointer for pIndexID and not NULL ppIndexID => S_OK") TEST_VARIATION(24, L"not NULL pointer for pIndexID and NULL ppIndexID =>S_OK") TEST_VARIATION(25, L"NULL pointer for pIndexID and NULL ppIndexID => E_INVALIDARG") TEST_VARIATION(26, L"*pIndexID == DB_NULLID => DB_E_BADINDEXID") TEST_VARIATION(27, L"pIndexID->uName.pwszName is NULL => DB_E_BADINDEXID") TEST_VARIATION(28, L"pIndexID->uName.pwszName is empty => DB_E_BADINDEXID") TEST_VARIATION(29, L"index name is invalid => DB_E_BADINDEXID") TEST_VARIATION(30, L"index name has maximum length => S_OK") TEST_VARIATION(31, L"index name exceeds maximum length name => DB_E_BADINDEXID") TEST_VARIATION(32, L"cIndexColumnDesc == 0 => E_INVALIDARG") TEST_VARIATION(33, L"rgIndexColumnDesc == NULL => E_INVALIDARG") TEST_VARIATION(34, L"cPropSets != 0 and rgPropSets == NULL => E_INVALIDARG") TEST_VARIATION(35, L"cPropSets == 0 and rgPropSets == NULL =>S_OK") TEST_VARIATION(36, L"cProperties == 0 and rgProperties != NULL in a rgPropertySets element => S_OK") TEST_VARIATION(37, L"cProperties == 0 and rgProperties == NULL in an rgPropertySets element => S_OK") TEST_VARIATION(38, L"cProperties != 0 and rgProperties == NULL in an element of rgPropertySets => E_INVALIDARG") TEST_VARIATION(39, L"eIndexColumnDesc invalid for at least one column => E_INVALIDARG") TEST_VARIATION(40, L"the index is made of all columns") TEST_VARIATION(41, L"Try to create a duplicate index => DB_E_DUPLICATEINDEX") TEST_VARIATION(42, L"Create an index on a single column table") TEST_VARIATION(43, L"all indexes on a 2 columns table") TEST_VARIATION(44, L"pIndexID and ppIndexID both not NULL => S_OK") TEST_VARIATION(45, L"valid, yet inexistent table name => DB_E_NOTABLE") TEST_VARIATION(46, L"inexistent column name => DB_E_NOCOLUMN") TEST_VARIATION(47, L"all DBKIND on pTableID") TEST_VARIATION(48, L"all DBKIND on pColumnID") TEST_VARIATION(49, L"all DBKIND on pIndexID") TEST_VARIATION(50, L"NULL pColumnID in an element of rgIndexColumnDesc => DB_E_NOCOLUMN") TEST_VARIATION(51, L"DB_NULLID pColumnID in an element of rgIndexColumnDesc => DB_E_NOCOLUMN") TEST_VARIATION(52, L"empty name for a column in an element of rgIndexColumnDesc => DB_E_NOCOLUMN") TEST_VARIATION(53, L"NULL column name in an element of rgIndexColumnDesc => DB_E_NOCOLUMN") TEST_VARIATION(54, L"Set DBPROP_INDEX_AUTOUPDATE") TEST_VARIATION(55, L"Set DBPROP_INDEX_CLUSTERED") TEST_VARIATION(56, L"Set DBPROP_INDEX_NULLS") TEST_VARIATION(57, L"Set DBPROP_INDEX_PRIMARYKEY") TEST_VARIATION(58, L"Set DBPROP_INDEX_SORTBOOKMARKS") TEST_VARIATION(59, L"Set DBPROP_INDEX_TEMPINDEX") TEST_VARIATION(60, L"Set DBPROP_INDEX_TYPE") TEST_VARIATION(61, L"Set DBPROP_INDEX_UNIQUE") TEST_VARIATION(62, L"Set DBPROP_INDEX_FILLFACTOR") TEST_VARIATION(63, L"Set DBPROP_INDEX_INITIALSIZE") TEST_VARIATION(64, L"Set DBPROP_INDEX_NULLCOLLATION") TEST_VARIATION(65, L"Set DBPROP_INDEX_SORTBOOKMARKS and DBPROP_INDEX_UNIQUE") TEST_VARIATION(66, L"Set DBPROP_INDEX_UNIQUE and DBPROP_INDEX_PRIMARYKEY") TEST_VARIATION(67, L"Set DBPROP_INDEX_UNIQUE and DBPROP_INDEX_NULLS") TEST_VARIATION(68, L"CONFLICTING properties (set both DBPROP_INDEX_NULLS and DBPROP_INDEX_PRIMARYKEY)") TEST_VARIATION(69, L"Non index dwPropertyID") TEST_VARIATION(70, L"Non index guidPropertySet") TEST_VARIATION(71, L"invalid value type for property") TEST_VARIATION(72, L"invalid value for a property") TEST_VARIATION(73, L"specifying a property twice") TEST_VARIATION(74, L"all the properties") TEST_VARIATION(75, L"column name is invalid => DB_E_NOCOLUMN") TEST_VARIATION(76, L"maximum length column name => S_OK") TEST_VARIATION(77, L"too long column name => DB_E_NOCOLUMN") TEST_VARIATION(78, L"multithreading") TEST_VARIATION(79, L"2 threads, the same index") TEST_VARIATION(80, L"Primary and clustered index properties") TEST_VARIATION(81, L"bogus colid in a non column specific index property") TEST_VARIATION(82, L"DB_NULLID passed as colid in a column specific index property") TEST_VARIATION(83, L"valid, non DB_NULLID colid in a column specific index property") TEST_VARIATION(84, L"bogus colid in a column specific index property => error") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCDropIndex) //*----------------------------------------------------------------------- // @class tests IIndexDefinition::DropIndex() method // class TCDropIndex : public TCIIndexDefinition { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCDropIndex,TCIIndexDefinition); // }} TCW_DECLARE_FUNCS_END unsigned MyThreadProc(ULONG); friend unsigned WINAPI ThreadProc(LPVOID lpvThreadParam); // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember NULL pointer for pTableID => E_INVALIDARG int Variation_1(); // @cmember *pTableID == DB_NULLID => DB_E_NOTABLE int Variation_2(); // @cmember pTableID->uName is NULL => DB_E_NOTABLE int Variation_3(); // @cmember pTableID->uName is empty => DB_E_NOTABLE int Variation_4(); // @cmember invalid table name => DB_E_NOTABLE int Variation_5(); // @cmember maximum sized table name => S_OK int Variation_6(); // @cmember table name exceeds maximum size => DB_E_NOTABLE int Variation_7(); // @cmember NULL pointer for pIndexID => drop all indexes int Variation_8(); // @cmember *pIndexID == DB_NULLID => DB_E_NOINDEX int Variation_9(); // @cmember pIndexID->uName is NULL => DB_E_NOINDEX int Variation_10(); // @cmember pIndexID->uName is empty => DB_E_NOINDEX int Variation_11(); // @cmember invalid index name => DB_E_NOINDEX int Variation_12(); // @cmember maximum size index name => S_OK int Variation_13(); // @cmember oversized index name => DB_E_NOINDEX int Variation_14(); // @cmember drop an index twice => DB_E_NOINDEX int Variation_15(); // @cmember inexistent table => DB_E_NOTABLE int Variation_16(); // @cmember All DBKIND for pTableID int Variation_17(); // @cmember All DBKIND for pIndexID int Variation_18(); // @cmember index in use => DB_E_INDEXINUSE int Variation_19(); // @cmember multithreading int Variation_20(); // @cmember 2 threads, the same index int Variation_21(); // @cmember Inexistent index name int Variation_22(); // }} TCW_TESTVARS_END } ; // {{ TCW_TESTCASE(TCDropIndex) #define THE_CLASS TCDropIndex BEG_TEST_CASE(TCDropIndex, TCIIndexDefinition, L"tests IIndexDefinition::DropIndex() method") TEST_VARIATION(1, L"NULL pointer for pTableID => E_INVALIDARG") TEST_VARIATION(2, L"*pTableID == DB_NULLID => DB_E_NOTABLE") TEST_VARIATION(3, L"pTableID->uName is NULL => DB_E_NOTABLE") TEST_VARIATION(4, L"pTableID->uName is empty => DB_E_NOTABLE") TEST_VARIATION(5, L"invalid table name => DB_E_NOTABLE") TEST_VARIATION(6, L"maximum sized table name => S_OK") TEST_VARIATION(7, L"table name exceeds maximum size => DB_E_NOTABLE") TEST_VARIATION(8, L"NULL pointer for pIndexID => drop all indexes") TEST_VARIATION(9, L"*pIndexID == DB_NULLID => DB_E_NOINDEX") TEST_VARIATION(10, L"pIndexID->uName is NULL => DB_E_NOINDEX") TEST_VARIATION(11, L"pIndexID->uName is empty => DB_E_NOINDEX") TEST_VARIATION(12, L"invalid index name => DB_E_NOINDEX") TEST_VARIATION(13, L"maximum size index name => S_OK") TEST_VARIATION(14, L"oversized index name => DB_E_NOINDEX") TEST_VARIATION(15, L"drop an index twice => DB_E_NOINDEX") TEST_VARIATION(16, L"inexistent table => DB_E_NOTABLE") TEST_VARIATION(17, L"All DBKIND for pTableID") TEST_VARIATION(18, L"All DBKIND for pIndexID") TEST_VARIATION(19, L"index in use => DB_E_INDEXINUSE") TEST_VARIATION(20, L"multithreading") TEST_VARIATION(21, L"2 threads, the same index") TEST_VARIATION(22, L"Inexistent index name") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCTrans) //*----------------------------------------------------------------------- // @class transactions // class TCTrans : public TCIIndexDefinition { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); // start the transaction HRESULT StartTransaction(ITransactionLocal*); VARIANT m_vSupportedTxnDDL; DBINDEXCOLUMNDESC m_rgIndexColumnDesc[1]; public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCTrans,TCIIndexDefinition); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember Abort retaining on CreateIndex int Variation_1(); // @cmember Abort non retaining on CreateIndex int Variation_2(); // @cmember Commit retain on CreateIndex int Variation_3(); // @cmember Commit non-retain on CreateIndex int Variation_4(); // @cmember Abort retain on DropIndex int Variation_5(); // @cmember Abort non-retain on DropIndex int Variation_6(); // @cmember Commit retain on DropIndex int Variation_7(); // @cmember Commit non retain on DropIndex int Variation_8(); // }} TCW_TESTVARS_END } ; // {{ TCW_TESTCASE(TCTrans) #define THE_CLASS TCTrans BEG_TEST_CASE(TCTrans, TCIIndexDefinition, L"transactions") TEST_VARIATION(1, L"Abort retaining on CreateIndex") TEST_VARIATION(2, L"Abort non retaining on CreateIndex") TEST_VARIATION(3, L"Commit retain on CreateIndex") TEST_VARIATION(4, L"Commit non-retain on CreateIndex") TEST_VARIATION(5, L"Abort retain on DropIndex") TEST_VARIATION(6, L"Abort non-retain on DropIndex") TEST_VARIATION(7, L"Commit retain on DropIndex") TEST_VARIATION(8, L"Commit non retain on DropIndex") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END // {{ TCW_TEST_CASE_MAP(TCRODataSource) //*----------------------------------------------------------------------- // @class read only data source // class TCRODataSource : public TCIIndexDefinition { private: // @cmember Static array of variations DECLARE_TEST_CASE_DATA(); IUnknown *m_pIUnknown, *m_pIUnknown2; DBID *m_pIndexID; IIndexDefinition *m_pIIndexDefinition2; public: // {{ TCW_DECLARE_FUNCS // @cmember Execution Routine DECLARE_TEST_CASE_FUNCS(TCRODataSource,TCIIndexDefinition); // }} TCW_DECLARE_FUNCS_END // @cmember Initialization Routine virtual BOOL Init(); // @cmember Termination Routine virtual BOOL Terminate(); // {{ TCW_TESTVARS() // @cmember try to create an index on a read only datasource int Variation_1(); // }} TCW_TESTVARS_END } ; // {{ TCW_TESTCASE(TCRODataSource) #define THE_CLASS TCRODataSource BEG_TEST_CASE(TCRODataSource, TCIIndexDefinition, L"read only data source") TEST_VARIATION(1, L"try to create an index on a read only datasource") END_TEST_CASE() #undef THE_CLASS // }} TCW_TESTCASE_END // }} TCW_TEST_CASE_MAP_END //-------------------------------------------------------------------- // @func Module level initialization routine // // @rdesc Success or Failure // @flag TRUE | Successful initialization // @flag FALSE | Initialization problems // BOOL ModuleInit(CThisTestModule * pThisTestModule) { IIndexDefinition *pIIndexDefinition = NULL; if (!pThisTestModule) return FALSE; //Create the session if(!ModuleCreateDBSession(pThisTestModule)) return FALSE; if (!VerifyInterface( pThisTestModule->m_pIUnknown2, IID_IIndexDefinition, SESSION_INTERFACE, (IUnknown**)&pIIndexDefinition)) { odtLog << TEXT("IIndexDefinition is not supported; test module skipped!\n"); return TEST_SKIPPED; } // external g_pIDBInitialize is to be used with Extralib if (!(VerifyInterface(pThisTestModule->m_pIUnknown, IID_IDBInitialize, DATASOURCE_INTERFACE, (IUnknown**)&g_pIDBInitialize))) { odtLog << "IDBInitialize not supported!\n"; return TEST_SKIPPED; } SAFE_RELEASE(pIIndexDefinition); return TRUE; } //-------------------------------------------------------------------- // @func Module level termination routine // // @rdesc Success or Failure // @flag TRUE | Successful initialization // @flag FALSE | Initialization problems // BOOL ModuleTerminate(CThisTestModule * pThisTestModule) { SAFE_RELEASE(g_pIDBInitialize); return ModuleReleaseDBSession(pThisTestModule); } //------------------------------------------------------------------------- // // @cmember Check whether the property sets asked for rowset was preserved // all the data should be inside, the only thing that is allowed to be modified // is the property status //------------------------------------------------------------------------- BOOL IsPropSetPreserved ( DBPROPSET *rgInPropertySets, // the array passed to IIndexDefinition::CreateIndex DBPROPSET *rgOutPropertySets, // the aray returned by IIndexDefinition::CreateIndex ULONG cPropertySets // the size of the arrays ) { ULONG ps, pc; HRESULT hr; for (ps=0; psdwOptions && DBPROPSTATUS_OK != pProp->dwStatus) fRes = CHECK(FAILED(hr), TRUE); if (!(guidPropertySet == DBPROPSET_INDEX)) { // check a couple of things and returns return COMPARE(pProp->dwStatus, DBPROPSTATUS_NOTSUPPORTED) && COMPARE(S_OK != hr, TRUE); } fSupported = SupportedProperty(pProp->dwPropertyID, guidPropertySet); fSettable = SettableProperty(pProp->dwPropertyID, guidPropertySet); if (!fSupported && !CHECK(S_OK != hr, TRUE)) fRes = FALSE; // status driven checking switch (pProp->dwStatus) { case DBPROPSTATUS_OK: fRes = COMPARE(fSupported != 0, TRUE); break; case DBPROPSTATUS_NOTSUPPORTED: fRes = COMPARE(fSupported == 0, TRUE); break; case DBPROPSTATUS_NOTSETTABLE: fRes = COMPARE(fSupported != 0, TRUE) && COMPARE(fSettable == 0, TRUE); break; case DBPROPSTATUS_BADOPTION: fRes = (pProp->dwOptions != DBPROPOPTIONS_OPTIONAL) && COMPARE(DBPROPOPTIONS_REQUIRED != pProp->dwOptions, TRUE); break; case DBPROPSTATUS_CONFLICTING: fRes = COMPARE(fSettable != 0, TRUE); break; case DBPROPSTATUS_BADVALUE: fRes = COMPARE(fSupported != 0, TRUE); break; default: break; } // DBPROPSTATUS_BADVALUE can be certainly got only if type of the prop is wrong // info about supported discret values of the prop cannot generally be obtained // before creating an index if ( GetPropInfoType(pProp->dwPropertyID, guidPropertySet) != pProp->vValue.vt && !COMPARE(DBPROPSTATUS_OK == pProp->dwStatus, FALSE)) { odtLog << "ERROR: bad propstatus on improper type value on property" << pProp->dwPropertyID << "\n"; fRes = FALSE; } return fRes; } //CheckProperty /////////////////////////////////////////////////////////////////////////////////// // // // class CIIndexDefinition // // /////////////////////////////////////////////////////////////////////////////////// CIIndexDefinition::CIIndexDefinition(IIndexDefinition *pIIndexDefinition) { // interface passed is released in the destructor IGetDataSource *pIGetDSO = NULL; ASSERT(pIIndexDefinition); m_pIIndexDefinition = pIIndexDefinition; if (COMPARE(VerifyInterface(m_pIIndexDefinition, IID_IGetDataSource, SESSION_INTERFACE, (IUnknown**)&pIGetDSO), TRUE)) { CHECK(pIGetDSO->GetDataSource(IID_IUnknown, &m_pIDSOUnknown), S_OK); } SAFE_RELEASE(pIGetDSO); } //CIIndexDefinition::CIIndexDefinition CIIndexDefinition::CIIndexDefinition(IUnknown *pISessionUnknown) { // interface passed is NOT released in the destructor; it should be released by user IGetDataSource *pIGetDSO = NULL; ASSERT(pISessionUnknown); COMPARE(VerifyInterface(pISessionUnknown, IID_IIndexDefinition, SESSION_INTERFACE, (IUnknown**)&m_pIIndexDefinition), TRUE); if (COMPARE(VerifyInterface(pISessionUnknown, IID_IGetDataSource, SESSION_INTERFACE, (IUnknown**)&pIGetDSO), TRUE)) { CHECK(pIGetDSO->GetDataSource(IID_IUnknown, &m_pIDSOUnknown), S_OK); } SAFE_RELEASE(pIGetDSO); } //CIIndexDefinition::CIIndexDefinition // basic methods for index manipulation HRESULT CIIndexDefinition::CreateIndex( DBID *pTableID, // [in] the ID of the table DBID *pIndexID, // [in] the ID of the index DBORDINAL nIndexSize, // [in] index size (no of columns) DBINDEXCOLUMNDESC *rgIndexColumnDesc, // [in] columns to be part of index ULONG cPropSets, // [in] count of property sets DBPROPSET *rgPropSets, // [in] array of property sets DBID **ppIndexID // [in/out] stores output ptr to IndexID ) { HRESULT hr; HRESULT rgValidRes[] = { S_OK, DB_S_ERRORSOCCURRED, DB_E_TABLEINUSE, E_FAIL, E_INVALIDARG, DB_E_BADINDEXID, DB_E_DUPLICATEINDEXID, DB_E_ERRORSOCCURRED, DB_E_NOCOLUMN, DB_E_NOTABLE, DB_SEC_E_PERMISSIONDENIED, }; ULONG cValidRes = NUMELEM(rgValidRes); // create the index according the requirements hr = m_pIIndexDefinition->CreateIndex( pTableID, pIndexID, nIndexSize, rgIndexColumnDesc, cPropSets, rgPropSets, ppIndexID); COMPARE(CheckResult(hr, cValidRes, rgValidRes), TRUE); return hr; } // CIIndexDefinition::CreateIndex HRESULT CIIndexDefinition::DropIndex( DBID *pTableID, // [in] the ID of the table DBID *pIndexID // [in] the ID of the index ) { HRESULT hr = E_FAIL; HRESULT rgValidRes[] = { S_OK, DB_S_ERRORSOCCURRED, E_FAIL, E_INVALIDARG, DB_E_ERRORSOCCURRED, DB_E_INDEXINUSE, DB_E_NOINDEX, DB_E_NOTABLE, DB_E_TABLEINUSE, DB_SEC_E_PERMISSIONDENIED, }; ULONG cValidRes = NUMELEM(rgValidRes); BOOL fIndexExists = FALSE; if (pIndexID && pTableID) CHECK(DoesIndexExist(pTableID, pIndexID, &fIndexExists), S_OK); hr = m_pIIndexDefinition->DropIndex(pTableID, pIndexID); COMPARE(CheckResult(hr, cValidRes, rgValidRes), TRUE); switch (hr) { case S_OK: if ( pIndexID && COMPARE(fIndexExists, TRUE) && CHECK(DoesIndexExist(pTableID, pIndexID, &fIndexExists), S_OK)) COMPARE(fIndexExists, FALSE); break; case E_INVALIDARG: // Note: some provider will not support dropping all indexes COMPARE((NULL == pTableID) || (NULL == pIndexID), TRUE); break; case DB_S_ERRORSOCCURRED: case DB_E_ERRORSOCCURRED: COMPARE(NULL != pTableID, TRUE); COMPARE(NULL == pIndexID, TRUE); break; case DB_E_NOINDEX: COMPARE(fIndexExists, FALSE); break; case DB_E_NOTABLE: { BOOL fTableExists = FALSE; CTable Table(m_pIIndexDefinition, (LPWSTR)gwszModuleName); if ( COMPARE(NULL != pTableID, TRUE) && CHECK(Table.DoesTableExist(pTableID, &fTableExists), S_OK)) COMPARE(fTableExists, FALSE); } break; case DB_E_INDEXINUSE: case DB_E_TABLEINUSE: case DB_SEC_E_PERMISSIONDENIED: COMPARE(NULL != pTableID, TRUE); COMPARE(!pIndexID || fIndexExists, TRUE); break; default: break; } return hr; } //CIIndexDefinition::DropIndex // helper methods HRESULT CIIndexDefinition::CreateIndexAndCheck( DBID *pTableID, // [in] the ID of the table DBID *pIndexID, // [in] the ID of the index DBORDINAL nIndexSize, // [in] index size (no of columns) DBINDEXCOLUMNDESC *rgIndexColumnDesc, // [in] columns to be part of index ULONG cPropSets, // [in] count of property sets DBPROPSET *rgPropSets, // [in] array of property sets DBID **ppIndexID // [in/out] stores output ptr to IndexID ) { DBID *pNewIndexID = NULL; // DBID of the newly created index DBPROPSET *rgPropSets1 = NULL; // saves the property sets HRESULT hres; BOOL fExists; BOOL fIndexAlreadyExists = FALSE;; ULONG nIndexPropSet; ULONG nIndexProp; DBPROP *pProp; // save the array of property sets, as asked DuplicatePropertySets(cPropSets, rgPropSets, &cPropSets, &rgPropSets1); if (ppIndexID) *ppIndexID = NULL; if (pIndexID && CHECK(DoesIndexExist(pTableID, pIndexID, &fExists), S_OK) && fExists) fIndexAlreadyExists = TRUE; // create the index according the requirements hres = CreateIndex(pTableID, pIndexID, nIndexSize, rgIndexColumnDesc, cPropSets, rgPropSets, ppIndexID); // get an DBID of the index if ((NULL != pIndexID) || (NULL != ppIndexID)) pNewIndexID = pIndexID? pIndexID: *ppIndexID; else { CHECK(hres, E_INVALIDARG); goto CLEANUP; } // check index property status if (rgPropSets) { for (nIndexPropSet=0; nIndexPropSet < cPropSets; nIndexPropSet++) { pProp = rgPropSets[nIndexPropSet].rgProperties; if (!pProp) continue; for (nIndexProp=0; nIndexProp < rgPropSets[nIndexPropSet].cProperties; nIndexProp++) { CheckProperty(rgPropSets[nIndexPropSet].guidPropertySet, &pProp[nIndexProp], hres); } } } if (SUCCEEDED(hres)) { if (!COMPARE(fIndexAlreadyExists, FALSE)) { odtLog << "ERROR: success in creating an already existing index\n"; goto CLEANUP; } // the index is reported to be created, check it thoroughfully if ( NULL == pNewIndexID || !CHECK(DoesIndexExist(pTableID, pNewIndexID, &fExists), S_OK) || !COMPARE(fExists, TRUE) ) { odtLog << "ERROR: the method succeeded, but the index was not created or ppIndexID was not created!\n"; } else { // check the columns, their collation and the index properties on // IDBSchemaRowset or IRowsetIndex if (!COMPARE(CheckIndex(pTableID, pNewIndexID, nIndexSize, rgIndexColumnDesc, cPropSets, rgPropSets), TRUE)) { odtLog << "ERROR: the index was not properly created!\n"; } // check the properties as returned if (!(IsPropSetPreserved(rgPropSets1, rgPropSets, cPropSets))) { odtLog << "ERROR: properties are not preserved!\n"; } } // compare *pIndexID and **ppIndexID if (!CheckReturnedDBID(pIndexID, ppIndexID)) { odtLog << "the returned IndexID was not created ok!\n"; } } else { // failed to create the index if (!pIndexID && DB_E_DUPLICATEINDEXID == hres) { odtLog << "ERROR: DB_E_DUPLICATEINDEXID return on a NULL pIndexID!\n"; COMPARE(TRUE, FALSE); } // check that the index is not created if ( !fIndexAlreadyExists && NULL != pNewIndexID && CHECK(DoesIndexExist(pTableID, pNewIndexID, &fExists), S_OK) && !COMPARE(fExists, FALSE)) { odtLog << "ERROR: the method failed, but the index was created!\n"; CHECK(m_pIIndexDefinition->DropIndex(pTableID, pNewIndexID), S_OK); } // should not allocate memory for the index ID if (ppIndexID && !COMPARE(NULL == *ppIndexID, TRUE)) { odtLog << "ERROR: the index was not created, but *ppIndexID was returned not null!\n"; ReleaseDBID(*ppIndexID); *ppIndexID = NULL; } } CLEANUP: // release the old properties FreeProperties( &cPropSets, &rgPropSets1); return hres; } //CIIndexDefinition::CreateIndexAndCheck HRESULT CIIndexDefinition::CreateCheckAndDropIndex( DBID *pTableID, // [in] the ID of the table DBID *pIndexID, // [in] the ID of the index DBORDINAL nIndexSize, // [in] index size (no of columns) DBINDEXCOLUMNDESC *rgIndexColumnDesc, // [in] columns to be part of index ULONG cPropSets, // [in] count of property sets DBPROPSET *rgPropSets // [in] array of property sets ) { CDBIDPtr pOutIndexID; HRESULT hr = E_FAIL; BOOL fExists; hr = CreateIndexAndCheck(pTableID, pIndexID, nIndexSize, rgIndexColumnDesc, cPropSets, rgPropSets, (DBID**)pOutIndexID); if (E_FAIL == hr || NULL == (DBID*)pOutIndexID) goto CLEANUP; // check that the index is not created if ( CHECK(DoesIndexExist(pTableID, pOutIndexID, &fExists), S_OK) && fExists) CHECK(DropIndex(pTableID, pOutIndexID), S_OK); CLEANUP: // ReleaseDBID(&pOutIndexID); return hr; } //CIIndexDefinition::CreateCheckAndDropIndex // Check whether the index is created and property settings BOOL CIIndexDefinition::CheckIndex( DBID *pTableID, // the index of the table DBID *pIndexID, // the index to be checked DBORDINAL cIndexColumnDesc, // how many elements DBINDEXCOLUMNDESC *rgIndexColumnDesc, // array with index original descriprion ULONG cPropertySets, // number of property sets DBPROPSET *rgPropertySets // the array of property sets ) { return (!s_fIRowsetIndex || CheckIndexUsingIRowsetIndex(pTableID, pIndexID, cIndexColumnDesc, rgIndexColumnDesc, cPropertySets, rgPropertySets)) && CheckIndexUsingIDBSchemaRowset(pTableID, pIndexID, cIndexColumnDesc, rgIndexColumnDesc, cPropertySets, rgPropertySets); } //CIIndexDefinition::CheckIndex // Sets/Resets the nullibility of each column in the table. BOOL TCIIndexDefinition::MakeColsNullable( CTable *pTable, BOOL bNullable ) { CList *pColList; POSITION Pos; pColList = pTable->GetColList(); Pos = pColList->GetHeadPosition(); while(Pos) { CCol &rCol = pColList->GetNext(Pos); rCol.SetNullable( bNullable ); } return TRUE; } // TCIIndexDefinition::MakeColsNullable BOOL CIIndexDefinition::CheckIndexUsingIRowsetIndex( DBID *pTableID, // the index of the table DBID *pIndexID, // the index to be checked DBORDINAL cIndexColumnDesc, // how many elements DBINDEXCOLUMNDESC *rgIndexColumnDesc, // array with index original descriprion ULONG cPropertySets, // number of property sets DBPROPSET *rgPropertySets // the array of property sets ) { TBEGIN IRowsetIndex *pIRowsetIndex = NULL; ULONG i; DBORDINAL cColumns = 0; ULONG cIndexPropSets=0, nPropSet, nProp; DBINDEXCOLUMNDESC *rgOutIndexColumnDesc = NULL; DBPROPSET *rgIndexPropSets = NULL; BOOL fResult = TRUE, fProp=TRUE; DBPROP *pProp=NULL; DBPROPSTATUS dwStatus; VARIANT *pvValue; DBPROPID dwPropID; IOpenRowset *pIOpenRowset = NULL; HRESULT hr; TESTC(VerifyInterface(m_pIIndexDefinition, IID_IOpenRowset, SESSION_INTERFACE, (IUnknown**)&pIOpenRowset)); TEST2C_(hr = pIOpenRowset->OpenRowset(NULL, pTableID, pIndexID, IID_IRowsetIndex, 0, NULL, (IUnknown**)&pIRowsetIndex), S_OK, E_NOINTERFACE); if (S_OK != hr) goto CLEANUP; // use IRowsetIndex->GetIndexInfo to check how the index was set TESTC_(pIRowsetIndex->GetIndexInfo(&cColumns, &rgOutIndexColumnDesc, &cIndexPropSets, &rgIndexPropSets), S_OK); TESTC(cColumns == cIndexColumnDesc); for (i=0; iuName.pwszName << "\n"; goto CLEANUP; } // this is based on the assumption that DBID returned for columns are in the same // format as they were input // otherwise one have to use a complete description of the columns in the table and make the conversion if (!COMPARE(CompareDBID(*rgIndexColumnDesc[i].pColumnID, *rgOutIndexColumnDesc[i].pColumnID, m_pIDSOUnknown), TRUE)) { odtLog << "column ID different for column " << rgIndexColumnDesc[i].pColumnID->uName.pwszName << "\n"; goto CLEANUP; } } if (!rgPropertySets) goto CLEANUP; for (nPropSet=0; nPropSetvValue, pvValue), TRUE); } } CLEANUP: SAFE_RELEASE(pIRowsetIndex); SAFE_RELEASE(pIOpenRowset); TRETURN } //CIIndexDefinition::CheckIndexUsingIRowsetIndex //-------------------------------------------------------------------------- // // @cmember Read the value of a column in the indexe schema rowset // // RETURNS FALSE if the value was read and differ than the original one //-------------------------------------------------------------------------- BOOL CIIndexDefinition::GetIndexValueFromFirstRow( LPVOID pVariable, // [OUT] value read BOOL *pfSet, // [OUT] if the value is set DBBINDING *rgDBBINDING, // [IN] binding array ULONG cColumn, // [IN] column to be read ULONG ulDBTYPE, // [IN] type of property variant BYTE *pData, // [IN] pointer to read DATA stru DBPROPID PropID, // [IN] property that is being read ULONG cPropSets, // [IN] number of property sets DBPROPSET *rgPropSets, // [IN] array of property sets WCHAR *lpwszMesaj // [IN] message text for error ) { BOOL fRes = TRUE; DBPROP *pProp = NULL;; TESTC(NULL != pfSet); *pfSet = FALSE; FindProperty(PropID, DBPROPSET_INDEX, cPropSets, rgPropSets, &pProp); if (!pProp) goto CLEANUP; // get the variable value switch (ulDBTYPE) { case DBTYPE_BOOL: *(VARIANT_BOOL*)pVariable = V_BOOL(&pProp->vValue); break; case DBTYPE_I4: *(LONG*)pVariable = V_I4(&pProp->vValue); break; case DBTYPE_UI2: *(unsigned short*)pVariable = V_UI2(&pProp->vValue); break; case DBTYPE_I2: *(SHORT*)pVariable = V_I2(&pProp->vValue); break; default: TESTC(FALSE); } *pfSet = (DBPROPSTATUS_OK == pProp->dwStatus); CLEANUP: fRes = GetIndexValue(pVariable, pfSet, rgDBBINDING, cColumn, ulDBTYPE, pData, lpwszMesaj); if (DBPROP_INDEX_FILLFACTOR == PropID && fProperRangeForFillFactor) { if (!COMPARE(0 <= *(LONG*)pVariable && *(LONG*)pVariable <= 100, TRUE)) fProperRangeForFillFactor = FALSE; } return fRes; } //CIIndexDefinition::GetIndexValueFromFirstRow //-------------------------------------------------------------------------- // // @cmember Read the value of a column in the index schema rowset // // if *pfSet is TRUE then there is a coparison value for the value read, // otherwise the new value will be used for further comparisons => save // it in *pVariable and set *pfSet to TRUE // RETURNS FALSE if the value was read and differ than the original one //-------------------------------------------------------------------------- BOOL CIIndexDefinition::GetIndexValue( LPVOID pVariable, // [OUT] value read BOOL *pfSet, // [OUT] if the value is set DBBINDING *rgDBBINDING, // [IN] binding array ULONG cColumn, // [IN] column to be read ULONG ulDBTYPE, // [IN] type of property variant BYTE *pData, // [IN] pointer to read DATA stru WCHAR *lpwszMesaj // [IN] message text for error ) { BOOL fRes = FALSE; BOOL fWStrComp = FALSE; DATA *pColumn = NULL; TESTC(NULL != pData); TESTC(NULL != rgDBBINDING); TESTC(NULL != pVariable); TESTC(NULL != pfSet); fRes = TRUE; // get the status of the read property value pColumn = (DATA*) (pData+rgDBBINDING[cColumn].obStatus); if (DBSTATUS_S_OK == pColumn->sStatus) { // get the value in pVariable switch (ulDBTYPE) { case DBTYPE_I4: if (!*pfSet) { *(LONG*)pVariable = *(LONG*)(&(pColumn->bValue)); *pfSet = TRUE; } else fRes = (*(LONG*)(&(pColumn->bValue)) == *(LONG*)pVariable); break; case DBTYPE_UI2: if (!*pfSet) { *(unsigned short*)pVariable = *(unsigned short*)(&(pColumn->bValue)); *pfSet = TRUE; } else fRes = (*(unsigned short*)(&(pColumn->bValue)) == *(unsigned short*)pVariable); break; case DBTYPE_I2: if (!*pfSet) { *(SHORT*)pVariable = *(SHORT*)(&(pColumn->bValue)); *pfSet = TRUE; } else fRes = (*(SHORT*)(&(pColumn->bValue)) == *(SHORT*)pVariable); break; case DBTYPE_BOOL: if (!*pfSet) { *(VARIANT_BOOL*)pVariable = *(VARIANT_BOOL*)(&(pColumn->bValue)); *pfSet = TRUE; } else fRes = (*(VARIANT_BOOL*)(&(pColumn->bValue)) == *(VARIANT_BOOL*)pVariable); break; case DBTYPE_WSTR: if (!*pfSet) { TESTC(NULL != *(WCHAR**)pVariable); // release the memory is wrongfully passed if (!*(WCHAR*)pVariable) SAFE_FREE(*(WCHAR**)pVariable); // set the variable *(WCHAR**)pVariable = wcsDuplicate(*(WCHAR**)(&(pColumn->bValue))); *pfSet = TRUE; } else // compare fRes = (NULL != *(WCHAR**)pVariable) && S_OK == CompareID(&fWStrComp, *(WCHAR**)pVariable, (WCHAR*)(&(pColumn->bValue)), m_pIDSOUnknown) && fWStrComp; break; default: ASSERT(FALSE); break; } if (!fRes) odtLog << lpwszMesaj; } CLEANUP: return fRes; } // CIIndexDefinition::GetIndexValue BOOL CIIndexDefinition::CheckIndexUsingIDBSchemaRowset( DBID *pTableID, // the index of the table DBID *pIndexID, // the index to be checked DBORDINAL cIndexColumnDesc, // how many elements DBINDEXCOLUMNDESC *rgIndexColumnDesc, // array with index original descriprion ULONG cPropertySets, // number of property sets DBPROPSET *rgPropertySets // the array of property sets ) { TBEGIN HRESULT hr = E_FAIL; BOOL bIsSchemaSupported; DBLENGTH ulRowSize = 0; // size of row DBCOUNTITEM cDBBINDING = 0; // count of bindings DBORDINAL iRow = 0; // count of rows DBCOUNTITEM cRowsObtained = 0; // number of rows returned, should be 1 ULONG cSchema = 0; // number of supported Schemas ULONG *prgRestrictions= 0; // restrictions for each Schema GUID *prgSchemas = NULL; // array of GUIDs HROW hRow; // handler of rows HROW *phRow = &hRow; // pointer to handler IRowset *pIndexRowset = NULL; // returned rowset DBBINDING *rgDBBINDING = NULL; // array of bindings BYTE *pData = NULL; // pointer to data HACCESSOR hAccessor = NULL; // accessor BOOL *rgColPresent = NULL; const int cRest = 5; VARIANT rgRestrictIndexes[cRest]; ULONG i, index; ULONG nColPresent=0; ULONG nTABLE_NAME = 2; ULONG nINDEX_NAME = 5; ULONG nPRIMARY_KEY = 6; ULONG nUNIQUE = 7; ULONG nCLUSTERED = 8; ULONG nTYPE = 9; ULONG nFILL_FACTOR = 10; ULONG nINITIAL_SIZE = 11; ULONG nNULLS = 12; ULONG nSORT_BOOKMARKS = 13; ULONG nAUTO_UPDATE = 14; ULONG nNULL_COLLATION = 15; ULONG nORDINAL_POSITION = 16; ULONG nCOLUMN_NAME = 17; ULONG nCOLLATION = 20; // column entries in index schema rowset and their presence flags LPWSTR pwszIndexName = NULL; BOOL fIndexName = FALSE; LPWSTR pwszTableName = NULL; BOOL fTableName = FALSE; VARIANT_BOOL vbAutoUpdate; BOOL fAutoUpdate = FALSE; VARIANT_BOOL vbClustered; BOOL fClustered = FALSE; LONG lFillFactor; BOOL fFillFactor = FALSE; LONG lInitialSize; BOOL fInitialSize = FALSE; LONG lNullCollation; BOOL fNullCollation = FALSE; unsigned short uiOrdinalPosition; BOOL fOrdinalPosition; SHORT iCollation; BOOL fCollation = FALSE; LPWSTR pwszColumnName = NULL; BOOL fColumnName = FALSE; LONG lNulls; BOOL fNulls = FALSE; VARIANT_BOOL vbPrimaryKey; BOOL fPrimaryKey = FALSE; VARIANT_BOOL vbSortBookmarks; BOOL fSortBookmarks = FALSE; unsigned short usType; BOOL fType = FALSE; VARIANT_BOOL vbUnique; BOOL fUnique = FALSE; IDBSchemaRowset *pIDBSchemaRowset = NULL; // Set restrictions for(index=0;indexGetSchemas(&cSchema, &prgSchemas, &prgRestrictions),S_OK); ASSERT(NULL != pIndexID); ASSERT(NULL != pTableID); if (DBKIND_NAME == pIndexID->eKind) { pwszIndexName = wcsDuplicate(pIndexID->uName.pwszName); fIndexName = TRUE; } if (DBKIND_NAME == pTableID->eKind) { pwszTableName = wcsDuplicate(pTableID->uName.pwszName); fTableName = TRUE; } // Check to see if DBSCHEMA_INDEXES is supported for(i=0, bIsSchemaSupported=FALSE; iuName.pwszName); rgRestrictIndexes[4].vt = VT_BSTR; rgRestrictIndexes[4].bstrVal = SysAllocString(pTableID->uName.pwszName); SAFE_ALLOC(rgColPresent, BOOL, cIndexColumnDesc); for (i=0; iGetRowset( NULL, // aggregation DBSCHEMA_INDEXES, // REFGUID cRest, // count of restrictions (1:types) rgRestrictIndexes, // list of restrictions IID_IRowset, // REFFID 0, // count of properties NULL, // range of properties (IUnknown**)&pIndexRowset // returned result set ),S_OK); TESTC_(hr = GetAccessorAndBindings( pIndexRowset, DBACCESSOR_ROWDATA, &hAccessor, &rgDBBINDING, &cDBBINDING, &ulRowSize, DBPART_VALUE |DBPART_STATUS |DBPART_LENGTH, ALL_COLS_EXCEPTBOOKMARK, FORWARD, NO_COLS_BY_REF, NULL, // OUT: Array of DBCOLUMNINFOs 0, // OUT: Count of DBCOULMNINFOs NULL, //&pStringsBuffer, DBTYPE_EMPTY, 0, NULL),S_OK); SAFE_ALLOC(pData, BYTE, ulRowSize); //data // read the first row, check local data and initialize variables TESTC_(hr=pIndexRowset->GetNextRows(0, 0, 1, &cRowsObtained, &phRow), S_OK); TESTC_((long)cRowsObtained, 1); TESTC_(hr=pIndexRowset->GetData(hRow, hAccessor, pData),S_OK); // get the first values and verifications COMPARE(GetIndexValue(&pwszIndexName, &fIndexName, rgDBBINDING, nINDEX_NAME, DBTYPE_WSTR, pData, L"ERROR: Bad index name\n"), TRUE); COMPARE(GetIndexValue(&pwszTableName, &fTableName, rgDBBINDING, nTABLE_NAME, DBTYPE_WSTR, pData, L"ERROR: Bad table name\n"), TRUE); // check column ordinal position of the first column in the index (1 is the first value) and name fOrdinalPosition = FALSE; COMPARE(GetIndexValue(&uiOrdinalPosition, &fOrdinalPosition, rgDBBINDING, nORDINAL_POSITION, DBTYPE_UI2, pData, L"ERROR: OrdinalPosition\n"), TRUE); if (fOrdinalPosition) { TESTC(cIndexColumnDesc >= uiOrdinalPosition); DBID *pColumnID = rgIndexColumnDesc[uiOrdinalPosition-1].pColumnID; // can compare both column name and collation order TESTC(NULL != pColumnID); fColumnName = TRUE; switch (pColumnID->eKind) { case DBKIND_NAME: pwszColumnName = wcsDuplicate(pColumnID->uName.pwszName); COMPARE(GetIndexValue(&pwszColumnName, &fColumnName, rgDBBINDING, nCOLUMN_NAME, DBTYPE_WSTR, pData, L"ERROR: Column name\n"), TRUE); SAFE_FREE(pwszColumnName); break; } fCollation = TRUE; iCollation = (short)((DBINDEX_COL_ORDER_ASC == rgIndexColumnDesc[uiOrdinalPosition-1].eIndexColOrder) ? DB_COLLATION_ASC: DB_COLLATION_DESC); COMPARE(GetIndexValue(&iCollation, &fCollation, rgDBBINDING, nCOLLATION, DBTYPE_I2, pData, L"ERROR: Collation\n"), TRUE); rgColPresent[uiOrdinalPosition-1] = TRUE; nColPresent++; } if (cPropertySets > 0 && rgPropertySets) { COMPARE(GetIndexValueFromFirstRow(&vbAutoUpdate, &fAutoUpdate, rgDBBINDING, nAUTO_UPDATE, DBTYPE_BOOL, pData, DBPROP_INDEX_AUTOUPDATE, cPropertySets, rgPropertySets, L"ERROR: Auto update\n"), TRUE); COMPARE(GetIndexValueFromFirstRow(&vbClustered, &fClustered, rgDBBINDING, nCLUSTERED, DBTYPE_BOOL, pData, DBPROP_INDEX_CLUSTERED, cPropertySets, rgPropertySets, L"ERROR: Clustered\n"), TRUE); COMPARE(GetIndexValueFromFirstRow(&lFillFactor, &fFillFactor, rgDBBINDING, nFILL_FACTOR, DBTYPE_I4, pData, DBPROP_INDEX_FILLFACTOR, cPropertySets, rgPropertySets, L"ERROR: Fill factor\n"), TRUE); COMPARE(GetIndexValueFromFirstRow(&lInitialSize, &fInitialSize, rgDBBINDING, nINITIAL_SIZE, DBTYPE_I4, pData, DBPROP_INDEX_INITIALSIZE, cPropertySets, rgPropertySets, L"ERROR: Initial Size\n"), TRUE); COMPARE(GetIndexValueFromFirstRow(&lNullCollation, &fNullCollation, rgDBBINDING, nNULL_COLLATION, DBTYPE_I4, pData, DBPROP_INDEX_NULLCOLLATION, cPropertySets, rgPropertySets, L"ERROR: Null Collation\n"), TRUE); COMPARE(GetIndexValueFromFirstRow(&lNulls, &fNulls, rgDBBINDING, nNULLS, DBTYPE_I4, pData, DBPROP_INDEX_NULLS, cPropertySets, rgPropertySets, L"ERROR: Nulls\n"), TRUE); COMPARE(GetIndexValueFromFirstRow(&vbPrimaryKey, &fPrimaryKey, rgDBBINDING, nPRIMARY_KEY, DBTYPE_BOOL, pData, DBPROP_INDEX_PRIMARYKEY, cPropertySets, rgPropertySets, L"ERROR: Primary Key\n"), TRUE); COMPARE(GetIndexValueFromFirstRow(&vbSortBookmarks, &fSortBookmarks, rgDBBINDING, nSORT_BOOKMARKS, DBTYPE_BOOL, pData, DBPROP_INDEX_SORTBOOKMARKS, cPropertySets, rgPropertySets, L"ERROR: SortBookmarks\n"), TRUE); COMPARE(GetIndexValueFromFirstRow(&usType, &fType, rgDBBINDING, nTYPE, DBTYPE_UI2, pData, DBPROP_INDEX_TYPE, cPropertySets, rgPropertySets, L"ERROR: Type\n"), TRUE); COMPARE(GetIndexValueFromFirstRow(&vbUnique, &fUnique, rgDBBINDING, nUNIQUE, DBTYPE_BOOL, pData, DBPROP_INDEX_UNIQUE, cPropertySets, rgPropertySets, L"ERROR: Unique\n"), TRUE); } TESTC_(pIndexRowset->ReleaseRows(1, &hRow, NULL, NULL, NULL), S_OK); // Get data for each row for(iRow=1;iRowGetNextRows(0, 0, 1, &cRowsObtained, &phRow), S_OK); TESTC_((long)cRowsObtained, 1); TESTC_(hr=pIndexRowset->GetData(hRow, hAccessor, pData),S_OK); // check that the properties are the same: COMPARE(GetIndexValue(&pwszIndexName, &fIndexName, rgDBBINDING, nINDEX_NAME, DBTYPE_WSTR, pData, L"ERROR: Bad index name\n"), TRUE); COMPARE(GetIndexValue(&pwszTableName, &fTableName, rgDBBINDING, nTABLE_NAME, DBTYPE_WSTR, pData, L"ERROR: Bad table name\n"), TRUE); // check column ordinal and name fOrdinalPosition = FALSE; COMPARE(GetIndexValue(&uiOrdinalPosition, &fOrdinalPosition, rgDBBINDING, nORDINAL_POSITION, DBTYPE_UI2, pData, L"ERROR: OrdinalPosition\n"), TRUE); if (fOrdinalPosition) { TESTC(cIndexColumnDesc >= uiOrdinalPosition); DBID *pColumnID = rgIndexColumnDesc[uiOrdinalPosition-1].pColumnID; // can compare both column name and collation order TESTC(NULL != pColumnID); fColumnName = TRUE; switch (pColumnID->eKind) { case DBKIND_NAME: pwszColumnName = wcsDuplicate(pColumnID->uName.pwszName); COMPARE(GetIndexValue(&pwszColumnName, &fColumnName, rgDBBINDING, nCOLUMN_NAME, DBTYPE_WSTR, pData, L"ERROR: Column name\n"), TRUE); SAFE_FREE(pwszColumnName); break; default: break; } fCollation = TRUE; iCollation = (short)((DBINDEX_COL_ORDER_ASC == rgIndexColumnDesc[uiOrdinalPosition-1].eIndexColOrder) ? DB_COLLATION_ASC: DB_COLLATION_DESC); COMPARE(GetIndexValue(&iCollation, &fCollation, rgDBBINDING, nCOLLATION, DBTYPE_I2, pData, L"ERROR: Collation\n"), TRUE); rgColPresent[uiOrdinalPosition-1] = TRUE; nColPresent++; } COMPARE(GetIndexValue(&vbAutoUpdate, &fAutoUpdate, rgDBBINDING, nAUTO_UPDATE, DBTYPE_BOOL, pData, L"ERROR: Auto update\n"), TRUE); COMPARE(GetIndexValue(&vbClustered, &fClustered, rgDBBINDING, nCLUSTERED, DBTYPE_BOOL, pData, L"ERROR: Clustered\n"), TRUE); COMPARE(GetIndexValue(&lFillFactor, &fFillFactor, rgDBBINDING, nFILL_FACTOR, DBTYPE_I4, pData, L"ERROR: Fill factor\n"), TRUE); COMPARE(GetIndexValue(&lInitialSize, &fInitialSize, rgDBBINDING, nINITIAL_SIZE, DBTYPE_I4, pData, L"ERROR: Initial Size\n"), TRUE); COMPARE(GetIndexValue(&lNullCollation, &fNullCollation, rgDBBINDING, nNULL_COLLATION, DBTYPE_I4, pData, L"ERROR: Null Collation\n"), TRUE); COMPARE(GetIndexValue(&lNulls, &fNulls, rgDBBINDING, nNULLS, DBTYPE_I4, pData, L"ERROR: Nulls\n"), TRUE); COMPARE(GetIndexValue(&vbPrimaryKey, &fPrimaryKey, rgDBBINDING, nPRIMARY_KEY, DBTYPE_BOOL, pData, L"ERROR: Primary Key\n"), TRUE); COMPARE(GetIndexValue(&vbSortBookmarks, &fSortBookmarks, rgDBBINDING, nSORT_BOOKMARKS, DBTYPE_BOOL, pData, L"ERROR: SortBookmarks\n"), TRUE); COMPARE(GetIndexValue(&usType, &fType, rgDBBINDING, nTYPE, DBTYPE_UI2, pData, L"ERROR: Type\n"), TRUE); COMPARE(GetIndexValue(&vbUnique, &fUnique, rgDBBINDING, nUNIQUE, DBTYPE_BOOL, pData, L"ERROR: Unique\n"), TRUE); TESTC_(pIndexRowset->ReleaseRows(1, &hRow, NULL, NULL, NULL), S_OK); } TESTC(nColPresent == cIndexColumnDesc); CLEANUP: SAFE_RELEASE(pIDBSchemaRowset); // Free the memory SAFE_FREE(pwszIndexName); SAFE_FREE(pwszTableName); SAFE_FREE(rgColPresent); SAFE_FREE(prgRestrictions); SAFE_FREE(prgSchemas); SAFE_FREE(pData); SAFE_RELEASE(pIndexRowset); SAFE_FREE(rgDBBINDING); for(index=0;indexeKind==DBKIND_NAME || pIndexID->eKind==DBKIND_GUID_NAME || pIndexID->eKind==DBKIND_PGUID_NAME) rgRestrictIndexes[2].bstrVal = SysAllocString(pIndexID->uName.pwszName); else rgRestrictIndexes[2].bstrVal = NULL; } if (pTableID) { rgRestrictIndexes[4].vt = VT_BSTR; if (pTableID->eKind==DBKIND_NAME || pTableID->eKind==DBKIND_GUID_NAME || pTableID->eKind==DBKIND_PGUID_NAME) rgRestrictIndexes[4].bstrVal = SysAllocString(pTableID->uName.pwszName); else rgRestrictIndexes[4].bstrVal = NULL; } if (!CHECK(hr = pIDBSchemaRowset->GetRowset( NULL, // aggregation DBSCHEMA_INDEXES, // REFGUID cRest, // count of restrictions (1:types) rgRestrictIndexes, // list of restrictions IID_IRowset, // REFFID 0, // count of properties NULL, // range of properties (IUnknown**)&pIRowset // returned result set ),S_OK)) goto CLEANUP; // Only do this once, if there is a rowset then // there is a table already in the data source hr = pIRowset->GetNextRows(0, 0, 1, &cRowsObtained, &rghRows); if (pfExists) *pfExists = (1 == cRowsObtained); CHECK(hr=pIRowset->ReleaseRows(cRowsObtained,rghRows,NULL,NULL,NULL),S_OK); CLEANUP: SAFE_RELEASE(pIDBSchemaRowset); SAFE_RELEASE(pIRowset); SAFE_FREE(rghRows); for(index=0;indexOpenRowset(NULL, pTableID, pIndexID, IID_IRowsetIndex, 0, NULL, (IUnknown**)&pRowsetIndex); if (pfExist) *pfExist = (S_OK == hr)? TRUE: FALSE; CLEANUP: SAFE_RELEASE(pRowsetIndex); SAFE_RELEASE(pIOpenRowset); return S_OK; } //CIIndexDefinition::DoesIndexExistRowsetIndex //--------------------------------------------------------------------------- // CIIndexDefinition::DoesIndexExist // // CIIndexDefinition | // DoesIndexExist | // If this index is on this table return true If function runs correctly // but doesn't find the table name, function will return S_OK, but pfExists // will be FALSE. If strIndexName is empty, returns E_FAIL. // // @mfunc DoesIndexExist // @rdesc HRESULT indicating success or failure // @flag S_OK | Function ran without problem // @flag E_FAIL | Function ran with problems // //--------------------------------------------------------------------------- HRESULT CIIndexDefinition::DoesIndexExist( DBID *pTableID, // @parm [IN] Table ID DBID *pIndexID, // @parm [IN] Index ID BOOL *pfExists, // @parm [OUT] TRUE if index exists BOOL fAnyIndex // @parm [IN] TRUE if search for all indexes // DEFAULT FALSE ) { HRESULT hr = E_FAIL; IDBSchemaRowset *pIDBSchemaRowset = NULL; if (!pfExists) return E_INVALIDARG; TESTC_PROVIDER(VerifyInterface(m_pIIndexDefinition, IID_IDBSchemaRowset, SESSION_INTERFACE, (IUnknown**)&pIDBSchemaRowset)); if (fAnyIndex) if (pIDBSchemaRowset) hr = DoesIndexExistInIndexSchemaRowset(pTableID, NULL, pfExists, fAnyIndex); else { odtLog << "WARNING: IDBSchemaRowset is not supported\n"; *pfExists = FALSE; hr = DB_S_ERRORSOCCURRED; } else if (s_fIRowsetIndex) hr = DoesIndexExistRowsetIndex(pTableID, pIndexID, pfExists); if (pIDBSchemaRowset) hr = DoesIndexExistInIndexSchemaRowset(pTableID, pIndexID, pfExists); else PRVTRACE("**TCIIndexDefinition::DoesIndexExist: how did I get here?\n"); CLEANUP: SAFE_RELEASE(pIDBSchemaRowset); return hr; } //CIIndexDefinition::DoesIndexExist // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Test Case Section // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // }} END_DECLARE_TEST_CASES() // {{ TCW_TESTMODULE(ThisModule) TEST_MODULE(4, ThisModule, gwszModuleDescrip) TEST_CASE(1, TCCreateIndex) TEST_CASE(2, TCDropIndex) TEST_CASE(3, TCTrans) TEST_CASE(4, TCRODataSource) END_TEST_MODULE() // }} TCW_TESTMODULE_END // @cmember Display the index columns and orders BOOL TCIIndexDefinition::DisplayIndex( DBINDEXCOLUMNDESC *rgIndexColumnDesc, // columns and order in index DBORDINAL nIndexSize // index size ) { DBORDINAL i; if (!rgIndexColumnDesc) return FALSE; for (i=0; iuName.pwszName) odtLog << "\t" << rgIndexColumnDesc[i].pColumnID->uName.pwszName; else odtLog << "\t NULL"; odtLog << ((DBINDEX_COL_ORDER_ASC == rgIndexColumnDesc[i].eIndexColOrder)? " (Asc)": " (Desc)"); } odtLog << "\n"; return TRUE; } //TCIIndexDefinition::DisplayIndex //------------------------------------------------------------------------- // // @cmember Iterator on indexes (as col no) //------------------------------------------------------------------------- int TCIIndexDefinition::GetNextIndex( DBORDINAL *rgIndexColumns, // array containing the column numbers of the index BOOL *rgColumnPresent, // array of flags for membership to the index DBORDINAL nIndexSize, // index size DBORDINAL nColumns // number of columns ) // client is suppose to initialize rgIndexColumns with the first index // and rgColumnPresent accordingly // a return value less than 0 means end of index sequence { ULONG l; DBORDINAL pos; int nLastUpdate; for (nLastUpdate=(int)nIndexSize-1; nLastUpdate>=0; ) { // try to set the next value for position nLastUpdate of the index rgColumnPresent[rgIndexColumns[nLastUpdate]] = FALSE; // find the first column available for (pos=rgIndexColumns[nLastUpdate]+1; pos<=nColumns && rgColumnPresent[pos]; pos++); if (pos<=nColumns) { // set position nLastUpdate in index to this column rgIndexColumns[nLastUpdate] = pos; rgColumnPresent[pos] = TRUE; // set all the column in the index bigger than nLastUpdate to min values (guaranted success) for (l=(ULONG)nLastUpdate+1; l=0; ) { // try to set the next value for position i of the index rgIndexOrder[nLastUpdate] = (DBINDEX_COL_ORDER_ASC == rgIndexOrder[nLastUpdate]) ? DBINDEX_COL_ORDER_DESC: DBINDEX_COL_ORDER_ASC; if (DBINDEX_COL_ORDER_DESC == rgIndexOrder[nLastUpdate]) { // set all the column in the index bigger than i to min values (guaranted success) for (l=(ULONG)nLastUpdate+1; lDropIndex(pTableID, *ppIndexID), S_OK)) { if (CHECK(DoesIndexExist(pTableID, *ppIndexID, &fExist), S_OK) && !fExist) fRes = TRUE; else odtLog << "ERROR: index not dropped \n"; } CLEANUP0: if (ppIndexID && *ppIndexID) { ReleaseDBID(*ppIndexID); *ppIndexID = NULL; } CLEANUP: return fRes; } //TCIIndexDefinition::DropIndexAndReleaseID */ //------------------------------------------------------------------------- // // @cmember Sets an index with 1 column, then drops the index // tries all the columns if necessary to determine a column on which // an index could be created //------------------------------------------------------------------------- /* HRESULT TCIIndexDefinition::SetIndex( DBID *pIndexID, // [in] index ID ULONG *nIndex, // [out] index column DBID **ppIndexID // [out] index ID created by IIndexDefinition::CreateIndex() ) { return SetIndex(&(m_pTable->GetTableID()), pIndexID, nIndex, ppIndexID); } //TCIIndexDefinition::SetIndex */ // @cmember Sets an index with 1 column // tries all the columns if necessary HRESULT TCIIndexDefinition::SetIndex( DBID *pTableID, // [in] table to which to attach the index DBID *pIndexID, // [in] index ID ULONG *pnIndex, // [out] index column DBID **ppIndexID // [out] index ID created by IIndexDefinition::CreateIndex() ) { ULONG i; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; HRESULT hr = E_FAIL; TESTC(NULL != pTableID); rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; for (i=0; iCreateIndexAndCheck(pTableID, pIndexID, 1, rgIndexColumnDesc, 0, NULL, ppIndexID))) { if (pnIndex) *pnIndex = i+1; return hr; } // display info odtLog << "could not create index: "; DisplayIndex(rgIndexColumnDesc, 1); } CLEANUP: return hr; } //TCIIndexDefinition::SetIndex //------------------------------------------------------------------------- // // @cmember Builds and tries all indexes on a table // returns S_OK on success //------------------------------------------------------------------------- HRESULT TCIIndexDefinition::DoAllIndexes( CTable *pTable, // table DBORDINAL nCol // number of columns in index ) { DBORDINAL nIndexSize; HRESULT hr = S_OK; for (nIndexSize=1; nIndexSize<=nCol; nIndexSize++) { if (S_OK != (m_hr = DoAllKIndexes(pTable, nIndexSize, nCol) )) hr = m_hr; } return hr; } //TCIIndexDefinition::DoAllIndexes // @cmember Builds and tries all indexes on a table // returns S_OK on success HRESULT TCIIndexDefinition::DoAllIndexes( CTable *pTable, // table DBORDINAL nCol, // number of columns in table DBORDINAL nMaxIndexSize // maximum index size ) { DBORDINAL nIndexSize; HRESULT hr = S_OK; for (nIndexSize=1; nIndexSize<=nMaxIndexSize; nIndexSize++) { if (S_OK != (m_hr = DoAllKIndexes(pTable, nIndexSize, nCol) )) hr = m_hr; } return hr; } //TCIIndexDefinition::DoAllIndexes //------------------------------------------------------------------------- // // @cmember Builds and tries all indexes of a given size defined upon a table // return S_OK on success (results are consistent) // E_FAIL if something was wrong //------------------------------------------------------------------------- HRESULT TCIIndexDefinition::DoAllKIndexes( CTable *pTable, // table DBORDINAL nIndexSize, // index size DBORDINAL nCols // number of columns in table ) { HRESULT hr = E_FAIL; DBORDINAL *rgIndexColumns = NULL; BOOL *rgColumnPresent = NULL; int nLastUpdate; DBORDINAL i; int iOrder; DBINDEX_COL_ORDER *rgOrder = NULL; DBINDEXCOLUMNDESC *rgIndexColumnDesc = NULL; DBCOLUMNDESC *rgColumnDesc = NULL; DBORDINAL cColumnDesc = 0; TESTC(NULL != pTable); SAFE_ALLOC(rgIndexColumns, DBORDINAL, nIndexSize); SAFE_ALLOC(rgOrder, DBINDEX_COL_ORDER, nIndexSize); SAFE_ALLOC(rgColumnPresent, BOOL, nCols+1); // get the column descriptors on the table pTable->BuildColumnDescs(&rgColumnDesc); cColumnDesc = pTable->CountColumnsOnTable(); hr = S_OK; for (i=0; i<=nCols; rgColumnPresent[i++] = FALSE); for (i=0; i= 0;) { // initialize the array of column ordering for (i=0; i< nIndexSize; rgOrder[i++]=0); // try all combination for ordering for (iOrder=(int)nIndexSize; iOrder>=0; ) { // prepare parameters MakeIndexColumnDesc(rgColumnDesc, cColumnDesc, rgIndexColumns, rgOrder, nIndexSize, &rgIndexColumnDesc); ASSERT(m_pCIIndexDefinition); m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&(pTable->GetTableID()), NULL, nIndexSize, rgIndexColumnDesc, 0, NULL); if (!SUCCEEDED(m_hr)) { odtLog << "could not create index: "; DisplayIndex(rgIndexColumnDesc, nIndexSize); } // release memory ReleaseIndexColumnDesc(rgIndexColumnDesc, nIndexSize); // get the next ordering iOrder = GetNextOrder(rgOrder, nIndexSize); } // pick the next column configuration nLastUpdate=GetNextIndex(rgIndexColumns, rgColumnPresent, nIndexSize, nCols); } CLEANUP: ReleaseColumnDesc(rgColumnDesc, cColumnDesc); SAFE_FREE(rgIndexColumns); SAFE_FREE(rgColumnPresent); SAFE_FREE(rgOrder); return hr; }//TCIIndexDefinition::DoAllKIndexes //------------------------------------------------------------------------- // @cmember Find the list of the indexable columns // //------------------------------------------------------------------------- BOOL TCIIndexDefinition::FindIndexableColumns( DBCOLUMNDESC *rgColumnDesc, // [IN] array of column desc on the new table DBORDINAL cColumnDesc, // [IN] number of column desc DBORDINAL **prgIndexCols, // [OUT] array of indexable columns DBORDINAL *cIndexCols // [OUT] number of indexable columns ) { BOOL fResult = FALSE; BOOL fFind; CCol col; WCHAR *pwszTypeName; ULONG nOrdinal, nIndex; DBORDINAL *rgIndexCols = NULL; TESTC((NULL != cIndexCols) && (NULL != prgIndexCols)); SAFE_ALLOC(rgIndexCols, DBORDINAL, cColumnDesc); *prgIndexCols = rgIndexCols; for (nOrdinal = 0; nOrdinal < cColumnDesc; nOrdinal++) { if (NULL == rgColumnDesc[nOrdinal].pwszTypeName) continue; // check whether the current column is indexable // to do this, search in m_ColList all indexable types // use m_rgIndexCols and cIndexCols for this fFind = FALSE; for (nIndex = 0; nIndex < m_cIndexCols && !fFind; nIndex++) { // get the type name of the next indexable type col = m_pTable-> GetColInfoForUpdate(m_rgIndexCols[nIndex]); pwszTypeName = col.GetProviderTypeName(); if (NULL == pwszTypeName) continue; // check if it's the current type if (0 == wcscmp(rgColumnDesc[nOrdinal].pwszTypeName, pwszTypeName)) { // found an indexable column rgIndexCols[(*cIndexCols)++] = nOrdinal+1; fFind = TRUE; } } } fResult = TRUE; CLEANUP: return fResult; } //TCIIndexDefinition::FindIndexableColumns //------------------------------------------------------------------------- // // @cmember Prepare DBINDEXCOLUMNDESC array // RETURN // TRUE - function executed ok and memory was properly allocated // FALSE - otherwise //------------------------------------------------------------------------- BOOL TCIIndexDefinition::MakeIndexColumnDesc( DBCOLUMNDESC *rgColumnDesc, // [IN] the array of column desc DBORDINAL cColumnDesc, // [IN] the number of columns in the table DBORDINAL *rgIndexCol, // [IN] the array of the column in the index DBINDEX_COL_ORDER *rgOrder, // [IN] the array of column order DBORDINAL nIndexSize, // [IN] index size DBINDEXCOLUMNDESC **prgIndexColumnDesc// [OUT] the desc of the index cols ) { BOOL fRes=FALSE; ULONG nIndexCol; DBINDEXCOLUMNDESC *rgIndexColumnDesc = NULL; TESTC(NULL != prgIndexColumnDesc); *prgIndexColumnDesc = NULL; SAFE_ALLOC(*prgIndexColumnDesc, DBINDEXCOLUMNDESC, nIndexSize); rgIndexColumnDesc = *prgIndexColumnDesc; for (nIndexCol = 0; nIndexCol < nIndexSize; nIndexCol++) { TESTC(rgIndexCol[nIndexCol] <= cColumnDesc); SAFE_ALLOC(rgIndexColumnDesc[nIndexCol].pColumnID, DBID, 1); DuplicateDBID(rgColumnDesc[rgIndexCol[nIndexCol]-1].dbcid, rgIndexColumnDesc[nIndexCol].pColumnID); rgIndexColumnDesc[nIndexCol].eIndexColOrder = rgOrder[nIndexCol]; } fRes = TRUE; CLEANUP: return fRes; } //TCIIndexDefinition::MakeIndexColumnDesc //------------------------------------------------------------------------- // // @cmember Releases the memory allocated for the structure // RETURN: // TRUE - everything OK // FALSE - bad argument //------------------------------------------------------------------------- BOOL TCIIndexDefinition::ReleaseIndexColumnDesc( DBINDEXCOLUMNDESC *rgIndexColumnDesc, // [IN] the desc of the index cols DBORDINAL nIndexSize // [IN] index size ) { BOOL fRes = TRUE; DBORDINAL nCol; TESTC(NULL != rgIndexColumnDesc); for (nCol = 0; nCol < nIndexSize; nCol++) ReleaseDBID(rgIndexColumnDesc[nCol].pColumnID); SAFE_FREE(rgIndexColumnDesc); fRes = TRUE; CLEANUP: return fRes; } //TCIIndexDefinition::ReleaseIndexColumnDesc //------------------------------------------------------------------------- // // @cmember release the property of all columns // RETURNS: // TRUE - function executed correctly // FALSE - parameters look strange //------------------------------------------------------------------------- BOOL TCIIndexDefinition::ReleaseAllColumnPropSets( DBORDINAL cColumnDesc, // [in] number of columns DBCOLUMNDESC *rgColumnDesc // [in] column descriptor array ) { DBORDINAL i; BOOL fRes = FALSE; TESTC(NULL != rgColumnDesc); TESTC(0 != cColumnDesc); for (i=0; iCreateIndex( pTableID, pIndexID, nIndexSize, rgIndexColumnDesc, cPropSets, rgPropSets, ppIndexID); hr = hres; // hr will be used to build the return value PRVTRACE("TCIIndexDefinition::CreateAndCheckIndex: IIndexDefinition::CreateIndex returns %d\n", hr); // get an DBID of the index if ((NULL != pIndexID) || (NULL != ppIndexID)) pNewIndexID = pIndexID? pIndexID: *ppIndexID; else { if (!CHECK(hr, E_INVALIDARG)) hr = E_FAIL; goto CLEANUP; } // check index property status if (rgPropSets) { for (nIndexPropSet=0; nIndexPropSet < cPropSets; nIndexPropSet++) { pProp = rgPropSets[nIndexPropSet].rgProperties; if (!pProp) continue; for (nIndexProp=0; nIndexProp < rgPropSets[nIndexPropSet].cProperties; nIndexProp++) { if (!CheckProperty(rgPropSets[nIndexPropSet].guidPropertySet, &pProp[nIndexProp], hres)) hr = E_FAIL; } } } if (SUCCEEDED(hr)) { if (fIndexAlreadyExists) { odtLog << "ERROR: success in creating an already existing index\n"; hr = E_FAIL; goto CLEANUP; } // the index is reported to be created, check it thoroughfully if ( NULL == pNewIndexID || !CHECK(m_hr = DoesIndexExist(pTableID, pNewIndexID, &fExists), S_OK) || !fExists ) { odtLog << "ERROR: the method succeeded, but the index was not created or ppIndexID was not created!\n"; hr = E_FAIL; } else { // check the columns, their collation and the index properties on // IDBSchemaRowset or IRowsetIndex if (!CHECK(m_hr = CheckIndex(pTableID, pNewIndexID, nIndexSize, rgIndexColumnDesc, cPropSets, rgPropSets), TRUE)) { odtLog << "ERROR: the index was not properly created!\n"; hr = E_FAIL; } // check the properties as returned if (!(m_hr = IsPropSetPreserved(rgPropSets1, rgPropSets, cPropSets))) { odtLog << "ERROR: properties are not preserved!\n"; hr = E_FAIL; } } // compare *pIndexID and **ppIndexID if (!CheckReturnedDBID(pIndexID, ppIndexID)) { odtLog << "the returned IndexID was not created ok!\n"; hr = E_FAIL; } if (E_FAIL == hr) { // drop the index and return E_FAIL CHECK(m_pIIndexDefinition->DropIndex(pTableID, pNewIndexID), S_OK); if (ppIndexID && *ppIndexID) { ReleaseDBID(*ppIndexID); *ppIndexID = NULL; } } } else { // failed to create the index if (!pIndexID && DB_E_DUPLICATEINDEXID == m_hr) { odtLog << "ERROR: DB_E_DUPLICATEINDEXID return on a NULL pIndexID!\n"; hr = E_FAIL; } // check that the index is not created if ( !fIndexAlreadyExists && NULL != pNewIndexID && (!CHECK(m_hr = DoesIndexExist(pTableID, pNewIndexID, &fExists), S_OK) || fExists) ) { odtLog << "ERROR: the method failed, but the index was created!\n"; CHECK(m_pIIndexDefinition->DropIndex(pTableID, pNewIndexID), S_OK); hr = E_FAIL; } // should not allocate memory for the index ID if (ppIndexID && *ppIndexID) { odtLog << "ERROR: the index was not created, but *ppIndexID was returned not null!\n"; ReleaseDBID(*ppIndexID); *ppIndexID = NULL; hr = E_FAIL; } } CLEANUP: // release the old properties FreeProperties( &cPropSets, &rgPropSets1); return hr; } //TCIIndexDefinition::CreateAndCheckIndex //------------------------------------------------------------------------- // // @cmember create an index out of index column descriptors // Drops the index and returns just the result of the operation // // RETURNS: // E_FAIL if there is a consistency error // hr of the IIndexDefinition::CreateIndex() otherwise //------------------------------------------------------------------------- HRESULT TCIIndexDefinition::CreateCheckAndDropIndex( DBID *pTableID, // [in] the ID of the table DBID *pIndexID, // [in] the ID of the index DBORDINAL nIndexSize, // [in] index size (no of columns) DBINDEXCOLUMNDESC *rgIndexColumnDesc, // [in] columns to be part of index ULONG cPropSets, // [in] count of property sets DBPROPSET *rgPropSets // [in] array of property sets ) { DBID *pOutIndexID=NULL; HRESULT hr = E_FAIL; BOOL fExists; hr = CreateAndCheckIndex(pTableID, pIndexID, &pOutIndexID, nIndexSize, rgIndexColumnDesc, cPropSets, rgPropSets); if (E_FAIL == hr || !pOutIndexID) goto CLEANUP; // check that the index is not created if ( !CHECK(m_hr = DoesIndexExist(pTableID, pOutIndexID, &fExists), S_OK) || !fExists || !DropIndexAndReleaseID(pTableID, &pOutIndexID) ) hr = E_FAIL; CLEANUP: return hr; } //TCIIndexDefinition::CreateCheckAndDropIndex */ //------------------------------------------------------------------------- // // @cmember create an index out of column ordinals // // // RETURNS: // E_FAIL if there is a consistency error // S_OK if function completes ok //------------------------------------------------------------------------- HRESULT TCIIndexDefinition::CNCIndexFromOrdinals( CTable *pTable, // [in] the ID of the table DBID *pIndexID, // [in] the ID of the index DBID **ppIndexID, // [out] ID of the newly created index DBCOLUMNDESC *rgColumnDesc, // [in] array of column descriptors DBORDINAL cColumnDesc, // [in] number of column desc DBORDINAL nIndexSize, // [in] index size (no of columns) DBORDINAL *rgIndexColumns, // [in] columns to be part of index DBINDEX_COL_ORDER *rgOrder, // [in] order on index columns ULONG cPropSets, /*=0*/ // [in] count of property sets DBPROPSET *rgPropSets /*=NULL*/ // [in] array of property sets ) { DBINDEXCOLUMNDESC *rgIndexColumnDesc; HRESULT hr = E_FAIL; // prepare parameters TESTC(MakeIndexColumnDesc(rgColumnDesc, cColumnDesc, rgIndexColumns, rgOrder, nIndexSize, &rgIndexColumnDesc)); ASSERT(m_pCIIndexDefinition); hr = m_pCIIndexDefinition->CreateIndexAndCheck(&pTable->GetTableID(), pIndexID, nIndexSize, rgIndexColumnDesc, cPropSets, rgPropSets, ppIndexID); // release memory if (!ReleaseIndexColumnDesc(rgIndexColumnDesc, nIndexSize)) hr = E_FAIL; CLEANUP: return hr; } //TCIIndexDefinition::CNCIndexFromOrdinals //------------------------------------------------------------------------- // // @cmember create an index out of column ordinals // Drops the index afterwards // // // RETURNS: // E_FAIL if there is a consistency error // S_OK hr of the IIndexDefinition::CreateIndex() otherwise //------------------------------------------------------------------------- HRESULT TCIIndexDefinition::CCNDropIndexFromOrdinals( CTable *pTable, // [in] the ID of the table DBID *pIndexID, // [in] the ID of the index DBCOLUMNDESC *rgColumnDesc, // [in] array of column descriptors DBORDINAL cColumnDesc, // [in] number of column desc DBORDINAL nIndexSize, // [in] index size (no of columns) DBORDINAL *rgIndexColumns, // [in] columns to be part of index DBINDEX_COL_ORDER *rgOrder, // [in] order on index columns ULONG cPropSets, /*=0*/ // [in] count of property sets DBPROPSET *rgPropSets /*=NULL*/ // [in] array of property sets ) { DBINDEXCOLUMNDESC *rgIndexColumnDesc; HRESULT hr = E_FAIL; // prepare parameters TESTC(MakeIndexColumnDesc(rgColumnDesc, cColumnDesc, rgIndexColumns, rgOrder, nIndexSize, &rgIndexColumnDesc)); TESTC(NULL != m_pCIIndexDefinition); hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&(pTable->GetTableID()), pIndexID, nIndexSize, rgIndexColumnDesc, cPropSets, rgPropSets); // release memory if (!ReleaseIndexColumnDesc(rgIndexColumnDesc, nIndexSize)) hr = E_FAIL; CLEANUP: return hr; } //TCIIndexDefinition::CCNDropIndexFromOrdinals //-------------------------------------------------------------------------- // // @cmember Check the result and property status //-------------------------------------------------------------------------- BOOL TCIIndexDefinition::CheckProperty( const GUID guidPropertySet,// [in] property set guid (should be DBPROPSET_INDEX DBPROP *pProp, // [in] property HRESULT hr // [in] the result ) { BOOL fRes = TRUE; BOOL fSupported; BOOL fSettable; if (!pProp) return TRUE; // general checking if (DBPROPOPTIONS_REQUIRED == pProp->dwOptions && DBPROPSTATUS_OK != pProp->dwStatus) fRes = CHECK(FAILED(hr), TRUE); if (!(guidPropertySet == DBPROPSET_INDEX)) { // check a couple of things and returns return COMPARE(pProp->dwStatus, DBPROPSTATUS_NOTSUPPORTED) && COMPARE(S_OK != hr, TRUE); } fSupported = SupportedProperty(pProp->dwPropertyID, guidPropertySet); fSettable = SettableProperty(pProp->dwPropertyID, guidPropertySet); if (!fSupported && !CHECK(S_OK != hr, TRUE)) fRes = FALSE; // status driven checking switch (pProp->dwStatus) { case DBPROPSTATUS_OK: fRes = COMPARE(fSupported != 0, TRUE); break; case DBPROPSTATUS_NOTSUPPORTED: fRes = COMPARE(fSupported == 0, TRUE); break; case DBPROPSTATUS_NOTSETTABLE: fRes = COMPARE(fSupported != 0, TRUE) && COMPARE(fSettable == 0, TRUE); break; case DBPROPSTATUS_BADOPTION: fRes = (pProp->dwOptions != DBPROPOPTIONS_OPTIONAL) && COMPARE(DBPROPOPTIONS_REQUIRED != pProp->dwOptions, TRUE); break; case DBPROPSTATUS_CONFLICTING: fRes = COMPARE(fSettable != 0, TRUE); break; case DBPROPSTATUS_BADVALUE: fRes = COMPARE(fSupported != 0, TRUE); break; default: break; } // DBPROPSTATUS_BADVALUE can be certainly got only if type of the prop is wrong // info about supported discret values of the prop cannot generally be obtained // before creating an index if ( GetPropInfoType(pProp->dwPropertyID, guidPropertySet) != pProp->vValue.vt && !COMPARE(DBPROPSTATUS_OK == pProp->dwStatus, FALSE)) { odtLog << "ERROR: bad propstatus on improper type value on property" << pProp->dwPropertyID << "\n"; fRes = FALSE; } return fRes; } //TCIIndexDefinition::CheckProperty /*//------------------------------------------------------------------------- // // @cmember Check whether all the columns specified appear in index // and whether the properties are properly set // uses IRowsetIndex //------------------------------------------------------------------------- BOOL TCIIndexDefinition::CheckIndex2( DBID *pTableID, // the index of the table DBID *pIndexID, // the index to be checked DBORDINAL cIndexColumnDesc, // how many elements DBINDEXCOLUMNDESC *rgIndexColumnDesc, // array with index original descriprion ULONG cPropertySets, // number of property sets DBPROPSET *rgPropertySets // the array of property sets ) { IRowsetIndex *pIRowsetIndex = NULL; ULONG i; DBORDINAL cColumns = 0; ULONG cIndexPropSets=0, nPropSet, nProp; DBINDEXCOLUMNDESC *rgOutIndexColumnDesc = NULL; DBPROPSET *rgIndexPropSets = NULL; BOOL fResult = TRUE, fProp=TRUE; DBPROP *pProp=NULL; DBPROPSTATUS dwStatus; VARIANT *pvValue; DBPROPID dwPropID; TESTC_(m_hr = m_pIOpenRowset->OpenRowset(NULL, pTableID, pIndexID, IID_IRowsetIndex, 0, NULL, (IUnknown**)&pIRowsetIndex), S_OK); fResult = FALSE; // use IRowsetIndex->GetIndexInfo to check how the index was set TESTC_(pIRowsetIndex->GetIndexInfo(&cColumns, &rgOutIndexColumnDesc, &cIndexPropSets, &rgIndexPropSets), S_OK); TESTC(cColumns == cIndexColumnDesc); for (i=0; iuName.pwszName << "\n"; goto CLEANUP; } // this is based on the assumption that DBID returned for columns are in the same // format as they were input // otherwise one have to use a complete description of the columns in the table and make the conversion if (!CompareDBID(*rgIndexColumnDesc[i].pColumnID, *rgOutIndexColumnDesc[i].pColumnID, m_pIDBInitialize)) { odtLog << "column ID different for column " << rgIndexColumnDesc[i].pColumnID->uName.pwszName << "\n"; goto CLEANUP; } } fResult = TRUE; if (!rgPropertySets) goto CLEANUP; for (nPropSet=0; nPropSetvValue, pvValue), TRUE); } } fResult = fProp; CLEANUP: SAFE_RELEASE(pIRowsetIndex); return fResult; } //TCIIndexDefinition::CheckIndex2 //-------------------------------------------------------------------------- // // @cmember Read the value of a column in the index schema rowset // // if *pfSet is TRUE then there is a coparison value for the value read, // otherwise the new value will be used for further comparisons => save // it in *pVariable and set *pfSet to TRUE // RETURNS FALSE if the value was read and differ than the original one //-------------------------------------------------------------------------- BOOL TCIIndexDefinition::GetIndexValue( LPVOID pVariable, // [OUT] value read BOOL *pfSet, // [OUT] if the value is set DBBINDING *rgDBBINDING, // [IN] binding array ULONG cColumn, // [IN] column to be read ULONG ulDBTYPE, // [IN] type of property variant BYTE *pData, // [IN] pointer to read DATA stru WCHAR *lpwszMesaj // [IN] message text for error ) { BOOL fRes = FALSE; BOOL fWStrComp = FALSE; DATA *pColumn = NULL; TESTC(NULL != pData); TESTC(NULL != rgDBBINDING); TESTC(NULL != pVariable); TESTC(NULL != pfSet); fRes = TRUE; // get the status of the read property value pColumn = (DATA*) (pData+rgDBBINDING[cColumn].obStatus); if (DBSTATUS_S_OK == pColumn->sStatus) { // get the value in pVariable switch (ulDBTYPE) { case DBTYPE_I4: if (!*pfSet) { *(LONG*)pVariable = *(LONG*)(&(pColumn->bValue)); *pfSet = TRUE; } else fRes = (*(LONG*)(&(pColumn->bValue)) == *(LONG*)pVariable); break; case DBTYPE_UI2: if (!*pfSet) { *(unsigned short*)pVariable = *(unsigned short*)(&(pColumn->bValue)); *pfSet = TRUE; } else fRes = (*(unsigned short*)(&(pColumn->bValue)) == *(unsigned short*)pVariable); break; case DBTYPE_I2: if (!*pfSet) { *(SHORT*)pVariable = *(SHORT*)(&(pColumn->bValue)); *pfSet = TRUE; } else fRes = (*(SHORT*)(&(pColumn->bValue)) == *(SHORT*)pVariable); break; case DBTYPE_BOOL: if (!*pfSet) { *(VARIANT_BOOL*)pVariable = *(VARIANT_BOOL*)(&(pColumn->bValue)); *pfSet = TRUE; } else fRes = (*(VARIANT_BOOL*)(&(pColumn->bValue)) == *(VARIANT_BOOL*)pVariable); break; case DBTYPE_WSTR: if (!*pfSet) { TESTC(NULL != *(WCHAR**)pVariable); // release the memory is wrongfully passed if (!*(WCHAR*)pVariable) SAFE_FREE(*(WCHAR**)pVariable); // set the variable *(WCHAR**)pVariable = wcsDuplicate(*(WCHAR**)(&(pColumn->bValue))); *pfSet = TRUE; } else // compare fRes = (NULL != *(WCHAR**)pVariable) && S_OK == CompareID(&fWStrComp, *(WCHAR**)pVariable, (WCHAR*)(&(pColumn->bValue)), m_pIDBInitialize) && fWStrComp; break; default: ASSERT(FALSE); break; } if (!fRes) odtLog << lpwszMesaj; } CLEANUP: return fRes; } // TCIIndexDefinition::GetIndexValue //-------------------------------------------------------------------------- // // @cmember Read the value of a column in the indexe schema rowset // // RETURNS FALSE if the value was read and differ than the original one //-------------------------------------------------------------------------- BOOL TCIIndexDefinition::GetIndexValueFromFirstRow( LPVOID pVariable, // [OUT] value read BOOL *pfSet, // [OUT] if the value is set DBBINDING *rgDBBINDING, // [IN] binding array ULONG cColumn, // [IN] column to be read ULONG ulDBTYPE, // [IN] type of property variant BYTE *pData, // [IN] pointer to read DATA stru DBPROPID PropID, // [IN] property that is being read ULONG cPropSets, // [IN] number of property sets DBPROPSET *rgPropSets, // [IN] array of property sets WCHAR *lpwszMesaj // [IN] message text for error ) { BOOL fRes = TRUE; DBPROP *pProp = NULL;; TESTC(NULL != pfSet); *pfSet = FALSE; FindProperty(PropID, DBPROPSET_INDEX, cPropSets, rgPropSets, &pProp); if (!pProp) goto CLEANUP; // get the variable value switch (ulDBTYPE) { case DBTYPE_BOOL: *(VARIANT_BOOL*)pVariable = V_BOOL(&pProp->vValue); break; case DBTYPE_I4: *(LONG*)pVariable = V_I4(&pProp->vValue); break; case DBTYPE_UI2: *(unsigned short*)pVariable = V_UI2(&pProp->vValue); break; case DBTYPE_I2: *(SHORT*)pVariable = V_I2(&pProp->vValue); break; default: TESTC(FALSE); } *pfSet = (DBPROPSTATUS_OK == pProp->dwStatus); CLEANUP: fRes = GetIndexValue(pVariable, pfSet, rgDBBINDING, cColumn, ulDBTYPE, pData, lpwszMesaj); if (DBPROP_INDEX_FILLFACTOR == PropID && fProperRangeForFillFactor) { if (!COMPARE(0 < *(LONG*)pVariable && *(LONG*)pVariable <= 100, TRUE)) fProperRangeForFillFactor = FALSE; } return fRes; } //------------------------------------------------------------------------- // // @cmember Check whether all the columns specified appear in index // and the properties are properly set // returns TRUE - everything was set ok // FALSE - problems //------------------------------------------------------------------------- BOOL TCIIndexDefinition::CheckIndex( DBID *pTableID, // the index of the table DBID *pIndexID, // the index to be checked DBORDINAL cIndexColumnDesc, // how many elements DBINDEXCOLUMNDESC *rgIndexColumnDesc, // array with index original descriprion ULONG cPropertySets, // number of property sets DBPROPSET *rgPropertySets // the array of property sets ) { HRESULT hr = E_FAIL; BOOL fReturn = FALSE; BOOL fProps = TRUE; BOOL bIsSchemaSupported; DBLENGTH ulRowSize = 0; // size of row DBCOUNTITEM cDBBINDING = 0; // count of bindings DBORDINAL iRow = 0; // count of rows DBCOUNTITEM cRowsObtained = 0; // number of rows returned, should be 1 ULONG cSchema = 0; // number of supported Schemas ULONG *prgRestrictions= 0; // restrictions for each Schema GUID *prgSchemas = NULL; // array of GUIDs HROW hRow; // handler of rows HROW *phRow = &hRow; // pointer to handler IRowset *pIndexRowset = NULL; // returned rowset DBBINDING *rgDBBINDING = NULL; // array of bindings BYTE *pData = NULL; // pointer to data HACCESSOR hAccessor = NULL; // accessor BOOL *rgColPresent = NULL; const int cRest = 5; VARIANT rgRestrictIndexes[cRest]; ULONG i, index; ULONG nColPresent=0; ULONG nTABLE_NAME = 2; ULONG nINDEX_NAME = 5; ULONG nPRIMARY_KEY = 6; ULONG nUNIQUE = 7; ULONG nCLUSTERED = 8; ULONG nTYPE = 9; ULONG nFILL_FACTOR = 10; ULONG nINITIAL_SIZE = 11; ULONG nNULLS = 12; ULONG nSORT_BOOKMARKS = 13; ULONG nAUTO_UPDATE = 14; ULONG nNULL_COLLATION = 15; ULONG nORDINAL_POSITION = 16; ULONG nCOLUMN_NAME = 17; ULONG nCOLLATION = 20; // column entries in index schema rowset and their presence flags LPWSTR pwszIndexName = NULL; BOOL fIndexName = FALSE; LPWSTR pwszTableName = NULL; BOOL fTableName = FALSE; VARIANT_BOOL vbAutoUpdate; BOOL fAutoUpdate = FALSE; VARIANT_BOOL vbClustered; BOOL fClustered = FALSE; LONG lFillFactor; BOOL fFillFactor = FALSE; LONG lInitialSize; BOOL fInitialSize = FALSE; LONG lNullCollation; BOOL fNullCollation = FALSE; unsigned short uiOrdinalPosition; BOOL fOrdinalPosition; SHORT iCollation; BOOL fCollation = FALSE; LPWSTR pwszColumnName = NULL; BOOL fColumnName = FALSE; LONG lNulls; BOOL fNulls = FALSE; VARIANT_BOOL vbPrimaryKey; BOOL fPrimaryKey = FALSE; VARIANT_BOOL vbSortBookmarks; BOOL fSortBookmarks = FALSE; unsigned short usType; BOOL fType = FALSE; VARIANT_BOOL vbUnique; BOOL fUnique = FALSE; // Set restrictions for(index=0;indexGetSchemas(&cSchema, &prgSchemas, &prgRestrictions),S_OK); if (DBKIND_NAME == pIndexID->eKind) { pwszIndexName = wcsDuplicate(pIndexID->uName.pwszName); fIndexName = TRUE; } if (DBKIND_NAME == pTableID->eKind) { pwszTableName = wcsDuplicate(pTableID->uName.pwszName); fTableName = TRUE; } // Check to see if DBSCHEMA_INDEXES is supported for(i=0, bIsSchemaSupported=FALSE; iuName.pwszName); rgRestrictIndexes[4].vt = VT_BSTR; rgRestrictIndexes[4].bstrVal = SysAllocString(pTableID->uName.pwszName); SAFE_ALLOC(rgColPresent, BOOL, cIndexColumnDesc); for (i=0; iGetRowset( NULL, // aggregation DBSCHEMA_INDEXES, // REFGUID cRest, // count of restrictions (1:types) rgRestrictIndexes, // list of restrictions IID_IRowset, // REFFID 0, // count of properties NULL, // range of properties (IUnknown**)&pIndexRowset // returned result set ),S_OK); TESTC_(hr = GetAccessorAndBindings( pIndexRowset, DBACCESSOR_ROWDATA, &hAccessor, &rgDBBINDING, &cDBBINDING, &ulRowSize, DBPART_VALUE |DBPART_STATUS |DBPART_LENGTH, ALL_COLS_EXCEPTBOOKMARK, FORWARD, NO_COLS_BY_REF, NULL, // OUT: Array of DBCOLUMNINFOs 0, // OUT: Count of DBCOULMNINFOs NULL, //&pStringsBuffer, DBTYPE_EMPTY, 0, NULL),S_OK); SAFE_ALLOC(pData, BYTE, ulRowSize); //data // read the first row, check local data and initialize variables TESTC_(hr=pIndexRowset->GetNextRows(0, 0, 1, &cRowsObtained, &phRow), S_OK); TESTC_((long)cRowsObtained, 1); TESTC_(hr=pIndexRowset->GetData(hRow, hAccessor, pData),S_OK); // get the first values and verifications fProps = fProps && GetIndexValue(&pwszIndexName, &fIndexName, rgDBBINDING, nINDEX_NAME, DBTYPE_WSTR, pData, L"ERROR: Bad index name\n"); fProps = fProps && GetIndexValue(&pwszTableName, &fTableName, rgDBBINDING, nTABLE_NAME, DBTYPE_WSTR, pData, L"ERROR: Bad table name\n"); // check column ordinal position of the first column in the index (1 is the first value) and name fOrdinalPosition = FALSE; fProps = GetIndexValue(&uiOrdinalPosition, &fOrdinalPosition, rgDBBINDING, nORDINAL_POSITION, DBTYPE_UI2, pData, L"ERROR: OrdinalPosition\n") && fProps; if (fOrdinalPosition) { TESTC(cIndexColumnDesc >= uiOrdinalPosition); DBID *pColumnID = rgIndexColumnDesc[uiOrdinalPosition-1].pColumnID; // can compare both column name and collation order TESTC(NULL != pColumnID); fColumnName = TRUE; switch (pColumnID->eKind) { case DBKIND_NAME: pwszColumnName = wcsDuplicate(pColumnID->uName.pwszName); fProps = fProps && GetIndexValue(&pwszColumnName, &fColumnName, rgDBBINDING, nCOLUMN_NAME, DBTYPE_WSTR, pData, L"ERROR: Column name\n"); SAFE_FREE(pwszColumnName); break; } fCollation = TRUE; iCollation = (short)((DBINDEX_COL_ORDER_ASC == rgIndexColumnDesc[uiOrdinalPosition-1].eIndexColOrder) ? DB_COLLATION_ASC: DB_COLLATION_DESC); fProps = fProps && GetIndexValue(&iCollation, &fCollation, rgDBBINDING, nCOLLATION, DBTYPE_I2, pData, L"ERROR: Collation\n"); rgColPresent[uiOrdinalPosition-1] = TRUE; nColPresent++; } if (cPropertySets > 0 && rgPropertySets) { fProps = fProps && GetIndexValueFromFirstRow(&vbAutoUpdate, &fAutoUpdate, rgDBBINDING, nAUTO_UPDATE, DBTYPE_BOOL, pData, DBPROP_INDEX_AUTOUPDATE, cPropertySets, rgPropertySets, L"ERROR: Auto update\n"); fProps = fProps && GetIndexValueFromFirstRow(&vbClustered, &fClustered, rgDBBINDING, nCLUSTERED, DBTYPE_BOOL, pData, DBPROP_INDEX_CLUSTERED, cPropertySets, rgPropertySets, L"ERROR: Clustered\n"); fProps = fProps && GetIndexValueFromFirstRow(&lFillFactor, &fFillFactor, rgDBBINDING, nFILL_FACTOR, DBTYPE_I4, pData, DBPROP_INDEX_FILLFACTOR, cPropertySets, rgPropertySets, L"ERROR: Fill factor\n"); fProps = fProps && GetIndexValueFromFirstRow(&lInitialSize, &fInitialSize, rgDBBINDING, nINITIAL_SIZE, DBTYPE_I4, pData, DBPROP_INDEX_INITIALSIZE, cPropertySets, rgPropertySets, L"ERROR: Initial Size\n"); fProps = fProps && GetIndexValueFromFirstRow(&lNullCollation, &fNullCollation, rgDBBINDING, nNULL_COLLATION, DBTYPE_I4, pData, DBPROP_INDEX_NULLCOLLATION, cPropertySets, rgPropertySets, L"ERROR: Null Collation\n"); fProps = fProps && GetIndexValueFromFirstRow(&lNulls, &fNulls, rgDBBINDING, nNULLS, DBTYPE_I4, pData, DBPROP_INDEX_NULLS, cPropertySets, rgPropertySets, L"ERROR: Nulls\n"); fProps = fProps && GetIndexValueFromFirstRow(&vbPrimaryKey, &fPrimaryKey, rgDBBINDING, nPRIMARY_KEY, DBTYPE_BOOL, pData, DBPROP_INDEX_PRIMARYKEY, cPropertySets, rgPropertySets, L"ERROR: Primary Key\n"); fProps = fProps && GetIndexValueFromFirstRow(&vbSortBookmarks, &fSortBookmarks, rgDBBINDING, nSORT_BOOKMARKS, DBTYPE_BOOL, pData, DBPROP_INDEX_SORTBOOKMARKS, cPropertySets, rgPropertySets, L"ERROR: SortBookmarks\n"); fProps = fProps && GetIndexValueFromFirstRow(&usType, &fType, rgDBBINDING, nTYPE, DBTYPE_UI2, pData, DBPROP_INDEX_TYPE, cPropertySets, rgPropertySets, L"ERROR: Type\n"); fProps = fProps && GetIndexValueFromFirstRow(&vbUnique, &fUnique, rgDBBINDING, nUNIQUE, DBTYPE_BOOL, pData, DBPROP_INDEX_UNIQUE, cPropertySets, rgPropertySets, L"ERROR: Unique\n"); } TESTC_(pIndexRowset->ReleaseRows(1, &hRow, NULL, NULL, NULL), S_OK); // Get data for each row for(iRow=1;iRowGetNextRows(0, 0, 1, &cRowsObtained, &phRow), S_OK); TESTC_((long)cRowsObtained, 1); TESTC_(hr=pIndexRowset->GetData(hRow, hAccessor, pData),S_OK); // check that the properties are the same: fProps = fProps && GetIndexValue(&pwszIndexName, &fIndexName, rgDBBINDING, nINDEX_NAME, DBTYPE_WSTR, pData, L"ERROR: Bad index name\n"); fProps = fProps && GetIndexValue(&pwszTableName, &fTableName, rgDBBINDING, nTABLE_NAME, DBTYPE_WSTR, pData, L"ERROR: Bad table name\n"); // check column ordinal and name fOrdinalPosition = FALSE; fProps = fProps && GetIndexValue(&uiOrdinalPosition, &fOrdinalPosition, rgDBBINDING, nORDINAL_POSITION, DBTYPE_UI2, pData, L"ERROR: OrdinalPosition\n"); if (fOrdinalPosition) { TESTC(cIndexColumnDesc >= uiOrdinalPosition); DBID *pColumnID = rgIndexColumnDesc[uiOrdinalPosition-1].pColumnID; // can compare both column name and collation order TESTC(NULL != pColumnID); fColumnName = TRUE; switch (pColumnID->eKind) { case DBKIND_NAME: pwszColumnName = wcsDuplicate(pColumnID->uName.pwszName); fProps = fProps && GetIndexValue(&pwszColumnName, &fColumnName, rgDBBINDING, nCOLUMN_NAME, DBTYPE_WSTR, pData, L"ERROR: Column name\n"); SAFE_FREE(pwszColumnName); break; default: break; } fCollation = TRUE; iCollation = (short)((DBINDEX_COL_ORDER_ASC == rgIndexColumnDesc[uiOrdinalPosition-1].eIndexColOrder) ? DB_COLLATION_ASC: DB_COLLATION_DESC); fProps = fProps && GetIndexValue(&iCollation, &fCollation, rgDBBINDING, nCOLLATION, DBTYPE_I2, pData, L"ERROR: Collation\n"); rgColPresent[uiOrdinalPosition-1] = TRUE; nColPresent++; } fProps = fProps && GetIndexValue(&vbAutoUpdate, &fAutoUpdate, rgDBBINDING, nAUTO_UPDATE, DBTYPE_BOOL, pData, L"ERROR: Auto update\n"); fProps = fProps && GetIndexValue(&vbClustered, &fClustered, rgDBBINDING, nCLUSTERED, DBTYPE_BOOL, pData, L"ERROR: Clustered\n"); fProps = fProps && GetIndexValue(&lFillFactor, &fFillFactor, rgDBBINDING, nFILL_FACTOR, DBTYPE_I4, pData, L"ERROR: Fill factor\n"); fProps = fProps && GetIndexValue(&lInitialSize, &fInitialSize, rgDBBINDING, nINITIAL_SIZE, DBTYPE_I4, pData, L"ERROR: Initial Size\n"); fProps = fProps && GetIndexValue(&lNullCollation, &fNullCollation, rgDBBINDING, nNULL_COLLATION, DBTYPE_I4, pData, L"ERROR: Null Collation\n"); fProps = fProps && GetIndexValue(&lNulls, &fNulls, rgDBBINDING, nNULLS, DBTYPE_I4, pData, L"ERROR: Nulls\n"); fProps = fProps && GetIndexValue(&vbPrimaryKey, &fPrimaryKey, rgDBBINDING, nPRIMARY_KEY, DBTYPE_BOOL, pData, L"ERROR: Primary Key\n"); fProps = fProps && GetIndexValue(&vbSortBookmarks, &fSortBookmarks, rgDBBINDING, nSORT_BOOKMARKS, DBTYPE_BOOL, pData, L"ERROR: SortBookmarks\n"); fProps = fProps && GetIndexValue(&usType, &fType, rgDBBINDING, nTYPE, DBTYPE_UI2, pData, L"ERROR: Type\n"); fProps = fProps && GetIndexValue(&vbUnique, &fUnique, rgDBBINDING, nUNIQUE, DBTYPE_BOOL, pData, L"ERROR: Unique\n"); TESTC_(pIndexRowset->ReleaseRows(1, &hRow, NULL, NULL, NULL), S_OK); } if ((nColPresent == cIndexColumnDesc) && fProps) fReturn = TRUE; CLEANUP: // Free the memory SAFE_FREE(pwszIndexName); SAFE_FREE(pwszTableName); SAFE_FREE(rgColPresent); SAFE_FREE(prgRestrictions); SAFE_FREE(prgSchemas); SAFE_FREE(pData); SAFE_RELEASE(pIndexRowset); SAFE_FREE(rgDBBINDING); for(index=0;index ListNativeTemp; CList ListDataTypes; ULONG cSchema = 0; // number of supported Schemas ULONG *prgRestrictions= NULL; // restrictions for each Schema GUID *prgSchemas = NULL; // array of GUIDs VARIANT vVal; IIndexDefinition *pIIndexDefinition = NULL; m_pCIIndexDefinition = NULL; // m_pIIndexDefinition = NULL; m_pIDBSchemaRowset = NULL; m_pwszInvalidTableChars = NULL; m_pwszInvalidIndexChars = NULL; m_pwszInvalidColumnChars = NULL; if(CSessionObject::Init()) { // check for IIndexDefinition SetDataSourceObject(m_pThisTestModule->m_pIUnknown, TRUE); SetDBSession(m_pThisTestModule->m_pIUnknown2); GetLiteralInfo(); if (!(m_hr=VerifyInterface(m_pIOpenRowset, IID_IIndexDefinition, SESSION_INTERFACE, (IUnknown**)&pIIndexDefinition))) { odtLog << L"IIndexDefinition is not implemented\n"; return FALSE; } //wrap pIIndexDefinition in the helper class m_pCIIndexDefinition = new CIIndexDefinition(pIIndexDefinition); // check whether IDBSchemaRowset is available if (!(m_hr=VerifyInterface( m_pIOpenRowset, IID_IDBSchemaRowset, SESSION_INTERFACE, (IUnknown**)&m_pIDBSchemaRowset))) odtLog << L"IDBSchemaRowset is not implemented\n"; else { // check whether it supports INDEXES Schema Rowset and its restrictions if (S_OK == (m_hr = m_pIDBSchemaRowset->GetSchemas(&cSchema, &prgSchemas, &prgRestrictions))) { for(i=0; i= cSchema) || !(prgRestrictions[i] & 0x4) || !(prgRestrictions[i] & 0x10)) { SAFE_RELEASE(m_pIDBSchemaRowset); odtLog << "INDEXES Schema Rowset or table and index restrictions are not supported \n"; } } if (prgSchemas) SAFE_FREE(prgSchemas); if (prgRestrictions) SAFE_FREE(prgRestrictions); } // create a table and get info about all the data types GetModInfo()->UseITableDefinition(TRUE); m_pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName); TESTC(NULL != m_pTable); m_pPopulatedTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName); TESTC(NULL != m_pPopulatedTable); // get the provider types list m_pTable->CreateColInfo(ListNativeTemp, ListDataTypes, ALLTYPES); // Make all columns non-Nullable MakeColsNullable(m_pTable, FALSE); // get the column description array TESTC_(m_pTable->BuildColumnDescs(&m_rgColumnDesc), S_OK); m_cColumnDesc=m_pTable->CountColumnsOnTable(); m_pTable->SetColumnDesc(m_rgColumnDesc, m_cColumnDesc); m_pTable->SetBuildColumnDesc(FALSE); TESTC(SUCCEEDED(m_hr = m_pTable->CreateTable(0, 0))); m_pTable->DuplicateColList(m_ColList); m_pPopulatedTable->SetColumnDesc(m_rgColumnDesc, m_cColumnDesc); m_pPopulatedTable->SetBuildColumnDesc(FALSE); TESTC(SUCCEEDED(m_hr = m_pPopulatedTable->CreateTable(0, 0))); // check whether IRowsetIndex is available rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; m_nIndex = 0; SAFE_ALLOC(m_rgIndexCols, DBORDINAL, m_cColumnDesc); m_cIndexCols = 0; for (i=0; iCreateIndex(&(m_pTable->GetTableID()), NULL, 1, rgIndexColumnDesc, 0, NULL, &pIndexID))) { m_nIndex = i+1; m_rgIndexCols[m_cIndexCols++] = m_nIndex; } if (pIndexID) { m_pCIIndexDefinition->DropIndex(&(m_pTable->GetTableID()), pIndexID); ReleaseDBID(pIndexID); pIndexID = NULL; } } // if I succeed to create some index, try to open an RowsetIndex on it // m_fIRowsetIndex = FALSE; m_fSupportORS = SupportedProperty(DBPROP_OPENROWSETSUPPORT, DBPROPSET_DATASOURCEINFO); m_fORSIndex = m_fSupportORS && GetProperty(DBPROP_OPENROWSETSUPPORT, DBPROPSET_DATASOURCEINFO, *m_pCIIndexDefinition, &vVal) && VT_I4 == vVal.vt && (vVal.lVal & DBPROPVAL_ORS_INDEX); m_fORSIntegratedIndex = m_fSupportORS && GetProperty(DBPROP_OPENROWSETSUPPORT, DBPROPSET_DATASOURCEINFO, *m_pCIIndexDefinition, &vVal) && VT_I4 == vVal.vt && (vVal.lVal & DBPROPVAL_ORS_INTEGRATEDINDEX); if (m_fORSIntegratedIndex && !COMPARE(m_fORSIndex, TRUE)) return FALSE; if (m_cIndexCols>0) { rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[m_rgIndexCols[0]].dbcid; if (SUCCEEDED(m_hr = m_pCIIndexDefinition->CreateIndex(&(m_pTable->GetTableID()), NULL, 1, rgIndexColumnDesc, 0, NULL, &pIndexID))) m_hr = m_pIOpenRowset->OpenRowset( NULL, &(m_pTable->GetTableID()), pIndexID, IID_IRowsetIndex, 0, NULL, (IUnknown**)&pIRowsetIndex ); if (m_fORSIndex && !CHECK(m_hr, S_OK)) return FALSE; if (S_OK == m_hr) { CIIndexDefinition::s_fIRowsetIndex = TRUE; //m_fIRowsetIndex = TRUE; SAFE_RELEASE(pIRowsetIndex); } if (pIndexID) { m_pCIIndexDefinition->DropIndex(&(m_pTable->GetTableID()), pIndexID); ReleaseDBID(pIndexID); pIndexID = NULL; } } else return FALSE; if (CIIndexDefinition::s_fIRowsetIndex) { odtLog << "there is IRowsetIndex\n"; CIIndexDefinition::s_fIRowsetIndex = GetModInfo()->IsUsingIRowsetIndex(); if (!CIIndexDefinition::s_fIRowsetIndex) odtLog << "but it is overridden\n"; } else odtLog << "there is not IRowsetIndex\n"; if ((NULL == m_pIDBSchemaRowset) && (FALSE == CIIndexDefinition::s_fIRowsetIndex)) { odtLog << "can not perform the test\n"; return FALSE; } return TRUE; } CLEANUP: return FALSE; } //TCIIndexDefinition::Init //*----------------------------------------------------------------------- // // @mfunc TestCase Termination Routine // // @rdesc TEST_PASS or TEST_FAIL //------------------------------------------------------------------------- BOOL TCIIndexDefinition::Terminate() { m_pTable->SetColumnDesc(NULL); m_pPopulatedTable->SetColumnDesc(NULL); ReleaseColumnDesc(m_rgColumnDesc, m_cColumnDesc); SAFE_DELETE(m_pCIIndexDefinition); if (m_pTable) { m_pTable->DropTable(); delete m_pTable; m_pTable = NULL; } if (m_pPopulatedTable) { m_pPopulatedTable->DropTable(); delete m_pPopulatedTable; m_pPopulatedTable = NULL; } m_ColList.RemoveAll(); // SAFE_RELEASE(m_pIIndexDefinition); SAFE_RELEASE(m_pIDBSchemaRowset); SAFE_FREE(m_pwszInvalidTableChars); SAFE_FREE(m_pwszInvalidIndexChars); SAFE_FREE(m_pwszInvalidColumnChars); SAFE_FREE(m_rgIndexCols); ReleaseDBSession(); ReleaseDataSourceObject(); return(CSessionObject::Terminate()); } //TCIIndexDefinition::Terminate //------------------------------------------------------------------------- // // @cmember Set a property in the property sets of a DBCOLUMNDESC //------------------------------------------------------------------------- BOOL TCIIndexDefinition::SetProperty ( DBPROPSET **prgPropertySets, // [in/out] array of property sets ULONG *pcPropertySets, // [in/out] number of property sets DBPROPID propID, // [in] property ID DBTYPE wType, // [in] value type LPVOID value, // [in] property value DBPROPOPTIONS dwOption, // [in] prop options DBID colid, // [in] col id GUID guidPropertySet, // [in] the GUID of the propset ULONG *pcPropSet/*=NULL*/,// [out] index of property set where the prop was set ULONG *pcProp/*=NULL*/ // [out] index in the rgProperties array ) { LONG i; DBPROPSET *pPropSet; BOOL fRes = FALSE, fFound; TESTC(::SetProperty(propID, guidPropertySet, pcPropertySets, prgPropertySets, value, wType, dwOption, colid)); if (!pcPropSet || !pcProp) { fRes = TRUE; goto CLEANUP; } for (i=*pcPropertySets - 1, fFound = FALSE; i >= 0 && !fFound; i--) { fFound = (*prgPropertySets)[i].guidPropertySet == guidPropertySet; *pcPropSet = i; } TESTC(fFound); pPropSet = &(*prgPropertySets[*pcPropSet]); for (i=pPropSet->cProperties - 1, fFound = FALSE; i >= 0 && !fFound; i--) { fFound = pPropSet->rgProperties[i].dwPropertyID == propID; *pcProp = i; } TESTC(fFound); fRes = TRUE; CLEANUP: return fRes; } //TCIIndexDefinition::SetProperty /* //--------------------------------------------------------------------------- // TCIIndexDefinition::DoesIndexExistInIndexSchemaRowset // // TCIIndexDefinition | // DoesIndexExist | // If this index is on this table return true. If function runs correctly // but doesn't find the table name, function will return S_OK, but fExists // will be FALSE. If strIndexName is empty, returns E_FAIL. The index is sought in // index schema rowset. // // @mfunc DoesIndexExist // @rdesc HRESULT indicating success or failure // @flag S_OK | Function ran without problem // @flag E_FAIL | Function ran with problems // //--------------------------------------------------------------------------- HRESULT TCIIndexDefinition::DoesIndexExistInIndexSchemaRowset( DBID *pTableID, // @parm [IN] Table ID DBID *pIndexID, // @parm [IN] Index ID BOOL *fExists, // @parm [OUT] TRUE if index exists BOOL fAnyIndex // @parm [IN] TRUE if search for all indexes // DEFAULT FALSE ) { HRESULT hr = E_FAIL; DBCOUNTITEM cRowsObtained = 0; // number of rows returned, should be 1 HROW *rghRows = NULL; // array of handles of rows IRowset *pIRowset = NULL; // returned rowset const int cRest = 5; // restrictions on INDEXES Schema Rowset VARIANT rgRestrictIndexes[cRest]; ULONG index; // Set restrictions for(index=0;indexuName.pwszName); } if (pTableID) { rgRestrictIndexes[4].vt = VT_BSTR; rgRestrictIndexes[4].bstrVal = SysAllocString(pTableID->uName.pwszName); } if (!CHECK(hr = m_pIDBSchemaRowset->GetRowset( NULL, // aggregation DBSCHEMA_INDEXES, // REFGUID cRest, // count of restrictions (1:types) rgRestrictIndexes, // list of restrictions IID_IRowset, // REFFID 0, // count of properties NULL, // range of properties (IUnknown**)&pIRowset // returned result set ),S_OK)) goto CLEANUP; // Only do this once, if there is a rowset then // there is a table already in the data source hr=pIRowset->GetNextRows(0, 0, 1, &cRowsObtained, &rghRows); if (fExists) *fExists = (1 == cRowsObtained); CHECK(hr=pIRowset->ReleaseRows(cRowsObtained,rghRows,NULL,NULL,NULL),S_OK); if(FAILED(hr)) goto CLEANUP; CLEANUP: SAFE_RELEASE(pIRowset); SAFE_FREE(rghRows); for(index=0;indexOpenRowset(NULL, pTableID, pIndexID, IID_IRowsetIndex, 0, NULL, (IUnknown**)&pRowsetIndex); if (fExist) *fExist = (S_OK == hr)? TRUE: FALSE; SAFE_RELEASE(pRowsetIndex); return S_OK; } //TCIIndexDefinition::DoesIndexExistRowsetIndex //--------------------------------------------------------------------------- // TCIIndexDefinition::DoesIndexExist // // TCIIndexDefinition | // DoesIndexExist | // If this index is on this table return true If function runs correctly // but doesn't find the table name, function will return S_OK, but fExists // will be FALSE. If strIndexName is empty, returns E_FAIL. // // @mfunc DoesIndexExist // @rdesc HRESULT indicating success or failure // @flag S_OK | Function ran without problem // @flag E_FAIL | Function ran with problems // //--------------------------------------------------------------------------- HRESULT TCIIndexDefinition::DoesIndexExist( DBID *pTableID, // @parm [IN] Table ID DBID *pIndexID, // @parm [IN] Index ID BOOL *pfExists, // @parm [OUT] TRUE if index exists BOOL fAnyIndex // @parm [IN] TRUE if search for all indexes // DEFAULT FALSE ) { if (!pfExists) return E_INVALIDARG; if (fAnyIndex) if (m_pIDBSchemaRowset) return DoesIndexExistInIndexSchemaRowset(pTableID, NULL, pfExists, fAnyIndex); else { odtLog << "WARNING: IDBSchemaRowset is not supported\n"; *pfExists = FALSE; return DB_S_ERRORSOCCURRED; } if (m_fIRowsetIndex) return DoesIndexExistRowsetIndex(pTableID, pIndexID, pfExists); if (m_pIDBSchemaRowset) return DoesIndexExistInIndexSchemaRowset(pTableID, pIndexID, pfExists); PRVTRACE("**TCIIndexDefinition::DoesIndexExist: how did I get here?\n"); return E_FAIL; } //TCIIndexDefinition::DoesIndexExist */ //------------------------------------------------------------------------- // // @cmember create an index out of column numbers // creates, checks it and then drops it // index size == 1 //------------------------------------------------------------------------- BOOL TCIIndexDefinition::CreateIndexWithOneProperty( ULONG nValues, // [in] elements in the array VARIANT *rgValues, // [in] the values to be checked DBPROPID dwPropID, // [in] prop id GUID guidPropertySet // [in] ) // it supposes that the value are not repeating! { ULONG i; HRESULT hr; DBPROPSET rgPropSets; DBPROP rgProp; BOOL fResult = TRUE; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; VARIANT *pvValue = NULL; ULONG nOptional=0, nRequired=0; BOOL fSupported; BOOL fSettable; fSupported = SupportedProperty(dwPropID, guidPropertySet); fSettable = SettableProperty(dwPropID, guidPropertySet); hr = S_OK; rgIndexColumnDesc[0].pColumnID = NULL; // protection for jump to CLEANUP; FILL_PROP_SET(rgPropSets, 1, &rgProp, guidPropertySet); memset(&rgProp.colid, 0, sizeof(DBID)); rgProp.dwPropertyID = dwPropID; // prepare parameters SAFE_ALLOC(rgIndexColumnDesc[0].pColumnID, DBID, 1); DuplicateDBID(m_rgColumnDesc[m_nIndex-1].dbcid, rgIndexColumnDesc[0].pColumnID); rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; for (i=0; iCreateCheckAndDropIndex( &(m_pTable->GetTableID()), NULL, 1, rgIndexColumnDesc, 1, &rgPropSets); if (S_OK == hr) { nOptional++; odtLog << "\tS_OK\n"; if (!COMPARE(rgProp.dwStatus, DBPROPSTATUS_OK)) fResult = FALSE; } else if (DB_S_ERRORSOCCURRED == hr) { odtLog << "\tDB_S_ERRORSOCCURRED\n"; } else { odtLog << "\tERROR\n"; CHECK(hr, DB_S_ERRORSOCCURRED); fResult = FALSE; } rgProp.dwOptions = DBPROPOPTIONS_REQUIRED; odtLog << "\tDBPROPOPTIONS_REQUIRED:"; hr = m_pCIIndexDefinition->CreateCheckAndDropIndex( &m_pTable->GetTableID(), NULL, 1, rgIndexColumnDesc, 1, &rgPropSets); if (S_OK == hr) { nRequired++; odtLog << "\tS_OK\n"; } else if (DB_E_ERRORSOCCURRED == hr) { odtLog << "\tDB_E_ERRORSOCCURRED\n"; if (!CHECK(DBPROPSTATUS_OK == rgProp.dwStatus, FALSE)) fResult = FALSE; } else { odtLog << "\tERROR\n"; CHECK(hr, DB_E_ERRORSOCCURRED); fResult = FALSE; } } if (DBPROPSET_INDEX == guidPropertySet && fSupported && !fSettable && (nOptional>1 || nRequired > 1)) { odtLog << "ERROR: a read-only property could be set to several values!\n"; fResult = FALSE; } CLEANUP: ReleaseDBID(rgIndexColumnDesc[0].pColumnID); return fResult; } //TCIIndexDefinition::CreateIndexWithOneProperty //------------------------------------------------------------------------- // // @cmember create an index out of column numbers // creates, checks it and then drops it // index size == 1 //------------------------------------------------------------------------- BOOL TCIIndexDefinition::CreateIndexWithOneLogicalProperty( DBPROPID dwPropID, // [in] prop id GUID guidPropertySet // [in] ) { VARIANT values[2]; values[0].vt = values[1].vt = VT_BOOL; V_BOOL(&values[0]) = VARIANT_TRUE; V_BOOL(&values[1]) = VARIANT_FALSE; return CreateIndexWithOneProperty(2, values, dwPropID, guidPropertySet); } //TCIIndexDefinition::CreateIndexWithOneLogicalProperty //------------------------------------------------------------------------- // // GetLiteralInfo //------------------------------------------------------------------------- HRESULT TCIIndexDefinition::GetLiteralInfo() { IDBInfo* pInterface = NULL; const int nLiteral=3; DBLITERAL rgLiteral[nLiteral]={DBLITERAL_TABLE_NAME, DBLITERAL_INDEX_NAME, DBLITERAL_COLUMN_NAME}; DBLITERALINFO* rgLiteralInfo = NULL; ULONG cLiteralInfo, i; OLECHAR* pCharBuffer = NULL; IGetDataSource* pIGetDataSource=NULL; // IGetDataSource interface pointer if(!VerifyInterface(m_pIOpenRowset, IID_IGetDataSource, SESSION_INTERFACE, (IUnknown**)&pIGetDataSource)) return E_FAIL; m_hr=pIGetDataSource->GetDataSource(IID_IDBInfo,(IUnknown**)&pInterface); SAFE_RELEASE(pIGetDataSource); TESTC_(m_hr = pInterface->GetLiteralInfo( nLiteral, rgLiteral, &cLiteralInfo, &rgLiteralInfo, &pCharBuffer), S_OK); for (i=0; i< cLiteralInfo; i++) { switch (rgLiteralInfo[i].lt) { case DBLITERAL_TABLE_NAME: // get the maximum size of a valid table name and the invalid chars for a table name m_cMaxTableName = rgLiteralInfo[i].cchMaxLen; SAFE_FREE(m_pwszInvalidTableChars); m_pwszInvalidTableChars = wcsDuplicate(rgLiteralInfo[i].pwszInvalidChars? rgLiteralInfo[i].pwszInvalidChars: L""); break; case DBLITERAL_INDEX_NAME: m_cMaxIndexName = rgLiteralInfo[i].cchMaxLen; SAFE_FREE(m_pwszInvalidIndexChars); m_pwszInvalidIndexChars = wcsDuplicate(rgLiteralInfo[i].pwszInvalidChars? rgLiteralInfo[i].pwszInvalidChars: L""); break; case DBLITERAL_COLUMN_NAME: // get the maximum size of a valid column name and the invalid chars for a table name m_cMaxColumnName = rgLiteralInfo[i].cchMaxLen; SAFE_FREE(m_pwszInvalidColumnChars); m_pwszInvalidColumnChars = wcsDuplicate(rgLiteralInfo[i].pwszInvalidChars? rgLiteralInfo[i].pwszInvalidChars: L""); break; default: break; } } CLEANUP: SAFE_RELEASE(pInterface); SAFE_FREE(pCharBuffer); SAFE_FREE(rgLiteralInfo); return m_hr; } //TCIIndexDefinition::GetLiteralInfo //------------------------------------------------------------------------- // // @cmember Build a valid table name of a certain length //------------------------------------------------------------------------- WCHAR* TCIIndexDefinition::BuildValidName(size_t length, WCHAR* pattern) { WCHAR* pwszBuffer; size_t cLen = wcslen(pattern), i; i=length+1; SAFE_ALLOC(pwszBuffer, WCHAR, i); memset(pwszBuffer, 0, i*sizeof(WCHAR)); for (i=0; i< length - cLen; i+=cLen) wcscat(pwszBuffer, pattern); // manage the rest of the characters wcsncat(pwszBuffer, pattern, length-i); CLEANUP: return pwszBuffer; } //TCIIndexDefinition::BuildValidName //------------------------------------------------------------------------- // // @cmember Build an invalid table name of a certain length // the pattern is supposed to be shorter than the string to be build //------------------------------------------------------------------------- WCHAR* TCIIndexDefinition::BuildInvalidName(size_t length, WCHAR* pattern, WCHAR* invchars) { WCHAR* pwszBuffer; size_t cLen = wcslen(pattern), i, cInvLen=wcslen(invchars); SAFE_ALLOC(pwszBuffer, WCHAR, length+1); if (length > cInvLen+cLen) { wcscpy(pwszBuffer, pattern); wcscat(pwszBuffer, invchars); } else { wcscpy(pwszBuffer, L"aa"); wcsncat(pwszBuffer, invchars, length-wcslen(pwszBuffer)); return pwszBuffer; } for (i=wcslen(pwszBuffer); i< length - cLen; i+=cLen) wcscat(pwszBuffer, pattern); // manage the rest of the characters for (; i S_OK // // @rdesc TEST_PASS or TEST_FAIL // // tests all the index of length 1 int TCCreateIndex::Variation_2() { DBORDINAL n = m_pPopulatedTable->CountColumnsOnTable(); return S_OK == DoAllIndexes(m_pPopulatedTable, n, 1)? TEST_PASS: TEST_FAIL; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc create an index on an empty table => S_OK // // @rdesc TEST_PASS or TEST_FAIL // // tests all indexes of length 1 int TCCreateIndex::Variation_3() { DBORDINAL n = m_pTable->CountColumnsOnTable(); return S_OK == DoAllIndexes(m_pTable, n, 1)? TEST_PASS: TEST_FAIL; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc create an index on a table created with a SQL command => S_OK // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_4() { BOOL fOldCreateTable; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; CTable *pTable = NULL; DBCOLUMNDESC *rgColumnDesc = NULL; DBORDINAL cColumnDesc = 0; DBORDINAL *rgIndexCols = NULL; DBORDINAL cIndexCols = 0; // set use SQL commands fOldCreateTable = GetModInfo()->UseITableDefinition(FALSE); TESTC_PROVIDER(m_pTable->GetCommandSupOnCTable()); pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName); TESTC(NULL != pTable); TESTC_(m_hr = pTable->CreateTable(0, 0), S_OK); // get the indexable columns on the newly created table pTable->BuildColumnDescs(&rgColumnDesc); cColumnDesc = pTable->CountColumnsOnTable(); FindIndexableColumns(rgColumnDesc, cColumnDesc, &rgIndexCols, &cIndexCols); TESTC(0 < cIndexCols); // try to create an index on the first element of the indexable column TESTC_(CCNDropIndexFromOrdinals(pTable, NULL, rgColumnDesc, cColumnDesc, 1, &rgIndexCols[0], &rgOrder[0]), S_OK); CLEANUP: ReleaseColumnDesc(rgColumnDesc, cColumnDesc); SAFE_FREE(rgIndexCols); if (pTable) { pTable->DropTable(); pTable->SetColumnDesc(NULL, 0); delete pTable; } GetModInfo()->UseITableDefinition(fOldCreateTable); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc create an index and get an IRowsetIndex interface on it => S_OK // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_5() { TBEGIN HRESULT hr; DBINDEX_COL_ORDER rgOrder[] = {DBINDEX_COL_ORDER_ASC}; IRowsetIndex *pIRowsetIndex = NULL; CDBIDPtr IndexID; TESTC_(CNCIndexFromOrdinals(m_pTable, NULL, (DBID**)IndexID, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, &rgOrder[0]), S_OK); // try to open a rowset index on it if (FAILED(hr = m_pIOpenRowset->OpenRowset(NULL, &(m_pTable->GetTableID()), (DBID*)IndexID, IID_IRowsetIndex, 0, NULL, (IUnknown**)&pIRowsetIndex))) { odtLog << "Could not open a RowsetIndex on the table; VARIATION ABORT\n"; TEST2C_(hr, E_NOINTERFACE, DB_E_NOINDEX); } CLEANUP: SAFE_RELEASE(pIRowsetIndex); m_pCIIndexDefinition->DropIndex(&(m_pTable->GetTableID()), (DBID*)IndexID); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc create an index on a table generated with ITableDefinition => S_OK // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_6() { CTable *pTable = NULL; BOOL fTestResult = TEST_FAIL; BOOL fOldCreateTable; DBINDEX_COL_ORDER rgOrder[] = {DBINDEX_COL_ORDER_ASC}; DBCOLUMNDESC *rgColumnDesc = NULL; DBORDINAL cColumnDesc = 0; DBORDINAL *rgIndexCols = NULL; DBORDINAL cIndexCols = 0; ITableDefinition *pITableDefinition = NULL; // set use ITableDefinition fOldCreateTable = GetModInfo()->UseITableDefinition(TRUE); // check ITableDefinition exists TESTC(VerifyInterface(*m_pCIIndexDefinition, IID_ITableDefinition, SESSION_INTERFACE, (IUnknown**)&pITableDefinition)); SAFE_RELEASE(pITableDefinition); pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName); TESTC(NULL != pTable); if (!CHECK(m_hr = pTable->CreateTable(0, 0), S_OK)) { odtLog << "\tcould not create an empty table\n"; goto CLEANUP; } // get the indexable columns on the newly created table pTable->BuildColumnDescs(&rgColumnDesc); cColumnDesc = pTable->CountColumnsOnTable(); FindIndexableColumns(rgColumnDesc, cColumnDesc, &rgIndexCols, &cIndexCols); TESTC(0 < cIndexCols); TESTC_(CCNDropIndexFromOrdinals(pTable, NULL, rgColumnDesc, cColumnDesc, 1, &rgIndexCols[0], rgOrder), S_OK); fTestResult = TEST_PASS; CLEANUP: ReleaseColumnDesc(rgColumnDesc, cColumnDesc); SAFE_FREE(rgIndexCols); if (pTable) { CHECK(pTable->DropTable(), S_OK); delete pTable; } GetModInfo()->UseITableDefinition(fOldCreateTable); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc create an index on a table that has a rowset open on it => S_OK // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_7() { BOOL fTestResult = TEST_FAIL; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; IRowset *pIRowset = NULL; if (!CHECK(m_hr = m_pIOpenRowset->OpenRowset(NULL, &m_pTable->GetTableID(), NULL, IID_IRowset, 0, NULL, (IUnknown**)&pIRowset), S_OK)) { odtLog << "Could not open a Rowset on the table\n"; goto CLEANUP; } m_hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder); if (S_OK == m_hr) fTestResult = TEST_PASS; else if (DB_E_TABLEINUSE == m_hr) { odtLog << "DB_E_TABLEINUSE returned\n"; fTestResult = TEST_PASS; } CLEANUP: SAFE_RELEASE(pIRowset); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc create an index on a table using column names and colID's read from IColumnsInfo // tries to insert 2 indexes: one in which colID are given as GUID and one mixed // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_8() { TBEGIN DBINDEXCOLUMNDESC rgIndexColumnDesc[2]; CCol col; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; col = m_ColList.GetAt(m_ColList.FindIndex(m_rgIndexCols[0]-1)); rgIndexColumnDesc[0].pColumnID = col.GetColID(); odtLog << "index with a column GUID: "; if (!CHECK(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), NULL, 1, rgIndexColumnDesc), DB_E_NOCOLUMN)) { odtLog << "INSUCCESS\n"; goto CLEANUP; } // check names rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[m_rgIndexCols[0]-1].dbcid; // index on 2 columns 1GUID and one as is if (m_cIndexCols < 2) { odtLog << "there are not enough indexable columns on the table\n"; goto CLEANUP; } rgIndexColumnDesc[1].eIndexColOrder = DBINDEX_COL_ORDER_ASC; rgIndexColumnDesc[0].pColumnID = col.GetColID(); rgIndexColumnDesc[1].pColumnID = &m_rgColumnDesc[m_rgIndexCols[1]-1].dbcid; odtLog << "index with a column GUID and a column name"; if (!CHECK(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), NULL, 2, rgIndexColumnDesc), DB_E_NOCOLUMN)) { odtLog << "INSUCCESS\n"; goto CLEANUP; } // need to check name against name! rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[m_rgIndexCols[0]-1].dbcid; CLEANUP: TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(9) //*----------------------------------------------------------------------- // @mfunc include a column twice in an index // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_9() { DBORDINAL rgIndexColumns[]={m_nIndex, m_nIndex}; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC, DBINDEX_COL_ORDER_ASC}; if (S_OK == CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, NUMELEM(rgIndexColumns), rgIndexColumns, rgOrder)) odtLog << "\tcould add a column twice\n"; else odtLog << "\tcould not add a column twice\n"; return TEST_PASS; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(10) //*----------------------------------------------------------------------- // @mfunc create an index on an autoincrement column => S_OK // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_10() { CTable *pTable = NULL; BOOL fTestResult = TEST_SKIPPED; BOOL fOldCreateTable; BOOL flag; DBORDINAL rgIndexColumns[1]; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; DBORDINAL nAutoInc; // index of an autoincrementable column DBORDINAL nIndex; // "array index of the index column" CCol col; DBCOLUMNDESC *pCD = NULL; VARIANT value; ITableDefinition *pITableDefinition = NULL; DBPROPSET *rgPropSets = NULL; ULONG cPropSets = 0; DBCOLUMNDESC *rgColumnDesc = NULL; // set use ITableDefinition fOldCreateTable = GetModInfo()->UseITableDefinition(TRUE); // get sure ITaleDefinition is supported TESTC(VerifyInterface(*m_pCIIndexDefinition, IID_ITableDefinition, SESSION_INTERFACE, (IUnknown**)&pITableDefinition)); SAFE_RELEASE(pITableDefinition); pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName); TESTC(NULL != pTable); // create a table with an autoincrement column pTable->SetBuildColumnDesc(FALSE); DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc); ReleaseAllColumnPropSets(m_cColumnDesc, rgColumnDesc); pTable->SetColumnDesc(rgColumnDesc, m_cColumnDesc); // get an autoincrementable type for (nIndex = 0, flag = FALSE; nIndex< m_cIndexCols && !flag; nIndex++) { // get the column coresponding to the nIndex-th indexable type col = m_pTable->GetColInfoForUpdate(m_rgIndexCols[nIndex]); // check it is autoincrementable flag = (1 == col.CanAutoInc()); if (flag) { nAutoInc = m_rgIndexCols[nIndex]; PRVTRACE(L"autoinc column %d\n", nAutoInc); } } if (!flag) { odtLog << "could not find an autoincrementable type that could generate an index\n"; goto CLEANUP; } // get the autoinc column pCD = &m_rgColumnDesc[nAutoInc-1]; rgPropSets = pCD->rgPropertySets; cPropSets = pCD->cPropertySets; pCD->rgPropertySets = NULL; pCD->cPropertySets = 0; odtLog << "try to create an index on autoincrementable column of type " << pCD->pwszTypeName << "\n"; TESTC(NULL != pCD); // set the column autoinc value.vt = VT_BOOL; V_BOOL(&value)=VARIANT_TRUE; TESTC_(SetProperty(&rgColumnDesc[nAutoInc-1].rgPropertySets, &rgColumnDesc[nAutoInc-1].cPropertySets, DBPROP_COL_AUTOINCREMENT, VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED, DB_NULLID, DBPROPSET_COLUMN), TRUE); if (!CHECK(m_hr = pTable->CreateTable(0, 0), S_OK)) { odtLog << "\tcould not create the table\n"; fTestResult = TEST_FAIL; goto CLEANUP; } rgIndexColumns[0] = nAutoInc; // do not forget the offset fTestResult = (S_OK == (m_hr = CCNDropIndexFromOrdinals(pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, rgIndexColumns, rgOrder)))? TEST_PASS: TEST_FAIL; CLEANUP: if (pCD) { FreeProperties( &pCD->cPropertySets, &pCD->rgPropertySets); pCD->rgPropertySets = rgPropSets; pCD->cPropertySets = cPropSets; } if (pTable) { pTable->DropTable(); delete pTable; } GetModInfo()->UseITableDefinition(fOldCreateTable); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(11) //*----------------------------------------------------------------------- // @mfunc create an index on a column, drop the column // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_11() { TBEGIN HRESULT hr; CTable *pTable; CDBIDPtr IndexID; CCol col; DBINDEX_COL_ORDER rgOrder[] = {DBINDEX_COL_ORDER_ASC}; DBCOLUMNDESC *rgColumnDesc = NULL; DBORDINAL cColumnDesc = 0; DBORDINAL *rgIndexCols = NULL; DBORDINAL cIndexCols = 0; pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName); TESTC(NULL!=pTable); TESTC_(pTable->CreateTable(0, 0), S_OK); // get the indexable columns on the newly created table pTable->BuildColumnDescs(&rgColumnDesc); cColumnDesc = pTable->CountColumnsOnTable(); FindIndexableColumns(rgColumnDesc, cColumnDesc, &rgIndexCols, &cIndexCols); TESTC(0 < cIndexCols); // set an index TESTC_(hr = CNCIndexFromOrdinals(pTable, NULL, (DBID**)IndexID, rgColumnDesc, cColumnDesc, 1, &rgIndexCols[0], rgOrder), S_OK); // expect error when dropping an index column COMPARE(S_OK != (hr = pTable->DropColumn(rgIndexCols[0])), TRUE); CHECK(m_pCIIndexDefinition->DropIndex(&pTable->GetTableID(), (DBID*)IndexID), S_OK); CLEANUP: if (pTable) { pTable->DropTable(); delete pTable; } ReleaseColumnDesc(rgColumnDesc, cColumnDesc); SAFE_FREE(rgIndexCols); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(12) //*----------------------------------------------------------------------- // @mfunc create an index on a view // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_12() { TBEGIN HRESULT hr; CDBIDPtr IndexID; WCHAR wszViewName[]=L"dodoView"; DBID ViewID; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; // since there is a CTable object, we can querry for command support if (!m_pTable->GetCommandSupOnCTable()) { odtLog << "can't run this variation because commands are not supported\n"; TRETURN; } // create a view on the current table if (S_OK != m_pTable->ExecuteCommand(CREATE_VIEW, IID_NULL, wszViewName)) { odtLog << "could not create a view on the base table\n"; goto CLEANUP; } // set an index ViewID.eKind = DBKIND_NAME; ViewID.uName.pwszName = wszViewName; rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[m_nIndex-1].dbcid; //create index on view hr = m_pCIIndexDefinition->CreateIndex(&ViewID, NULL, NUMELEM(rgIndexColumnDesc), rgIndexColumnDesc, 0, NULL, (DBID**)IndexID); if (SUCCEEDED(hr)) { odtLog << "an index on the view was successfully created\n"; CHECK(m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), (DBID*)IndexID), S_OK); } CLEANUP: // drop the view m_pTable->ExecuteCommand(DROP_VIEW, IID_NULL, wszViewName); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(13) //*----------------------------------------------------------------------- // @mfunc create multiple indexes on the same table // // @rdesc TEST_PASS or TEST_FAIL // // 1. tries to create an index for each indexable column in the table // 2. check the number of the successfully created indexes // 3. check the cleanning int TCCreateIndex::Variation_13() { BOOL fTestResult = TEST_PASS; ULONG nIndex = 0; ULONG i; DBID **rgIndexID = NULL; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; ULONG nMaxIndexes = (1+rand()%5) * m_cIndexCols; // create an index array SAFE_ALLOC(rgIndexID, DBID*, nMaxIndexes); rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; for (nIndex=i=0; iCreateIndexAndCheck(&m_pTable->GetTableID(), NULL, 1, rgIndexColumnDesc, 0, NULL, &rgIndexID[nIndex]), S_OK)) nIndex++; else fTestResult = TEST_FAIL; } TESTC(0DropIndex(&m_pTable->GetTableID(), rgIndexID[i]); ReleaseDBID(rgIndexID[i], TRUE); } SAFE_FREE(rgIndexID); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(14) //*----------------------------------------------------------------------- // @mfunc create an index on a table, drop the table and check if the index is dropped as well) // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_14() { TBEGIN BOOL fExists = FALSE; CDBIDPtr IndexID; CCol col; CTable *pTable = NULL; DBINDEX_COL_ORDER rgOrder[] = {DBINDEX_COL_ORDER_ASC}; DBCOLUMNDESC *rgColumnDesc = NULL; DBORDINAL cColumnDesc = 0; DBORDINAL *rgIndexCols = NULL; DBORDINAL cIndexCols = 0; pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName); TESTC(NULL != pTable); if (!CHECK(m_hr = pTable->CreateTable(0, 0), S_OK)) { odtLog << "\tcould not create the table\n"; goto CLEANUP; } // get the indexable columns on the newly created table pTable->BuildColumnDescs(&rgColumnDesc); cColumnDesc = pTable->CountColumnsOnTable(); FindIndexableColumns(rgColumnDesc, cColumnDesc, &rgIndexCols, &cIndexCols); TESTC(0 < cIndexCols); // set an index TESTC_(CNCIndexFromOrdinals(pTable, NULL, (DBID**)IndexID, rgColumnDesc, cColumnDesc, 1, &rgIndexCols[0], &rgOrder[0]), S_OK); // drop the table and check the existence of the index CHECK(m_hr = pTable->DropTable(), S_OK); TESTC(NULL != (DBID*)IndexID); CHECK(m_hr = m_pCIIndexDefinition->DoesIndexExist(NULL, (DBID*)IndexID, &fExists), S_OK); COMPARE(fExists, FALSE); CLEANUP: if (pTable) { m_pCIIndexDefinition->DropIndex(&pTable->GetTableID(), (DBID*)IndexID); m_hr = pTable->DropTable(); delete pTable; } ReleaseColumnDesc(rgColumnDesc, cColumnDesc); SAFE_FREE(rgIndexCols); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(15) //*----------------------------------------------------------------------- // @mfunc create an index on a table; drop a column from index and readd it with another type // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_15() { TBEGIN CTable *pTable = NULL; ULONG k; CDBIDPtr IndexID; CCol col; ITableDefinition *pITableDefinition = NULL; DBCOLUMNDESC *dbCD=NULL; DBINDEX_COL_ORDER rgOrder[] = {DBINDEX_COL_ORDER_ASC}; DBCOLUMNDESC *rgColumnDesc = NULL; DBORDINAL cColumnDesc = 0; DBORDINAL *rgIndexCols = NULL; DBORDINAL cIndexCols = 0; VerifyInterface(*m_pCIIndexDefinition, IID_ITableDefinition, SESSION_INTERFACE, (IUnknown**)&pITableDefinition); pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName); TESTC(NULL != pTable); if (!CHECK(m_hr = pTable->CreateTable(0, 0), S_OK)) { odtLog << "\tcould not create a table\n"; goto CLEANUP; } // get the indexable columns on the newly created table pTable->BuildColumnDescs(&rgColumnDesc); cColumnDesc = pTable->CountColumnsOnTable(); FindIndexableColumns(rgColumnDesc, cColumnDesc, &rgIndexCols, &cIndexCols); TESTC(0 < cIndexCols); // set an index TESTC_(CNCIndexFromOrdinals(pTable, NULL, (DBID**)IndexID, rgColumnDesc, cColumnDesc, 1, &rgIndexCols[0], &rgOrder[0]), S_OK); // try to drop the index column col = pTable->GetColInfoForUpdate(rgIndexCols[0]); if (S_OK == pTable->DropColumn(col)) { TESTC(NULL != pITableDefinition); // try to readd the same column with a different type DuplicateColumnDesc(&m_rgColumnDesc[rgIndexCols[0]-1], 1, &dbCD); SAFE_FREE(dbCD->pwszTypeName); // change the type for (k=0; k < m_cColumnDesc && dbCD->wType != m_rgColumnDesc[k].wType; k++); if (kwType = m_rgColumnDesc[k].wType; m_hr = pITableDefinition->AddColumn(&pTable->GetTableID(), dbCD, NULL); if (S_OK == m_hr) { COMPARE(FALSE, TRUE); odtLog << "column added\n"; } ReleaseColumnDesc(dbCD, 1); } else odtLog << "could not drop the index column\n"; CLEANUP: m_pCIIndexDefinition->DropIndex(&pTable->GetTableID(), (DBID*)IndexID); if (pTable) { pTable->DropTable(); delete pTable; } SAFE_RELEASE(pITableDefinition); ReleaseColumnDesc(rgColumnDesc, cColumnDesc); SAFE_FREE(rgIndexCols); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(16) //*----------------------------------------------------------------------- // @mfunc NULL pointer for pTableID => E_INVALIDARG // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_16() { TBEGIN DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; CDBIDPtr pIndexID = NULL; rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[m_nIndex-1].dbcid; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; if (!CHECK(m_hr = m_pCIIndexDefinition->CreateIndexAndCheck(NULL, NULL, 1, rgIndexColumnDesc, 0, NULL, (DBID**)pIndexID), E_INVALIDARG) && SUCCEEDED(m_hr)) m_pCIIndexDefinition->DropIndex(NULL, pIndexID); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(17) //*----------------------------------------------------------------------- // @mfunc *pTableID == DB_NULLID => DB_E_NOTABLE // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_17() { TBEGIN DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; CDBIDPtr pIndexID; rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[m_nIndex-1].dbcid; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; if (!CHECK(m_hr = m_pCIIndexDefinition->CreateIndexAndCheck((struct tagDBID*)&DB_NULLID, NULL, NUMELEM(rgIndexColumnDesc), rgIndexColumnDesc, 0, NULL, (DBID**)pIndexID), DB_E_NOTABLE) && SUCCEEDED(m_hr)) m_pCIIndexDefinition->DropIndex(NULL, pIndexID); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(18) //*----------------------------------------------------------------------- // @mfunc pTableID->uName.pwszName is NULL => DB_E_NOTABLE // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_18() { TBEGIN DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; CDBIDPtr pIndexID; DBID TableID; rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[m_nIndex-1].dbcid; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; TableID.eKind = DBKIND_NAME; TableID.uName.pwszName = NULL; if ( !CHECK(m_hr = m_pCIIndexDefinition->CreateIndexAndCheck(&TableID, NULL, 1, rgIndexColumnDesc, 0, NULL, (DBID**)pIndexID), DB_E_NOTABLE) && SUCCEEDED(m_hr)) m_pCIIndexDefinition->DropIndex(NULL, pIndexID); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(19) //*----------------------------------------------------------------------- // @mfunc pTableID->uName.pwszName is empty => DB_E_NOTABLE // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_19() { TBEGIN DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; CDBIDPtr pIndexID; DBID TableID; rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[m_nIndex-1].dbcid; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; TableID.eKind = DBKIND_NAME; TableID.uName.pwszName = L""; if ( !CHECK(m_hr = m_pCIIndexDefinition->CreateIndexAndCheck(&TableID, NULL, NUMELEM(rgIndexColumnDesc), rgIndexColumnDesc, 0, NULL, (DBID**)pIndexID), DB_E_NOTABLE) && SUCCEEDED(m_hr)) m_pCIIndexDefinition->DropIndex(NULL, pIndexID); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(20) //*----------------------------------------------------------------------- // @mfunc table name is invalid => DB_E_NOTABLE // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_20() { BOOL fTestResult = TEST_FAIL; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; CDBIDPtr pIndexID; DBID TableID; size_t m, n; rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[m_nIndex-1].dbcid; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; // get an invalid table name TableID.eKind = DBKIND_NAME; m = min(m_cMaxTableName, n=5+wcslen(m_pTable->GetTableName())); TableID.uName.pwszName = BuildInvalidName(m, m_pTable->GetTableName(), m_pwszInvalidTableChars); if ( !CHECK(m_hr = m_pCIIndexDefinition->CreateIndexAndCheck(&TableID, NULL, 1, rgIndexColumnDesc, 0, NULL, (DBID**)pIndexID), DB_E_NOTABLE) && SUCCEEDED(m_hr)) m_pCIIndexDefinition->DropIndex(NULL, pIndexID); ReleaseDBID(&TableID, FALSE); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(21) //*----------------------------------------------------------------------- // @mfunc table name has maximum length => S_OK // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_21() { BOOL fTestResult = TEST_FAIL; DBID TableID; LPWSTR pwszTableName; CTable *pTable = NULL; DBINDEX_COL_ORDER rgOrder[] = {DBINDEX_COL_ORDER_ASC}; DBCOLUMNDESC *rgColumnDesc = NULL; DBORDINAL cColumnDesc = 0;; DBORDINAL *rgIndexCols = NULL; DBORDINAL cIndexCols = 0; // get an valid table name TableID.eKind = DBKIND_NAME; TableID.uName.pwszName = pwszTableName = BuildValidName(m_cMaxTableName, m_pTable->GetTableName()); pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName); TESTC(NULL != pTable); if (!CHECK(m_hr = pTable->CreateTable(0, 0, pwszTableName), S_OK)) { odtLog << "\tcould not create an empty table\n"; goto CLEANUP; } // get the indexable columns on the newly created table pTable->BuildColumnDescs(&rgColumnDesc); cColumnDesc = pTable->CountColumnsOnTable(); FindIndexableColumns(rgColumnDesc, cColumnDesc, &rgIndexCols, &cIndexCols); TESTC(0 < cIndexCols); // set an index TESTC_(CCNDropIndexFromOrdinals(pTable, NULL, rgColumnDesc, cColumnDesc, 1, rgIndexCols, rgOrder), S_OK); fTestResult = TEST_PASS; CLEANUP: if (pTable) { m_hr = pTable->DropTable(); delete pTable; } ReleaseDBID(&TableID, FALSE); ReleaseColumnDesc(rgColumnDesc, cColumnDesc); SAFE_FREE(rgIndexCols); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(22) //*----------------------------------------------------------------------- // @mfunc table name exceeds maximum table name => DB_E_NOTABLE // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_22() { BOOL fTestResult = TEST_FAIL; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; DBID TableID; rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[m_nIndex-1].dbcid; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; // too long table name TableID.eKind = DBKIND_NAME; TableID.uName.pwszName = BuildValidName(m_cMaxTableName+1, m_pTable->GetTableName()); TESTC_(m_pCIIndexDefinition->CreateCheckAndDropIndex(&TableID, NULL, 1, rgIndexColumnDesc), DB_E_NOTABLE); fTestResult = TEST_PASS; CLEANUP: ReleaseDBID(&TableID, FALSE); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(23) //*----------------------------------------------------------------------- // @mfunc NULL pointer for pIndexID and not NULL ppIndexID => S_OK // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_23() { TBEGIN CDBIDPtr IndexID; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; TESTC_(CNCIndexFromOrdinals(m_pTable, NULL, (DBID**)IndexID, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder), S_OK); CLEANUP: CHECK(m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), (DBID*)IndexID), S_OK); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(24) //*----------------------------------------------------------------------- // @mfunc not NULL pointer for pIndexID and NULL ppIndexID =>S_OK // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_24() { DBID IndexID; BOOL fTestResult = TEST_FAIL; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = L"IndiceOarecare"; TESTC_(m_hr = CNCIndexFromOrdinals(m_pTable, &IndexID, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder), S_OK); fTestResult = TEST_PASS; CLEANUP: m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(25) //*----------------------------------------------------------------------- // @mfunc NULL pointer for pIndexID and NULL ppIndexID => E_INVALIDARG // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_25() { BOOL fTestResult = TEST_FAIL; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; TESTC_(m_hr = CNCIndexFromOrdinals(m_pTable, NULL, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder), E_INVALIDARG); fTestResult = TEST_PASS; CLEANUP: // drop all indexes m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), NULL); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(26) //*----------------------------------------------------------------------- // @mfunc *pIndexID == DB_NULLID => DB_E_BADINDEXID // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_26() { BOOL fTestResult = TEST_FAIL; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; TESTC_(m_hr = CCNDropIndexFromOrdinals(m_pTable, (struct tagDBID*)&DB_NULLID, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder), DB_E_BADINDEXID); fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(27) //*----------------------------------------------------------------------- // @mfunc pIndexID->uName.pwszName is NULL => DB_E_BADINDEXID // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_27() { BOOL fTestResult = TEST_FAIL; DBID IndexID; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = NULL; TESTC_(m_hr = CCNDropIndexFromOrdinals(m_pTable, &IndexID, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder), DB_E_BADINDEXID); fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(28) //*----------------------------------------------------------------------- // @mfunc pIndexID->uName.pwszName is empty => DB_E_BADINDEXID // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_28() { BOOL fTestResult = TEST_FAIL; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; DBID IndexID; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = L""; TESTC_(m_hr = CCNDropIndexFromOrdinals(m_pTable, &IndexID, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder), DB_E_BADINDEXID); fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(29) //*----------------------------------------------------------------------- // @mfunc index name is invalid => DB_E_BADINDEXID // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_29() { BOOL fTestResult = TEST_FAIL; DBID IndexID; size_t m, n; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; // get an invalid index name IndexID.eKind = DBKIND_NAME; m = min(m_cMaxIndexName, n=5+wcslen(m_pTable->GetTableName())); IndexID.uName.pwszName = BuildInvalidName(m, m_pTable->GetTableName(), m_pwszInvalidIndexChars); TESTC_(m_hr = CCNDropIndexFromOrdinals(m_pTable, &IndexID, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder), DB_E_BADINDEXID); fTestResult = TEST_PASS; CLEANUP: ReleaseDBID(&IndexID, FALSE); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(30) //*----------------------------------------------------------------------- // @mfunc index name has maximum length => S_OK // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_30() { BOOL fTestResult = TEST_FAIL; DBID IndexID; DBINDEX_COL_ORDER rgOrder[] = {DBINDEX_COL_ORDER_ASC}; // get a maximum length index name IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = BuildValidName(m_cMaxIndexName, m_pTable->GetTableName()); // set an index TESTC_(m_hr = CCNDropIndexFromOrdinals(m_pTable, &IndexID, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder), S_OK); fTestResult = TEST_PASS; CLEANUP: ReleaseDBID(&IndexID, FALSE); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(31) //*----------------------------------------------------------------------- // @mfunc index name exceeds maximum length name => DB_E_BADINDEXID // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_31() { BOOL fTestResult = TEST_FAIL; DBID IndexID; DBINDEX_COL_ORDER rgOrder[] = {DBINDEX_COL_ORDER_ASC}; // get a too long index name IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = BuildValidName(m_cMaxIndexName+1, m_pTable->GetTableName()); TESTC_(m_hr = CCNDropIndexFromOrdinals(m_pTable, &IndexID, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder), DB_E_BADINDEXID); fTestResult = TEST_PASS; CLEANUP: ReleaseDBID(&IndexID, FALSE); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(32) //*----------------------------------------------------------------------- // @mfunc cIndexColumnDesc == 0 => E_INVALIDARG // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_32() { BOOL fTestResult = TEST_FAIL; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; TESTC_(m_hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 0, &m_nIndex, rgOrder), E_INVALIDARG); TESTC_(m_hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 0, NULL, rgOrder), E_INVALIDARG); fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(33) //*----------------------------------------------------------------------- // @mfunc rgIndexColumnDesc == NULL => E_INVALIDARG // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_33() { BOOL fTestResult = TEST_FAIL; TESTC_(m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), NULL, 1, NULL), E_INVALIDARG); TESTC_(m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), NULL, 1, NULL), E_INVALIDARG); fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(34) //*----------------------------------------------------------------------- // @mfunc cPropSets != 0 and rgPropSets == NULL => E_INVALIDARG // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_34() { BOOL fTestResult = TEST_FAIL; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; TESTC_(m_hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, NULL), E_INVALIDARG); fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(35) //*----------------------------------------------------------------------- // @mfunc cPropSets == 0 and rgPropSets == NULL =>S_OK // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_35() { BOOL fTestResult = TEST_FAIL; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; TESTC_(m_hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 0, NULL), S_OK); fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(36) //*----------------------------------------------------------------------- // @mfunc cProperties == 0 and rgProperties != NULL in a rgPropertySets element => S_OK // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_36() { BOOL fTestResult = TEST_FAIL; DBPROPSET rgPropSet[1]; DBPROP rgProp[1]; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; // FILL_PROP_SET(rgPropSet[0], 0, rgProp, DBPROPSET_INDEX) rgPropSet[0].cProperties = 0; rgPropSet[0].rgProperties = rgProp; rgPropSet[0].guidPropertySet = DBPROPSET_INDEX; TESTC_(m_hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, NUMELEM(rgPropSet), rgPropSet), S_OK); fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(37) //*----------------------------------------------------------------------- // @mfunc cProperties == 0 and rgProperties == NULL in an rgPropertySets element => S_OK // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_37() { BOOL fTestResult = TEST_FAIL; DBPROPSET rgPropSet[1]; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; rgPropSet[0].cProperties = 0; rgPropSet[0].rgProperties = NULL; rgPropSet[0].guidPropertySet= DBPROPSET_ROWSET; TESTC_(m_hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, NUMELEM(rgPropSet), rgPropSet), S_OK); fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(38) //*----------------------------------------------------------------------- // @mfunc cProperties != 0 and rgProperties == NULL in an element of rgPropertySets => E_INVALIDARG // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_38() { BOOL fTestResult = TEST_PASS; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; DBPROPSET rgPropSet[1]; rgPropSet[0].cProperties = 2; rgPropSet[0].rgProperties = NULL; rgPropSet[0].guidPropertySet = DBPROPSET_INDEX; TESTC_(m_hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, NUMELEM(rgPropSet), rgPropSet), E_INVALIDARG); fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(39) //*----------------------------------------------------------------------- // @mfunc eIndexColumnDesc invalid for at least one column => E_INVALIDARG // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_39() { BOOL fTestResult = TEST_FAIL; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; const DBINDEX_COL_ORDER InvalidValue = 100; rgIndexColumnDesc[0].eIndexColOrder = InvalidValue; rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[m_nIndex-1].dbcid; TESTC_(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), NULL, NUMELEM(rgIndexColumnDesc), rgIndexColumnDesc), E_INVALIDARG); fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(40) //*----------------------------------------------------------------------- // @mfunc the index is made of all columns // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_40() { BOOL fTestResult = TEST_FAIL; DBINDEX_COL_ORDER *rgOrder=NULL; ULONG i; SAFE_ALLOC(rgOrder, DBINDEX_COL_ORDER, m_cIndexCols); for (i=0; i DB_E_DUPLICATEINDEX // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_41() { BOOL fTestResult = TEST_PASS; BOOL fExists; DBID IndexID; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; WCHAR wszIndexName[] = L"Indexul1"; DB_LORDINAL rgColNo[1]; DB_LORDINAL *prgColNo = rgColNo; DBORDINAL nColNo = NUMELEM(rgColNo); DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; // create an index through SQL and another one with IIndexDefinition IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = wszIndexName; rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[m_nIndex-1].dbcid; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; if (!m_pTable->GetCommandSupOnCTable()) { odtLog << "can not handle commands on tables\n"; goto STEP2; } // Execute statement rgColNo[0] = m_nIndex-1; CHECK(m_hr = m_pTable->ExecuteCommand(CREATE_INDEX, IID_NULL, wszIndexName, NULL, &nColNo, &prgColNo), S_OK); if (S_OK == m_hr && CHECK(m_hr = m_pCIIndexDefinition->DoesIndexExist(&m_pTable->GetTableID(), &IndexID, &fExists), S_OK) && fExists) { // check that is impossible to create another index with the same name on the same table if (!CHECK(m_hr = m_pCIIndexDefinition->CreateIndex(&m_pTable->GetTableID(), &IndexID, NUMELEM(rgIndexColumnDesc), rgIndexColumnDesc, 0, NULL, NULL), DB_E_DUPLICATEINDEXID)) fTestResult = TEST_FAIL; } else fTestResult = TEST_FAIL; // drop indexul1 if (!CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID), S_OK)) { fTestResult = TEST_FAIL; goto CLEANUP; } STEP2: m_hr = CNCIndexFromOrdinals(m_pTable, &IndexID, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder); if (S_OK == m_hr) { // check that is impossible to create another index with the same name on the same table if (!CHECK(m_hr = m_pCIIndexDefinition->CreateIndex(&m_pTable->GetTableID(), &IndexID, NUMELEM(rgIndexColumnDesc), rgIndexColumnDesc, 0, NULL, NULL), DB_E_DUPLICATEINDEXID)) fTestResult = TEST_FAIL; // check that is impossible to create another index with the same name on the same table if (m_pTable->GetCommandSupOnCTable()) { m_hr = m_pTable->ExecuteCommand(CREATE_INDEX, IID_NULL, wszIndexName, NULL, &nColNo, &prgColNo); if (!FAILED(m_hr)) { odtLog << "index duplicate by SQL command\n"; fTestResult = TEST_FAIL; } } } else { odtLog << "could not properly create the index by IIndexDefinition\n"; fTestResult = TEST_FAIL; } // drop indexul1 CHECK(m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID), S_OK); CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(42) //*----------------------------------------------------------------------- // @mfunc Create an index on a single column table // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_42() { CTable *pTable=NULL; BOOL fTestResult = TEST_FAIL; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; DBORDINAL nCol=1; pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName); TESTC(NULL != pTable); pTable->SetBuildColumnDesc(FALSE); pTable->SetColumnDesc(&m_rgColumnDesc[m_nIndex-1], 1); TESTC_(m_hr = pTable->CreateTable(0, 0), S_OK); TESTC_(m_hr = CCNDropIndexFromOrdinals(pTable, NULL, &m_rgColumnDesc[m_nIndex-1], 1, 1, &nCol, rgOrder), S_OK); fTestResult =TEST_PASS; CLEANUP: if (pTable) { pTable->DropTable(); pTable->SetColumnDesc(NULL, 0); delete pTable; } return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(43) //*----------------------------------------------------------------------- // @mfunc all indexes on a 2 columns table // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_43() { CTable *pTable = NULL; BOOL fTestResult = TEST_FAIL; pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName); TESTC(NULL != pTable); pTable->SetBuildColumnDesc(FALSE); pTable->SetColumnDesc(&m_rgColumnDesc[0], 2); TESTC_(m_hr = pTable->CreateTable(0, 0), S_OK); fTestResult = SUCCEEDED(DoAllIndexes(pTable, 2))? TEST_PASS: TEST_FAIL; CLEANUP: if (pTable) { pTable->DropTable(); pTable->SetColumnDesc(NULL, 0); delete pTable; } return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(44) //*----------------------------------------------------------------------- // @mfunc pIndexID and ppIndexID both not NULL => S_OK // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_44() { TBEGIN CDBIDPtr pIndexID; DBID IndexID; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = L"BiancoENero"; TESTC_(m_hr = CNCIndexFromOrdinals(m_pTable, &IndexID, (DBID**)pIndexID, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder), S_OK); COMPARE(CheckReturnedDBID(&IndexID, (DBID**)pIndexID), TRUE); CHECK(m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), (DBID*)pIndexID), S_OK); CLEANUP: TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(45) //*----------------------------------------------------------------------- // @mfunc valid, yet inexistent table name => DB_E_NOTABLE // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_45() { BOOL fTestResult = TEST_FAIL; LPWSTR pwszTableName = wcsDuplicate(m_pTable->GetTableName()); DBID TableID; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[0].dbcid; TableID.eKind = DBKIND_NAME; m_pTable->MakeTableName(NULL); TableID.uName.pwszName = m_pTable->GetTableName(); TESTC_(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&TableID, NULL, 1, rgIndexColumnDesc), DB_E_NOTABLE); fTestResult = TEST_PASS; CLEANUP: m_pTable->SetTableName(pwszTableName); SAFE_FREE(pwszTableName); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(46) //*----------------------------------------------------------------------- // @mfunc inexistent column name => DB_E_NOCOLUMN // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_46() { BOOL fTestResult = TEST_FAIL; DBID colID; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; rgIndexColumnDesc[0].pColumnID = &colID; colID.eKind = DBKIND_NAME; colID.uName.pwszName = L"NumeDeColoana"; TESTC_(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), NULL, 1, rgIndexColumnDesc), DB_E_NOCOLUMN); fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(47) //*----------------------------------------------------------------------- // @mfunc all DBKIND on pTableID // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_47() { BOOL fTestResult = TEST_PASS; DBID TableID; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[0].dbcid; memset(&TableID, 0, sizeof(DBID)); TableID.uName.pwszName = m_pTable->GetTableName(); // DBKIND_NAME TableID.eKind = DBKIND_NAME; if (!CHECK(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&TableID, NULL, 1, rgIndexColumnDesc), S_OK)) { odtLog << "ERROR: DBKIND_NAME\n"; fTestResult = TEST_FAIL; } // DBKIND_GUID_NAME TableID.eKind = DBKIND_GUID_NAME; TableID.uGuid.guid = guidModule; if (!CHECK(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&TableID, NULL, 1, rgIndexColumnDesc), DB_E_NOTABLE)) { odtLog << "ERROR: DBKIND_GUID_NAME\n"; fTestResult = TEST_FAIL; } // DBKIND_PGUID_NAME TableID.eKind = DBKIND_PGUID_NAME; TableID.uGuid.pguid = &guidModule; if (!CHECK(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&TableID, NULL, 1, rgIndexColumnDesc), DB_E_NOTABLE)) { odtLog << "ERROR: DBKIND_PGUID_NAME\n"; fTestResult = TEST_FAIL; } // DBKIND_GUID TableID.eKind = DBKIND_GUID; if (!CHECK(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&TableID, NULL, 1, rgIndexColumnDesc), DB_E_NOTABLE)) { odtLog << "ERROR: DBKIND_GUID\n"; fTestResult = TEST_FAIL; } // DBKIND_GUID_PROPID TableID.uName.ulPropid = 0; TableID.uName.pwszName = NULL; TableID.eKind = DBKIND_GUID_PROPID; if (!CHECK(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&TableID, NULL, 1, rgIndexColumnDesc), DB_E_NOTABLE)) { odtLog << "ERROR: DBKIND_GUID_PROPID\n"; fTestResult = TEST_FAIL; } // DBKIND_PROPID TableID.eKind = DBKIND_PROPID; if (!CHECK(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&TableID, NULL, 1, rgIndexColumnDesc), DB_E_NOTABLE)) { odtLog << "ERROR: DBKIND_PROPID\n"; fTestResult = TEST_FAIL; } // DBKIND_PGUID_PROPID TableID.eKind = DBKIND_PGUID_PROPID; TableID.uGuid.pguid = &guidModule; if (!CHECK(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&TableID, NULL, 1, rgIndexColumnDesc), DB_E_NOTABLE)) { odtLog << "ERROR: DBKIND_PGUID_PROPID\n"; fTestResult = TEST_FAIL; } return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(48) //*----------------------------------------------------------------------- // @mfunc all DBKIND on pColumnID // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_48() { TBEGIN DBID colID, *pIndexID=NULL; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; DBORDINAL *rgIndexCols = NULL; DBORDINAL cIndexCols = 0; FindIndexableColumns(m_rgColumnDesc, m_cColumnDesc, &rgIndexCols, &cIndexCols); TESTC(0 < cIndexCols); rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; rgIndexColumnDesc[0].pColumnID = &colID; colID.uName.pwszName = m_rgColumnDesc[rgIndexCols[0]].dbcid.uName.pwszName; colID.uGuid.pguid = &guidModule; // DBKIND_NAME colID.eKind = DBKIND_NAME; m_hr = m_pCIIndexDefinition->CreateIndex(&m_pTable->GetTableID(), NULL, 1, rgIndexColumnDesc, 0, NULL, &pIndexID); if (!CHECK(m_hr, S_OK)) odtLog << "DBKIND_NAME\n"; ReleaseDBID(pIndexID); pIndexID=NULL; // DBKIND_GUID_NAME colID.eKind = DBKIND_GUID_NAME; colID.uGuid.guid = guidModule; m_hr = m_pCIIndexDefinition->CreateIndex(&m_pTable->GetTableID(), NULL, 1, rgIndexColumnDesc, 0, NULL, &pIndexID); if (!CHECK(m_hr, DB_E_NOCOLUMN)) odtLog << "DBKIND_GUID_NAME\n"; ReleaseDBID(pIndexID); pIndexID=NULL; // DBKIND_PGUID_NAME colID.eKind = DBKIND_PGUID_NAME; colID.uGuid.pguid = &guidModule; m_hr = m_pCIIndexDefinition->CreateIndex(&m_pTable->GetTableID(), NULL, 1, rgIndexColumnDesc, 0, NULL, &pIndexID); if (!CHECK(m_hr, DB_E_NOCOLUMN)) odtLog << "DBKIND_PGUID_NAME\n"; ReleaseDBID(pIndexID); pIndexID=NULL; // DBKIND_GUID colID.eKind = DBKIND_GUID; colID.uGuid.guid = guidModule; m_hr = m_pCIIndexDefinition->CreateIndex(&m_pTable->GetTableID(), NULL, 1, rgIndexColumnDesc, 0, NULL, &pIndexID); if (!CHECK(m_hr, DB_E_NOCOLUMN)) odtLog << "DBKIND_GUID\n"; ReleaseDBID(pIndexID); pIndexID=NULL; colID.uName.ulPropid = 0; colID.uName.pwszName = NULL; // DBKIND_GUID_PROPID colID.eKind = DBKIND_GUID_PROPID; colID.uGuid.guid = guidModule; m_hr = m_pCIIndexDefinition->CreateIndex(&m_pTable->GetTableID(), NULL, 1, rgIndexColumnDesc, 0, NULL, &pIndexID); if (!CHECK(m_hr, DB_E_NOCOLUMN)) odtLog << "DBKIND_GUID_PROPID\n"; ReleaseDBID(pIndexID); pIndexID=NULL; // DBKIND_PROPID colID.eKind = DBKIND_PROPID; m_hr = m_pCIIndexDefinition->CreateIndex(&m_pTable->GetTableID(), NULL, 1, rgIndexColumnDesc, 0, NULL, &pIndexID); if (!CHECK(m_hr, DB_E_NOCOLUMN)) odtLog << "DBKIND_PROPID\n"; ReleaseDBID(pIndexID); pIndexID=NULL; // DBKIND_PGUID_PROPID colID.eKind = DBKIND_PGUID_PROPID; colID.uGuid.pguid = &guidModule; m_hr = m_pCIIndexDefinition->CreateIndex(&m_pTable->GetTableID(), NULL, 1, rgIndexColumnDesc, 0, NULL, &pIndexID); if (!CHECK(m_hr, DB_E_NOCOLUMN)) odtLog << "DBKIND_PGUID_PROPID\n"; ReleaseDBID(pIndexID); CLEANUP: SAFE_FREE(rgIndexCols); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(49) //*----------------------------------------------------------------------- // @mfunc all DBKIND on pIndexID // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_49() { BOOL fTestResult = TEST_PASS; DBID IndexID; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[0].dbcid; memset(&IndexID, 0, sizeof(DBID)); IndexID.uName.pwszName = L"galusca"; // DBKIND_NAME IndexID.eKind = DBKIND_NAME; odtLog << "DBKIND_NAME: "; m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), &IndexID, 1, rgIndexColumnDesc); if (S_OK ==m_hr) odtLog << "CREATED\n"; else { odtLog << "NOT created\n"; if (!CHECK(m_hr, DB_E_BADINDEXID)) fTestResult = TEST_FAIL; } // DBKIND_GUID_NAME IndexID.eKind = DBKIND_GUID_NAME; IndexID.uGuid.guid = guidModule; odtLog << "DBKIND_GUID_NAME: "; m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), &IndexID, 1, rgIndexColumnDesc); if (S_OK ==m_hr) odtLog << "CREATED\n"; else { odtLog << "NOT created\n"; if (!CHECK(m_hr, DB_E_BADINDEXID)) fTestResult = TEST_FAIL; } // DBKIND_PGUID_NAME IndexID.eKind = DBKIND_PGUID_NAME; IndexID.uGuid.pguid = &guidModule; odtLog << "DBKIND_PGUID_NAME: "; m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), &IndexID, 1, rgIndexColumnDesc); if (S_OK ==m_hr) odtLog << "CREATED\n"; else { odtLog << "NOT created\n"; if (!CHECK(m_hr, DB_E_BADINDEXID)) fTestResult = TEST_FAIL; } // DBKIND_GUID IndexID.eKind = DBKIND_GUID; odtLog << "DBKIND_GUID: "; m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), &IndexID, 1, rgIndexColumnDesc); if (S_OK ==m_hr) odtLog << "CREATED\n"; else { odtLog << "NOT created\n"; if (!CHECK(m_hr, DB_E_BADINDEXID)) fTestResult = TEST_FAIL; } IndexID.uName.ulPropid = 0; IndexID.uName.pwszName = NULL; // DBKIND_GUID_PROPID IndexID.eKind = DBKIND_GUID_PROPID; odtLog << "DBKIND_GUID_PROPID: "; m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), &IndexID, 1, rgIndexColumnDesc); if (S_OK ==m_hr) odtLog << "CREATED\n"; else { odtLog << "NOT created\n"; if (!CHECK(m_hr, DB_E_BADINDEXID)) fTestResult = TEST_FAIL; } // DBKIND_PROPID IndexID.eKind = DBKIND_PROPID; odtLog << "DBKIND_PROPID: "; m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), &IndexID, 1, rgIndexColumnDesc); if (S_OK ==m_hr) odtLog << "CREATED\n"; else { odtLog << "NOT created\n"; if (!CHECK(m_hr, DB_E_BADINDEXID)) fTestResult = TEST_FAIL; } // DBKIND_PGUID_PROPID IndexID.eKind = DBKIND_PGUID_PROPID; IndexID.uGuid.pguid = &guidModule; odtLog << "DBKIND_PGUID_PROPID: "; m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), &IndexID, 1, rgIndexColumnDesc); if (S_OK ==m_hr) odtLog << "CREATED\n"; else { odtLog << "NOT created\n"; if (!CHECK(m_hr, DB_E_BADINDEXID)) fTestResult = TEST_FAIL; } return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(50) //*----------------------------------------------------------------------- // @mfunc NULL pColumnID in an element of rgIndexColumnDesc => DB_E_NOCOLUMN // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_50() { BOOL fTestResult = TEST_FAIL; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; rgIndexColumnDesc[0].pColumnID = NULL; TESTC_(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), NULL, 1, rgIndexColumnDesc), DB_E_NOCOLUMN); fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(51) //*----------------------------------------------------------------------- // @mfunc DB_NULLID pColumnID in an element of rgIndexColumnDesc => DB_E_NOCOLUMN // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_51() { BOOL fTestResult = TEST_FAIL; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; rgIndexColumnDesc[0].pColumnID = (struct tagDBID*)&DB_NULLID; TESTC_(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), NULL, 1, rgIndexColumnDesc), DB_E_NOCOLUMN); fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(52) //*----------------------------------------------------------------------- // @mfunc empty name for a column in an element of rgIndexColumnDesc => DB_E_NOCOLUMN // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_52() { BOOL fTestResult = TEST_FAIL; DBID colID; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; rgIndexColumnDesc[0].pColumnID = &colID; colID.eKind = DBKIND_NAME; colID.uName.pwszName = L""; TESTC_(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), NULL, 1, rgIndexColumnDesc), DB_E_NOCOLUMN); fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(53) //*----------------------------------------------------------------------- // @mfunc NULL column name in an element of rgIndexColumnDesc => DB_E_NOCOLUMN // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_53() { BOOL fTestResult = TEST_FAIL; DBID colID; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; rgIndexColumnDesc[0].pColumnID = &colID; colID.eKind = DBKIND_NAME; colID.uName.pwszName = NULL; TESTC_(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), NULL, 1, rgIndexColumnDesc), DB_E_NOCOLUMN); fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(54) //*----------------------------------------------------------------------- // @mfunc Set DBPROP_INDEX_AUTOUPDATE // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_54() { BOOL fTestResult = TEST_FAIL; if (CreateIndexWithOneLogicalProperty(DBPROP_INDEX_AUTOUPDATE)) fTestResult = TEST_PASS; return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(55) //*----------------------------------------------------------------------- // @mfunc Set DBPROP_INDEX_CLUSTERED // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_55() { BOOL fTestResult = TEST_PASS; if (!CreateIndexWithOneLogicalProperty(DBPROP_INDEX_CLUSTERED)) fTestResult = TEST_FAIL; return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(56) //*----------------------------------------------------------------------- // @mfunc Set DBPROP_INDEX_NULLS // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_56() { TBEGIN HRESULT hr; BOOL fExists; const int n=4; VARIANT values[n]; ULONG i; LPWSTR pwszSQLText=NULL; CDBIDPtr IndexID; DBPROPSET rgPropSets[1]; DBPROP rgProp[1]; DBORDINAL oldIndex; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; CCol col; DBORDINAL nIndex; TESTC(0 < m_cColumnDesc); // the classical aproach: try all the values for (i=0; iGetColInfoForUpdate(m_rgIndexCols[i]); fExists = (1 == col.GetNullable()) && col.GetUpdateable(); } if (fExists) { nIndex = col.GetColNum(); // create an index on m_nIndex, with DBPROP_INDEX_NULLS = DBPROPVAL_IN_DISALLOWNULL odtLog << "add an index with DBPROP_INDEX_NULLS = DBPROP_IN_DISALLOWNULL\n"; FILL_PROP_SET(rgPropSets[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_NULLS, VT_I4, V_I4, DBPROPVAL_IN_DISALLOWNULL, DBPROPOPTIONS_REQUIRED) hr = CNCIndexFromOrdinals(m_pTable, NULL, (DBID**)IndexID, m_rgColumnDesc, m_cColumnDesc, 1, &nIndex, rgOrder, NUMELEM(rgPropSets), rgPropSets); if (FAILED(hr)) { CHECK(hr, DB_E_ERRORSOCCURRED); odtLog << "an index with DBPROP_INDEX_NULLS = DBPROP_IN_DISALLOWNULL could not be created\n"; goto CLEANUP; } odtLog << "an index with DBPROP_INDEX_NULLS = DBPROP_IN_DISALLOWNULL was created\n"; if (m_pTable->GetCommandSupOnCTable()) { // try to insert a row with a NULL index entry => should not be allowed odtLog << "try to insert a row with a NULL index entry\n"; // makes sure that not all the entries are NULL by setting a pseudo index oldIndex = m_pTable->SetIndexColumn((nIndex+1)%m_cColumnDesc+1); CHECK(hr = m_pTable->Insert(101, PRIMARY, FALSE, &pwszSQLText, TRUE), S_OK); // TRUE says try to insert NULLs m_pTable->SetIndexColumn(oldIndex); //remove the pseudoindex hr = m_pTable->BuildCommand(pwszSQLText, IID_NULL, EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, NULL); CHECK(hr, DB_E_INTEGRITYVIOLATION ); if (SUCCEEDED(hr)) { odtLog << "ERROR: NULL entry inserted!\n"; goto CLEANUP; } else odtLog << "OK: could not insert NULL\n"; } // check that when the index is dropped the row can be inserted TESTC(m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), (DBID*)IndexID)); if (m_pTable->GetCommandSupOnCTable()) { TESTC_(m_hr = m_pTable->BuildCommand(pwszSQLText, IID_NULL, EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, NULL), S_OK); } } CLEANUP: m_hr = m_pTable->Delete(); SAFE_FREE(pwszSQLText); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(57) //*----------------------------------------------------------------------- // @mfunc Set DBPROP_INDEX_PRIMARYKEY // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_57() { TBEGIN CTable *pTable = NULL; DBCOLUMNDESC *rgNewColumnDesc = NULL; DBORDINAL cNewColumnDesc = m_cColumnDesc-m_nIndex+1; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; DBPROPSET rgPropSet[1]; DBPROP rgProp[1]; CDBIDPtr IndexID; // check the index on the current table (m_pTable) COMPARE(CreateIndexWithOneLogicalProperty(DBPROP_INDEX_PRIMARYKEY), TRUE); // create a new table, set and check the column as primary key pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName); TESTC(NULL != pTable); DuplicateColumnDesc(&m_rgColumnDesc[m_nIndex-1], cNewColumnDesc, &rgNewColumnDesc); pTable->SetColumnDesc(rgNewColumnDesc, cNewColumnDesc); pTable->SetBuildColumnDesc(FALSE); TESTC_(SetProperty(&rgNewColumnDesc[0].rgPropertySets, &rgNewColumnDesc[0].cPropertySets, DBPROP_COL_NULLABLE, VT_BOOL, (LPVOID)VARIANT_FALSE, DBPROPOPTIONS_REQUIRED, DB_NULLID, DBPROPSET_COLUMN), TRUE); if (S_OK != (m_hr = pTable->CreateTable(5, 0))) { odtLog << "abort: there are errors in creating a table\n"; goto CLEANUP; } //create an index with DBPROP_INDEX_PRIMARYKEY property set to variant TRUE rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; rgIndexColumnDesc[0].pColumnID = &rgNewColumnDesc[0].dbcid; FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_PRIMARYKEY, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED) if (CHECK(m_hr = m_pCIIndexDefinition->CreateIndexAndCheck(&pTable->GetTableID(), NULL, 1, rgIndexColumnDesc, 1, rgPropSet, (DBID**)IndexID), S_OK)) { if (S_OK == (m_hr = pTable->Insert(2,PRIMARY,TRUE,NULL)) ) { odtLog << "a record with an already existing key was successfully inserted in the database!\n"; } } COMPARE(m_pCIIndexDefinition->DropIndex(&pTable->GetTableID(), (DBID*)IndexID), S_OK); // at this point, the table should forget about column 0 being a primary key column; has it? if (!CHECK(m_hr = pTable->Insert(2,PRIMARY,TRUE,NULL), S_OK)) { odtLog << "a record with an already existing key couldn't successfully be inserted in the database!\n"; } else { // the column contains a duplicate, try to open an index on it, defining the col as primary key m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&pTable->GetTableID(), NULL, 1, rgIndexColumnDesc, 1, rgPropSet); if (S_OK == m_hr) { odtLog << "could open an index with a primary key on a column containing duplicates!\n"; } } CLEANUP: if (pTable) { pTable->DropTable(); delete pTable; } TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(58) //*----------------------------------------------------------------------- // @mfunc Set DBPROP_INDEX_SORTBOOKMARKS // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_58() { BOOL fTestResult = TEST_PASS; if (!CreateIndexWithOneLogicalProperty(DBPROP_INDEX_SORTBOOKMARKS)) fTestResult = TEST_FAIL; return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(59) //*----------------------------------------------------------------------- // @mfunc Set DBPROP_INDEX_TEMPINDEX // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_59() { BOOL fTestResult = TEST_PASS; if (!CreateIndexWithOneLogicalProperty(DBPROP_INDEX_TEMPINDEX)) fTestResult = TEST_FAIL; return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(60) //*----------------------------------------------------------------------- // @mfunc Set DBPROP_INDEX_TYPE // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_60() { BOOL fTestResult = TEST_PASS; const int n=4; VARIANT values[n]; ULONG i; for (i=0; im_pIUnknown2, (LPWSTR)gwszModuleName); TESTC(NULL != pTable); DuplicateColumnDesc(&m_rgColumnDesc[m_nIndex-1], cNewColumnDesc, &rgNewColumnDesc); pTable->SetColumnDesc(rgNewColumnDesc, cNewColumnDesc); ReleaseAllColumnPropSets(cNewColumnDesc, rgNewColumnDesc); pTable->SetBuildColumnDesc(FALSE); TESTC_(SetProperty(&rgNewColumnDesc[0].rgPropertySets, &rgNewColumnDesc[0].cPropertySets, DBPROP_COL_NULLABLE, VT_BOOL, (LPVOID)VARIANT_FALSE, DBPROPOPTIONS_REQUIRED, DB_NULLID, DBPROPSET_COLUMN), TRUE); if (!CHECK(m_hr = pTable->CreateTable(5, 0), S_OK)) { odtLog << "abort: could not properly create the table\n"; goto CLEANUP; } // create a index with the unique property rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; rgIndexColumnDesc[0].pColumnID = &rgNewColumnDesc[0].dbcid; FILL_PROP_SET(rgPropSet[0], 1, rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_UNIQUE, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED) odtLog << "create an index with DBPROP_INDEX_UNIQUE set to VARIANT_TRUE: "; if (!CHECK(m_pCIIndexDefinition->CreateIndexAndCheck(&pTable->GetTableID(), NULL, 1, rgIndexColumnDesc, 1, rgPropSet, (DBID**)IndexID), S_OK)) goto CLEANUP; odtLog << "OK\n"; if (!CHECK(m_hr = pTable->Insert(2,PRIMARY,TRUE,NULL), DB_E_INTEGRITYVIOLATION)) { odtLog << "ERROR: a record with a duplicated value was successfully inserted in the database!\n"; } else odtLog << "OK: duplicated key could not be inserted\n"; CHECK(m_pCIIndexDefinition->DropIndex(&pTable->GetTableID(), (DBID*)IndexID), S_OK); odtLog << "unique index was dropped\n"; // at this point, the table should forget about column 0 being a primary key column; has it? if (!CHECK(m_hr = pTable->Insert(2,PRIMARY,TRUE,NULL), S_OK)) odtLog << "a record with a duplicated value couldn't successfully be inserted in the database!\n"; odtLog << "duplicate inserted\n"; odtLog << "try to create a unique index on the col containing duplicated values\n"; m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&pTable->GetTableID(), NULL, 1, rgIndexColumnDesc, 1, rgPropSet); if (!COMPARE(FAILED(m_hr), TRUE)) odtLog << "ERROR: could create an index on a column containing duplicates!\n"; else odtLog <<"OK: index could not be created\n"; CLEANUP: if (pTable) { pTable->DropTable(); delete pTable; } TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(62) //*----------------------------------------------------------------------- // @mfunc Set DBPROP_INDEX_FILLFACTOR // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_62() { BOOL fTestResult = TEST_PASS; const int n=4; VARIANT values[n]; ULONG i; for (i=0; i ListNativeTemp; CList ListDataTypes; ULONG cIndex; CCol col; pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName); TESTC(NULL != pTable); pTable->CreateColInfo(ListNativeTemp, ListDataTypes, ALLTYPES); pTable->BuildColumnDescs(&rgColumnDesc); cColumnDesc = pTable->CountColumnsOnTable(); cIndex = 0; pTable->SetColumnDesc(rgColumnDesc, cColumnDesc); pTable->SetBuildColumnDesc(FALSE); ::SetProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN, &rgColumnDesc[m_rgIndexCols[cIndex]-1].cPropertySets, &rgColumnDesc[m_rgIndexCols[cIndex]-1].rgPropertySets, (LPVOID)VARIANT_FALSE, VT_BOOL, DBPROPOPTIONS_REQUIRED, DB_NULLID); TESTC_(m_hr = pTable->CreateTable(0, 0), S_OK); fTestResult = TEST_PASS; odtLog << "\tunique, primary key index\n"; FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_UNIQUE, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED) FILL_PROP(rgProp[1], DBPROP_INDEX_PRIMARYKEY, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED) hr = CCNDropIndexFromOrdinals(pTable, NULL, rgColumnDesc, cColumnDesc, 1, &m_rgIndexCols[cIndex], rgOrder, 1, rgPropSet); if (S_OK != hr) { if (!CHECK(hr, DB_E_ERRORSOCCURRED)) fTestResult = TEST_FAIL; if ((DBPROPSTATUS_OK == rgProp[1].dwStatus) && (DBPROPSTATUS_OK == rgProp[0].dwStatus)) { odtLog << "both prop status are DBPROPSTATUS_OK\n"; fTestResult = TEST_FAIL; } } odtLog << "\tnot unique, primary key index\n"; FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_UNIQUE, VT_BOOL, V_BOOL, VARIANT_FALSE, DBPROPOPTIONS_REQUIRED) FILL_PROP(rgProp[1], DBPROP_INDEX_PRIMARYKEY, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED) hr = CCNDropIndexFromOrdinals(pTable, NULL, rgColumnDesc, cColumnDesc, 1, &m_rgIndexCols[cIndex], rgOrder, 1, rgPropSet); if (S_OK != hr) { if (!CHECK(hr, DB_E_ERRORSOCCURRED)) fTestResult = TEST_FAIL; if ((DBPROPSTATUS_OK == rgProp[1].dwStatus) && (DBPROPSTATUS_OK == rgProp[0].dwStatus)) { odtLog << "both prop status are DBPROPSTATUS_OK\n"; fTestResult = TEST_FAIL; } } odtLog << "\tunique, not primary key index\n"; FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_UNIQUE, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED) FILL_PROP(rgProp[1], DBPROP_INDEX_PRIMARYKEY, VT_BOOL, V_BOOL, VARIANT_FALSE, DBPROPOPTIONS_REQUIRED) hr = CCNDropIndexFromOrdinals(pTable, NULL, rgColumnDesc, cColumnDesc, 1, &m_rgIndexCols[cIndex], rgOrder, 1, rgPropSet); if (S_OK != hr) { if (!CHECK(hr, DB_E_ERRORSOCCURRED)) fTestResult = TEST_FAIL; if ((DBPROPSTATUS_OK == rgProp[1].dwStatus) && (DBPROPSTATUS_OK == rgProp[0].dwStatus)) { odtLog << "both prop status are DBPROPSTATUS_OK\n"; fTestResult = TEST_FAIL; } } odtLog << "\tnot unique, non primary key index\n"; FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_UNIQUE, VT_BOOL, V_BOOL, VARIANT_FALSE, DBPROPOPTIONS_REQUIRED) FILL_PROP(rgProp[1], DBPROP_INDEX_PRIMARYKEY, VT_BOOL, V_BOOL, VARIANT_FALSE, DBPROPOPTIONS_REQUIRED) hr = CCNDropIndexFromOrdinals(pTable, NULL, rgColumnDesc, cColumnDesc, 1, &m_rgIndexCols[cIndex], rgOrder, 1, rgPropSet); if (S_OK != hr) { if (!CHECK(hr, DB_E_ERRORSOCCURRED)) fTestResult = TEST_FAIL; if ((DBPROPSTATUS_OK == rgProp[1].dwStatus) && (DBPROPSTATUS_OK == rgProp[0].dwStatus)) { odtLog << "both prop status are DBPROPSTATUS_OK\n"; fTestResult = TEST_FAIL; } } CLEANUP: pTable->DropTable(); delete pTable; return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(67) //*----------------------------------------------------------------------- // @mfunc Set DBPROP_INDEX_UNIQUE and DBPROP_INDEX_NULLS // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_67() { BOOL fTestResult = TEST_PASS; DBPROPSET rgPropSet[1]; DBPROP rgProp[2]; HRESULT hr; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_UNIQUE, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED) FILL_PROP(rgProp[1], DBPROP_INDEX_NULLS, VT_I4, V_I4, DBPROPVAL_IN_DISALLOWNULL, DBPROPOPTIONS_REQUIRED) hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet); if (S_OK != hr) { if (!CHECK(hr, DB_E_ERRORSOCCURRED)) return fTestResult = TEST_FAIL; if ((DBPROPSTATUS_OK == rgProp[1].dwStatus) && (DBPROPSTATUS_OK == rgProp[0].dwStatus)) { odtLog << "both prop status are DBPROPSTATUS_OK\n"; fTestResult = TEST_FAIL; } } return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(68) //*----------------------------------------------------------------------- // @mfunc CONFLICTING properties (set both DBPROP_INDEX_NULLS and DBPROP_INDEX_PRIMARYKEY) // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_68() { BOOL fTestResult = TEST_PASS; DBPROPSET rgPropSet[1]; DBPROP rgProp[2]; HRESULT hr; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_NULLS, VT_I4, V_I4, DBPROPVAL_IN_DISALLOWNULL, DBPROPOPTIONS_REQUIRED) FILL_PROP(rgProp[1], DBPROP_INDEX_PRIMARYKEY, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED) hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet); if (S_OK != hr) { if (!CHECK(hr, DB_E_ERRORSOCCURRED)) return fTestResult = TEST_FAIL; if ((DBPROPSTATUS_OK == rgProp[1].dwStatus) && (DBPROPSTATUS_OK == rgProp[0].dwStatus)) { odtLog << "both prop status are DBPROPSTATUS_OK\n"; fTestResult = TEST_FAIL; } } return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(69) //*----------------------------------------------------------------------- // @mfunc Non index dwPropertyID // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_69() { BOOL fTestResult = TEST_PASS; DBPROPSET rgPropSet[1]; DBPROP rgProp[1]; HRESULT hr; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], 280, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL) odtLog << "\tDBPROPOPTIONS_OPTIONAL\n"; hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet); // should be DB_S_ERRORSOCCURRED if (!CHECK(hr, DB_S_ERRORSOCCURRED)) fTestResult = TEST_FAIL; // if errors occurred, the status should be DBPROPSTATUS_NOTSUPPORTED (it was OPTIONAL) if (((DB_S_ERRORSOCCURRED == hr) || (S_OK == hr )) && (DBPROPSTATUS_NOTSUPPORTED != rgProp[0].dwStatus) ) { odtLog << "Bad status for property " << rgProp[0].dwPropertyID << "\n"; fTestResult = TEST_FAIL; } FILL_PROP(rgProp[0], 280, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED) odtLog << "\tDBPROPOPTIONS_REQUIRED\n"; hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet); // should be DB_E_ERRORSOCCURRED if (!CHECK(hr, DB_E_ERRORSOCCURRED)) fTestResult = TEST_FAIL; // if errors occurred, the status should be DBPROPSTATUS_NOTSUPPORTED (it was OPTIONAL) if ((DB_E_ERRORSOCCURRED == hr) && (DBPROPSTATUS_NOTSUPPORTED != rgProp[0].dwStatus) ) { odtLog << "Bad status for property " << rgProp[0].dwPropertyID << "\n"; fTestResult = TEST_FAIL; } return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(70) //*----------------------------------------------------------------------- // @mfunc Non index guidPropertySet // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_70() { BOOL fTestResult = TEST_PASS; DBPROPSET rgPropSet[1]; DBPROP rgProp[1]; HRESULT hr; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_ROWSET) FILL_PROP(rgProp[0], DBPROP_INDEX_AUTOUPDATE, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL) odtLog << "\tDBPROPOPTIONS_OPTIONAL\n"; hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet); // should be DB_S_ERRORSOCCURRED if (!CHECK(hr, DB_S_ERRORSOCCURRED)) fTestResult = TEST_FAIL; // if errors occurred, the status should be DBPROPSTATUS_NOTSUPPORTED if ((DB_S_ERRORSOCCURRED == hr) && (DBPROPSTATUS_NOTSUPPORTED != rgProp[0].dwStatus) ) { odtLog << "Bad status for property " << rgProp[0].dwPropertyID << "\n"; fTestResult = TEST_FAIL; } rgProp[0].dwOptions = DBPROPOPTIONS_REQUIRED; odtLog << "\tDBPROPOPTIONS_REQUIRED\n"; hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet); // should be either DB_E_ERRORSOCCURRED if (!CHECK(hr, DB_E_ERRORSOCCURRED)) fTestResult = TEST_FAIL; // if errors occurred, the status should be DBPROPSTATUS_NOTSUPPORTED if ((DB_E_ERRORSOCCURRED == hr) && (DBPROPSTATUS_NOTSUPPORTED != rgProp[0].dwStatus) ) { odtLog << "Bad status for property " << rgProp[0].dwPropertyID << "\n"; fTestResult = TEST_FAIL; } return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(71) //*----------------------------------------------------------------------- // @mfunc invalid value type for property // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_71() { BOOL fTestResult = TEST_PASS; DBPROPSET rgPropSet[1]; DBPROP rgProp[1]; HRESULT hr; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_NULLS, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL) odtLog << "\tDBPROPOPTIONS_OPTIONAL\n"; hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet); // should be DB_S_ERRORSOCCURRED if (!CHECK(hr, DB_S_ERRORSOCCURRED)) fTestResult = TEST_FAIL; // if errors occurred, the status should be DBPROPSTATUS_BADVALUE or DBPROPSTATUS_NOTSUPPORTED if ( (DB_S_ERRORSOCCURRED == hr) && (DBPROPSTATUS_BADVALUE != rgProp[0].dwStatus) && (DBPROPSTATUS_NOTSUPPORTED != rgProp[0].dwStatus) ) { odtLog << "Bad status for property " << rgProp[0].dwPropertyID << "\n"; fTestResult = TEST_FAIL; } rgProp[0].dwOptions = DBPROPOPTIONS_REQUIRED; odtLog << "\tDBPROPOPTIONS_REQUIRED\n"; hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet); // should be DB_E_ERRORSOCCURRED if (!CHECK(hr, DB_E_ERRORSOCCURRED)) fTestResult = TEST_FAIL; // if errors occurred, the status should be DBPROPSTATUS_BADVALUE or DBPROPSTATUS_NOTSUPPORTED if ( (DB_E_ERRORSOCCURRED == hr) && (DBPROPSTATUS_BADVALUE != rgProp[0].dwStatus) && (DBPROPSTATUS_NOTSUPPORTED != rgProp[0].dwStatus) ) { odtLog << "Bad status for property " << rgProp[0].dwPropertyID << "\n"; fTestResult = TEST_FAIL; } return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(72) //*----------------------------------------------------------------------- // @mfunc invalid value for a property // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_72() { BOOL fTestResult = TEST_PASS; DBPROPSET rgPropSet[1]; DBPROP rgProp[1]; HRESULT hr; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; BOOL fSupported; DBPROPSTATUS dwStatus; fSupported = SupportedProperty(DBPROP_INDEX_NULLS, DBPROPSET_INDEX); FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_NULLS, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL) odtLog << "\tDBPROPOPTIONS_OPTIONAL\n"; hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet); // should be DB_S_ERRORSOCCURRED if (!CHECK(hr, DB_S_ERRORSOCCURRED)) fTestResult = TEST_FAIL; dwStatus = rgProp[0].dwStatus; // if errors occurred, the status should be DBPROPSTATUS_NOTSET (it was OPTIONAL) - IF THE PROP IS SUPPORTED! if ( (DB_S_ERRORSOCCURRED == hr) && ( (fSupported && !COMPARE(dwStatus, DBPROPSTATUS_BADVALUE)) || (!fSupported && !COMPARE(dwStatus, DBPROPSTATUS_NOTSUPPORTED)))) { odtLog << "Bad status for property " << rgProp[0].dwPropertyID << "\n"; fTestResult = TEST_FAIL; } rgProp[0].dwOptions = DBPROPOPTIONS_REQUIRED; odtLog << "\tDBPROPOPTIONS_REQUIRED\n"; hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet); // should be DB_E_ERRORSOCCURRED if (!CHECK(hr, DB_E_ERRORSOCCURRED)) fTestResult = TEST_FAIL; // if errors occurred, the status should be DBPROPSTATUS_BADVALUE or DBPROPSTATUS_NOTSUPPORTED if ( (DB_E_ERRORSOCCURRED == hr) && ( (fSupported && !COMPARE(dwStatus, DBPROPSTATUS_BADVALUE)) || (!fSupported && !COMPARE(dwStatus, DBPROPSTATUS_NOTSUPPORTED)))) { odtLog << "Bad status for property " << rgProp[0].dwPropertyID << "\n"; fTestResult = TEST_FAIL; } return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(73) //*----------------------------------------------------------------------- // @mfunc specifying a property twice // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_73() { BOOL fTestResult = TEST_PASS; DBPROPSET rgPropSet[1]; DBPROP rgProp[2]; HRESULT hr; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_NULLS, VT_I4, V_I4, DBPROPVAL_IN_DISALLOWNULL, DBPROPOPTIONS_REQUIRED) FILL_PROP(rgProp[1], DBPROP_INDEX_NULLS, VT_I4, V_I4, DBPROPVAL_IN_IGNORENULL, DBPROPOPTIONS_REQUIRED) hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet); // should be either S_OK or DB_E_ERRORSOCCURRED if (S_OK != hr && !CHECK(hr, DB_E_ERRORSOCCURRED)) fTestResult = TEST_FAIL; else { if ( ( S_OK == hr && (DBPROPSTATUS_OK != rgProp[0].dwStatus) && (DBPROPSTATUS_OK != rgProp[0].dwStatus)) || ( S_OK != hr && (DBPROPSTATUS_OK == rgProp[0].dwStatus) && (DBPROPSTATUS_OK == rgProp[0].dwStatus))) { odtLog << "Property " << rgProp[0].dwPropertyID << " set incorrectly\n"; fTestResult = TEST_FAIL; } } return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(74) //*----------------------------------------------------------------------- // @mfunc all the properties // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_74() { const int nProp = 11; BOOL fTestResult = TEST_PASS; DBPROPSET rgPropSet[1]; DBPROP rgProp[nProp]; HRESULT hr; ULONG iProp, k; DBINDEX_COL_ORDER rgOrder[] = {DBINDEX_COL_ORDER_ASC}; FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_AUTOUPDATE, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL) FILL_PROP(rgProp[1], DBPROP_INDEX_CLUSTERED, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL) FILL_PROP(rgProp[2], DBPROP_INDEX_FILLFACTOR, VT_I4, V_I4, 10, DBPROPOPTIONS_OPTIONAL) FILL_PROP(rgProp[3], DBPROP_INDEX_INITIALSIZE, VT_I4, V_I4, 2000, DBPROPOPTIONS_OPTIONAL) FILL_PROP(rgProp[4], DBPROP_INDEX_NULLCOLLATION, VT_I4, V_I4, DBPROPVAL_NC_END, DBPROPOPTIONS_OPTIONAL) FILL_PROP(rgProp[5], DBPROP_INDEX_NULLS, VT_I4, V_I4, DBPROPVAL_IN_DISALLOWNULL, DBPROPOPTIONS_OPTIONAL) FILL_PROP(rgProp[6], DBPROP_INDEX_PRIMARYKEY, VT_BOOL, V_BOOL, VARIANT_FALSE, DBPROPOPTIONS_OPTIONAL) FILL_PROP(rgProp[7], DBPROP_INDEX_SORTBOOKMARKS, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL) FILL_PROP(rgProp[8], DBPROP_INDEX_TEMPINDEX, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL) FILL_PROP(rgProp[9], DBPROP_INDEX_UNIQUE, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL) FILL_PROP(rgProp[10], DBPROP_INDEX_TYPE, VT_I4, V_I4, DBPROPVAL_IT_BTREE, DBPROPOPTIONS_OPTIONAL) hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet); // should be either S_OK or DB_S_ERRORSOCCURRED if (DB_S_ERRORSOCCURRED != hr) { if (!CHECK(hr, S_OK)) fTestResult = TEST_FAIL; } else { // if errors occurred, the status should be different from DBPROPSTATUS_OK for (iProp=0, k=0; iProp DB_E_NOCOLUMN // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_75() { BOOL fTestResult = TEST_FAIL; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; size_t m, n; DBID ColumnID; rgIndexColumnDesc[0].pColumnID = &ColumnID; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; // get an invalid column name ColumnID.eKind = DBKIND_NAME; m = min(m_cMaxColumnName, n=5+wcslen(m_pTable->GetTableName())); ColumnID.uName.pwszName = BuildInvalidName(m, m_pTable->GetTableName(), m_pwszInvalidColumnChars); TESTC_(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), NULL, NUMELEM(rgIndexColumnDesc), rgIndexColumnDesc), DB_E_NOCOLUMN); fTestResult = TEST_PASS; CLEANUP: ReleaseDBID(&ColumnID, FALSE); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(76) //*----------------------------------------------------------------------- // @mfunc maximum length column name => S_OK // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_76() { CTable *pTable = NULL; BOOL fTestResult = TEST_FAIL; DBORDINAL rgIndexCol[1] = {m_nIndex}; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; DBKIND eKind; LPWSTR pwszColumnName; pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName); eKind = m_rgColumnDesc[m_nIndex-1].dbcid.eKind; pwszColumnName = m_rgColumnDesc[m_nIndex-1].dbcid.uName.pwszName; TESTC(NULL != pTable); pTable->SetBuildColumnDesc(FALSE); pTable->SetColumnDesc(m_rgColumnDesc, m_cColumnDesc); m_rgColumnDesc[m_nIndex-1].dbcid.eKind = DBKIND_NAME; m_rgColumnDesc[m_nIndex-1].dbcid.uName.pwszName = BuildValidName(m_cMaxColumnName, m_pTable->GetTableName()); if (!CHECK(m_hr = pTable->CreateTable(0, 0), S_OK)) { odtLog << "\tcould not create a table\n"; goto CLEANUP; } TESTC_(m_hr = CCNDropIndexFromOrdinals(pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, rgIndexCol, rgOrder), S_OK); fTestResult = TEST_PASS; CLEANUP: if (pTable) { pTable->DropTable(); pTable->SetColumnDesc(NULL, 0); delete pTable; } m_rgColumnDesc[m_nIndex-1].dbcid.eKind = eKind; SAFE_FREE(m_rgColumnDesc[m_nIndex-1].dbcid.uName.pwszName); m_rgColumnDesc[m_nIndex-1].dbcid.uName.pwszName = pwszColumnName; return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(77) //*----------------------------------------------------------------------- // @mfunc too long column name => DB_E_NOCOLUMN // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_77() { BOOL fTestResult = TEST_FAIL; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; DBID ColumnID; rgIndexColumnDesc[0].pColumnID = &ColumnID; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; // get a too long column name ColumnID.eKind = DBKIND_NAME; ColumnID.uName.pwszName = BuildValidName(m_cMaxColumnName+1, m_pTable->GetTableName()); TESTC_(m_hr = m_pCIIndexDefinition->CreateCheckAndDropIndex(&m_pTable->GetTableID(), NULL, 1, rgIndexColumnDesc), DB_E_NOCOLUMN); fTestResult = TEST_PASS; CLEANUP: ReleaseDBID(&ColumnID, FALSE); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END //------------------------------------------------------------------ // // thread function //------------------------------------------------------------------ unsigned TCCreateIndex::MyThreadProc(ULONG i) { DBID IndexID; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; HRESULT hr; if (i>=nThreads) return 0; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = m_rgIndexName[i]; rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[m_nIndex-1].dbcid; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; Sleep(0); hr = m_pCIIndexDefinition->CreateIndex(&m_pTable->GetTableID(), &IndexID, 1, rgIndexColumnDesc, 0, NULL, NULL); Sleep(0); m_rgResult[i] = hr; return 1; } //TCCreateIndex::MyThreadProc // {{ TCW_VAR_PROTOTYPE(78) //*----------------------------------------------------------------------- // @mfunc multithreading // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_78() { unsigned IDThread[nThreads]; HANDLE hThread[nThreads]; CInParam ThreadParam[nThreads]; DBID IndexID; BOOL fTestResult = TEST_PASS, fExists; ULONG nIndex; WCHAR pwszNameSeed[]=L"Index"; for (nIndex = 0; nIndex < nThreads; nIndex++) { m_rgIndexName[nIndex] = NULL; m_rgResult[nIndex] = E_FAIL; } for (nIndex = 0; nIndex < nThreads; nIndex++) { ThreadParam[nIndex].i = nIndex; ThreadParam[nIndex].pObject = this; SAFE_ALLOC(m_rgIndexName[nIndex], WCHAR, wcslen(pwszNameSeed)+3); swprintf(m_rgIndexName[nIndex], L"%s%02d", pwszNameSeed, nIndex); hThread[nIndex] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, (void*)&ThreadParam[nIndex], 0, &IDThread[nIndex]); if (hThread[nIndex] == 0) { fTestResult = TEST_FAIL; goto CLEANUP; } } WaitForMultipleObjects(nThreads, hThread, TRUE, INFINITE); for (nIndex=0; nIndexDoesIndexExist( &m_pTable->GetTableID(), &IndexID, &fExists), S_OK) && fExists ) CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID), S_OK); else fTestResult = TEST_FAIL; if (m_rgIndexName[nIndex]) SAFE_FREE(m_rgIndexName[nIndex]); } return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(79) //*----------------------------------------------------------------------- // @mfunc 2 threads, the same index // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_79() { unsigned IDThread[nThreads]; HANDLE hThread[nThreads]; CInParam ThreadParam[nThreads]; DBID IndexID; BOOL fTestResult = TEST_FAIL; ULONG nSuccess = 0; ULONG nIndex; WCHAR pwszIndexName[] = L"theSameIndex"; for (nIndex = 0; nIndex < nThreads; nIndex++) { m_rgResult[nIndex] = E_FAIL; ThreadParam[nIndex].i = nIndex; ThreadParam[nIndex].pObject = this; m_rgIndexName[nIndex] = pwszIndexName; hThread[nIndex] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, (void*)&ThreadParam[nIndex], 0, &IDThread[nIndex]); if (hThread[nIndex] == 0) { fTestResult = TEST_FAIL; goto CLEANUP; } } WaitForMultipleObjects(nThreads, hThread, TRUE, INFINITE); for (nIndex=0; nIndexDropIndex(&m_pTable->GetTableID(), &IndexID); if (1 == nSuccess) fTestResult = TEST_PASS; CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(80) //*----------------------------------------------------------------------- // @mfunc Primary and clustered index properties // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_80() { BOOL fTestResult = TEST_PASS; DBPROPSET rgPropSet[1]; DBPROP rgProp[2]; HRESULT hr; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; CTable *pTable = NULL; DBCOLUMNDESC *rgColumnDesc = NULL; DBORDINAL cColumnDesc = 0; CList ListNativeTemp; CList ListDataTypes; ULONG cColIndex; ULONG cIndex; BOOL fFound; CCol col; pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName); TESTC(NULL != pTable); pTable->CreateColInfo(ListNativeTemp, ListDataTypes, ALLTYPES); pTable->BuildColumnDescs(&rgColumnDesc); cColumnDesc = pTable->CountColumnsOnTable(); // check for an indexable and nullable type cIndex = 0; for (cColIndex = 0, fFound = FALSE; cColIndex < m_cIndexCols && !fFound; cColIndex++) { col = pTable->GetColInfoForUpdate(m_rgIndexCols[cColIndex]); if (1 == col.GetNullable()) { fFound = TRUE; cIndex = cColIndex; } } pTable->SetColumnDesc(rgColumnDesc, cColumnDesc); pTable->SetBuildColumnDesc(FALSE); ::SetProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN, &rgColumnDesc[m_rgIndexCols[cIndex]-1].cPropertySets, &rgColumnDesc[m_rgIndexCols[cIndex]-1].rgPropertySets, (LPVOID)VARIANT_FALSE, VT_BOOL, DBPROPOPTIONS_REQUIRED, DB_NULLID); TESTC_(m_hr = pTable->CreateTable(0, 0), S_OK); odtLog << "\tclustered, primary key index\n"; FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_CLUSTERED, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED) FILL_PROP(rgProp[1], DBPROP_INDEX_PRIMARYKEY, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED) hr = CCNDropIndexFromOrdinals(pTable, NULL, rgColumnDesc, cColumnDesc, 1, &m_rgIndexCols[cIndex], rgOrder, 1, rgPropSet); if (S_OK != hr) { if (!CHECK(hr, DB_E_ERRORSOCCURRED)) fTestResult = TEST_FAIL; if ((DBPROPSTATUS_OK == rgProp[1].dwStatus) && (DBPROPSTATUS_OK == rgProp[0].dwStatus)) { odtLog << "both prop status are DBPROPSTATUS_OK\n"; fTestResult = TEST_FAIL; } } odtLog << "\tnot clustered, primary key index\n"; FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_CLUSTERED, VT_BOOL, V_BOOL, VARIANT_FALSE, DBPROPOPTIONS_REQUIRED) FILL_PROP(rgProp[1], DBPROP_INDEX_PRIMARYKEY, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED) hr = CCNDropIndexFromOrdinals(pTable, NULL, rgColumnDesc, cColumnDesc, 1, &m_rgIndexCols[cIndex], rgOrder, 1, rgPropSet); if (S_OK != hr) { if (!CHECK(hr, DB_E_ERRORSOCCURRED)) fTestResult = TEST_FAIL; if ((DBPROPSTATUS_OK == rgProp[1].dwStatus) && (DBPROPSTATUS_OK == rgProp[0].dwStatus)) { odtLog << "both prop status are DBPROPSTATUS_OK\n"; fTestResult = TEST_FAIL; } } odtLog << "\tclustered, not primary key index\n"; FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_CLUSTERED, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED) FILL_PROP(rgProp[1], DBPROP_INDEX_PRIMARYKEY, VT_BOOL, V_BOOL, VARIANT_FALSE, DBPROPOPTIONS_REQUIRED) hr = CCNDropIndexFromOrdinals(pTable, NULL, rgColumnDesc, cColumnDesc, 1, &m_rgIndexCols[cIndex], rgOrder, 1, rgPropSet); if (S_OK != hr) { if (!CHECK(hr, DB_E_ERRORSOCCURRED)) fTestResult = TEST_FAIL; if ((DBPROPSTATUS_OK == rgProp[1].dwStatus) && (DBPROPSTATUS_OK == rgProp[0].dwStatus)) { odtLog << "both prop status are DBPROPSTATUS_OK\n"; fTestResult = TEST_FAIL; } } odtLog << "\tnot clustered, non primary key index\n"; FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], DBPROP_INDEX_CLUSTERED, VT_BOOL, V_BOOL, VARIANT_FALSE, DBPROPOPTIONS_REQUIRED) FILL_PROP(rgProp[1], DBPROP_INDEX_PRIMARYKEY, VT_BOOL, V_BOOL, VARIANT_FALSE, DBPROPOPTIONS_REQUIRED) hr = CCNDropIndexFromOrdinals(pTable, NULL, rgColumnDesc, cColumnDesc, 1, &m_rgIndexCols[cIndex], rgOrder, 1, rgPropSet); if (S_OK != hr) { if (!CHECK(hr, DB_E_ERRORSOCCURRED)) fTestResult = TEST_FAIL; if ((DBPROPSTATUS_OK == rgProp[1].dwStatus) && (DBPROPSTATUS_OK == rgProp[0].dwStatus)) { odtLog << "both prop status are DBPROPSTATUS_OK\n"; fTestResult = TEST_FAIL; } } CLEANUP: pTable->DropTable(); delete pTable; return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(81) //*----------------------------------------------------------------------- // @mfunc bogus colid in a non column specific index property // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_81() { DBINDEX_COL_ORDER rgOrder[] = {DBINDEX_COL_ORDER_ASC}; BOOL fTestRes = TEST_SKIPPED; DBPROPSET rgPropSet[1]; DBPROP rgProp[1]; DBPROPID dwPropID; DBCOLUMNDESC *rgColumnDesc = NULL; ULONG cColumnDesc = 0; HRESULT hr; // make sure there is a non column specific index property that is settable TESTC_PROVIDER(GetNonColSpecProp(DBPROPSET_INDEX, &dwPropID)); fTestRes = TEST_FAIL; FILL_PROP_SET(rgPropSet[0], 1, rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], dwPropID, DBTYPE_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL) // set colID to a value different from DB_NULLID rgProp[0].colid.eKind = DBKIND_NAME; rgProp[0].colid.uName.pwszName = L"someColumn"; // check colid is ignored for the rowset property TESTC_(hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet), DB_S_ERRORSOCCURRED); TESTC(DBPROPSTATUS_BADCOLUMN == rgProp[0].dwStatus); // check colid is ignored for the column property rgProp[0].dwOptions = DBPROPOPTIONS_REQUIRED; TESTC_(hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet), DB_E_ERRORSOCCURRED); TESTC(DBPROPSTATUS_BADCOLUMN == rgProp[0].dwStatus); fTestRes = TEST_PASS; CLEANUP: ReleaseColumnDesc(rgColumnDesc, cColumnDesc); return fTestRes; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(82) //*----------------------------------------------------------------------- // @mfunc DB_NULLID passed as colid in a column specific index property // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_82() { DBINDEX_COL_ORDER rgOrder[] = {DBINDEX_COL_ORDER_ASC}; BOOL fTestRes = TEST_SKIPPED; DBPROPSET rgPropSet[1]; DBPROP rgProp[1]; DBPROPID dwPropID; DBCOLUMNDESC *rgColumnDesc = NULL; ULONG cColumnDesc = 0; HRESULT hr; // make sure there is a column specific index property that is settable TESTC_PROVIDER(GetColSpecProp(DBPROPSET_INDEX, &dwPropID)); fTestRes = TEST_FAIL; FILL_PROP_SET(rgPropSet[0], 1, rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], dwPropID, DBTYPE_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL) // set colID to DB_NULLID rgProp[0].colid = DB_NULLID; // check colid is ignored for the rowset property hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet); if (DB_S_ERRORSOCCURRED == hr) { TESTC(DBPROPSTATUS_NOTALLSETTABLE == rgProp[0].dwStatus); } else { TESTC_(hr, S_OK); TESTC(DBPROPSTATUS_OK == rgProp[0].dwStatus); } // check colid is ignored for the column property rgProp[0].dwOptions = DBPROPOPTIONS_REQUIRED; hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet); if (DB_E_ERRORSOCCURRED == hr) { TESTC(DBPROPSTATUS_NOTALLSETTABLE == rgProp[0].dwStatus); } else { TESTC_(hr, S_OK); TESTC(DBPROPSTATUS_OK == rgProp[0].dwStatus); } fTestRes = TEST_PASS; CLEANUP: ReleaseColumnDesc(rgColumnDesc, cColumnDesc); return fTestRes; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(83) //*----------------------------------------------------------------------- // @mfunc valid, non DB_NULLID colid in a column specific index property // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_83() { DBINDEX_COL_ORDER rgOrder[] = {DBINDEX_COL_ORDER_ASC}; BOOL fTestRes = TEST_SKIPPED; DBPROPSET rgPropSet[1]; DBPROP rgProp[1]; DBPROPID dwPropID; DBCOLUMNDESC *rgColumnDesc = NULL; ULONG cColumnDesc = 0; HRESULT hr; memset(&rgProp[0].colid, 0, sizeof(DBID)); // make sure there is a column specific index property that is settable TESTC_PROVIDER(GetColSpecProp(DBPROPSET_INDEX, &dwPropID)); fTestRes = TEST_FAIL; FILL_PROP_SET(rgPropSet[0], 1, rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], dwPropID, DBTYPE_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL) // set colID to a value different from DB_NULLID DuplicateDBID(m_rgColumnDesc[m_nIndex-1].dbcid, &rgProp[0].colid); // check colid is ignored for the rowset property TESTC_(hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet), DB_S_ERRORSOCCURRED); TESTC(DBPROPSTATUS_BADCOLUMN == rgProp[0].dwStatus); // check colid is ignored for the column property rgProp[0].dwOptions = DBPROPOPTIONS_REQUIRED; TESTC_(hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet), DB_S_ERRORSOCCURRED); TESTC(DBPROPSTATUS_BADCOLUMN == rgProp[0].dwStatus); fTestRes = TEST_PASS; CLEANUP: ReleaseColumnDesc(rgColumnDesc, cColumnDesc); ReleaseDBID(&rgProp[0].colid, FALSE); return fTestRes; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(84) //*----------------------------------------------------------------------- // @mfunc bogus colid in a column specific index property => error // // @rdesc TEST_PASS or TEST_FAIL // int TCCreateIndex::Variation_84() { DBINDEX_COL_ORDER rgOrder[] = {DBINDEX_COL_ORDER_ASC}; BOOL fTestRes = TEST_SKIPPED; DBPROPSET rgPropSet[1]; DBPROP rgProp[1]; DBPROPID dwPropID; DBCOLUMNDESC *rgColumnDesc = NULL; ULONG cColumnDesc = 0; HRESULT hr; // make sure there is a non column specific rowset property that is settable TESTC_PROVIDER(GetColSpecProp(DBPROPSET_INDEX, &dwPropID)); fTestRes = TEST_FAIL; FILL_PROP_SET(rgPropSet[0], 1, rgProp, DBPROPSET_INDEX) FILL_PROP(rgProp[0], dwPropID, DBTYPE_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL) // set colID to a value different from DB_NULLID rgProp[0].colid.eKind = DBKIND_NAME; rgProp[0].colid.uName.pwszName = L"someColumn"; // check colid is ignored for the rowset property TESTC_(hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet), DB_S_ERRORSOCCURRED); TESTC(DBPROPSTATUS_BADCOLUMN == rgProp[0].dwStatus); // check colid is ignored for the column property rgProp[0].dwOptions = DBPROPOPTIONS_REQUIRED; TESTC_(hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder, 1, rgPropSet), DB_E_ERRORSOCCURRED); TESTC(DBPROPSTATUS_BADCOLUMN == rgProp[0].dwStatus); fTestRes = TEST_PASS; CLEANUP: ReleaseColumnDesc(rgColumnDesc, cColumnDesc); return fTestRes; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_TERMINATE_METHOD //*----------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TEST_PASS or TEST_FAIL // BOOL TCCreateIndex::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(TCIIndexDefinition::Terminate()); } // }} // }} TCW_TERMINATE_METHOD_END // }} TCW_TC_PROTOTYPE_END // {{ TCW_TC_PROTOTYPE(TCDropIndex) //*----------------------------------------------------------------------- //| Test Case: TCDropIndex - tests IIndexDefinition::DropIndex() method //| Created: 11/6/97 //*----------------------------------------------------------------------- //*----------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCDropIndex::Init() { // {{ TCW_INIT_BASECLASS_CHECK if(TCIIndexDefinition::Init()) // }} return TRUE; return FALSE; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc NULL pointer for pTableID => E_INVALIDARG // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_1() { BOOL fTestResult = TEST_PASS; DBID IndexID; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = L"NewCrolo"; if (!CHECK(m_hr = m_pCIIndexDefinition->DropIndex(NULL, &IndexID), E_INVALIDARG)) fTestResult = TEST_FAIL; return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc *pTableID == DB_NULLID => DB_E_NOTABLE // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_2() { BOOL fTestResult = TEST_PASS; DBID IndexID; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = L"NewCrolo"; if (!CHECK(m_hr = m_pCIIndexDefinition->DropIndex((struct tagDBID*)&DB_NULLID, &IndexID), DB_E_NOTABLE)) fTestResult = TEST_FAIL; return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc pTableID->uName is NULL => DB_E_NOTABLE // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_3() { BOOL fTestResult = TEST_PASS; DBID IndexID, TableID; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = L"NewCrolo"; TableID.eKind = DBKIND_NAME; TableID.uName.pwszName = NULL; if (!CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&TableID, &IndexID), DB_E_NOTABLE)) fTestResult = TEST_FAIL; return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc pTableID->uName is empty => DB_E_NOTABLE // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_4() { BOOL fTestResult = TEST_PASS; DBID IndexID, TableID; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = L"NewCrolo"; TableID.eKind = DBKIND_NAME; TableID.uName.pwszName = L""; if (!CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&TableID, &IndexID), DB_E_NOTABLE)) fTestResult = TEST_FAIL; return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc invalid table name => DB_E_NOTABLE // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_5() { BOOL fTestResult = TEST_FAIL; DBID IndexID; DBID TableID; size_t m, n; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = L"Galusca"; // get an invalid table name TableID.eKind = DBKIND_NAME; m = min(m_cMaxTableName, n=5+wcslen(m_pTable->GetTableName())); TableID.uName.pwszName = BuildInvalidName(m, m_pTable->GetTableName(), m_pwszInvalidTableChars); TESTC_(m_hr = m_pCIIndexDefinition->DropIndex(&TableID, &IndexID), DB_E_NOTABLE); fTestResult = TEST_PASS; CLEANUP: ReleaseDBID(&TableID, FALSE); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc maximum sized table name => S_OK // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_6() { BOOL fTestResult = TEST_FAIL; DBID IndexID, *pIndexID=NULL; DBID TableID; ULONG nIndex; CTable *pTable = NULL; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = L"Galusca"; // get a valid large table name TableID.eKind = DBKIND_NAME; TableID.uName.pwszName = BuildValidName(m_cMaxTableName, m_pTable->GetTableName()); pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName); TESTC(NULL != pTable); pTable->SetColumnDesc(m_rgColumnDesc, m_cColumnDesc); pTable->SetBuildColumnDesc(FALSE); TESTC_(m_hr = pTable->CreateTable(0, 0, TableID.uName.pwszName), S_OK); if (CHECK(m_hr = SetIndex(&TableID, &IndexID, &nIndex, &pIndexID), S_OK)) { if (CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&TableID, &IndexID), S_OK)) fTestResult = TEST_PASS; } else { odtLog << "could not set index\n"; } CLEANUP: pTable->SetColumnDesc(NULL); pTable->DropTable(); delete pTable; ReleaseDBID(&TableID, FALSE); ReleaseDBID(pIndexID); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc table name exceeds maximum size => DB_E_NOTABLE // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_7() { BOOL fTestResult = TEST_FAIL; DBID IndexID; DBID TableID; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = L"Galusca"; // get an n extralarge valid table name TableID.eKind = DBKIND_NAME; TableID.uName.pwszName = BuildValidName(m_cMaxTableName+1, m_pTable->GetTableName()); if (CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&TableID, &IndexID), DB_E_NOTABLE)) fTestResult = TEST_PASS; SAFE_FREE(TableID.uName.pwszName); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc NULL pointer for pIndexID => drop all indexes // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_8() { TBEGIN BOOL fExists; ULONG nIndex = 0, i; DBID **rgIndexID=NULL; ULONG rgOrder[1] = {DBINDEX_COL_ORDER_ASC}; // create an index array SAFE_ALLOC(rgIndexID, DBID*, m_cColumnDesc); for (i=0; iDropIndex(&m_pPopulatedTable->GetTableID(), NULL), S_OK); TEST2C_(m_hr = m_pCIIndexDefinition->DoesIndexExist(&m_pPopulatedTable->GetTableID(), NULL, &fExists, TRUE), S_OK, DB_S_ERRORSOCCURRED); TESTC_PROVIDER(S_OK == m_hr); TESTC(!fExists); CLEANUP: for (i=0; i DB_E_NOINDEX // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_9() { TBEGIN CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), (struct tagDBID*)&DB_NULLID), DB_E_NOINDEX); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(10) //*----------------------------------------------------------------------- // @mfunc pIndexID->uName is NULL => DB_E_NOINDEX // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_10() { BOOL fTestResult = TEST_PASS; DBID IndexID; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = NULL; if (!CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID), DB_E_NOINDEX)) fTestResult = TEST_FAIL; return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(11) //*----------------------------------------------------------------------- // @mfunc pIndexID->uName is empty => DB_E_NOINDEX // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_11() { BOOL fTestResult = TEST_PASS; DBID IndexID; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = L""; if (!CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID), DB_E_NOINDEX)) fTestResult = TEST_FAIL; return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(12) //*----------------------------------------------------------------------- // @mfunc invalid index name => DB_E_NOINDEX // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_12() { BOOL fTestResult = TEST_FAIL; DBID IndexID; size_t m, n; // get an invalid index name IndexID.eKind = DBKIND_NAME; m = min(m_cMaxIndexName, n=5+wcslen(m_pTable->GetTableName())); IndexID.uName.pwszName = BuildInvalidName(m, m_pTable->GetTableName(), m_pwszInvalidIndexChars); CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID), DB_E_NOINDEX); SAFE_FREE(IndexID.uName.pwszName); if (DB_E_NOINDEX == m_hr) fTestResult = TEST_PASS; return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(13) //*----------------------------------------------------------------------- // @mfunc maximum size index name => S_OK // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_13() { BOOL fTestResult = TEST_FAIL; DBID IndexID; ULONG nIndex; // get a maximum size index name IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = BuildValidName(m_cMaxIndexName, m_pTable->GetTableName()); // set an index if (CHECK(m_hr = SetIndex(&m_pTable->GetTableID(), &IndexID, &nIndex, NULL), S_OK)) { // drop the table and check the existence of the index if (CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID), S_OK)) fTestResult = TEST_PASS; } SAFE_FREE(IndexID.uName.pwszName); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(14) //*----------------------------------------------------------------------- // @mfunc oversized index name => DB_E_NOINDEX // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_14() { BOOL fTestResult = TEST_FAIL; DBID IndexID; // get an too long index name IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = BuildValidName(m_cMaxIndexName+1, m_pTable->GetTableName()); if (CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID), DB_E_NOINDEX)) fTestResult = TEST_PASS; SAFE_FREE(IndexID.uName.pwszName); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(15) //*----------------------------------------------------------------------- // @mfunc drop an index twice => DB_E_NOINDEX // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_15() { BOOL fTestResult = TEST_FAIL; DBID IndexID; ULONG nIndex; // prepare an index name IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = L"Galusca"; // set an index if (CHECK(m_hr = SetIndex(&m_pTable->GetTableID(), &IndexID, &nIndex, NULL), S_OK)) { // drop the table and check the existence of the index if (CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID), S_OK) && CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID), DB_E_NOINDEX) ) fTestResult = TEST_PASS; } return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(16) //*----------------------------------------------------------------------- // @mfunc inexistent table => DB_E_NOTABLE // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_16() { BOOL fTestResult = TEST_FAIL; DBID *pIndexID=NULL; DBID TableID; CTable *pTable=NULL; ULONG nIndex; HRESULT hr; // create a table TESTC(NULL != (pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName))); pTable->SetColumnDesc(m_rgColumnDesc, m_cColumnDesc); pTable->SetBuildColumnDesc(FALSE); TESTC_(pTable->CreateTable(0, 0), S_OK); // set an index on the table if (!CHECK(m_hr = SetIndex(&pTable->GetTableID(), NULL, &nIndex, &pIndexID), S_OK)) { fTestResult = TEST_SKIPPED; goto CLEANUP; } // drop the table DuplicateDBID(pTable->GetTableID(), &TableID); TESTC_(pTable->DropTable(&TableID), S_OK); // try to drop the index hr = m_pCIIndexDefinition->DropIndex(&TableID, pIndexID); TEST2C_(hr, DB_E_NOTABLE, DB_E_NOINDEX); fTestResult = TEST_PASS; CLEANUP: pTable->SetColumnDesc(NULL); pTable->DropTable(); delete pTable; ReleaseDBID(pIndexID); ReleaseDBID(&TableID, FALSE); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(17) //*----------------------------------------------------------------------- // @mfunc All DBKIND for pTableID // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_17() { BOOL fTestResult = TEST_PASS; DBID TableID, IndexID; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = L"AltNume"; TableID.uName.pwszName = m_pTable->GetTableName(); TableID.uGuid.pguid = &guidModule; // DBKIND_NAME TableID.eKind = DBKIND_NAME; m_hr = m_pCIIndexDefinition->DropIndex(&TableID, &IndexID); if (!CHECK(m_hr, DB_E_NOINDEX)) { odtLog << "DBKIND_NAME\n"; fTestResult = TEST_FAIL; } // DBKIND_GUID_NAME TableID.eKind = DBKIND_GUID_NAME; TableID.uGuid.guid = guidModule; m_hr = m_pCIIndexDefinition->DropIndex(&TableID, &IndexID); if (!CHECK(m_hr, DB_E_NOTABLE)) { odtLog << "DBKIND_GUID_NAME\n"; fTestResult = TEST_FAIL; } // DBKIND_PGUID_NAME TableID.eKind = DBKIND_PGUID_NAME; TableID.uGuid.pguid = &guidModule; m_hr = m_pCIIndexDefinition->DropIndex(&TableID, &IndexID); if (!CHECK(m_hr, DB_E_NOTABLE)) { odtLog << "DBKIND_PGUID_NAME\n"; fTestResult = TEST_FAIL; } // DBKIND_GUID TableID.eKind = DBKIND_GUID; TableID.uGuid.guid = guidModule; m_hr = m_pCIIndexDefinition->DropIndex(&TableID, &IndexID); if (!CHECK(m_hr, DB_E_NOTABLE)) { odtLog << "DBKIND_GUID\n"; fTestResult = TEST_FAIL; } TableID.uName.ulPropid = 0; TableID.uName.pwszName = NULL; // DBKIND_GUID_PROPID TableID.eKind = DBKIND_GUID_PROPID; TableID.uGuid.guid = guidModule; m_hr = m_pCIIndexDefinition->DropIndex(&TableID, &IndexID); if (!CHECK(m_hr, DB_E_NOTABLE)) { odtLog << "DBKIND_GUID_PROPID\n"; fTestResult = TEST_FAIL; } // DBKIND_PROPID TableID.eKind = DBKIND_PROPID; m_hr = m_pCIIndexDefinition->DropIndex(&TableID, &IndexID); if (!CHECK(m_hr, DB_E_NOTABLE)) { odtLog << "DBKIND_PROPID\n"; fTestResult = TEST_FAIL; } // DBKIND_PGUID_PROPID TableID.eKind = DBKIND_PGUID_PROPID; TableID.uGuid.pguid = &guidModule; m_hr = m_pCIIndexDefinition->DropIndex(&TableID, &IndexID); if (!CHECK(m_hr, DB_E_NOTABLE)) { odtLog << "DBKIND_PGUID_PROPID\n"; fTestResult = TEST_FAIL; } return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(18) //*----------------------------------------------------------------------- // @mfunc All DBKIND for pIndexID // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_18() { BOOL fTestResult = TEST_PASS; DBID IndexID; IndexID.uName.pwszName = L"galusca"; IndexID.uGuid.pguid = &guidModule; // DBKIND_NAME IndexID.eKind = DBKIND_NAME; m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID); if (!CHECK(m_hr, DB_E_NOINDEX)) { odtLog << "DBKIND_NAME\n"; fTestResult = TEST_FAIL; } // DBKIND_GUID_NAME IndexID.eKind = DBKIND_GUID_NAME; IndexID.uGuid.guid = guidModule; m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID); if (!CHECK(m_hr, DB_E_NOINDEX)) { odtLog << "DBKIND_GUID_NAME\n"; fTestResult = TEST_FAIL; } // DBKIND_PGUID_NAME IndexID.eKind = DBKIND_PGUID_NAME; IndexID.uGuid.pguid = &guidModule; m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID); if (!CHECK(m_hr, DB_E_NOINDEX)) { odtLog << "DBKIND_PGUID_NAME\n"; fTestResult = TEST_FAIL; } // DBKIND_GUID IndexID.eKind = DBKIND_GUID; IndexID.uGuid.guid = guidModule; m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID); if (!CHECK(m_hr, DB_E_NOINDEX)) { odtLog << "DBKIND_GUID\n"; fTestResult = TEST_FAIL; } IndexID.uName.ulPropid = 0; IndexID.uName.pwszName = NULL; // DBKIND_GUID_PROPID IndexID.eKind = DBKIND_GUID_PROPID; IndexID.uGuid.guid = guidModule; m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID); if (!CHECK(m_hr, DB_E_NOINDEX)) { odtLog << "DBKIND_GUID_PROPID\n"; fTestResult = TEST_FAIL; } // DBKIND_PROPID IndexID.eKind = DBKIND_PROPID; m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID); if (!CHECK(m_hr, DB_E_NOINDEX)) { odtLog << "DBKIND_PROPID\n"; fTestResult = TEST_FAIL; } // DBKIND_PGUID_PROPID IndexID.eKind = DBKIND_PGUID_PROPID; IndexID.uGuid.pguid = &guidModule; m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID); if (!CHECK(m_hr, DB_E_NOINDEX)) { odtLog << "DBKIND_PGUID_PROPID\n"; fTestResult = TEST_FAIL; } return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(19) //*----------------------------------------------------------------------- // @mfunc index in use => DB_E_INDEXINUSE // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_19() { TBEGIN BOOL fExists; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; IRowsetIndex *pIRowsetIndex = NULL; CDBIDPtr IndexID; if (S_OK != CNCIndexFromOrdinals(m_pTable, NULL, (DBID**)IndexID, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder)) { odtLog << "Could not properly create an index!\n"; goto CLEANUP; } // try to open a rowset index on it TESTC_PROVIDER(SUCCEEDED(m_hr = m_pIOpenRowset->OpenRowset(NULL, &m_pTable->GetTableID(), (DBID*)IndexID, IID_IRowsetIndex, 0, NULL, (IUnknown**)&pIRowsetIndex))); if ((DBID*)IndexID && CHECK(m_pCIIndexDefinition->DoesIndexExist(&m_pTable->GetTableID(), (DBID*)IndexID, &fExists), S_OK) && fExists) m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), (DBID*)IndexID); // take care, DB_E_TABLEINUSE is also allowed according to the spec if (DB_E_TABLEINUSE != m_hr && !CHECK(m_hr, DB_E_INDEXINUSE)) { odtLog << "could drop the index while a RowsetIndex was open\n"; goto CLEANUP; } CLEANUP: SAFE_RELEASE(pIRowsetIndex); m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), (DBID*)IndexID); TRETURN } // }} TCW_VAR_PROTOTYPE_END //------------------------------------------------------------------ // // thread function //------------------------------------------------------------------ unsigned TCDropIndex::MyThreadProc(ULONG i) { DBID IndexID; BOOL fExists; HRESULT hr; if (i>=nThreads) return 0; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = m_rgIndexName[i]; Sleep(0); hr = ((IIndexDefinition*)*m_pCIIndexDefinition)->DropIndex(&m_pTable->GetTableID(), &IndexID); Sleep(0); m_rgResult[i] = hr; hr = m_pCIIndexDefinition->DoesIndexExist(&m_pTable->GetTableID(), &IndexID, &fExists); return !CHECK(hr, S_OK) || fExists? 0: 1; } //TCDropIndex::MyThreadProc // {{ TCW_VAR_PROTOTYPE(20) //*----------------------------------------------------------------------- // @mfunc multithreading // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_20() { unsigned IDThread[nThreads]; HANDLE hThread[nThreads]; CInParam ThreadParam[nThreads]; DBID IndexID; BOOL fTestResult = TEST_FAIL, fExists; DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; WCHAR pwszNameSeed[]=L"theSameThread"; ULONG nIndex; for (nIndex = 0; nIndex < nThreads; nIndex++) { m_rgResult[nIndex] = E_FAIL; ThreadParam[nIndex].i = nIndex; ThreadParam[nIndex].pObject = this; SAFE_ALLOC(m_rgIndexName[nIndex], WCHAR, wcslen(pwszNameSeed)+3); swprintf(m_rgIndexName[nIndex], L"%s%02d", pwszNameSeed, nIndex); IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = m_rgIndexName[nIndex]; if (!CHECK(CNCIndexFromOrdinals(m_pTable, &IndexID, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder), S_OK)) { odtLog << "index " << m_rgIndexName[0] << " could not be created\n"; goto CLEANUP; } } for (nIndex = 0; nIndex < nThreads; nIndex++) { hThread[nIndex] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, (void*)&ThreadParam[nIndex], 0, &IDThread[nIndex]); if (hThread[nIndex] == 0) { fTestResult = TEST_FAIL; goto CLEANUP; } } WaitForMultipleObjects(nThreads, hThread, TRUE, INFINITE); fTestResult = TEST_PASS; for (nIndex=0; nIndexDoesIndexExist(&m_pTable->GetTableID(), &IndexID, &fExists), S_OK) || fExists) fTestResult = TEST_FAIL; if (fExists) CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID), S_OK); SAFE_FREE(m_rgIndexName[nIndex]); } CLEANUP: return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(21) //*----------------------------------------------------------------------- // @mfunc 2 threads, the same index // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_21() { unsigned IDThread[nThreads]; HANDLE hThread[nThreads]; CInParam ThreadParam[nThreads]; DBID IndexID; BOOL fTestResult = TEST_FAIL, fExists; ULONG rgOrder[1] = {0}; ULONG nSuccess = 0; ULONG nIndex; WCHAR pwszIndexName[] = L"theSameIndex"; IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = pwszIndexName; TESTC_(m_hr = CNCIndexFromOrdinals(m_pTable, &IndexID, NULL, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder), S_OK); fTestResult = TEST_FAIL; for (nIndex = 0; nIndex < nThreads; nIndex++) { m_rgResult[nIndex] = E_FAIL; ThreadParam[nIndex].i = nIndex; ThreadParam[nIndex].pObject = this; m_rgIndexName[nIndex] = pwszIndexName; hThread[nIndex] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, (void*)&ThreadParam[nIndex], 0, &IDThread[nIndex]); if (hThread[nIndex] == 0) { fTestResult = TEST_FAIL; goto CLEANUP; } } WaitForMultipleObjects(nThreads, hThread, TRUE, INFINITE); fTestResult = TEST_PASS; nSuccess = 0; for (nIndex=0; nIndexDoesIndexExist(&m_pTable->GetTableID(), &IndexID, &fExists), S_OK) || !CHECK(fExists, FALSE)) { odtLog << "errors in dropping the index\n"; goto CLEANUP; } if ( ((S_OK == m_rgResult[0]) && (DB_E_NOINDEX == m_rgResult[1])) || ((S_OK == m_rgResult[0]) && (DB_E_NOINDEX == m_rgResult[1])) ) fTestResult = TEST_PASS; CLEANUP: IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = m_rgIndexName[0]; m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), &IndexID); return fTestResult; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(22) //*----------------------------------------------------------------------- // @mfunc Inexistent index name // // @rdesc TEST_PASS or TEST_FAIL // int TCDropIndex::Variation_22() { TBEGIN DBID IndexID; DBID TableID; CTable *pTable=NULL; HRESULT hr; // create a table TESTC(NULL != (pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName))); TESTC_(pTable->CreateTable(0, 0), S_OK); DuplicateDBID(pTable->GetTableID(), &TableID); // try to drop the index IndexID.eKind = DBKIND_NAME; IndexID.uName.pwszName = L"AltNume"; hr = m_pCIIndexDefinition->DropIndex(&TableID, &IndexID); TEST2C_(hr, DB_E_NOTABLE, DB_E_NOINDEX); CLEANUP: if (pTable) { pTable->SetColumnDesc(NULL); pTable->DropTable(); delete pTable; } ReleaseDBID(&TableID, FALSE); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_TERMINATE_METHOD //*----------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TEST_PASS or TEST_FAIL // BOOL TCDropIndex::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(TCIIndexDefinition::Terminate()); } // }} // }} TCW_TERMINATE_METHOD_END // }} TCW_TC_PROTOTYPE_END // {{ TCW_TC_PROTOTYPE(TCTrans) //*----------------------------------------------------------------------- //| Test Case: TCTrans - transactions //| Created: 11/19/97 //*----------------------------------------------------------------------- //*----------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCTrans::Init() { TBEGIN ITransactionLocal *pITransactionLocal = NULL; // {{ TCW_INIT_BASECLASS_CHECK if (!TCIIndexDefinition::Init()) return FALSE; // }} // there is at least one column on which an index can be set TESTC_PROVIDER(0 < m_cIndexCols); m_rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[m_rgIndexCols[0]-1].dbcid; m_rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; // if transaction are not supported, skip the testcase TESTC_PROVIDER(VerifyInterface(*m_pCIIndexDefinition, IID_ITransactionLocal, SESSION_INTERFACE, (IUnknown**)&pITransactionLocal)); // transaction are supporte, get the value of DBPROP_SUPPORTEDTXNDDL prop // it should be supported when transactions are supported VariantInit(&m_vSupportedTxnDDL); if (!GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO, g_pIDBInitialize, &m_vSupportedTxnDDL)) { TOUTPUT("Warning: ITransactionLocal is supported, but DBPROP_SUPPORTEDTXNDDL is not supported!"); TESTB = TEST_SKIPPED; goto CLEANUP; } TESTC(VT_I4 == m_vSupportedTxnDDL.vt); // what values should we accept? TESTC_PROVIDER(DBPROPVAL_TC_NONE != m_vSupportedTxnDDL.lVal); CLEANUP: SAFE_RELEASE(pITransactionLocal); TRETURN } HRESULT TCTrans::StartTransaction(ITransactionLocal *pITransactionLocal) { ULONG n, i; HRESULT hr; ISOLEVEL rgIsoLevel[] = {ISOLATIONLEVEL_BROWSE, ISOLATIONLEVEL_CURSORSTABILITY, ISOLATIONLEVEL_ISOLATED, ISOLATIONLEVEL_CHAOS}; if (NULL == pITransactionLocal) return E_FAIL; n = NUMELEM(rgIsoLevel); for (i=0; iStartTransaction(rgIsoLevel[i], 0, NULL, NULL))) return S_OK; } return E_FAIL; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc Abort retaining on CreateIndex // // @rdesc TEST_PASS or TEST_FAIL // int TCTrans::Variation_1() { TBEGIN BOOL fExists; ITransactionLocal *pITransactionLocal=NULL; DBID *pIndexID = NULL; TESTC(VerifyInterface(*m_pCIIndexDefinition, IID_ITransactionLocal, SESSION_INTERFACE, (IUnknown**)&pITransactionLocal)); // start the transaction if (!CHECK(m_hr = StartTransaction(pITransactionLocal), S_OK)) { odtLog << "Could not start an isolated local transaction\n"; TESTB = TEST_SKIPPED; goto CLEANUP; } switch (V_I4(&m_vSupportedTxnDDL)) { case DBPROPVAL_TC_DML: //check for XACT_E_XTIONEXISTS CHECK(m_hr = m_pCIIndexDefinition->CreateIndex( &m_pTable->GetTableID(), NULL, 1, m_rgIndexColumnDesc, 0, NULL, &pIndexID), XACT_E_XTIONEXISTS); break; case DBPROPVAL_TC_DDL_IGNORE: // the statement is not transacted case DBPROPVAL_TC_ALL: case DBPROPVAL_TC_DDL_COMMIT: // create an index CHECK(m_hr = m_pCIIndexDefinition->CreateIndexAndCheck(&m_pTable->GetTableID(), NULL, 1, m_rgIndexColumnDesc, 0, NULL, &pIndexID), S_OK); //CHECK(m_hr = SetIndex(&m_pTable->GetTableID(), NULL, &nIndex, &pIndexID), S_OK); break; case DBPROPVAL_TC_DDL_LOCK: // error should be returned CHECK(m_pCIIndexDefinition->CreateIndex( &m_pTable->GetTableID(), NULL, 1, m_rgIndexColumnDesc, 0, NULL, &pIndexID), S_OK); break; default: TESTC(FALSE); } if (DBPROPVAL_TC_DDL_COMMIT != V_I4(&m_vSupportedTxnDDL)) { // abort retaining CHECK(m_hr = pITransactionLocal->Abort(NULL, TRUE, FALSE), S_OK); // check a new transaction was created CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK); } // check index creation CHECK(m_hr = m_pCIIndexDefinition->DoesIndexExist(&m_pTable->GetTableID(), pIndexID, &fExists), S_OK); COMPARE(fExists, DBPROPVAL_TC_DDL_IGNORE == V_I4(&m_vSupportedTxnDDL) || DBPROPVAL_TC_DDL_COMMIT == V_I4(&m_vSupportedTxnDDL)); CLEANUP: SAFE_RELEASE(pITransactionLocal); if (pIndexID && CHECK(m_pCIIndexDefinition->DoesIndexExist(&m_pTable->GetTableID(), pIndexID, &fExists), S_OK) && fExists) m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID); ReleaseDBID(pIndexID); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(2) //*----------------------------------------------------------------------- // @mfunc Abort non retaining on CreateIndex // // @rdesc TEST_PASS or TEST_FAIL // int TCTrans::Variation_2() { TBEGIN BOOL fExists; ITransactionLocal *pITransactionLocal=NULL; DBID *pIndexID = NULL; TESTC(VerifyInterface(*m_pCIIndexDefinition, IID_ITransactionLocal, SESSION_INTERFACE, (IUnknown**)&pITransactionLocal)); // start the transaction if (!CHECK(m_hr = StartTransaction(pITransactionLocal), S_OK)) { odtLog << "Could not start an isolated local transaction\n"; TESTB = TEST_SKIPPED; goto CLEANUP; } switch (V_I4(&m_vSupportedTxnDDL)) { case DBPROPVAL_TC_DML: //check for XACT_E_XTIONEXISTS CHECK(m_hr = m_pCIIndexDefinition->CreateIndex( &m_pTable->GetTableID(), NULL, 1, m_rgIndexColumnDesc, 0, NULL, &pIndexID), XACT_E_XTIONEXISTS); break; case DBPROPVAL_TC_DDL_IGNORE: // the statement is not transacted case DBPROPVAL_TC_ALL: case DBPROPVAL_TC_DDL_COMMIT: // create an index CHECK(m_hr = m_pCIIndexDefinition->CreateIndexAndCheck(&m_pTable->GetTableID(), NULL, 1, m_rgIndexColumnDesc, 0, NULL, &pIndexID), S_OK); //CHECK(m_hr = SetIndex(&m_pTable->GetTableID(), NULL, &nIndex, &pIndexID), S_OK); break; case DBPROPVAL_TC_DDL_LOCK: // error should be returned CHECK(m_pCIIndexDefinition->CreateIndex( &m_pTable->GetTableID(), NULL, 1, m_rgIndexColumnDesc, 0, NULL, &pIndexID), S_OK); break; default: TESTC(FALSE); } if (DBPROPVAL_TC_DDL_COMMIT != V_I4(&m_vSupportedTxnDDL)) { // abort non retaining CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK); // check a new transaction was not created CHECK(pITransactionLocal->Abort(NULL, FALSE, FALSE), FAILED(m_hr)? S_OK: XACT_E_NOTRANSACTION); } // check index creation CHECK(m_hr = m_pCIIndexDefinition->DoesIndexExist(&m_pTable->GetTableID(), pIndexID, &fExists), S_OK); COMPARE(fExists, DBPROPVAL_TC_DDL_IGNORE == V_I4(&m_vSupportedTxnDDL) || DBPROPVAL_TC_DDL_COMMIT == V_I4(&m_vSupportedTxnDDL)); CLEANUP: SAFE_RELEASE(pITransactionLocal); if (pIndexID && CHECK(m_pCIIndexDefinition->DoesIndexExist(&m_pTable->GetTableID(), pIndexID, &fExists), S_OK) && fExists) m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID); ReleaseDBID(pIndexID); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(3) //*----------------------------------------------------------------------- // @mfunc Commit retain on CreateIndex // // @rdesc TEST_PASS or TEST_FAIL // int TCTrans::Variation_3() { TBEGIN BOOL fExists; ITransactionLocal *pITransactionLocal=NULL; DBID *pIndexID = NULL; TESTC(VerifyInterface(*m_pCIIndexDefinition, IID_ITransactionLocal, SESSION_INTERFACE, (IUnknown**)&pITransactionLocal)); // start the transaction if (!CHECK(m_hr = StartTransaction(pITransactionLocal), S_OK)) { odtLog << "Could not start an isolated local transaction\n"; TESTB = TEST_SKIPPED; goto CLEANUP; } switch (V_I4(&m_vSupportedTxnDDL)) { case DBPROPVAL_TC_DML: //check for XACT_E_XTIONEXISTS CHECK(m_hr = m_pCIIndexDefinition->CreateIndex( &m_pTable->GetTableID(), NULL, 1, m_rgIndexColumnDesc, 0, NULL, &pIndexID), XACT_E_XTIONEXISTS); break; case DBPROPVAL_TC_DDL_IGNORE: // the statement is not transacted case DBPROPVAL_TC_ALL: case DBPROPVAL_TC_DDL_COMMIT: // create an index CHECK(m_hr = m_pCIIndexDefinition->CreateIndexAndCheck(&m_pTable->GetTableID(), NULL, 1, m_rgIndexColumnDesc, 0, NULL, &pIndexID), S_OK); //CHECK(m_hr = SetIndex(&m_pTable->GetTableID(), NULL, &nIndex, &pIndexID), S_OK); break; case DBPROPVAL_TC_DDL_LOCK: // error should be returned CHECK(m_pCIIndexDefinition->CreateIndex( &m_pTable->GetTableID(), NULL, 1, m_rgIndexColumnDesc, 0, NULL, &pIndexID), S_OK); break; default: TESTC(FALSE); } if (DBPROPVAL_TC_DDL_COMMIT != V_I4(&m_vSupportedTxnDDL)) { // commit retaining CHECK(m_hr = pITransactionLocal->Commit(TRUE, 0, 0), S_OK); // check a new transaction was created CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK); } // check index creation CHECK(m_hr = m_pCIIndexDefinition->DoesIndexExist(&m_pTable->GetTableID(), pIndexID, &fExists), S_OK); COMPARE(fExists, DBPROPVAL_TC_DML != V_I4(&m_vSupportedTxnDDL)); CLEANUP: SAFE_RELEASE(pITransactionLocal); if (pIndexID && CHECK(m_pCIIndexDefinition->DoesIndexExist(&m_pTable->GetTableID(), pIndexID, &fExists), S_OK) && fExists) m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID); ReleaseDBID(pIndexID); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(4) //*----------------------------------------------------------------------- // @mfunc Commit non-retain on CreateIndex // // @rdesc TEST_PASS or TEST_FAIL // int TCTrans::Variation_4() { TBEGIN BOOL fExists; ITransactionLocal *pITransactionLocal=NULL; DBID *pIndexID = NULL; TESTC(VerifyInterface(*m_pCIIndexDefinition, IID_ITransactionLocal, SESSION_INTERFACE, (IUnknown**)&pITransactionLocal)); // start the transaction if (!CHECK(m_hr = StartTransaction(pITransactionLocal), S_OK)) { odtLog << "Could not start an isolated local transaction\n"; TESTB = TEST_SKIPPED; goto CLEANUP; } switch (V_I4(&m_vSupportedTxnDDL)) { case DBPROPVAL_TC_DML: //check for XACT_E_XTIONEXISTS CHECK(m_hr = m_pCIIndexDefinition->CreateIndex( &m_pTable->GetTableID(), NULL, 1, m_rgIndexColumnDesc, 0, NULL, &pIndexID), XACT_E_XTIONEXISTS); break; case DBPROPVAL_TC_DDL_IGNORE: // the statement is not transacted case DBPROPVAL_TC_ALL: case DBPROPVAL_TC_DDL_COMMIT: // create an index CHECK(m_hr = m_pCIIndexDefinition->CreateIndexAndCheck(&m_pTable->GetTableID(), NULL, 1, m_rgIndexColumnDesc, 0, NULL, &pIndexID), S_OK); //CHECK(m_hr = SetIndex(&m_pTable->GetTableID(), NULL, &nIndex, &pIndexID), S_OK); break; case DBPROPVAL_TC_DDL_LOCK: // error should be returned CHECK(m_pCIIndexDefinition->CreateIndex( &m_pTable->GetTableID(), NULL, 1, m_rgIndexColumnDesc, 0, NULL, &pIndexID), S_OK); break; default: TESTC(FALSE); } if (DBPROPVAL_TC_DDL_COMMIT != V_I4(&m_vSupportedTxnDDL)) { // commit non retaining CHECK(m_hr = pITransactionLocal->Commit(FALSE, 0, 0), S_OK); // check a new transaction was not created CHECK(pITransactionLocal->Abort(NULL, FALSE, FALSE), FAILED(m_hr)? S_OK: XACT_E_NOTRANSACTION); } // check index creation CHECK(m_hr = m_pCIIndexDefinition->DoesIndexExist(&m_pTable->GetTableID(), pIndexID, &fExists), S_OK); COMPARE(fExists, DBPROPVAL_TC_DML != V_I4(&m_vSupportedTxnDDL)); CLEANUP: SAFE_RELEASE(pITransactionLocal); if (pIndexID && CHECK(m_pCIIndexDefinition->DoesIndexExist(&m_pTable->GetTableID(), pIndexID, &fExists), S_OK) && fExists) m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID); ReleaseDBID(pIndexID); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(5) //*----------------------------------------------------------------------- // @mfunc Abort retain on DropIndex // // @rdesc TEST_PASS or TEST_FAIL // int TCTrans::Variation_5() { TBEGIN BOOL fExists; ITransactionLocal *pITransactionLocal=NULL; DBID *pIndexID = NULL; ULONG nIndex; TESTC(VerifyInterface(*m_pCIIndexDefinition, IID_ITransactionLocal, SESSION_INTERFACE, (IUnknown**)&pITransactionLocal)); // create an index TESTC_(m_hr = SetIndex(&m_pTable->GetTableID(), NULL, &nIndex, &pIndexID), S_OK); // start the transaction if (!CHECK(m_hr = StartTransaction(pITransactionLocal), S_OK)) { odtLog << "Could not start an isolated local transaction\n"; TESTB = TEST_SKIPPED; goto CLEANUP; } switch (V_I4(&m_vSupportedTxnDDL)) { case DBPROPVAL_TC_DML: //check for XACT_E_XTIONEXISTS CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID), XACT_E_XTIONEXISTS); break; case DBPROPVAL_TC_DDL_IGNORE: // the statement is not transacted case DBPROPVAL_TC_ALL: case DBPROPVAL_TC_DDL_COMMIT: // create an index CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID), S_OK); break; case DBPROPVAL_TC_DDL_LOCK: // error should be returned CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID), S_OK); break; default: TESTC(FALSE); } if (DBPROPVAL_TC_DDL_COMMIT != V_I4(&m_vSupportedTxnDDL)) { // abort retaining CHECK(m_hr = pITransactionLocal->Abort(NULL, TRUE, FALSE), S_OK); // check a new transaction was created CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK); } // check index deletion CHECK(m_hr = m_pCIIndexDefinition->DoesIndexExist(&m_pTable->GetTableID(), pIndexID, &fExists), S_OK); COMPARE(fExists, DBPROPVAL_TC_DDL_IGNORE != V_I4(&m_vSupportedTxnDDL) || DBPROPVAL_TC_DDL_COMMIT != V_I4(&m_vSupportedTxnDDL)); CLEANUP: SAFE_RELEASE(pITransactionLocal); m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID); ReleaseDBID(pIndexID); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(6) //*----------------------------------------------------------------------- // @mfunc Abort non-retain on DropIndex // // @rdesc TEST_PASS or TEST_FAIL // int TCTrans::Variation_6() { TBEGIN BOOL fExists; ITransactionLocal *pITransactionLocal=NULL; DBID *pIndexID = NULL; ULONG nIndex; TESTC_PROVIDER(VerifyInterface(*m_pCIIndexDefinition, IID_ITransactionLocal, SESSION_INTERFACE, (IUnknown**)&pITransactionLocal)); // create an index TESTC_(SetIndex(&m_pTable->GetTableID(), NULL, &nIndex, &pIndexID), S_OK); // start the transaction if (!CHECK(m_hr = StartTransaction(pITransactionLocal), S_OK)) { odtLog << "Could not start an isolated local transaction\n"; TESTB = TEST_SKIPPED; goto CLEANUP; } switch (V_I4(&m_vSupportedTxnDDL)) { case DBPROPVAL_TC_DML: //check for XACT_E_XTIONEXISTS CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID), XACT_E_XTIONEXISTS); break; case DBPROPVAL_TC_DDL_IGNORE: // the statement is not transacted case DBPROPVAL_TC_ALL: case DBPROPVAL_TC_DDL_COMMIT: // create an index CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID), S_OK); break; case DBPROPVAL_TC_DDL_LOCK: // error should be returned CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID), S_OK); break; default: TESTC(FALSE); } if (DBPROPVAL_TC_DDL_COMMIT != V_I4(&m_vSupportedTxnDDL)) { // abort non retaining CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK); // check a new transaction was not created CHECK(pITransactionLocal->Abort(NULL, FALSE, FALSE), FAILED(m_hr)? S_OK: XACT_E_NOTRANSACTION); } // check index deletion CHECK(m_hr = m_pCIIndexDefinition->DoesIndexExist(&m_pTable->GetTableID(), pIndexID, &fExists), S_OK); COMPARE(fExists, DBPROPVAL_TC_DDL_IGNORE != V_I4(&m_vSupportedTxnDDL) || DBPROPVAL_TC_DDL_COMMIT != V_I4(&m_vSupportedTxnDDL)); CLEANUP: SAFE_RELEASE(pITransactionLocal); // drop the index m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID); ReleaseDBID(pIndexID); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(7) //*----------------------------------------------------------------------- // @mfunc Commit retain on DropIndex // // @rdesc TEST_PASS or TEST_FAIL // int TCTrans::Variation_7() { TBEGIN BOOL fExists; ITransactionLocal *pITransactionLocal=NULL; DBID *pIndexID = NULL; ULONG nIndex; TESTC_PROVIDER(VerifyInterface(*m_pCIIndexDefinition, IID_ITransactionLocal, SESSION_INTERFACE, (IUnknown**)&pITransactionLocal)); // create an index TESTC_(SetIndex(&m_pTable->GetTableID(), NULL, &nIndex, &pIndexID), S_OK); // start the transaction if (!CHECK(m_hr = StartTransaction(pITransactionLocal), S_OK)) { odtLog << "Could not start an isolated local transaction\n"; TESTB = TEST_SKIPPED; goto CLEANUP; } switch (V_I4(&m_vSupportedTxnDDL)) { case DBPROPVAL_TC_DML: //check for XACT_E_XTIONEXISTS CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID), XACT_E_XTIONEXISTS); break; case DBPROPVAL_TC_DDL_IGNORE: // the statement is not transacted case DBPROPVAL_TC_ALL: case DBPROPVAL_TC_DDL_COMMIT: // create an index CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID), S_OK); break; case DBPROPVAL_TC_DDL_LOCK: // error should be returned CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID), S_OK); break; default: TESTC(FALSE); } if (DBPROPVAL_TC_DDL_COMMIT != V_I4(&m_vSupportedTxnDDL)) { // commit retaining CHECK(m_hr = pITransactionLocal->Commit(TRUE, 0, 0), S_OK); // check a new transaction was created CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK); } // check index deletion CHECK(m_hr = m_pCIIndexDefinition->DoesIndexExist(&m_pTable->GetTableID(), pIndexID, &fExists), S_OK); COMPARE(fExists, DBPROPVAL_TC_DML == V_I4(&m_vSupportedTxnDDL)); CLEANUP: SAFE_RELEASE(pITransactionLocal); // drop the index m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID); ReleaseDBID(pIndexID); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_VAR_PROTOTYPE(8) //*----------------------------------------------------------------------- // @mfunc Commit non retain on DropIndex // // @rdesc TEST_PASS or TEST_FAIL // int TCTrans::Variation_8() { TBEGIN BOOL fExists; ITransactionLocal *pITransactionLocal=NULL; DBID *pIndexID = NULL; ULONG nIndex; TESTC_PROVIDER(VerifyInterface(*m_pCIIndexDefinition, IID_ITransactionLocal, SESSION_INTERFACE, (IUnknown**)&pITransactionLocal)); // create an index TESTC_(SetIndex(&m_pTable->GetTableID(), NULL, &nIndex, &pIndexID), S_OK); // start the transaction if (!CHECK(m_hr = StartTransaction(pITransactionLocal), S_OK)) { odtLog << "Could not start an isolated local transaction\n"; TESTB = TEST_SKIPPED; goto CLEANUP; } switch (V_I4(&m_vSupportedTxnDDL)) { case DBPROPVAL_TC_DML: //check for XACT_E_XTIONEXISTS CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID), XACT_E_XTIONEXISTS); break; case DBPROPVAL_TC_DDL_IGNORE: // the statement is not transacted case DBPROPVAL_TC_ALL: case DBPROPVAL_TC_DDL_COMMIT: // create an index CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID), S_OK); break; case DBPROPVAL_TC_DDL_LOCK: // error should be returned CHECK(m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID), S_OK); break; default: TESTC(FALSE); } if (DBPROPVAL_TC_DDL_COMMIT != V_I4(&m_vSupportedTxnDDL)) { // commit non retaining CHECK(m_hr = pITransactionLocal->Commit(FALSE, 0, 0), S_OK); // check a new transaction does not exist CHECK(pITransactionLocal->Abort(NULL, FALSE, FALSE), FAILED(m_hr)? S_OK: XACT_E_NOTRANSACTION); } // check index deletion CHECK(m_hr = m_pCIIndexDefinition->DoesIndexExist(&m_pTable->GetTableID(), pIndexID, &fExists), S_OK); COMPARE(fExists, DBPROPVAL_TC_DML == V_I4(&m_vSupportedTxnDDL)); CLEANUP: // drop the index m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), pIndexID); SAFE_RELEASE(pITransactionLocal); ReleaseDBID(pIndexID); TRETURN } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_TERMINATE_METHOD //*----------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TEST_PASS or TEST_FAIL // BOOL TCTrans::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 return(TCIIndexDefinition::Terminate()); } // }} // }} TCW_TERMINATE_METHOD_END // }} TCW_TC_PROTOTYPE_END // {{ TCW_TC_PROTOTYPE(TCRODataSource) //*----------------------------------------------------------------------- //| Test Case: TCRODataSource - read only data source //| Created: 11/21/97 //*----------------------------------------------------------------------- //*----------------------------------------------------------------------- // @mfunc TestCase Initialization Routine // // @rdesc TRUE or FALSE // BOOL TCRODataSource::Init() { BOOL fResults = TEST_SKIPPED; IDBInitialize *pIDBInitialize = NULL; IDBProperties *pIDBProperties = NULL; DBPROPSET *rgPropSets = NULL; ULONG cPropSets = 0; HRESULT hr = NOERROR; DBPROP *rgProperties = NULL; // vars for an index DBINDEX_COL_ORDER rgOrder[]={DBINDEX_COL_ORDER_ASC}; const int n=1; const int nINIT_MODE = 0; DBPROPIDSET rgPropIDSet[n]; DBPROPID rgPropID1[1]; ULONG nActualSize = n;; m_pIUnknown = NULL; m_pIUnknown2 = NULL; m_pIndexID = NULL; m_pIIndexDefinition2 = NULL; // {{ TCW_INIT_BASECLASS_CHECK if(!TCIIndexDefinition::Init()) // }} goto CLEANUP; if (!SettableProperty(DBPROP_INIT_MODE, DBPROPSET_DBINIT)) { odtLog << "DBPROP_INIT_MODE is not supported or is not a read-write property\n"; fResults = TEST_SKIPPED; goto CLEANUP; } fResults = TEST_FAIL; // create a spare index if (!CHECK(m_hr = CNCIndexFromOrdinals(m_pTable, NULL, &m_pIndexID, m_rgColumnDesc, m_cColumnDesc, 1, &m_nIndex, rgOrder), S_OK)) { odtLog << "could not create an index on the read-write data source!\n"; goto CLEANUP; } // Setup the arrays needed for init, based on string LTM passed to us if(!GetInitProps(&cPropSets, &rgPropSets)) goto CLEANUP; if(!SUCCEEDED(m_hr = GetModInfo()->CreateProvider(NULL, IID_IDBInitialize, (IUnknown**)&pIDBInitialize))) goto CLEANUP; // Get IDBProperties Pointer pIDBProperties = NULL; if (!VerifyInterface(pIDBInitialize, IID_IDBProperties, DATASOURCE_INTERFACE, (IUnknown**)&pIDBProperties)) goto CLEANUP; // Set the properties before we Initialize, only if we have Properties to set... if (FAILED(m_hr = pIDBProperties->SetProperties(cPropSets, rgPropSets))) goto CLEANUP; // free the structures FreeProperties(&cPropSets, &rgPropSets); rgPropSets = NULL; cPropSets = 0; TESTC_(SetProperty(&rgPropSets, &cPropSets, DBPROP_INIT_MODE, VT_I4, (LPVOID)1, DBPROPOPTIONS_REQUIRED, DB_NULLID, DBPROPSET_DBINIT), TRUE); // Set the properties before we Initialize, only if we have Properties to set... if (FAILED(m_hr = pIDBProperties->SetProperties(cPropSets, rgPropSets))) { FindProperty(DBPROP_INIT_MODE, DBPROPSET_DBINIT, cPropSets, rgPropSets, &rgProperties); if (DBPROPSTATUS_OK != rgProperties->dwStatus) odtLog << "Read only property could not be initialized!\n"; goto CLEANUP1; } FreeProperties( &cPropSets, &rgPropSets); // Initialize if(!GCHECK(m_hr = pIDBInitialize->Initialize(), S_OK)) { odtLog << wszInitializeFailed; goto CLEANUP1; } // check that the read only property was set rgPropID1[0] = DBPROP_INIT_MODE; rgPropIDSet[nINIT_MODE].cPropertyIDs = 1; rgPropIDSet[nINIT_MODE].rgPropertyIDs = rgPropID1; rgPropIDSet[nINIT_MODE].guidPropertySet = DBPROPSET_DBINIT; CHECK(m_hr = pIDBProperties->GetProperties(nActualSize, rgPropIDSet, &cPropSets, &rgPropSets), S_OK); if ( (DBPROPSTATUS_OK == rgPropSets[nINIT_MODE].rgProperties[0].dwStatus) && ( (VT_I4 != rgPropSets[nINIT_MODE].rgProperties[0].vValue.vt) || (DB_MODE_READ != V_I4(&rgPropSets[nINIT_MODE].rgProperties[0].vValue)))) { odtLog << "despite ok reports, DBPROP_INIT_MODE is not set to read only\n"; goto CLEANUP1; } // Obtain IDBCreateSesson, placing the new DSO interface // in CThisTestModule's m_pIUnknown, so that all testcases can use // it via their back pointer to this object. No need to call AddRef // here as we will own it, rather than the test module. if (!VerifyInterface(pIDBInitialize, IID_IDBCreateSession, DATASOURCE_INTERFACE, (IUnknown**)&m_pIUnknown)) goto CLEANUP1; // Create a DB session object // Set the m_pIUnknown2 to IOpenRowset if (!GCHECK(((IDBCreateSession*)m_pIUnknown)->CreateSession( NULL, IID_IOpenRowset, (IUnknown **)&m_pIUnknown2), S_OK)) goto CLEANUP1; SetDBSession(m_pIUnknown2); // calls ReleaseDBSession Before if (!(m_hr=VerifyInterface(m_pIUnknown2, IID_IIndexDefinition, SESSION_INTERFACE, (IUnknown**)&m_pIIndexDefinition2))) goto CLEANUP1; fResults = TRUE; CLEANUP1: FreeProperties( &cPropSets, &rgPropSets); CLEANUP: SAFE_RELEASE(pIDBProperties); SAFE_RELEASE(pIDBInitialize); return fResults; } // {{ TCW_VAR_PROTOTYPE(1) //*----------------------------------------------------------------------- // @mfunc try to create an index on a read only datasource // // @rdesc TEST_PASS or TEST_FAIL // int TCRODataSource::Variation_1() { DBID *pIndexID = NULL; DBINDEXCOLUMNDESC rgIndexColumnDesc[1]; BOOL fTestResults = TEST_PASS; rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[m_nIndex-1].dbcid; rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC; m_hr = m_pIIndexDefinition2->CreateIndex(&m_pTable->GetTableID(), m_pIndexID, 1, rgIndexColumnDesc, 0, NULL, &pIndexID); if (!CHECK(m_hr, DB_SEC_E_PERMISSIONDENIED)) fTestResults = TEST_FAIL; if (!CHECK(m_hr = m_pIIndexDefinition2->DropIndex(&m_pTable->GetTableID(), m_pIndexID), DB_SEC_E_PERMISSIONDENIED)) fTestResults = TEST_FAIL; ReleaseDBID(pIndexID); return fTestResults; } // }} TCW_VAR_PROTOTYPE_END // {{ TCW_TERMINATE_METHOD //*----------------------------------------------------------------------- // @mfunc TestCase Termination Routine // // @rdesc TEST_PASS or TEST_FAIL // BOOL TCRODataSource::Terminate() { // {{ TCW_TERM_BASECLASS_CHECK2 // destroy the index built on the read-write data source if (m_pCIIndexDefinition && m_pIndexID) m_hr = m_pCIIndexDefinition->DropIndex(&m_pTable->GetTableID(), m_pIndexID); ReleaseDBID(m_pIndexID); SetDBSession(m_pThisTestModule->m_pIUnknown2); SAFE_RELEASE(m_pIUnknown); SAFE_RELEASE(m_pIUnknown2); SAFE_RELEASE(m_pIIndexDefinition2); return(TCIIndexDefinition::Terminate()); } // }} // }} TCW_TERMINATE_METHOD_END // }} TCW_TC_PROTOTYPE_END // Hack to defile CoInitializeEx WINOLEAPI CoInitializeEx(LPVOID pvReserved, DWORD dwCoInit); unsigned WINAPI ThreadProc(LPVOID lpvThreadParam) { CoInitializeEx(NULL, 0); TCIIndexDefinition *pObject = ((CInParam*)lpvThreadParam)->pObject; pObject->MyThreadProc(((CInParam*)lpvThreadParam)->i); CoUninitialize(); return 0; } //ThreadProc