10210 lines
304 KiB
C++
10210 lines
304 KiB
C++
//--------------------------------------------------------------------
|
|
// 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 <process.h>
|
|
|
|
#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<CCol, CCol&> 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 <nl>
|
|
// 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 <nl>
|
|
// 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; ps<cPropertySets; ps++)
|
|
{
|
|
// compare the props in that prop set
|
|
if (!CHECK(rgInPropertySets[ps].guidPropertySet == rgOutPropertySets[ps].guidPropertySet, TRUE))
|
|
return FALSE;
|
|
if (!CHECK(rgInPropertySets[ps].cProperties == rgOutPropertySets[ps].cProperties, TRUE))
|
|
return FALSE;
|
|
for (pc=0; pc<rgInPropertySets[ps].cProperties; pc++)
|
|
{
|
|
if (!CHECK(rgInPropertySets[ps].rgProperties[pc].dwPropertyID ==
|
|
rgOutPropertySets[ps].rgProperties[pc].dwPropertyID, TRUE))
|
|
return FALSE;
|
|
if (!CHECK(rgInPropertySets[ps].rgProperties[pc].dwOptions ==
|
|
rgOutPropertySets[ps].rgProperties[pc].dwOptions, TRUE))
|
|
return FALSE;
|
|
if (!CHECK(hr = CompareDBID(rgInPropertySets[ps].rgProperties[pc].colid,
|
|
rgOutPropertySets[ps].rgProperties[pc].colid), TRUE))
|
|
return FALSE;
|
|
if (!CHECK(CompareVariant(&rgInPropertySets[ps].rgProperties[pc].vValue,
|
|
&rgOutPropertySets[ps].rgProperties[pc].vValue), TRUE))
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
} //IsPropSetPreserved
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// CheckReturnedDBID
|
|
//-------------------------------------------------------------------------
|
|
BOOL CheckReturnedDBID(
|
|
DBID *pIndexID, // passed to CreateIndex
|
|
DBID **ppIndexID // returned by CreateIndex
|
|
)
|
|
{
|
|
if (!pIndexID)
|
|
return *ppIndexID != NULL;
|
|
|
|
if (!ppIndexID)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
if (*ppIndexID == NULL)
|
|
return FALSE;
|
|
|
|
return CompareDBID(*pIndexID, **ppIndexID);
|
|
} //CheckReturnedDBID
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
// Check the result and property status
|
|
//--------------------------------------------------------------------------
|
|
BOOL 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;
|
|
} //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<CCol, CCol&> *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; i<cIndexColumnDesc; i++)
|
|
{
|
|
if (!COMPARE(rgIndexColumnDesc[i].eIndexColOrder == rgOutIndexColumnDesc[i].eIndexColOrder, TRUE))
|
|
{
|
|
odtLog << "order (A/D) differ for column " << rgIndexColumnDesc[i].pColumnID->uName.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; nPropSet<cPropertySets; nPropSet++)
|
|
{
|
|
if (DBPROPSET_INDEX != rgPropertySets[nPropSet].guidPropertySet)
|
|
{
|
|
for (nProp=0; nProp<rgPropertySets[nPropSet].cProperties; nProp++)
|
|
{
|
|
COMPARE(rgPropertySets[nPropSet].rgProperties[nProp].dwStatus, DBPROPSTATUS_NOTSUPPORTED);
|
|
}
|
|
continue;
|
|
}
|
|
if (!rgPropertySets[nPropSet].rgProperties)
|
|
continue;
|
|
for (nProp=0; nProp<rgPropertySets[nPropSet].cProperties; nProp++)
|
|
{
|
|
dwStatus = rgPropertySets[nPropSet].rgProperties[nProp].dwStatus;
|
|
dwPropID = rgPropertySets[nPropSet].rgProperties[nProp].dwPropertyID;
|
|
pvValue = &rgPropertySets[nPropSet].rgProperties[nProp].vValue;
|
|
|
|
// try to find corresponding property got from IRowsetIndex
|
|
if (!FindProperty( dwPropID,
|
|
rgPropertySets[nPropSet].guidPropertySet,
|
|
cIndexPropSets,
|
|
rgIndexPropSets,
|
|
&pProp))
|
|
{
|
|
COMPARE(dwStatus, DBPROPSTATUS_NOTSUPPORTED);
|
|
}
|
|
else
|
|
// prop status were check in CreateAndCheckIndex by calling CheckProperty
|
|
if (DBPROPSTATUS_OK == dwStatus)
|
|
COMPARE(CompareVariant(&pProp->vValue, 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;index<cRest;index++)
|
|
VariantInit(&rgRestrictIndexes[index]);
|
|
|
|
TESTC_PROVIDER(VerifyInterface(m_pIIndexDefinition, IID_IDBSchemaRowset, SESSION_INTERFACE, (IUnknown**)&pIDBSchemaRowset));
|
|
|
|
// Check to see if the schema is supported
|
|
TESTC_(hr = pIDBSchemaRowset->GetSchemas(&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; i<cSchema && !bIsSchemaSupported;)
|
|
{
|
|
if(prgSchemas[i] == DBSCHEMA_INDEXES)
|
|
bIsSchemaSupported = TRUE;
|
|
else
|
|
i++;
|
|
}
|
|
|
|
if(!bIsSchemaSupported || !(prgRestrictions[i] & 0x4) || !(prgRestrictions[i] & 0x10))
|
|
{
|
|
odtLog << "Index Schema Rowset or the required constraints are not supported\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
rgRestrictIndexes[2].vt = VT_BSTR;
|
|
rgRestrictIndexes[2].bstrVal = SysAllocString(pIndexID->uName.pwszName);
|
|
rgRestrictIndexes[4].vt = VT_BSTR;
|
|
rgRestrictIndexes[4].bstrVal = SysAllocString(pTableID->uName.pwszName);
|
|
|
|
SAFE_ALLOC(rgColPresent, BOOL, cIndexColumnDesc);
|
|
for (i=0; i<cIndexColumnDesc; i++)
|
|
rgColPresent[i] = FALSE;
|
|
|
|
TESTC_(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**)&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;iRow<cIndexColumnDesc;iRow++)
|
|
{
|
|
TESTC_(hr=pIndexRowset->GetNextRows(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;index<cRest;index++)
|
|
GCHECK(VariantClear(&(rgRestrictIndexes[index])),S_OK);
|
|
|
|
TRETURN
|
|
} //CIIndexDefinition::CheckIndexUsingIDBSchemaRowset
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// CIIndexDefinition::DoesIndexExistInIndexSchemaRowset
|
|
//
|
|
// 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. 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 CIIndexDefinition::DoesIndexExistInIndexSchemaRowset(
|
|
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;
|
|
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;
|
|
IDBSchemaRowset *pIDBSchemaRowset = NULL;
|
|
|
|
// Set restrictions
|
|
for(index=0;index<cRest;index++)
|
|
VariantInit(&rgRestrictIndexes[index]);
|
|
|
|
TESTC_PROVIDER(VerifyInterface(m_pIIndexDefinition, IID_IDBSchemaRowset, SESSION_INTERFACE, (IUnknown**)&pIDBSchemaRowset));
|
|
|
|
TESTC((NULL != pIndexID) || ((NULL != pTableID) && fAnyIndex));
|
|
|
|
if (pIndexID && !fAnyIndex)
|
|
{
|
|
rgRestrictIndexes[2].vt = VT_BSTR;
|
|
if (pIndexID->eKind==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;index<cRest;index++)
|
|
GCHECK(VariantClear(&(rgRestrictIndexes[index])),S_OK);
|
|
|
|
return hr;
|
|
} //CIIndexDefinition::DoesIndexExistInIndexSchemaRowset
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// CIIndexDefinition::DoesIndexExistRowsetIndex
|
|
//
|
|
// 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. 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 CIIndexDefinition::DoesIndexExistRowsetIndex(
|
|
DBID *pTableID, // @parm [IN] Table ID
|
|
DBID *pIndexID, // @parm [IN] Index ID
|
|
BOOL *pfExist // @parm [OUT] TRUE if index exists
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
IRowsetIndex *pRowsetIndex = NULL;
|
|
IOpenRowset *pIOpenRowset = NULL;
|
|
|
|
TESTC(VerifyInterface(m_pIIndexDefinition, IID_IOpenRowset, SESSION_INTERFACE, (IUnknown**)&pIOpenRowset));
|
|
hr = pIOpenRowset->OpenRowset(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; i<nIndexSize; i++)
|
|
{
|
|
if (rgIndexColumnDesc[i].pColumnID && rgIndexColumnDesc[i].pColumnID->uName.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<nIndexSize; l++)
|
|
{
|
|
for (pos=1; rgColumnPresent[pos]; pos++);
|
|
rgIndexColumns[l] = pos;
|
|
rgColumnPresent[pos] = TRUE;
|
|
}
|
|
// we have a new valid index, so flee!
|
|
return nLastUpdate;
|
|
}
|
|
else
|
|
{
|
|
// could not make any pick for this column, must try to modify the previous one first
|
|
nLastUpdate--;
|
|
}
|
|
}
|
|
return nLastUpdate;
|
|
} //TCIIndexDefinition::GetNextIndex
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// @cmember Iterator on order (ascending/descending)
|
|
//-------------------------------------------------------------------------
|
|
int TCIIndexDefinition::GetNextOrder(
|
|
DBINDEX_COL_ORDER *rgIndexOrder, // array containing the column numbers of the index
|
|
DBORDINAL nIndexSize // index size
|
|
)
|
|
{
|
|
ULONG l;
|
|
int nLastUpdate;
|
|
|
|
for (nLastUpdate=(int)nIndexSize-1; nLastUpdate>=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; l<nIndexSize; l++)
|
|
{
|
|
rgIndexOrder[l] = DBINDEX_COL_ORDER_ASC;
|
|
}
|
|
// we have a new valid index, so flee!
|
|
return nLastUpdate;
|
|
}
|
|
else
|
|
{
|
|
// one step back
|
|
nLastUpdate--;
|
|
}
|
|
}
|
|
return nLastUpdate;
|
|
} //TCIIndexDefinition::GetNextOrder
|
|
|
|
|
|
|
|
|
|
/*//-------------------------------------------------------------------------
|
|
//
|
|
// @cmember Drops the index and releases its DBID
|
|
//-------------------------------------------------------------------------
|
|
BOOL TCIIndexDefinition::DropIndexAndReleaseID(
|
|
DBID *pTableID,
|
|
DBID **ppIndexID
|
|
)
|
|
{
|
|
BOOL fRes = FALSE;
|
|
BOOL fExist;
|
|
|
|
TESTC(NULL != pTableID);
|
|
TESTC(NULL != ppIndexID);
|
|
TESTC(NULL != *ppIndexID);
|
|
|
|
if (CHECK(DoesIndexExist(pTableID, *ppIndexID, &fExist), S_OK) && !fExist)
|
|
{
|
|
fRes = TRUE;
|
|
goto CLEANUP0;
|
|
}
|
|
|
|
if (CHECK(m_pIIndexDefinition->DropIndex(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; i<m_cColumnDesc; i++)
|
|
{
|
|
rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[i].dbcid;
|
|
if (ppIndexID)
|
|
*ppIndexID = NULL;
|
|
ASSERT(m_pCIIndexDefinition);
|
|
if (S_OK == (hr = m_pCIIndexDefinition->CreateIndexAndCheck(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<nIndexSize; i++)
|
|
{
|
|
rgIndexColumns[i] = i+1;
|
|
rgColumnPresent[i+1] = TRUE;
|
|
}
|
|
|
|
for (nLastUpdate=(int)nIndexSize-1; nLastUpdate >= 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; i<cColumnDesc; i++)
|
|
{
|
|
FreeProperties(&rgColumnDesc[i].cPropertySets,
|
|
&rgColumnDesc[i].rgPropertySets);
|
|
}
|
|
|
|
fRes = TRUE;
|
|
|
|
CLEANUP:
|
|
return fRes;
|
|
} //TCIIndexDefinition::ReleaseAllColumnPropSets
|
|
|
|
|
|
|
|
|
|
|
|
/*//-------------------------------------------------------------------------
|
|
//
|
|
// @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 TCIIndexDefinition::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, // [in] count of property sets
|
|
DBPROPSET *rgPropSets // [in] array of property sets
|
|
)
|
|
{
|
|
DBID *pNewIndexID = NULL; // DBID of the newly created index
|
|
DBPROPSET *rgPropSets1 = NULL; // saves the property sets
|
|
HRESULT hr;
|
|
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 = m_pIIndexDefinition->CreateIndex( 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; i<cIndexColumnDesc; i++)
|
|
{
|
|
if (rgIndexColumnDesc[i].eIndexColOrder != rgOutIndexColumnDesc[i].eIndexColOrder)
|
|
{
|
|
odtLog << "order (A/D) differ for column " << rgIndexColumnDesc[i].pColumnID->uName.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; nPropSet<cPropertySets; nPropSet++)
|
|
{
|
|
if (DBPROPSET_INDEX != rgPropertySets[nPropSet].guidPropertySet)
|
|
{
|
|
for (nProp=0; nProp<rgPropertySets[nPropSet].cProperties; nProp++)
|
|
{
|
|
if (!COMPARE(rgPropertySets[nPropSet].rgProperties[nProp].dwStatus, DBPROPSTATUS_NOTSUPPORTED))
|
|
fProp = FALSE;
|
|
}
|
|
continue;
|
|
}
|
|
if (!rgPropertySets[nPropSet].rgProperties)
|
|
continue;
|
|
for (nProp=0; nProp<rgPropertySets[nPropSet].cProperties; nProp++)
|
|
{
|
|
dwStatus = rgPropertySets[nPropSet].rgProperties[nProp].dwStatus;
|
|
dwPropID = rgPropertySets[nPropSet].rgProperties[nProp].dwPropertyID;
|
|
pvValue = &rgPropertySets[nPropSet].rgProperties[nProp].vValue;
|
|
|
|
// try to find coresponding property got from IRowsetIndex
|
|
if (!FindProperty( dwPropID,
|
|
rgPropertySets[nPropSet].guidPropertySet,
|
|
cIndexPropSets,
|
|
rgIndexPropSets,
|
|
&pProp))
|
|
{
|
|
fProp = fProp && COMPARE(dwStatus, DBPROPSTATUS_NOTSUPPORTED);
|
|
continue;
|
|
}
|
|
|
|
// prop status were check in CreateAndCheckIndex by calling CheckProperty
|
|
if (DBPROPSTATUS_OK == dwStatus)
|
|
fProp = fProp && COMPARE(CompareVariant(&pProp->vValue, 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;index<cRest;index++)
|
|
VariantInit(&rgRestrictIndexes[index]);
|
|
|
|
if (m_fIRowsetIndex)
|
|
TESTC(CheckIndex2(pTableID, pIndexID, cIndexColumnDesc, rgIndexColumnDesc,
|
|
cPropertySets, rgPropertySets));
|
|
|
|
if (NULL == m_pIDBSchemaRowset)
|
|
{
|
|
fReturn = TRUE;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// Check to see if the schema is supported
|
|
TESTC_(hr = m_pIDBSchemaRowset->GetSchemas(&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; i<cSchema && !bIsSchemaSupported;)
|
|
{
|
|
if(prgSchemas[i] == DBSCHEMA_INDEXES)
|
|
bIsSchemaSupported = TRUE;
|
|
else
|
|
i++;
|
|
}
|
|
|
|
if(!bIsSchemaSupported || !(prgRestrictions[i] & 0x4) || !(prgRestrictions[i] & 0x10))
|
|
{
|
|
odtLog << "Index Schema Rowset or the required constraints are not supported\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
rgRestrictIndexes[2].vt = VT_BSTR;
|
|
rgRestrictIndexes[2].bstrVal = SysAllocString(pIndexID->uName.pwszName);
|
|
rgRestrictIndexes[4].vt = VT_BSTR;
|
|
rgRestrictIndexes[4].bstrVal = SysAllocString(pTableID->uName.pwszName);
|
|
|
|
SAFE_ALLOC(rgColPresent, BOOL, cIndexColumnDesc);
|
|
for (i=0; i<cIndexColumnDesc; i++)
|
|
rgColPresent[i] = FALSE;
|
|
|
|
TESTC_(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**)&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;iRow<cIndexColumnDesc;iRow++)
|
|
{
|
|
TESTC_(hr=pIndexRowset->GetNextRows(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<cRest;index++)
|
|
GCHECK(VariantClear(&(rgRestrictIndexes[index])),S_OK);
|
|
|
|
return fReturn;
|
|
} //TCIIndexDefinition::CheckIndex
|
|
*/
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// TCIIndexDefinition
|
|
//-------------------------------------------------------------------------
|
|
TCIIndexDefinition::TCIIndexDefinition(WCHAR *wstrTestCaseName) : CSessionObject(wstrTestCaseName)
|
|
{
|
|
// m_pIIndexDefinition = NULL;
|
|
m_rgColumnDesc = NULL;
|
|
m_cColumnDesc = 0;
|
|
m_pIDBSchemaRowset = NULL;
|
|
// m_fIRowsetIndex = FALSE;
|
|
m_pPopulatedTable = NULL;
|
|
m_rgIndexCols = NULL;
|
|
m_cIndexCols = 0;
|
|
} // TCIIndexDefinition::TCIIndexDefinition
|
|
|
|
|
|
//*-----------------------------------------------------------------------
|
|
//
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//-------------------------------------------------------------------------
|
|
BOOL TCIIndexDefinition::Init()
|
|
{
|
|
DBINDEXCOLUMNDESC rgIndexColumnDesc[1];
|
|
DBID *pIndexID = NULL;
|
|
ULONG i;
|
|
IRowsetIndex *pIRowsetIndex = NULL;
|
|
CList <WCHAR*, WCHAR*> ListNativeTemp;
|
|
CList <DBTYPE, DBTYPE> 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; i++)
|
|
{
|
|
if(prgSchemas[i] == DBSCHEMA_INDEXES)
|
|
break;
|
|
}
|
|
if( (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; i<m_cColumnDesc; i++)
|
|
{
|
|
rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[i].dbcid;
|
|
if (SUCCEEDED(m_hr = m_pCIIndexDefinition->CreateIndex(&(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;index<cRest;index++)
|
|
VariantInit(&rgRestrictIndexes[index]);
|
|
|
|
TESTC(NULL != m_pIDBSchemaRowset);
|
|
TESTC((NULL != pIndexID) || ((NULL != pTableID) && fAnyIndex));
|
|
|
|
if (pIndexID && !fAnyIndex)
|
|
{
|
|
rgRestrictIndexes[2].vt = VT_BSTR;
|
|
rgRestrictIndexes[2].bstrVal = SysAllocString(pIndexID->uName.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;index<cRest;index++)
|
|
GCHECK(VariantClear(&(rgRestrictIndexes[index])),S_OK);
|
|
|
|
return hr;
|
|
} //TCIIndexDefinition::DoesIndexExistInIndexSchemaRowset
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
// 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 TCIIndexDefinition::DoesIndexExistRowsetIndex(
|
|
DBID *pTableID, // @parm [IN] Table ID
|
|
DBID *pIndexID, // @parm [IN] Index ID
|
|
BOOL *fExist // @parm [OUT] TRUE if index exists
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
IRowsetIndex *pRowsetIndex=NULL;
|
|
|
|
hr = m_pIOpenRowset->OpenRowset(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; i<nValues; i++)
|
|
{
|
|
odtLog << "Value Number " << i << "\t";
|
|
switch (rgValues[i].vt)
|
|
{
|
|
case VT_BOOL:
|
|
odtLog << (VARIANT_TRUE == rgValues[i].boolVal ? L"VARIANT_TRUE": L"VARIANT_FALSE") << L"\n";
|
|
break;
|
|
case VT_I4:
|
|
odtLog << rgValues[i].lVal << "\n";
|
|
break;
|
|
default:
|
|
odtLog << "certainly a bad value\n";
|
|
}
|
|
rgProp.vValue = rgValues[i];
|
|
rgProp.dwOptions = DBPROPOPTIONS_OPTIONAL;
|
|
odtLog << "\tDBPROPOPTIONS_OPTIONAL:";
|
|
hr = m_pCIIndexDefinition->CreateCheckAndDropIndex( &(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<length; i++)
|
|
wcscat(pwszBuffer, L"a");
|
|
CLEANUP:
|
|
return pwszBuffer;
|
|
} //TCIIndexDefinition::BuildInvalidName
|
|
|
|
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(TCCreateIndex)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: TCCreateIndex - tests IIndexDefinition::CreateIndex() method
|
|
//| Created: 11/6/97
|
|
//*-----------------------------------------------------------------------
|
|
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL TCCreateIndex::Init()
|
|
{
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
if(TCIIndexDefinition::Init())
|
|
// }}
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Check the session object
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCreateIndex::Variation_1()
|
|
{
|
|
return DefaultObjectTesting(*m_pCIIndexDefinition, SESSION_INTERFACE);
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc create an index on a a non-empty table => 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; i<nMaxIndexes; i++)
|
|
{
|
|
rgIndexColumnDesc[0].pColumnID = &m_rgColumnDesc[m_rgIndexCols[i%m_cIndexCols]-1].dbcid;
|
|
rgIndexID[nIndex] = NULL;
|
|
TESTC(NULL != m_pCIIndexDefinition);
|
|
if (CHECK(m_hr = m_pCIIndexDefinition->CreateIndexAndCheck(&m_pTable->GetTableID(), NULL,
|
|
1, rgIndexColumnDesc, 0, NULL, &rgIndexID[nIndex]), S_OK))
|
|
nIndex++;
|
|
else
|
|
fTestResult = TEST_FAIL;
|
|
}
|
|
|
|
TESTC(0<nIndex);
|
|
odtLog << "\t" << nIndex << " indexes out of " << nMaxIndexes << " were created on the table\n";
|
|
|
|
CLEANUP:
|
|
if (rgIndexID)
|
|
for (i=0; i<nIndex; i++)
|
|
{
|
|
// drop index i
|
|
m_pCIIndexDefinition->DropIndex(&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 (k<m_cColumnDesc)
|
|
dbCD->wType = 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<m_cIndexCols; i++)
|
|
rgOrder[i] = DBINDEX_COL_ORDER_ASC;
|
|
|
|
TESTC_(m_hr = CCNDropIndexFromOrdinals(m_pTable, NULL, m_rgColumnDesc, m_cColumnDesc,
|
|
m_cIndexCols, m_rgIndexCols, rgOrder), S_OK);
|
|
|
|
fTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(rgOrder);
|
|
return fTestResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(41)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Try to create a duplicate index => 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; i<n; values[i++].vt = VT_I4);
|
|
V_I4(&values[0]) = DBPROPVAL_IN_DISALLOWNULL;
|
|
V_I4(&values[1]) = DBPROPVAL_IN_IGNORENULL;
|
|
V_I4(&values[2]) = DBPROPVAL_IN_IGNOREANYNULL;
|
|
V_I4(&values[3]) = DBPROPVAL_IN_ALLOWNULL;
|
|
|
|
COMPARE(CreateIndexWithOneProperty(n, values, DBPROP_INDEX_NULLS), TRUE);
|
|
|
|
// if m_nIndex column m_nIndex is not NULLable go to the end
|
|
for (i=0, fExists = FALSE; i < m_cIndexCols && !fExists; i++)
|
|
{
|
|
col = m_pTable->GetColInfoForUpdate(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; i<n; values[i++].vt = VT_I4);
|
|
V_I4(&values[0]) = DBPROPVAL_IT_BTREE;
|
|
V_I4(&values[1]) = DBPROPVAL_IT_HASH;
|
|
V_I4(&values[2]) = DBPROPVAL_IT_CONTENT;
|
|
V_I4(&values[3]) = DBPROPVAL_IT_OTHER;
|
|
if (!CreateIndexWithOneProperty(n, values, DBPROP_INDEX_TYPE))
|
|
fTestResult = TEST_FAIL;
|
|
return fTestResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(61)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set DBPROP_INDEX_UNIQUE
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCreateIndex::Variation_61()
|
|
{
|
|
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;
|
|
|
|
TESTC(CreateIndexWithOneLogicalProperty(DBPROP_INDEX_UNIQUE));
|
|
|
|
pTable = new CTable(m_pThisTestModule->m_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<n; values[i++].vt = VT_I4);
|
|
V_I4(&values[0]) = 1;
|
|
V_I4(&values[1]) = 20;
|
|
V_I4(&values[2]) = 60;
|
|
V_I4(&values[3]) = 100;
|
|
if (!CreateIndexWithOneProperty(n, values, DBPROP_INDEX_FILLFACTOR))
|
|
fTestResult = TEST_FAIL;
|
|
return fTestResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(63)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set DBPROP_INDEX_INITIALSIZE
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCreateIndex::Variation_63()
|
|
{
|
|
BOOL fTestResult = TEST_PASS;
|
|
const int n=4;
|
|
VARIANT values[n];
|
|
ULONG i;
|
|
|
|
for (i=0; i<n; values[i++].vt = VT_I4);
|
|
V_I4(&values[0]) = 0;
|
|
V_I4(&values[1]) = 100;
|
|
V_I4(&values[2]) = 5000;
|
|
V_I4(&values[3]) = 10000;
|
|
if (!CreateIndexWithOneProperty(n, values, DBPROP_INDEX_INITIALSIZE))
|
|
fTestResult = TEST_FAIL;
|
|
return fTestResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(64)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set DBPROP_INDEX_NULLCOLLATION
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCreateIndex::Variation_64()
|
|
{
|
|
BOOL fTestResult = TEST_PASS;
|
|
const int n=4;
|
|
VARIANT values[n];
|
|
ULONG i;
|
|
|
|
for (i=0; i<n; values[i++].vt = VT_I4);
|
|
V_I4(&values[0]) = DBPROPVAL_NC_END;
|
|
V_I4(&values[1]) = DBPROPVAL_NC_START;
|
|
V_I4(&values[2]) = DBPROPVAL_NC_HIGH;
|
|
V_I4(&values[3]) = DBPROPVAL_NC_LOW;
|
|
if (!CreateIndexWithOneProperty(n, values, DBPROP_INDEX_NULLCOLLATION))
|
|
fTestResult = TEST_FAIL;
|
|
return fTestResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(65)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set DBPROP_INDEX_SORTBOOKMARKS and DBPROP_INDEX_UNIQUE
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCreateIndex::Variation_65()
|
|
{
|
|
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], 2, rgProp,DBPROPSET_INDEX)
|
|
FILL_PROP(rgProp[0], DBPROP_INDEX_SORTBOOKMARKS, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED)
|
|
FILL_PROP(rgProp[1], DBPROP_INDEX_UNIQUE, 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))
|
|
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(66)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Set DBPROP_INDEX_UNIQUE and DBPROP_INDEX_PRIMARYKEY
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCreateIndex::Variation_66()
|
|
{
|
|
BOOL fTestResult = TEST_FAIL;
|
|
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 <WCHAR*, WCHAR*> ListNativeTemp;
|
|
CList <DBTYPE, DBTYPE> 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<nProp; iProp++)
|
|
{
|
|
if (DBPROPSTATUS_OK == rgProp[iProp].dwStatus )
|
|
k++;
|
|
}
|
|
if (nProp==k || 0 == k)
|
|
{
|
|
odtLog << "Property " << rgProp[0].dwPropertyID << " set incorrectly\n";
|
|
fTestResult = TEST_FAIL;
|
|
}
|
|
}
|
|
|
|
return fTestResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(75)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc column name is invalid => 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; nIndex<nThreads; nIndex++)
|
|
CloseHandle(hThread[nIndex]);
|
|
|
|
CLEANUP:
|
|
for (nIndex=0; nIndex<nThreads; nIndex++)
|
|
{
|
|
IndexID.eKind = DBKIND_NAME;
|
|
IndexID.uName.pwszName = m_rgIndexName[nIndex];
|
|
|
|
if ( S_OK == m_rgResult[nIndex]
|
|
&& CHECK(m_hr = m_pCIIndexDefinition->DoesIndexExist( &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; nIndex<nThreads; nIndex++)
|
|
{
|
|
CloseHandle(hThread[nIndex]);
|
|
if (S_OK == m_rgResult[nIndex])
|
|
nSuccess++;
|
|
}
|
|
|
|
IndexID.eKind = DBKIND_NAME;
|
|
IndexID.uName.pwszName = pwszIndexName;
|
|
m_hr = m_pCIIndexDefinition->DropIndex(&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 <WCHAR*, WCHAR*> ListNativeTemp;
|
|
CList <DBTYPE, DBTYPE> 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; i<m_cIndexCols; i++)
|
|
{
|
|
rgIndexID[nIndex] = NULL;
|
|
if (S_OK == CNCIndexFromOrdinals(m_pPopulatedTable, NULL, &rgIndexID[nIndex],
|
|
m_rgColumnDesc, m_cColumnDesc, 1, &m_rgIndexCols[i], rgOrder))
|
|
nIndex++;
|
|
}
|
|
|
|
odtLog << "\t" << nIndex << " indexes were created on the table\n";
|
|
|
|
// drop indexes and tables
|
|
TESTC_(m_hr = m_pCIIndexDefinition->DropIndex(&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<nIndex; i++)
|
|
ReleaseDBID(rgIndexID[i]);
|
|
SAFE_FREE(rgIndexID);
|
|
TRETURN
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(9)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc *pIndexID == DB_NULLID => 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; nIndex<nThreads; nIndex++)
|
|
{
|
|
CloseHandle(hThread[nIndex]);
|
|
IndexID.eKind = DBKIND_NAME;
|
|
IndexID.uName.pwszName = m_rgIndexName[nIndex];
|
|
fExists = FALSE;
|
|
if (S_OK != m_rgResult[nIndex]
|
|
|| !CHECK(m_hr = m_pCIIndexDefinition->DoesIndexExist(&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; nIndex<nThreads; nIndex++)
|
|
{
|
|
CloseHandle(hThread[nIndex]);
|
|
fExists = FALSE;
|
|
if (S_OK == m_rgResult[nIndex])
|
|
nSuccess++;
|
|
}
|
|
|
|
IndexID.eKind = DBKIND_NAME;
|
|
IndexID.uName.pwszName = m_rgIndexName[0];
|
|
if ( !GCOMPARE(nSuccess, 1)
|
|
|| !CHECK(m_hr = m_pCIIndexDefinition->DoesIndexExist(&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; i<n; i++)
|
|
{
|
|
if (S_OK == (hr = pITransactionLocal->StartTransaction(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
|