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

32839 lines
1009 KiB
C++

//--------------------------------------------------------------------
// Microsoft OLE DB Test
//
// Copyright 1995-2000 Microsoft Corporation.
//
// @doc
//
// @module ITblDef.CPP | Source for ITableDefinition test module
//
#define DBINITCONSTANTS // Must be defined to initialize constants in OLEDB.H
#define INITGUID
#include "modstandard.hpp"
#include "itbldef.h"
#include "Extralib.h"
#include <initguid.h>
#include <process.h>
#include "clib.hpp"
#include "DataSource.hpp"
const ULONG cMaxName = 300;
// maximum columns allowed per constraint
const DBORDINAL cMaxColsPerCons = 16;
// Maximum combined column length of constraint
const DBORDINAL cMaxColLengthPerCons = 900;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Module Values
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// {{ TCW_MODULE_GLOBALS
DECLARE_MODULE_CLSID = { 0xae3d5c1e, 0x2a0b, 0x11d1, { 0xaf, 0x9d, 0x00, 0xc0, 0x4f, 0xc2, 0x27, 0x93 }};
DECLARE_MODULE_NAME("ITableDefinition");
DECLARE_MODULE_OWNER("Microsoft");
DECLARE_MODULE_DESCRIP("The module tests the ITableDefinition interface");
DECLARE_MODULE_VERSION(795921705);
// TCW_WizardVersion(2)
// TCW_Automation(True)
// }} TCW_MODULE_GLOBALS_END
GUID guidModule = { 0xae3d5c1e, 0x2a0b, 0x11d1, { 0xaf, 0x9d, 0x00, 0xc0, 0x4f, 0xc2, 0x27, 0x93 }};
//Globals
BOOL g_fSQLOLEDB25 = FALSE;
// macros
#define FILL_PROP_SET(RGPROPSET_EL, NPROP, RGPROP, PROP_GUID) \
RGPROPSET_EL.cProperties = NPROP; \
RGPROPSET_EL.rgProperties = RGPROP; \
RGPROPSET_EL.guidPropertySet = PROP_GUID; \
if (NULL != RGPROP) \
memset(RGPROP, 0, NPROP*sizeof(DBPROP));
#define FILL_PROP(RGPROP_EL, PROPID, VAR_TYPE, VAR_MACRO, VAR_VALUE, OPTION) \
memset(&RGPROP_EL, 0, sizeof(DBPROP)); \
RGPROP_EL.dwPropertyID = PROPID; \
RGPROP_EL.vValue.vt = VAR_TYPE; \
VAR_MACRO(&RGPROP_EL.vValue) = VAR_VALUE; \
RGPROP_EL.dwOptions = OPTION;
#define INVALID_DBKIND 1001
class TCITableDefinition;
class CTransactionLocal;
class CAddUniqueConsTxnAdapter;
// define argument stru for threading function parameters
typedef struct inparam{
ULONG i;
TCITableDefinition *pObject;
} CInParam;
// the number of threads that will be created in the multithreading test variations
const int nThreads = 7; // must be less than 100 and greater than 1
// the dispatcher thread function
unsigned WINAPI ThreadProc(LPVOID lpvThreadParam);
void ReleaseAllColumnPropSets(
DBCOLUMNDESC *rgColumnDesc, // [in] aray to be release
DBORDINAL cColumnDesc // [in] no of elementrs in the array
);
ULONG nResidualTables;
//--------------------------------------------------------------------
// @func Module level initialization routine
//
// @rdesc Success or Failure
// @flag TRUE | Successful initialization
// @flag FALSE | Initialization problems
//
BOOL ModuleInit(CThisTestModule * pThisTestModule)
{
TBEGIN;
ITableDefinition *pITableDefinition = NULL;
HRESULT hr;
nResidualTables = 0;
//Create the session
if(!ModuleCreateDBSession(pThisTestModule))
return FALSE;
g_pIOpenRowset = (IOpenRowset*)pThisTestModule->m_pIUnknown2;
CConsDesc::s_pSessionIUnknown = g_pIOpenRowset;
CConsDesc::s_pDSOIUnknown = pThisTestModule->m_pIUnknown;
CConsDesc::s_pConstraints = new CConstraints(g_pIOpenRowset);
CConsDesc::s_fInsideTransaction = FALSE;
if (!(hr=VerifyInterface(pThisTestModule->m_pIUnknown2, IID_ITableDefinition,
SESSION_INTERFACE, (IUnknown**)&pITableDefinition)))
{
odtLog << "ITableDefinition not supported!\n";
TESTB = TEST_SKIPPED;;
goto CLEANUP;
}
if (!(hr=VerifyInterface(pThisTestModule->m_pIUnknown, IID_IDBInitialize,
DATASOURCE_INTERFACE, (IUnknown**)&g_pIDBInitialize)))
{
odtLog << "IDBInitialize not supported!\n";
TESTB = TEST_SKIPPED;
goto CLEANUP;
}
if (IsSQLProvider())
{
if (GetModInfo()->GetProviderVer() && wcsncmp(GetModInfo()->GetProviderVer(), L"07", 2)==0)
g_fSQLOLEDB25 = TRUE;
}
CLEANUP:
SAFE_RELEASE(pITableDefinition);
TRETURN;
}
//--------------------------------------------------------------------
// @func Module level termination routine
//
// @rdesc Success or Failure
// @flag TRUE | Successful initialization
// @flag FALSE | Initialization problems
//
BOOL ModuleTerminate(CThisTestModule * pThisTestModule)
{
SAFE_DELETE( CConsDesc::s_pConstraints);
CConsDesc::s_pSessionIUnknown = NULL;
CConsDesc::s_pDSOIUnknown = NULL;
if (0 < nResidualTables)
odtLog << "Total number of residual tables: " << nResidualTables << "\n";
SAFE_RELEASE(g_pIDBInitialize);
CCheckConsRowset::s_fMetadataInitialized = FALSE;
CCheckConsRowset::s_fSchemaSupported = FALSE;
CCheckConsRowset::s_fConsCatalogR = FALSE;
CCheckConsRowset::s_fConsSchemaR = FALSE;
CCheckConsRowset::s_fConsNameR = FALSE;
CPKRowset::s_fMetadataInitialized = FALSE;
CPKRowset::s_fSchemaSupported = FALSE;
CPKRowset::s_fTableCatalogR = FALSE;
CPKRowset::s_fTableSchemaR = FALSE;
CPKRowset::s_fTableNameR = FALSE;
CFKRowset::s_fMetadataInitialized = FALSE;
CFKRowset::s_fSchemaSupported = FALSE;
CFKRowset::s_fTableCatalogR = FALSE;
CFKRowset::s_fTableSchemaR = FALSE;
CFKRowset::s_fTableNameR = FALSE;
CKeyColumnUsageRowset::s_fMetadataInitialized = FALSE;
CKeyColumnUsageRowset::s_fSchemaSupported = FALSE;
CKeyColumnUsageRowset::s_fTableCatalogR = FALSE;
CKeyColumnUsageRowset::s_fTableSchemaR = FALSE;
CKeyColumnUsageRowset::s_fTableNameR = FALSE;
CKeyColumnUsageRowset::s_fConsCatalogR = FALSE;
CKeyColumnUsageRowset::s_fConsSchemaR = FALSE;
CKeyColumnUsageRowset::s_fConsNameR = FALSE;
return ModuleReleaseDBSession(pThisTestModule);
}
//--------------------------------------------------------------------------
// Given DBCOLUMNDESC, returns the Type name.
//--------------------------------------------------------------------------
WCHAR* GetColumnTypeName(DBCOLUMNDESC *pColumnDesc)
{
return pColumnDesc->pwszTypeName;
}
//--------------------------------------------------------------------------
//
// release the property of all columns
//--------------------------------------------------------------------------
void ReleaseAllColumnPropSets(
DBCOLUMNDESC *rgColumnDesc, // [in] aray to be release
DBORDINAL cColumnDesc // [in] no of elementrs in the array
)
{
ULONG i;
if ( (NULL == rgColumnDesc) ||
(0 == cColumnDesc))
return;
for (i=0; i<cColumnDesc; i++)
{
FreeProperties(&rgColumnDesc[i].cPropertySets, &rgColumnDesc[i].rgPropertySets);
ASSERT(0 == rgColumnDesc[i].cPropertySets);
ASSERT(NULL == rgColumnDesc[i].rgPropertySets);
}
} //ReleaseAllColumnPropSets
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Test Case Section
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//--------------------------------------------------------------------
// @class Base Class
//
class TCITableDefinition : public CSessionObject {
protected:
// add critical section
CRITICAL_SECTION m_CriticalSection;
// used to check for residual tables
ULONG m_nTables;
// @cmember pointer to ITableDefinition interface
ITableDefinition *m_pITableDefinition;
ITableDefinitionWithConstraints *m_pITDWC;
BOOL m_fIsIDBInfo;
// @cmember list of CCol storing info about provider data types
CList <CCol, CCol&> m_ColList;
// @cmember data about table and column name
ULONG m_cMaxTableName, m_cMaxColName;
LPOLESTR m_pwszInvalidTableChars;
LPOLESTR m_pwszInvalidColChars;
// @cmember array of column descriptors on the table (limited operations on it)
DBCOLUMNDESC *m_rgColumnDesc;
DBORDINAL m_cColumnDesc;
// @cmembe aray of result for multithreading processing
HRESULT m_rgResult[nThreads];
// @cmember array of table name for multithreading
LPWSTR m_rgName[nThreads];
DBMATCHTYPE m_SupportedMatchType;
// @cmember Check the result and property status
BOOL CheckPropertyStatus(
GUID guidPropertySet, // [in] property set guid
GUID guidExpectedPS, // [in] expected prop set guid
DBPROP *pProp, // [in] property
HRESULT hr // [in] the result
);
// @cmember Check the prop status of a list of col desc
BOOL CheckColPropStatus(
DBORDINAL cColDesc, // [in]
DBCOLUMNDESC *rgColDesc, // [in] the size of the propset array
HRESULT hr // [in] the result of the previous op
);
// @cmember Drops the column and checks the result
HRESULT DropColumnAndCheck(
DBID *pTableID, // [in] the table ID
DBID *pColumnID, // [in] the ID of the column to be dropped
ITableDefinition *pITableDefinition = NULL, // [in] pointer to ITableDefinition interface
DBID *pBaseTableID = NULL // [in] if pTableID is exotic (e.g. fuly qualified) use this
);
// @cmember Drops the table and checks the result
HRESULT DropTableAndCheck(
DBID *pTableID, // [in] ID of the table to be dropped
ITableDefinition *pITableDefinition = NULL // [in] pointer to ITableDefinition interface
);
// @cmember Gets literal info about tables and columns
HRESULT GetLiteralInfo();
// @cmember Gets the catalog and schema name for a given table
BOOL GetCatalogSchemaNames(
LPWSTR pwszTableName, // [in] the name of the table
LPWSTR *ppwszCatalogName, // [out] catalog name
LPWSTR *ppwszSchemaName, // [out] schema name
CTable *pTable = NULL // [in] table object (DEFAULT NULL - use m_pTable)
);
// @cmember Check whether the array of ColumnDesc sent was preserved
// all the data should be inside, the only thing that is allowed to be modified <nl>
// is the property status
BOOL IsColumnDescPreserved
(
DBCOLUMNDESC *rgInColumnDesc, // the array passed to ITableDefinition
DBCOLUMNDESC *rgOutColumnDesc, // the aray returned by ITableDefinition
DBORDINAL cColumnDesc // the size of the arrays
);
// @cmember Build a valid table name of a certain length
WCHAR* BuildValidName(size_t, WCHAR*);
// @cmember Build an invalid table name of a certain length
WCHAR* BuildInvalidName(size_t, WCHAR*, WCHAR*);
// @cmember Uses m_pTable to get a column description mentioning all the provider types
void GetProviderTypes(void);
// @cmember Passes a type name and retrieves the column from m_ColList with info about that type
CCol GetType(WCHAR *pwszTypeName, DBTYPE wType, BOOL *fExists=NULL);
// @cmember Sets all the columns to maximum size as got from m_ColList (from PROVIDER_TYPES Rowset)
BOOL SetMaximumColSize(DBCOLUMNDESC*, DBORDINAL);
// @cmember Sets all the column sizes to 0
BOOL SetZeroColSize(DBCOLUMNDESC*, DBORDINAL);
// @cmember Set a default property in the property sets of a DBCOLUMNDESC
BOOL SetDefaultProperty(
DBPROPSET **prgPropertySets, // [in/out] array of property sets
ULONG *pcPropertySets, // [in/out] number of property sets
VARIANT *pvalue, // [in] property value
DBPROPOPTIONS dwOption = DBPROPOPTIONS_OPTIONAL, // [in] prop options
DBID colid = DB_NULLID, // [in] col id
GUID guidPropertySet = DBPROPSET_COLUMN, // [in] the GUID of the propset
ULONG *pcPropSet = NULL, // [out] index of property set
ULONG *pcProp =NULL // [out] index in the rgProperties array
);
// @cmember Compare the list of old columns against the list of new columns and the new column
BOOL CheckColInfo(DBCOLUMNDESC*, DBORDINAL, DBCOLUMNDESC*, DBORDINAL, DBCOLUMNDESC*);
// @cmember Compare the list of old columns against the list of new columns
BOOL AreColEqual(DBCOLUMNDESC*, DBORDINAL, DBCOLUMNDESC*, DBORDINAL);
// @cmember CheckReturnedDBID about the columns in the table
// pIndexID - [IN] the DBID asked for
// ppIndexID - [IN] the DBID created
BOOL CheckReturnedDBID(
DBID *pIndexID, // passed to CreateIndex
DBID **ppIndexID // returned by CreateIndex
);
// @member Add a column using ITableDefinition::AddColumn and check its addition
HRESULT AddColumnAndCheck(
DBID *pTableID, // [IN] table ID
DBCOLUMNDESC *pColumnDesc, // [IN] descriptor of the column to be added
DBID **ppColumnID, // [OUT] column ID for the resulted column
ITableDefinition *pITableDefinition = NULL, // [IN] pointer to ITableDefinition
DBID *pBaseTableID = NULL
);
// @member Check properties on rowseet and table
BOOL CheckRwstTblPropStatus(
ULONG cPropSet, // [in] the size of the propset array
DBPROPSET *rgPropSet, // [in] propset array
HRESULT hr // [in] the result of the previous op
);
// @member Create the table using ITableDefinition::CreateTable and check its creation
// then drops the table
HRESULT CCNDropTable(
DBID *pTableID, // [in] pointer to the input table ID
DBORDINAL cColumnDescs, // [in] the number of columns to be created
DBCOLUMNDESC *rgColumnDesc, // [in/out] array of columns to be created
REFIID riid, // [in] rowset interface to be returned
ULONG cPropertySets, // [in] number of roset property sets asked
DBPROPSET *rgPropertySets, // [in/out] array of rowset property sets
BOOL fNullPPTableID = FALSE // [in] if TRUE ppTableID will be NULL
);
// @cmember Check whether the columns were properly created
// The columns of the m_pTable are checked against the column descriptor array <nl>
// returned by ITableDefinition::CreateTable method.
BOOL AreColumnsCreatedOK(
DBCOLUMNDESC *rgOutColumnDesc, // [in] the aray returned by ITableDefinition::CreateTable
DBORDINAL cColumnDesc, // [in] the size of the arrays
DBID *pTableID = NULL, // [in] Table ID of the table that is checked
IUnknown *pIUnknown = NULL // [in] pointer to a rowset interface on the table
);
// @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 IsRowsetPropSetPreserved
(
DBPROPSET *rgInPropertySets, // the array passed to ITableDefinition::CreateTable
DBPROPSET *rgOutPropertysets, // the aray returned by ITableDefinition::CreateTable
ULONG cPropertySets // the size of the arrays
);
// @cmember Check whether the rowset properties were properly created
// The rowset properties of the m_pTable are checked against the property set<nl>
// returned by ITableDefinition::CreateTable method.
BOOL IsRowsetPropSetCreatedOK
(
DBPROPSET *rgOutPropertySets, // the aray returned by ITableDefinition::CreateTable
ULONG cPropertySets, // the size of the arrays
IUnknown *pIUnknown // pointer to rowset interface
);
// @cmember Creates a table with a column of each provider type and returns a rowset
// to the new created table. The rowset is created with the properties required and it
// is tested
BOOL CreateWithRowsetProps
(
ULONG nProperties, // number of the properties to be set
DBPROPID *rgPropID, // array with the propIDs
DBTYPE *rgDBType, // type of property values
LPVOID *rgValue, // values to be set
DBPROPOPTIONS *rgOptions, // options of properties
struct _GUID *pRIID // interface asked on rowset
);
// @cmember Creates a table with a column of each provider type and returns a rowset
// to the new created table. The rowset is created with the property required and it
// is tested
int CreateWithOneRowsetProps
(
DBPROPID PropID, // Property ID
DBTYPE DBType, // type of property value
LPVOID Value, // value to be set
struct _GUID *pRIID // interface asked on rowset
);
public:
HRESULT AddUniqueConstraint(
CTable *pTable,
DBORDINAL ulCol,
DBDEFERRABILITY Deferrability = 0
);
HRESULT AddUniqueConstraint(
CTable *pTable,
DBORDINAL cCol,
DBORDINAL *rgCol,
DBDEFERRABILITY Deferrability = 0
);
HRESULT AddPrimaryKeyConstraint(
CTable *pTable,
DBORDINAL ulCol,
DBDEFERRABILITY Deferrability = 0
);
HRESULT AddPrimaryKeyConstraint(
CTable *pTable,
DBORDINAL cCol,
DBORDINAL *rgCol,
DBDEFERRABILITY Deferrability = 0
);
HRESULT AddKeyConstraint(
DBCONSTRAINTTYPE ConstraintType,
CTable *pTable,
DBORDINAL cCol,
DBORDINAL *rgCol,
DBDEFERRABILITY Deferrability = 0
);
HRESULT AddForeignKeyConstraint(
CTable *pBaseTable,
DBORDINAL cBaseCol,
DBORDINAL *rgBaseCol,
CTable *pReferencedTable,
DBORDINAL cReferencedCol,
DBORDINAL *rgReferencedCol,
DBMATCHTYPE MatchType,
DBUPDELRULE UpdateRule = DBUPDELRULE_NOACTION,
DBUPDELRULE DeleteRule = DBUPDELRULE_NOACTION,
DBDEFERRABILITY Deferrability = 0
);
ITableDefinition *pITableDefinition() {return m_pITableDefinition;}
ITableDefinitionWithConstraints *pITDWC() {return m_pITDWC;}
DBMATCHTYPE SupportedMatchType() {
return m_SupportedMatchType;
}
// @member Add a constraint to a table using ITableDefinitionWithConstraints::AddConstraint and check its creation
HRESULT AddConstraintAndCheck(
ITableDefinitionWithConstraints *pITableDefinitionWithConstraints, // [in] pointer to the ITableDefinitionWithConstraints interface to be used
DBID *pTableID, // [in] pointer to the input table ID
DBCONSTRAINTDESC *pConstraintDescs, // [in] new constraint
BOOL fDifferentColTypesInFK = FALSE
);
// @member Drop a constraint to a table using ITableDefinitionWithConstraints::DropConstraint and check its deletion
HRESULT DropConstraintAndCheck(
ITableDefinitionWithConstraints *pITableDefinitionWithConstraints, // [in] pointer to the ITableDefinitionWithConstraints interface to be used
DBID *pTableID, // [in] pointer to the input table ID
DBID *pConstraintID // [in] pointer to the DBID of the constraint
);
// @cmember Start a local transaction using the interface pointer passed
HRESULT StartTransaction(ITransactionLocal *pITransactionLocal);
// @cmember Fills in a variant with whatever it needs
BOOL FillVariant(VARIANT *pVariant);
// @cmember Builds a default value for a given column type
BOOL GetDefaultValue(
DBCOLUMNDESC *pColumnDesc, // [in] column for which the default is build
VARIANT *pVariant, // [out] variant that contains the default value
CTable *pTable=NULL // [in] CTable to use
);
// @cmember CompareColumnDesc
// check the new column (first parameter against the result of
BOOL CompareColumnDesc(DBCOLUMNDESC*, DBCOLUMNDESC*);
// @cmember Compare 2 columns got by GetColumnDescOnTable
BOOL AreColEqual(DBCOLUMNDESC*, DBCOLUMNDESC *);
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
virtual unsigned MyThreadProc(ULONG i) {return i;}
//constructor
TCITableDefinition(WCHAR *wstrTestCaseName);
// checks the interfaces on the object, as well as count reference and parent of the rowset
BOOL CheckRowset(IUnknown* pIRowset);
// @cmember GetInfo about the columns in the table
BOOL GetColumnInfo(DBID*, DBORDINAL*, DBCOLUMNINFO**, OLECHAR**);
// @cmember Get an array od Column Descriptors on a Table
BOOL GetColumnDescOnTable(DBID*, DBCOLUMNDESC**, DBORDINAL*);
//destructor
virtual ~TCITableDefinition(){;}
// @cmember Get the number of tables in a data sources, based on IDBSchemaRowset
ULONG GetNoOfTables();
//---------------------------------------------------------------------------
// Insert |
// Inserts 1 row in table using IRowsetChange.
//
// @mfunc Insert
// @rdesc HRESULT indicating success or failure
// @flag S_OK | Function ran without problem
// @flag E_FAIL | No Columns Marked for use or SetNewData failed
//
//---------------------------------------------------------------------------
HRESULT Insert(
DBCOUNTITEM ulRowNumber, // @parm [IN] Row number to insert (0 for next)
IUnknown *pIUnknown, // @parm [IN] Pointer to rowset interface
ULONG cNulls = 0, // @parm [IN] Number of columns to be set to NULL
DBORDINAL *rgNulls = NULL, // @parm [IN] Array of columns to be set to NULL
CTable *pTable = NULL // @parm [IN] Table (DEFAULT NULL - use m_pTable)
);
// creates a table with not nullable column
HRESULT CreateTableWithNoNullableColumns(
CTable *pTable, // @param [IN] pointer to CTable
DBCOUNTITEM ulRowCount, // @parm [IN] # of Rows to insert into table, 1 based
DBORDINAL ulIndex = 0, // @parm [IN] Column Number of index, 1 based (Default=1)
WCHAR *pwszTableName = NULL, // @parm [IN] TableName, if NULL call MakeTableName() (Default=NULL)
EVALUE eValue = PRIMARY, // @parm [IN] Insert PRIMARY or SECONDARY data (Default=PRIMARY)
BOOL fFirstUpdateable = FALSE // @parm [IN] TRUE means first column will be autoinc (Default=FALSE)
);
// @member Create the table using ITableDefinition::CreateTable and check its creation
virtual HRESULT CreateAndCheckTable(
ITableDefinition *pITableDefinition, // [in] pointer to the ITableDefinition interface to be used
IUnknown *pUnkOuter, // [in] pointer to controlling unknown
DBID *pTableID, // [in] pointer to the input table ID
DBORDINAL cColumnDescs, // [in] the number of columns to be created
DBCOLUMNDESC *rgColumnDescs, // [in/out] array of columns to be created
REFIID riid, // [in] rowset interface to be returned
ULONG cPropertySets, // [in] number of roset property sets asked
DBPROPSET *rgPropertySets, // [in/out] array of rowset property sets
DBID **ppTableID, // [out] returned table ID
IUnknown **ppRowset // [out] pointer to outer interface
);
// @member Create the table using ITableDefinitionWithConstraints::CreateTableWithConstraints and check its creation
HRESULT CreateAndCheckTableWithConstraints(
ITableDefinitionWithConstraints *pITableDefinitionWithConstraints, // [in] pointer to the ITableDefinitionWithConstraints interface to be used
IUnknown *pUnkOuter, // [in] pointer to controlling unknown
DBID *pTableID, // [in] pointer to the input table ID
DBORDINAL cColumnDescs, // [in] the number of columns to be created
DBCOLUMNDESC *rgColumnDescs, // [in/out] array of columns to be created
ULONG cConstraintDescs, // [in] the number of constraints to be created
DBCONSTRAINTDESC *rgConstraintDescs, // [in/out] array of constraints
REFIID riid, // [in] rowset interface to be returned
ULONG cPropertySets, // [in] number of roset property sets asked
DBPROPSET *rgPropertySets, // [in/out] array of rowset property sets
DBID **ppTableID, // [out] returned table ID
IUnknown **ppRowset // [out] pointer to outer interface
);
// @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 = DBPROPOPTIONS_OPTIONAL, // [in] prop options
DBID colid = DB_NULLID, // [in] col id
GUID guidPropertySet = DBPROPSET_COLUMN, // [in] the GUID of the propset
ULONG *pcPropSet = NULL, // [out] index of property set
ULONG *pcProp =NULL // [out] index in the rgProperties array
);
};
class CLimitTable {
IDBSchemaRowset *m_pIDBSchemaRowset;
ITableDefinitionWithConstraints *m_pITDWC;
DBCOUNTITEM m_IndexColSize,
m_IndexNullable,
m_IndexLong,
m_IndexFixedLength,
m_IndexDataType,
m_IndexTypeName;
// Selected column specs
DBLENGTH m_cSelectedColSize;
DBTYPE m_dbtSelectedCol;
WCHAR *m_pwszSelectedCol;
HRESULT Init();
HRESULT GetBestType();
HRESULT FindIndexes(IRowset *pIRowset);
HRESULT CreateTable(DBCOUNTITEM cTotalCol, DBID **ppTableID);
HRESULT CreatePrimaryKey(DBID *pTableID, DBCOUNTITEM cTotalCols);
HRESULT CreateUniqueKey(DBID *pTableID, DBCOUNTITEM cTotalCols);
HRESULT CreateForeignKey(DBID *pBaseID, DBID *pRefID, DBCOUNTITEM cTotalCols);
public:
CLimitTable();
~CLimitTable();
HRESULT CheckPrimaryKeyLimit();
HRESULT CheckUniqueKeyLimit();
HRESULT CheckForeignKeyLimit();
HRESULT DropTable(DBID *pTableID);
};
CLimitTable::CLimitTable() {
m_pIDBSchemaRowset = NULL;
m_pITDWC = NULL;
m_IndexColSize = -1;
m_IndexNullable = -1;
m_IndexLong = -1;
m_IndexFixedLength = -1;
m_IndexDataType = -1;
m_IndexTypeName = -1;
m_cSelectedColSize = ULONG_MAX;
m_dbtSelectedCol = -1;
m_pwszSelectedCol = NULL;
}
CLimitTable::~CLimitTable() {
PROVIDER_FREE(m_pwszSelectedCol);
SAFE_RELEASE(m_pITDWC);
SAFE_RELEASE(m_pIDBSchemaRowset);
}
HRESULT CLimitTable::Init() {
TBEGIN
ULONG ulTotalSchemas = 0,
i;
GUID *rgSchemas = NULL;
ULONG *rgRestrictions = NULL;
bool fResult = false;
// init varaibles
m_IndexColSize = -1;
m_IndexNullable = -1;
m_IndexLong = -1;
m_IndexFixedLength = -1;
m_IndexDataType = -1;
m_IndexTypeName = -1;
m_cSelectedColSize = ULONG_MAX;
m_dbtSelectedCol = -1;
PROVIDER_FREE(m_pwszSelectedCol);
SAFE_RELEASE(m_pITDWC);
SAFE_RELEASE(m_pIDBSchemaRowset);
// Verify that IDBSchemaRowset is supported
TESTC_PROVIDER(VerifyInterface(GetModInfo()->GetThisTestModule()->m_pIUnknown2, IID_IDBSchemaRowset,
SESSION_INTERFACE, (IUnknown**) &m_pIDBSchemaRowset));
// Verify that ITableDefinitionWithConstraints is supported
TESTC_PROVIDER(VerifyInterface(GetModInfo()->GetThisTestModule()->m_pIUnknown2, IID_ITableDefinitionWithConstraints,
SESSION_INTERFACE, (IUnknown**) &m_pITDWC));
// Now check if DBSCHEMA_PROVIDER_TYPES is supported
TESTC_(m_pIDBSchemaRowset->GetSchemas(&ulTotalSchemas, &rgSchemas, &rgRestrictions), S_OK);
fResult = false;
for(i = 0; i < ulTotalSchemas; i++)
if (rgSchemas[i] == DBSCHEMA_PROVIDER_TYPES)
fResult = true;
TESTC(fResult);
CLEANUP:
PROVIDER_FREE(rgSchemas);
PROVIDER_FREE(rgRestrictions);
TRETURN
}
HRESULT CLimitTable::FindIndexes(IRowset *pIRowset) {
TBEGIN
IColumnsInfo *pIColInfo = NULL;
DBORDINAL cTotalCols = 0;
DBCOLUMNINFO *rgColInfo = NULL;
OLECHAR *pwszBuffer = NULL;
ULONG i;
TESTC(pIRowset!=NULL);
TESTC_(pIRowset->QueryInterface(IID_IColumnsInfo, (void**) &pIColInfo), S_OK);
TESTC_(pIColInfo->GetColumnInfo(&cTotalCols, &rgColInfo, &pwszBuffer), S_OK);
for(i=0;i<cTotalCols;i++) {
if (!wcscmp(rgColInfo[i].pwszName, L"COLUMN_SIZE"))
m_IndexColSize = i;
else if (!wcscmp(rgColInfo[i].pwszName, L"IS_NULLABLE"))
m_IndexNullable = i;
else if (!wcscmp(rgColInfo[i].pwszName, L"IS_LONG"))
m_IndexLong = i;
else if (!wcscmp(rgColInfo[i].pwszName, L"IS_FIXEDLENGTH"))
m_IndexFixedLength = i;
else if (!wcscmp(rgColInfo[i].pwszName, L"DATA_TYPE"))
m_IndexDataType = i;
else if (!wcscmp(rgColInfo[i].pwszName, L"TYPE_NAME"))
m_IndexTypeName = i;
}
TESTC(m_IndexColSize!=-1 && m_IndexNullable!=-1 && m_IndexLong!=-1 && m_IndexFixedLength!=-1 &&
m_IndexDataType!=-1 && m_IndexTypeName!=-1);
CLEANUP:
PROVIDER_FREE(pwszBuffer);
PROVIDER_FREE(rgColInfo);
SAFE_RELEASE(pIColInfo);
TRETURN
}
HRESULT CLimitTable::GetBestType() {
TBEGIN
IRowset *pIRowset = NULL;
IAccessor *pIAccessor = NULL;
HACCESSOR hAccessor = NULL;
DBBINDING *rgBindings = NULL;
DBCOUNTITEM cBindings = 0,
cRowSize = 0;
HROW *phRows = NULL;
DBCOUNTITEM cRowsObtained = 0;
char *pszRowData = NULL;
bool fResult = false,
IsSQLServer7 = false;
WCHAR *pwszVer = NULL;
CLSID clsidSQL;
TESTC(m_pIDBSchemaRowset && m_pITDWC);
// Hack for SQL Server 7.0 which doesnt allow keys on BIT data type but provides
// no way to determine this behavior.
TESTC_(CLSIDFromProgID(L"SQLOLEDB", &clsidSQL), S_OK);
if (PROVIDER_CLSID == clsidSQL) {
if (::SupportedProperty(DBPROP_DBMSVER, DBPROPSET_DATASOURCEINFO,
GetModInfo()->GetThisTestModule()->m_pIUnknown)) {
TESTC(::GetProperty(DBPROP_DBMSVER, DBPROPSET_DATASOURCEINFO,
GetModInfo()->GetThisTestModule()->m_pIUnknown,
&pwszVer));
if (wcscmp(pwszVer, L"08.00.0000")<0)
IsSQLServer7 = true;
}
}
// Get provider types rowset
TESTC_(m_pIDBSchemaRowset->GetRowset(NULL, DBSCHEMA_PROVIDER_TYPES, 0, NULL,
IID_IRowset, 0, NULL, (IUnknown**) &pIRowset), S_OK);
// find indexes to different columns
TESTC(FindIndexes(pIRowset));
// get accessor
TESTC(VerifyInterface(pIRowset, IID_IAccessor, ROWSET_INTERFACE, (IUnknown**)&pIAccessor));
// Create accessor
TESTC_(GetAccessorAndBindings(pIRowset, DBACCESSOR_ROWDATA, &hAccessor,
&rgBindings, &cBindings, &cRowSize, DBPART_VALUE | DBPART_STATUS | DBPART_LENGTH,
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL, NULL,
NULL, DBTYPE_EMPTY, 0, NULL), S_OK);
// Now get data and find best matching row
pszRowData = (char*) PROVIDER_ALLOC(cRowSize);
fResult = false;
while(pIRowset->GetNextRows(DB_NULL_HCHAPTER, 0, 1, &cRowsObtained, &phRows)==S_OK) {
pIRowset->GetData(phRows[0], hAccessor, pszRowData);
if (*(VARIANT_BOOL*)&pszRowData[rgBindings[m_IndexNullable].obValue] == VARIANT_TRUE &&
*(VARIANT_BOOL*)&pszRowData[rgBindings[m_IndexLong].obValue] == VARIANT_FALSE &&
*(VARIANT_BOOL*)&pszRowData[rgBindings[m_IndexFixedLength].obValue] == VARIANT_TRUE &&
!(IsSQLServer7 && !wcscmp((WCHAR*)&pszRowData[rgBindings[m_IndexTypeName].obValue], L"bit"))
) {
if (*(DWORD*)&pszRowData[rgBindings[m_IndexColSize].obValue] < m_cSelectedColSize) {
m_cSelectedColSize = *(DWORD*)&pszRowData[rgBindings[m_IndexColSize].obValue];
m_dbtSelectedCol = *(WORD*) &pszRowData[rgBindings[m_IndexDataType].obValue];
PROVIDER_FREE(m_pwszSelectedCol);
m_pwszSelectedCol = wcsDuplicate((WCHAR*) &pszRowData[rgBindings[m_IndexTypeName].obValue]);
fResult = true;
}
}
TESTC_(pIRowset->ReleaseRows(1, phRows, NULL, NULL, NULL), S_OK)
PROVIDER_FREE(phRows);
cRowsObtained = 0;
}
TESTC(fResult);
odtLog << "Using '" << m_pwszSelectedCol << "' data type to find maximum limit\n";
CLEANUP:
PROVIDER_FREE(rgBindings);
PROVIDER_FREE(pszRowData);
PROVIDER_FREE(pwszVer);
if (hAccessor && pIAccessor)
pIAccessor->ReleaseAccessor(hAccessor, NULL);
SAFE_RELEASE(pIAccessor);
SAFE_RELEASE(pIRowset);
TRETURN
}
HRESULT CLimitTable::CreateTable(DBCOUNTITEM cTotalCol, DBID **ppTableID) {
TBEGIN
DBCOLUMNDESC *rgColDesc = NULL;
DBCOUNTITEM i;
WCHAR *pwszColName = NULL;
IRowset *pIRowset = NULL;
DBID *pid = NULL;
DBPROPSET PropSet;
DBPROP Prop;
rgColDesc = (DBCOLUMNDESC*) PROVIDER_ALLOC(cTotalCol * sizeof(DBCOLUMNDESC));
pwszColName = (WCHAR*) PROVIDER_ALLOC(1024);
Prop.dwPropertyID = DBPROP_COL_NULLABLE;
Prop.dwOptions = DBPROPOPTIONS_REQUIRED;
Prop.dwStatus = DBPROPSTATUS_OK;
Prop.colid = DB_NULLID;
VariantInit(&Prop.vValue);
V_VT(&Prop.vValue) = VT_BOOL;
V_BOOL(&Prop.vValue) = VARIANT_FALSE;
PropSet.guidPropertySet = DBPROPSET_COLUMN;
PropSet.cProperties = 1;
PropSet.rgProperties = &Prop;
// Create Column Description structure
for (i=0; i<cTotalCol; i++) {
swprintf(pwszColName, L"Col%d", i);
rgColDesc[i].pwszTypeName = m_pwszSelectedCol;
rgColDesc[i].pTypeInfo = NULL;
rgColDesc[i].rgPropertySets = &PropSet; //NULL;
rgColDesc[i].pclsid = NULL;
rgColDesc[i].cPropertySets = 1; //0;
rgColDesc[i].ulColumnSize = m_cSelectedColSize;
rgColDesc[i].dbcid.eKind = DBKIND_NAME;
rgColDesc[i].dbcid.uName.pwszName = wcsDuplicate(pwszColName);
rgColDesc[i].bPrecision = 0;
rgColDesc[i].bScale = 0;
}
// Now create table
TESTC_(m_pITDWC->CreateTable(NULL, NULL, cTotalCol,
rgColDesc, IID_IRowset, 0, NULL,
&pid, (IUnknown**) &pIRowset), S_OK);
*ppTableID = pid;
for(i=0;i < cTotalCol; i++)
PROVIDER_FREE(rgColDesc[i].dbcid.uName.pwszName);
CLEANUP:
PROVIDER_FREE(pwszColName);
PROVIDER_FREE(rgColDesc);
SAFE_RELEASE(pIRowset);
TRETURN
}
HRESULT CLimitTable::CreatePrimaryKey(DBID *pTableID, DBCOUNTITEM cTotalCols) {
DBID *pPKDBID = NULL;
DBCOUNTITEM i;
WCHAR *pwszColName = NULL;
HRESULT hr = E_FAIL;
DBCONSTRAINTDESC Cons;
DBID ConsID;
ASSERT(pTableID && cTotalCols > 0);
pwszColName = (WCHAR*) PROVIDER_ALLOC(1024);
// Build PK columns list
pPKDBID = (DBID*) PROVIDER_ALLOC(sizeof(DBID) * cTotalCols);
for(i=0; i<cTotalCols; i++) {
swprintf(pwszColName, L"Col%d", i);
pPKDBID[i].eKind = DBKIND_NAME;
pPKDBID[i].uName.pwszName = wcsDuplicate(pwszColName);
}
// Build constraint DBID
ConsID.eKind = DBKIND_NAME;
ConsID.uName.pwszName = L"PKConstraint";
// Build constraint structure
Cons.pConstraintID = &ConsID;
Cons.ConstraintType = DBCONSTRAINTTYPE_PRIMARYKEY;
Cons.cColumns = cTotalCols;
Cons.rgColumnList = pPKDBID;
Cons.pReferencedTableID = NULL;
Cons.cForeignKeyColumns = 0;
Cons.rgForeignKeyColumnList = NULL;
Cons.pwszConstraintText = NULL;
Cons.cReserved = 0;
Cons.rgReserved = NULL;
Cons.Deferrability = 0;
hr = m_pITDWC->AddConstraint(pTableID, &Cons);
for(i=0; i<cTotalCols; i++)
PROVIDER_FREE(pPKDBID[i].uName.pwszName);
PROVIDER_FREE(pPKDBID);
PROVIDER_FREE(pwszColName);
return hr;
}
HRESULT CLimitTable::CreateUniqueKey(DBID *pTableID, DBCOUNTITEM cTotalCols) {
DBID *pPKDBID = NULL;
DBCOUNTITEM i;
WCHAR *pwszColName = NULL;
HRESULT hr = E_FAIL;
DBCONSTRAINTDESC Cons;
DBID ConsID;
ASSERT(pTableID && cTotalCols > 0);
pwszColName = (WCHAR*) PROVIDER_ALLOC(1024);
// Build PK columns list
pPKDBID = (DBID*) PROVIDER_ALLOC(sizeof(DBID) * cTotalCols);
for(i=0; i<cTotalCols; i++) {
swprintf(pwszColName, L"Col%d", i);
pPKDBID[i].eKind = DBKIND_NAME;
pPKDBID[i].uName.pwszName = wcsDuplicate(pwszColName);
}
// Build constraint DBID
ConsID.eKind = DBKIND_NAME;
ConsID.uName.pwszName = L"UniqueConstraint";
// Build constraint structure
Cons.pConstraintID = &ConsID;
Cons.ConstraintType = DBCONSTRAINTTYPE_UNIQUE;
Cons.cColumns = cTotalCols;
Cons.rgColumnList = pPKDBID;
Cons.pReferencedTableID = NULL;
Cons.cForeignKeyColumns = 0;
Cons.rgForeignKeyColumnList = NULL;
Cons.pwszConstraintText = NULL;
Cons.cReserved = 0;
Cons.rgReserved = NULL;
Cons.Deferrability = 0;
hr = m_pITDWC->AddConstraint(pTableID, &Cons);
for(i=0; i<cTotalCols; i++)
PROVIDER_FREE(pPKDBID[i].uName.pwszName);
PROVIDER_FREE(pPKDBID);
PROVIDER_FREE(pwszColName);
return hr;
}
HRESULT CLimitTable::CreateForeignKey(DBID *pBaseID, DBID *pRefID, DBCOUNTITEM cTotalCols) {
DBID *pPKDBID = NULL,
*pFKDBID = NULL;
DBCOUNTITEM i;
WCHAR *pwszColName = NULL;
HRESULT hr = E_FAIL;
DBCONSTRAINTDESC Cons;
DBID ConsID;
ASSERT(pBaseID && pRefID && cTotalCols > 0);
pwszColName = (WCHAR*) PROVIDER_ALLOC(1024);
// Build PK columns list
pPKDBID = (DBID*) PROVIDER_ALLOC(sizeof(DBID) * cTotalCols);
for(i=0; i<cTotalCols; i++) {
swprintf(pwszColName, L"Col%d", i);
pPKDBID[i].eKind = DBKIND_NAME;
pPKDBID[i].uName.pwszName = wcsDuplicate(pwszColName);
}
// Build FK columns list
pFKDBID = (DBID*) PROVIDER_ALLOC(sizeof(DBID) * cTotalCols);
for(i=0; i<cTotalCols; i++) {
swprintf(pwszColName, L"Col%d", i);
pFKDBID[i].eKind = DBKIND_NAME;
pFKDBID[i].uName.pwszName = wcsDuplicate(pwszColName);
}
// Build constraint DBID
ConsID.eKind = DBKIND_NAME;
ConsID.uName.pwszName = L"FKConstraint";
// Build constraint structure
Cons.pConstraintID = &ConsID;
Cons.ConstraintType = DBCONSTRAINTTYPE_FOREIGNKEY;
Cons.cColumns = cTotalCols;
Cons.rgColumnList = pPKDBID;
Cons.pReferencedTableID = pRefID;
Cons.cForeignKeyColumns = cTotalCols;
Cons.rgForeignKeyColumnList = pFKDBID;
Cons.pwszConstraintText = NULL;
Cons.cReserved = 0;
Cons.rgReserved = NULL;
Cons.Deferrability = 0;
Cons.UpdateRule = DBUPDELRULE_NOACTION;
Cons.DeleteRule = DBUPDELRULE_NOACTION;
Cons.MatchType = DBMATCHTYPE_NONE;
TESTC_(hr = m_pITDWC->AddConstraint(pBaseID, &Cons), S_OK);
for(i=0; i<cTotalCols; i++) {
PROVIDER_FREE(pPKDBID[i].uName.pwszName);
PROVIDER_FREE(pFKDBID[i].uName.pwszName);
}
PROVIDER_FREE(pPKDBID);
PROVIDER_FREE(pFKDBID);
PROVIDER_FREE(pwszColName);
CLEANUP:
return hr;
}
HRESULT CLimitTable::CheckPrimaryKeyLimit() {
TBEGIN
DBID *pTableID = NULL;
DBCOUNTITEM i = 0;
HRESULT hr = S_OK;
// Initialize everything
TESTC(Init());
// Get provider types to be used in testing
TESTC(GetBestType());
// find the limit
for(i = 1; i <= 256; i++) {
TESTC(CreateTable(i, &pTableID));
hr = CreatePrimaryKey(pTableID, i);
TESTC(DropTable(pTableID));
if (FAILED(hr)) {
hr = S_OK;
break;
}
}
i--;
odtLog << "Maximum columns in Primary Key allowed: " << i << "\n";
TESTC(i != 0);
CLEANUP:
return hr;
}
HRESULT CLimitTable::CheckUniqueKeyLimit() {
TBEGIN
DBID *pTableID = NULL;
DBCOUNTITEM i = 0;
HRESULT hr = S_OK;
// Initialize everything
TESTC(Init());
// Get provider types to be used in testing
TESTC(GetBestType());
// find the limit
for(i = 1; i <= 256; i++) {
TESTC(CreateTable(i, &pTableID));
hr = CreateUniqueKey(pTableID, i);
TESTC(DropTable(pTableID));
if (FAILED(hr)) {
hr = S_OK;
break;
}
}
i--;
odtLog << "Maximum columns in Unique Key allowed: " << i << "\n";
TESTC(i != 0);
CLEANUP:
return hr;
}
HRESULT CLimitTable::CheckForeignKeyLimit() {
TBEGIN
DBID *pBaseID = NULL,
*pRefID = NULL;
DBCOUNTITEM i = 0;
HRESULT hr = S_OK;
// Initialize everything
TESTC(Init());
// Get provider types to be used in testing
TESTC(GetBestType());
// find the limit
for(i = 1; i <= 256; i++) {
TESTC(CreateTable(i, &pBaseID));
TESTC(CreateTable(i, &pRefID));
hr = CreatePrimaryKey(pBaseID, i);
if (SUCCEEDED(hr)) {
hr = CreateUniqueKey(pRefID, i);
if (SUCCEEDED(hr)) {
hr = CreateForeignKey(pBaseID, pRefID, i);
}
}
TESTC(DropTable(pBaseID));
TESTC(DropTable(pRefID));
PROVIDER_FREE(pBaseID);
PROVIDER_FREE(pRefID);
if (FAILED(hr)) {
hr = S_OK;
break;
}
}
i--;
odtLog << "Maximum columns in Foreign Key allowed: " << i << "\n";
TESTC(i != 0);
CLEANUP:
return hr;
}
HRESULT CLimitTable::DropTable(DBID *pTableID)
{
TBEGIN
TESTC(m_pITDWC != NULL);
TESTC_(m_pITDWC->DropTable(pTableID), S_OK);
CLEANUP:
TRETURN
}
// {{ TCW_TEST_CASE_MAP(TCAddColumn)
//--------------------------------------------------------------------
// @class Testcase for ITableDefinition::AddColumn
//
class TCAddColumn : public TCITableDefinition {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCAddColumn,TCITableDefinition);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Table doesn't exist => DB_E_NOTABLE
int Variation_1();
// @cmember The table is in use => DB_E_TABLEINUSE
int Variation_2();
// @cmember *pTableID = DB_NULLID => DB_E_NOTABLE
int Variation_3();
// @cmember pTableID = NULL => E_INVALIDARG
int Variation_4();
// @cmember Maximum length for table name => S_OK
int Variation_5();
// @cmember the table name is 1 char too long => DB_E_NOTABLE
int Variation_6();
// @cmember invalid table name => DB_E_NOTABLE
int Variation_7();
// @cmember pColumnDesc->dbcid = DB_NULLID
int Variation_8();
// @cmember Column name pointer is NULL => DB_E_BADCOLUMNID
int Variation_9();
// @cmember column name is an empty string => DB_E_BADCOLUMNID
int Variation_10();
// @cmember Maximum length of column name => S_OK
int Variation_11();
// @cmember 1-char-too-long column name => DB_E_BADCOLUMNID
int Variation_12();
// @cmember Add a column for each provider type, maximum column size => S_OK
int Variation_13();
// @cmember Add a column for each known type; ulColumnsize == 0 => S_OK
int Variation_14();
// @cmember Add a column for each provider type (table is populated) => S_OK
int Variation_15();
// @cmember Precision testing
int Variation_16();
// @cmember Scale testing
int Variation_17();
// @cmember Invalid value for the property of a column => DB_E_ERRORSOCCURRED
int Variation_18();
// @cmember Non-column property => DBPROPSTATUS_NOTSUPPORTED
int Variation_19();
// @cmember Inexistent property => DBPROPSTATUS_NOTSUPPORTED
int Variation_20();
// @cmember Bad option => DBPROPSTATUS_BADOPTION
int Variation_21();
// @cmember Conflicting property => DBPROPSTATUS_CONFLICTING
int Variation_22();
// @cmember Bad column ID for a property => ignored
int Variation_23();
// @cmember Bad column type (wType in DBCOLUMNDESC)
int Variation_24();
// @cmember Invalid provider type name for a column => DB_E_BADTYPE
int Variation_25();
// @cmember NULL ppColumnDesc => S_OK
int Variation_26();
// @cmember Autoincrementable column - DBPROP_COL_AUTOINCREMENT
int Variation_27();
// @cmember DBPROP_COL_DEFAULT
int Variation_28();
// @cmember DBPROP_COL_DESCRIPTION
int Variation_29();
// @cmember DBPROP_COL_FIXEDLENGTH
int Variation_30();
// @cmember DBPROP_COL_NULLABLE
int Variation_31();
// @cmember DBPROP_PRIMARYKEY
int Variation_32();
// @cmember DBPROP_COL_UNIQUE
int Variation_33();
// @cmember Duplicate an existing column => DB_E_DUPLCATECOLUMNID
int Variation_34();
// @cmember Abort retaining
int Variation_35();
// @cmember Abort without retaining
int Variation_36();
// @cmember Commit with retain
int Variation_37();
// @cmember Commit without retain
int Variation_38();
// @cmember Add a column for each provider type in an empty table => S_OK
int Variation_39();
// @cmember Add a column to a table created with a SQL command => S_OK
int Variation_40();
// @cmember Drop all the column of a table (via SQL stmt) and then try to add a column => S_OK
int Variation_41();
// @cmember Non NULL pTypeInfo in DBCOLUMNDESC => DB_E_BADTYPE
int Variation_42();
// @cmember Missmatch between wType and pwszTypeName => DB_E_BADTYPE
int Variation_43();
// @cmember Add a not nullable column and try to insert a null value for it
int Variation_44();
// @cmember Add a column on a view
int Variation_45();
// @cmember eKind != DBKIND_NAME for a column
int Variation_46();
// @cmember threads with different column
int Variation_47();
// @cmember threads on the same column
int Variation_48();
// @cmember add columns of alll known wType => S_OK
int Variation_49();
// @cmember Fully Qualified table name
int Variation_50();
// @cmember Quoted Table Name
int Variation_51();
// @cmember pColumnDesc == NULL => E_INVALIDARG
int Variation_52();
// @cmember cPropertySets != 0 and rgPropertySets == NULL in pColumnDesc => E_INVALIDARG
int Variation_53();
// @cmember cPropertySets == 0 and rgPropertySets != NULL in pColumnDesc => S_OK
int Variation_54();
// @cmember cProperties == 0 and rgProperties != NULL in pColumnDesc's propset => S_OK
int Variation_55();
// @cmember cProperties != 0 and rgProperties == NULL in pColumnDesc's propset => E_INVALIDARG
int Variation_56();
// @cmember pclsid not null
int Variation_57();
// @cmember NULL pwszTypeName => S_OK
int Variation_58();
// }} TCW_TESTVARS_END
unsigned MyThreadProc(ULONG i);
};
// {{ TCW_TESTCASE(TCAddColumn)
#define THE_CLASS TCAddColumn
BEG_TEST_CASE(TCAddColumn, TCITableDefinition, L"Testcase for ITableDefinition::AddColumn")
TEST_VARIATION(1, L"Table doesn't exist => DB_E_NOTABLE")
TEST_VARIATION(2, L"The table is in use => DB_E_TABLEINUSE")
TEST_VARIATION(3, L"*pTableID = DB_NULLID => DB_E_NOTABLE")
TEST_VARIATION(4, L"pTableID = NULL => E_INVALIDARG")
TEST_VARIATION(5, L"Maximum length for table name => S_OK")
TEST_VARIATION(6, L"the table name is 1 char too long => DB_E_NOTABLE")
TEST_VARIATION(7, L"invalid table name => DB_E_NOTABLE")
TEST_VARIATION(8, L"pColumnDesc->dbcid = DB_NULLID")
TEST_VARIATION(9, L"Column name pointer is NULL => DB_E_BADCOLUMNID")
TEST_VARIATION(10, L"column name is an empty string => DB_E_BADCOLUMNID")
TEST_VARIATION(11, L"Maximum length of column name => S_OK")
TEST_VARIATION(12, L"1-char-too-long column name => DB_E_BADCOLUMNID")
TEST_VARIATION(13, L"Add a column for each provider type, maximum column size => S_OK")
TEST_VARIATION(14, L"Add a column for each known type; ulColumnsize == 0 => S_OK")
TEST_VARIATION(15, L"Add a column for each provider type (table is populated) => S_OK")
TEST_VARIATION(16, L"Precision testing")
TEST_VARIATION(17, L"Scale testing")
TEST_VARIATION(18, L"Invalid value for the property of a column => DB_E_ERRORSOCCURRED")
TEST_VARIATION(19, L"Non-column property => DBPROPSTATUS_NOTSUPPORTED")
TEST_VARIATION(20, L"Inexistent property => DBPROPSTATUS_NOTSUPPORTED")
TEST_VARIATION(21, L"Bad option => DBPROPSTATUS_BADOPTION")
TEST_VARIATION(22, L"Conflicting property => DBPROPSTATUS_CONFLICTING")
TEST_VARIATION(23, L"Bad column ID for a property => ignored")
TEST_VARIATION(24, L"Bad column type (wType in DBCOLUMNDESC)")
TEST_VARIATION(25, L"Invalid provider type name for a column => DB_E_BADTYPE")
TEST_VARIATION(26, L"NULL ppColumnDesc => S_OK")
TEST_VARIATION(27, L"Autoincrementable column - DBPROP_COL_AUTOINCREMENT")
TEST_VARIATION(28, L"DBPROP_COL_DEFAULT")
TEST_VARIATION(29, L"DBPROP_COL_DESCRIPTION")
TEST_VARIATION(30, L"DBPROP_COL_FIXEDLENGTH")
TEST_VARIATION(31, L"DBPROP_COL_NULLABLE")
TEST_VARIATION(32, L"DBPROP_PRIMARYKEY")
TEST_VARIATION(33, L"DBPROP_COL_UNIQUE")
TEST_VARIATION(34, L"Duplicate an existing column => DB_E_DUPLCATECOLUMNID")
TEST_VARIATION(35, L"Abort retaining")
TEST_VARIATION(36, L"Abort without retaining")
TEST_VARIATION(37, L"Commit with retain")
TEST_VARIATION(38, L"Commit without retain")
TEST_VARIATION(39, L"Add a column for each provider type in an empty table => S_OK")
TEST_VARIATION(40, L"Add a column to a table created with a SQL command => S_OK")
TEST_VARIATION(41, L"Drop all the column of a table (via SQL stmt) and then try to add a column => S_OK")
TEST_VARIATION(42, L"Non NULL pTypeInfo in DBCOLUMNDESC => DB_E_BADTYPE")
TEST_VARIATION(43, L"Missmatch between wType and pwszTypeName => DB_E_BADTYPE")
TEST_VARIATION(44, L"Add a not nullable column and try to insert a null value for it")
TEST_VARIATION(45, L"Add a column on a view")
TEST_VARIATION(46, L"eKind != DBKIND_NAME for a column")
TEST_VARIATION(47, L"threads with different column")
TEST_VARIATION(48, L"threads on the same column")
TEST_VARIATION(49, L"add columns of alll known wType => S_OK")
TEST_VARIATION(50, L"Fully Qualified table name")
TEST_VARIATION(51, L"Quoted Table Name")
TEST_VARIATION(52, L"pColumnDesc == NULL => E_INVALIDARG")
TEST_VARIATION(53, L"cPropertySets != 0 and rgPropertySets == NULL in pColumnDesc => E_INVALIDARG")
TEST_VARIATION(54, L"cPropertySets == 0 and rgPropertySets != NULL in pColumnDesc => S_OK")
TEST_VARIATION(55, L"cProperties == 0 and rgProperties != NULL in pColumnDesc's propset => S_OK")
TEST_VARIATION(56, L"cProperties != 0 and rgProperties == NULL in pColumnDesc's propset => E_INVALIDARG")
TEST_VARIATION(57, L"pclsid not null")
TEST_VARIATION(58, L"NULL pwszTypeName => S_OK")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCDropColumn)
//--------------------------------------------------------------------
// @class Test case for dropping columns
//
class TCDropColumn : public TCITableDefinition {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCDropColumn,TCITableDefinition);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember pTableID is NULL => E_INVALIDARG
int Variation_1();
// @cmember pColumnID in NULL => E_INVALIDARG
int Variation_2();
// @cmember *pTableID is DB_NULLID => DB_E_NOTABLE
int Variation_3();
// @cmember *pColumnID is DB_NULLID => DB_E_NOCOLUMN
int Variation_4();
// @cmember Maximum length table name => S_OK
int Variation_5();
// @cmember 1-char-too long table name => DB_E_NOTABLE
int Variation_6();
// @cmember *pTableID contains a NULL table name => DB_E_NOTABLE
int Variation_7();
// @cmember *pTableID contains an invalid name => DB_E_NOTABLE
int Variation_8();
// @cmember Maximum length for a column name => S_OK
int Variation_9();
// @cmember 1-char-too-long column name => DB_E_NOCOLUMN
int Variation_10();
// @cmember *pColumnID contains a NULL column name pointer => E_INVALIDARG
int Variation_11();
// @cmember *pColumnID contains an invalid column name => E_INVALID ARG
int Variation_12();
// @cmember Drop all the columns of a table => S_OK
int Variation_13();
// @cmember Try to delete an inexistent column => DB_E_NOCOLUMN
int Variation_14();
// @cmember Table in use => DB_E_TABLEINUSE
int Variation_15();
// @cmember Valid name of an inexistent table => DB_E_NOTABLE
int Variation_16();
// @cmember Abort with retaining
int Variation_17();
// @cmember Abort without retaining
int Variation_18();
// @cmember Commit with retaining
int Variation_19();
// @cmember Commit without retaining
int Variation_20();
// @cmember threads on different columns
int Variation_21();
// @cmember threads on the same column
int Variation_22();
// @cmember Drop a column twice => DB_E_NOCOLUMN
int Variation_23();
// @cmember 2 TableDefinition interfaces on the same table, try to drop 2 different columns => S_OK
int Variation_24();
// @cmember Drop as many column as possible from a table created with a SQL statement
int Variation_25();
// @cmember Drop a column from a 2 column table
int Variation_26();
// @cmember drop a column from a 1 column table
int Variation_27();
// @cmember drop a column from a non empty table => S_OK
int Variation_28();
// @cmember drop a column from an empty table
int Variation_29();
// @cmember drop a nullable, an autoincrementable and a default value column
int Variation_30();
// @cmember try to drop a column from a view
int Variation_31();
// @cmember drop a column added with an alter table command => S_OK
int Variation_32();
// @cmember try to drop columns using different DBKIND pattern
int Variation_33();
// @cmember Fully Qualified Table Name
int Variation_34();
// @cmember Quoted Table Name
int Variation_35();
// }} TCW_TESTVARS_END
unsigned MyThreadProc(ULONG i);
};
// {{ TCW_TESTCASE(TCDropColumn)
#define THE_CLASS TCDropColumn
BEG_TEST_CASE(TCDropColumn, TCITableDefinition, L"Test case for dropping columns")
TEST_VARIATION(1, L"pTableID is NULL => E_INVALIDARG")
TEST_VARIATION(2, L"pColumnID in NULL => E_INVALIDARG")
TEST_VARIATION(3, L"*pTableID is DB_NULLID => DB_E_NOTABLE")
TEST_VARIATION(4, L"*pColumnID is DB_NULLID => DB_E_NOCOLUMN")
TEST_VARIATION(5, L"Maximum length table name => S_OK")
TEST_VARIATION(6, L"1-char-too long table name => DB_E_NOTABLE")
TEST_VARIATION(7, L"*pTableID contains a NULL table name => DB_E_NOTABLE")
TEST_VARIATION(8, L"*pTableID contains an invalid name => DB_E_NOTABLE")
TEST_VARIATION(9, L"Maximum length for a column name => S_OK")
TEST_VARIATION(10, L"1-char-too-long column name => DB_E_NOCOLUMN")
TEST_VARIATION(11, L"*pColumnID contains a NULL column name pointer => E_INVALIDARG")
TEST_VARIATION(12, L"*pColumnID contains an invalid column name => E_INVALID ARG")
TEST_VARIATION(13, L"Drop all the columns of a table => S_OK")
TEST_VARIATION(14, L"Try to delete an inexistent column => DB_E_NOCOLUMN")
TEST_VARIATION(15, L"Table in use => DB_E_TABLEINUSE")
TEST_VARIATION(16, L"Valid name of an inexistent table => DB_E_NOTABLE")
TEST_VARIATION(17, L"Abort with retaining")
TEST_VARIATION(18, L"Abort without retaining")
TEST_VARIATION(19, L"Commit with retaining")
TEST_VARIATION(20, L"Commit without retaining")
TEST_VARIATION(21, L"threads on different columns")
TEST_VARIATION(22, L"threads on the same column")
TEST_VARIATION(23, L"Drop a column twice => DB_E_NOCOLUMN")
TEST_VARIATION(24, L"2 TableDefinition interfaces on the same table, try to drop 2 different columns => S_OK")
TEST_VARIATION(25, L"Drop as many column as possible from a table created with a SQL statement")
TEST_VARIATION(26, L"Drop a column from a 2 column table")
TEST_VARIATION(27, L"drop a column from a 1 column table")
TEST_VARIATION(28, L"drop a column from a non empty table => S_OK")
TEST_VARIATION(29, L"drop a column from an empty table")
TEST_VARIATION(30, L"drop a nullable, an autoincrementable and a default value column")
TEST_VARIATION(31, L"try to drop a column from a view")
TEST_VARIATION(32, L"drop a column added with an alter table command => S_OK")
TEST_VARIATION(33, L"try to drop columns using different DBKIND pattern")
TEST_VARIATION(34, L"Fully Qualified Table Name")
TEST_VARIATION(35, L"Quoted Table Name")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCDropTable)
//--------------------------------------------------------------------
// @class Test Case fo dropping a table
//
class TCDropTable : public TCITableDefinition {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCDropTable,TCITableDefinition);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember pTableID is NULL => E_INVALIDARG
int Variation_1();
// @cmember *pTableID is DB_NULLID => DB_E_NOTABLE
int Variation_2();
// @cmember Maximum length for table name => S_OK
int Variation_3();
// @cmember 1-char-too-long table name => DB_E_NOTABLE
int Variation_4();
// @cmember The pointer to the table name is NULL => DB_E_NOTABLE
int Variation_5();
// @cmember Table name is empty => DB_E_NOTABLE
int Variation_6();
// @cmember Invalid table name => DB_E_NOTABLE
int Variation_7();
// @cmember A rowset is opened on table => DB_E_TABLEINUSE
int Variation_8();
// @cmember Table in use => DB_E_TABLEINUSE
int Variation_9();
// @cmember Inexistent table => DB_E_NOTABLE
int Variation_10();
// @cmember Abort with retaining
int Variation_11();
// @cmember Abort without retaining
int Variation_12();
// @cmember Commit with retaining
int Variation_13();
// @cmember Commit without retaining
int Variation_14();
// @cmember Drop a table created with an SQL command => S_OK
int Variation_15();
// @cmember Drop a table created with ITableDefinition, no rowset created => S_OK
int Variation_16();
// @cmember Drop a table created with ITableDefinition, rowset released => S_OK
int Variation_17();
// @cmember ITableDefinition::CreateTable, insert 10 rows, release rowset, drop the table => S_OK
int Variation_18();
// @cmember For each provider type, create a table with a single column and then drop it => S_OK
int Variation_19();
// @cmember Drop a table twice => DB_E_NOTABLE
int Variation_20();
// @cmember threads on different tables
int Variation_21();
// @cmember threads on same table
int Variation_22();
// @cmember Fully Qualified Table Name
int Variation_23();
// @cmember Quoted Table Name
int Variation_24();
// @cmember Different DBKINDs for pTableID
int Variation_25();
// }} TCW_TESTVARS_END
unsigned MyThreadProc(ULONG i);
};
// {{ TCW_TESTCASE(TCDropTable)
#define THE_CLASS TCDropTable
BEG_TEST_CASE(TCDropTable, TCITableDefinition, L"Test Case fo dropping a table")
TEST_VARIATION(1, L"pTableID is NULL => E_INVALIDARG")
TEST_VARIATION(2, L"*pTableID is DB_NULLID => DB_E_NOTABLE")
TEST_VARIATION(3, L"Maximum length for table name => S_OK")
TEST_VARIATION(4, L"1-char-too-long table name => DB_E_NOTABLE")
TEST_VARIATION(5, L"The pointer to the table name is NULL => DB_E_NOTABLE")
TEST_VARIATION(6, L"Table name is empty => DB_E_NOTABLE")
TEST_VARIATION(7, L"Invalid table name => DB_E_NOTABLE")
TEST_VARIATION(8, L"A rowset is opened on table => DB_E_TABLEINUSE")
TEST_VARIATION(9, L"Table in use => DB_E_TABLEINUSE")
TEST_VARIATION(10, L"Inexistent table => DB_E_NOTABLE")
TEST_VARIATION(11, L"Abort with retaining")
TEST_VARIATION(12, L"Abort without retaining")
TEST_VARIATION(13, L"Commit with retaining")
TEST_VARIATION(14, L"Commit without retaining")
TEST_VARIATION(15, L"Drop a table created with an SQL command => S_OK")
TEST_VARIATION(16, L"Drop a table created with ITableDefinition, no rowset created => S_OK")
TEST_VARIATION(17, L"Drop a table created with ITableDefinition, rowset released => S_OK")
TEST_VARIATION(18, L"ITableDefinition::CreateTable, insert 10 rows, release rowset, drop the table => S_OK")
TEST_VARIATION(19, L"For each provider type, create a table with a single column and then drop it => S_OK")
TEST_VARIATION(20, L"Drop a table twice => DB_E_NOTABLE")
TEST_VARIATION(21, L"threads on different tables")
TEST_VARIATION(22, L"threads on same table")
TEST_VARIATION(23, L"Fully Qualified Table Name")
TEST_VARIATION(24, L"Quoted Table Name")
TEST_VARIATION(25, L"Different DBKINDs for pTableID")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCCreateTable)
//--------------------------------------------------------------------
// @class TestCase for table creation
//
class TCCreateTable : public TCITableDefinition {
public:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCCreateTable,TCITableDefinition);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Session interfaces
int Variation_1();
// @cmember pTableID is NULL => S_OK
int Variation_2();
// @cmember ppTableID is a NULL pointer => S_OK
int Variation_3();
// @cmember pTableID and ppTableID both NULL => E_INVALIDARG
int Variation_4();
// @cmember *pTableID == DB_NULLID => DB_E_BADTABLEID
int Variation_5();
// @cmember cColumnDesc == 0 => E_INVALIDARG or S_OK
int Variation_6();
// @cmember rgColumnDesc == NULL => E_INVALIDARG
int Variation_7();
// @cmember cPropertySets != 0 and rgPropertySets == NULL => E_INVALIDARG
int Variation_8();
// @cmember cPropertySets is 0 and rgPropertySets != NULL => S_OK
int Variation_9();
// @cmember for a property sets, cProperties != 0 and rgProperties == NULL => E_INVALIDARG
int Variation_10();
// @cmember cProperties == 0 on a property set => S_OK
int Variation_11();
// @cmember for a column, rgPropertySets is NULL though cPropertySets != 0 => E_INVALIDARG
int Variation_12();
// @cmember dbcid in an element of rgColumnDesc is DB_NULLID => DB_E_BADCOLUMNID
int Variation_13();
// @cmember dbcid in an element of rgColumnDesc is NULL => DB_E_BADCOLUMNID
int Variation_14();
// @cmember not null pclsid in a DBCOLUMNDESC element
int Variation_15();
// @cmember empty column name => DB_E_BADCOLUMNID
int Variation_16();
// @cmember empty table name => DB_E_BADTABLEID
int Variation_17();
// @cmember Maximum length for table name => S_OK
int Variation_18();
// @cmember 1 char too long table name => DB_E_BADTABLEID
int Variation_19();
// @cmember Maximum length column name => S_OK
int Variation_20();
// @cmember 1 char too long column name => DB_E_BADCOLUMNID
int Variation_21();
// @cmember ulColumnSize 0 for a variable-length column => S_OK
int Variation_22();
// @cmember For each provider type create and drop a table with a single column => S_OK
int Variation_23();
// @cmember invalid table name => DB_E_BADTABLEID
int Variation_24();
// @cmember pTableID provides the name of an existing table => DB_E_DUPLICATETABLEID
int Variation_25();
// @cmember valid riid and NULL ppRowset => S_OK
int Variation_26();
// @cmember invalid column name => DB_E_BADCOLUMNID
int Variation_27();
// @cmember invalid type name for a column (NULL, empty or inexistent)
int Variation_28();
// @cmember invalid wType for a column => DB_E_BADTYPE
int Variation_29();
// @cmember wType and pswzTypeName mismatch in a column description => DB_E_BADTYPE
int Variation_30();
// @cmember not null pTypeInfo => DB_E_BADTYPE (for the time being
int Variation_31();
// @cmember duplicate column identifiers => DB_E_DUPLICATECOLUMNID
int Variation_32();
// @cmember improper eKind value in a DBID => DB_E_BADCOLUMNID
int Variation_33();
// @cmember invalid property value on column
int Variation_34();
// @cmember Invalid column precision => DB_E_BADPRECISION
int Variation_35();
// @cmember invalid scale on column => DB_E_BADSCALE
int Variation_36();
// @cmember col prop is not in the Column, Rowset or Table property group and dwOption is DBPROP_SETIFCHEAP => DB_S_ERRORSOCCURRED
int Variation_37();
// @cmember col prop is not in the Column, Rowset or Table property group and dwOption is DBPROP_REQUIRED => DB_E_ERRORSOCCURRED
int Variation_38();
// @cmember invalid propID for a column propriety
int Variation_39();
// @cmember colid in DBPROP of a column property is ignored
int Variation_40();
// @cmember Abort retaining
int Variation_41();
// @cmember Abort without retaining
int Variation_42();
// @cmember Commit retain
int Variation_43();
// @cmember Commit non-retaining
int Variation_44();
// @cmember Autoincrementable columns
int Variation_45();
// @cmember Default values
int Variation_46();
// @cmember Column descriptions
int Variation_47();
// @cmember Variable length columns
int Variation_48();
// @cmember Nullable/non nullable columns
int Variation_49();
// @cmember Primary key column
int Variation_50();
// @cmember Unique columns
int Variation_51();
// @cmember Test conflicting properties
int Variation_52();
// @cmember Create a table and ask for a rowset, setting DBPROP_ABORTPRESERVE
int Variation_53();
// @cmember Inserting rows after table creation, using the resulting rowset
int Variation_54();
// @cmember Delete rows in the created rowset
int Variation_55();
// @cmember Aggregation, ask for IID_IUnknown
int Variation_56();
// @cmember Create a table and ask for a rowset, setting DBPROP_COMMITPRESERVE
int Variation_57();
// @cmember Create a table and ask for a rowset, setting DBPROP_OWNINSERT
int Variation_58();
// @cmember Create a table and ask for a rowset, setting DBPROP_BOOKMARKS
int Variation_59();
// @cmember Create a table and ask for a rowset, setting DBPROP_CANHOLDROWS
int Variation_60();
// @cmember Create a table and ask for a rowset, setting DBPROP_MAYWRITECOLUMN
int Variation_61();
// @cmember Ask for a rowset mandatory/optional interface when table creation => S_OK
int Variation_62();
// @cmember threads on different tables
int Variation_63();
// @cmember threads on the same table
int Variation_64();
// @cmember try all interfaces on rowset that can be returned
int Variation_65();
// @cmember create with a table property => S_OK
int Variation_66();
// @cmember create a table and update a row, using the rowset interface got => S_OK
int Variation_67();
// @cmember Fully Qualified Table Name
int Variation_68();
// @cmember Quoted table name
int Variation_69();
// @cmember Aggregation, non IID_IUnknown
int Variation_70();
// @cmember Aggregation -> IRowsetInfo::GetReferencedRowset
int Variation_71();
// @cmember Agg session -> IRowsetInfo::GetSpecification
int Variation_72();
// @cmember Table -> Agg ColumnRowset, ask for non IID_IUnknown
int Variation_73();
// @cmember Table -> Agg ColumnRowset, ask for IID_IUnknown
int Variation_74();
// @cmember Table -> Agg ColumnRowset -> IRowsetInfo::GetSpecification
int Variation_75();
// @cmember colid is ignored in a non column specific rowset property
int Variation_76();
// @cmember colid is DB_NULLID in a column specific rowset property => S_OK
int Variation_77();
// @cmember valid, non DB_NULLID colid for a column specific rowset property
int Variation_78();
// @cmember invalid colid for a column specific rowset property
int Variation_79();
// @cmember Create a table. Retrieve a rowset on it (IRowsetInfo). Check GetSpecification()
int Variation_80();
// @cmember DB_NULLID is ignored for non column-related table properties
int Variation_81();
// @cmember Column related table property set to bad colid
int Variation_82();
// @cmember How many DBTYPE_I4 columns?
int Variation_83();
// @cmember Open a rowset with CE, call IColumnRowset with an aggregated pIUnk
int Variation_84();
// @cmember Different DBKINDs for pTableID
int Variation_85();
// @cmember Different DBKINDs for column IDs
int Variation_86();
// }} TCW_TESTVARS_END
unsigned MyThreadProc(ULONG i);
};
// {{ TCW_TESTCASE(TCCreateTable)
#define THE_CLASS TCCreateTable
BEG_TEST_CASE(TCCreateTable, TCITableDefinition, L"TestCase for table creation")
TEST_VARIATION(1, L"Session interfaces")
TEST_VARIATION(2, L"pTableID is NULL => S_OK")
TEST_VARIATION(3, L"ppTableID is a NULL pointer => S_OK")
TEST_VARIATION(4, L"pTableID and ppTableID both NULL => E_INVALIDARG")
TEST_VARIATION(5, L"*pTableID == DB_NULLID => DB_E_BADTABLEID")
TEST_VARIATION(6, L"cColumnDesc == 0 => E_INVALIDARG or S_OK")
TEST_VARIATION(7, L"rgColumnDesc == NULL => E_INVALIDARG")
TEST_VARIATION(8, L"cPropertySets != 0 and rgPropertySets == NULL => E_INVALIDARG")
TEST_VARIATION(9, L"cPropertySets is 0 and rgPropertySets != NULL => S_OK")
TEST_VARIATION(10, L"for a property sets, cProperties != 0 and rgProperties == NULL => E_INVALIDARG")
TEST_VARIATION(11, L"cProperties == 0 on a property set => S_OK")
TEST_VARIATION(12, L"for a column, rgPropertySets is NULL though cPropertySets != 0 => E_INVALIDARG")
TEST_VARIATION(13, L"dbcid in an element of rgColumnDesc is DB_NULLID => DB_E_BADCOLUMNID")
TEST_VARIATION(14, L"dbcid in an element of rgColumnDesc is NULL => DB_E_BADCOLUMNID")
TEST_VARIATION(15, L"not null pclsid in a DBCOLUMNDESC element")
TEST_VARIATION(16, L"empty column name => DB_E_BADCOLUMNID")
TEST_VARIATION(17, L"empty table name => DB_E_BADTABLEID")
TEST_VARIATION(18, L"Maximum length for table name => S_OK")
TEST_VARIATION(19, L"1 char too long table name => DB_E_BADTABLEID")
TEST_VARIATION(20, L"Maximum length column name => S_OK")
TEST_VARIATION(21, L"1 char too long column name => DB_E_BADCOLUMNID")
TEST_VARIATION(22, L"ulColumnSize 0 for a variable-length column => S_OK")
TEST_VARIATION(23, L"For each provider type create and drop a table with a single column => S_OK")
TEST_VARIATION(24, L"invalid table name => DB_E_BADTABLEID")
TEST_VARIATION(25, L"pTableID provides the name of an existing table => DB_E_DUPLICATETABLEID")
TEST_VARIATION(26, L"valid riid and NULL ppRowset => S_OK")
TEST_VARIATION(27, L"invalid column name => DB_E_BADCOLUMNID")
TEST_VARIATION(28, L"invalid type name for a column (NULL, empty or inexistent)")
TEST_VARIATION(29, L"invalid wType for a column => DB_E_BADTYPE")
TEST_VARIATION(30, L"wType and pswzTypeName mismatch in a column description => DB_E_BADTYPE")
TEST_VARIATION(31, L"not null pTypeInfo => DB_E_BADTYPE (for the time being")
TEST_VARIATION(32, L"duplicate column identifiers => DB_E_DUPLICATECOLUMNID")
TEST_VARIATION(33, L"improper eKind value in a DBID => DB_E_BADCOLUMNID")
TEST_VARIATION(34, L"invalid property value on column")
TEST_VARIATION(35, L"Invalid column precision => DB_E_BADPRECISION")
TEST_VARIATION(36, L"invalid scale on column => DB_E_BADSCALE")
TEST_VARIATION(37, L"col prop is not in the Column, Rowset or Table property group and dwOption is DBPROP_SETIFCHEAP => DB_S_ERRORSOCCURRED")
TEST_VARIATION(38, L"col prop is not in the Column, Rowset or Table property group and dwOption is DBPROP_REQUIRED => DB_E_ERRORSOCCURRED")
TEST_VARIATION(39, L"invalid propID for a column propriety")
TEST_VARIATION(40, L"colid in DBPROP of a column property is ignored")
TEST_VARIATION(41, L"Abort retaining")
TEST_VARIATION(42, L"Abort without retaining")
TEST_VARIATION(43, L"Commit retain")
TEST_VARIATION(44, L"Commit non-retaining")
TEST_VARIATION(45, L"Autoincrementable columns")
TEST_VARIATION(46, L"Default values")
TEST_VARIATION(47, L"Column descriptions")
TEST_VARIATION(48, L"Variable length columns")
TEST_VARIATION(49, L"Nullable/non nullable columns")
TEST_VARIATION(50, L"Primary key column")
TEST_VARIATION(51, L"Unique columns")
TEST_VARIATION(52, L"Test conflicting properties")
TEST_VARIATION(53, L"Create a table and ask for a rowset, setting DBPROP_ABORTPRESERVE")
TEST_VARIATION(54, L"Inserting rows after table creation, using the resulting rowset")
TEST_VARIATION(55, L"Delete rows in the created rowset")
TEST_VARIATION(56, L"Aggregation, ask for IID_IUnknown")
TEST_VARIATION(57, L"Create a table and ask for a rowset, setting DBPROP_COMMITPRESERVE")
TEST_VARIATION(58, L"Create a table and ask for a rowset, setting DBPROP_OWNINSERT")
TEST_VARIATION(59, L"Create a table and ask for a rowset, setting DBPROP_BOOKMARKS")
TEST_VARIATION(60, L"Create a table and ask for a rowset, setting DBPROP_CANHOLDROWS")
TEST_VARIATION(61, L"Create a table and ask for a rowset, setting DBPROP_MAYWRITECOLUMN")
TEST_VARIATION(62, L"Ask for a rowset mandatory/optional interface when table creation => S_OK")
TEST_VARIATION(63, L"threads on different tables")
TEST_VARIATION(64, L"threads on the same table")
TEST_VARIATION(65, L"try all interfaces on rowset that can be returned")
TEST_VARIATION(66, L"create with a table property => S_OK")
TEST_VARIATION(67, L"create a table and update a row, using the rowset interface got => S_OK")
TEST_VARIATION(68, L"Fully Qualified Table Name")
TEST_VARIATION(69, L"Quoted table name")
TEST_VARIATION(70, L"Aggregation, non IID_IUnknown")
TEST_VARIATION(71, L"Aggregation -> IRowsetInfo::GetReferencedRowset")
TEST_VARIATION(72, L"Agg session -> IRowsetInfo::GetSpecification")
TEST_VARIATION(73, L"Table -> Agg ColumnRowset, ask for non IID_IUnknown")
TEST_VARIATION(74, L"Table -> Agg ColumnRowset, ask for IID_IUnknown")
TEST_VARIATION(75, L"Table -> Agg ColumnRowset -> IRowsetInfo::GetSpecification")
TEST_VARIATION(76, L"colid is ignored in a non column specific rowset property")
TEST_VARIATION(77, L"colid is DB_NULLID in a column specific rowset property => S_OK")
TEST_VARIATION(78, L"valid, non DB_NULLID colid for a column specific rowset property")
TEST_VARIATION(79, L"invalid colid for a column specific rowset property")
TEST_VARIATION(80, L"Create a table. Retrieve a rowset on it (IRowsetInfo). Check GetSpecification()")
TEST_VARIATION(81, L"DB_NULLID is ignored for non column-related table properties")
TEST_VARIATION(82, L"Column related table property set to bad colid")
TEST_VARIATION(83, L"How many DBTYPE_I4 columns?")
TEST_VARIATION(84, L"Open a rowset with CE, call IColumnRowset with an aggregated pIUnk")
TEST_VARIATION(85, L"Different DBKINDs for pTableID")
TEST_VARIATION(86, L"Different DBKINDs for column IDs")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(RODataSource)
//--------------------------------------------------------------------
// @class Test case for operating on a read only data source
//
class RODataSource : public TCDropColumn {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
IUnknown *m_pIUnknown;
IUnknown *m_pIUnknown2;
ITableDefinition *m_pITableDefinition2;
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(RODataSource,TCDropColumn);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Add a column
int Variation_1();
// @cmember Drop a column
int Variation_2();
// @cmember Create a table
int Variation_3();
// @cmember Drop a table
int Variation_4();
// }} TCW_TESTVARS_END
} ;
// {{ TCW_TESTCASE(RODataSource)
#define THE_CLASS RODataSource
BEG_TEST_CASE(RODataSource, TCDropColumn, L"Test case for operating on a read only data source")
TEST_VARIATION(1, L"Add a column")
TEST_VARIATION(2, L"Drop a column")
TEST_VARIATION(3, L"Create a table")
TEST_VARIATION(4, L"Drop a table")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCAddConstraint_Boundary)
//*-----------------------------------------------------------------------
// @class General and boundary/null test for ITableDefinitionWithConstraints::AddConstraint
//
class TCAddConstraint_Boundary : public TCITableDefinition {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCAddConstraint_Boundary,TCITableDefinition);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Check the session object (QI for interfaces)
int Variation_1();
// @cmember pTableID is NULL => E_INVALIDARG
int Variation_2();
// @cmember *pTableID is DB_NULLID => DB_E_NOTABLE
int Variation_3();
// @cmember Table name is NULL => DB_E_NOTABLE
int Variation_4();
// @cmember Table name is the empty string => DB_E_NOTABLE
int Variation_5();
// @cmember Table name has maximum length
int Variation_6();
// @cmember Table name exceeds maximum length => DB_E_NOTABLE
int Variation_7();
// @cmember Table name contains illegal characters
int Variation_8();
// @cmember Invalid DBKIND value for the base table
int Variation_9();
// @cmember NULL column list in a constraint, column size is not 0 => E_INVALIDARG
int Variation_10();
// @cmember NULL column name in a constraint
int Variation_11();
// @cmember Empty string for a column name
int Variation_12();
// @cmember Maximum length column name in a constraint
int Variation_13();
// @cmember Column name exceeds maximum length
int Variation_14();
// @cmember Invalid DBKIND for a column DBID of a constraint
int Variation_15();
// @cmember Column ID is DB_NULLID
int Variation_16();
// @cmember NULL pReferencedTableID for a foreign key constraint (with and without cForeignKeyColumns being 0)
int Variation_17();
// @cmember DBNULL_ID *pReferencedTableID for a foreign key constraint
int Variation_18();
// @cmember NULL referenced table name for a foreign key constraint
int Variation_19();
// @cmember Emptry string referenced table name for a foreign key constraint
int Variation_20();
// @cmember Maximum length referenced table name for a foreign key constraint
int Variation_21();
// @cmember Referenced table name longer than allowed for a foreign key constraint
int Variation_22();
// @cmember Illegal characters in the referenced table name for a foreign key constraint
int Variation_23();
// @cmember Bad constraint type
int Variation_24();
// @cmember Empty list of columns for a unique, primay key or foreign key constraint
int Variation_25();
// @cmember Non empty list of columns for a check constraint
int Variation_26();
// @cmember Not null pwszConstraintText in a unique, PK or FK constraint
int Variation_27();
// @cmember NULL pConstraintDesc => E_INVALIDARG
int Variation_28();
// @cmember 0 < cColumns and NULL == rgColumnList => E_INVALIDARG
int Variation_29();
// @cmember 0 < cForeignKeyColumns and NULL == rgForeignKeyColumnList => E_INVALIDARG
int Variation_30();
// @cmember Constraint is not foreign key and pReferencedTableID is not NULL
int Variation_31();
// @cmember Non empty list of foreign keys for a constraint that is not foreign key
int Variation_32();
// @cmember Inexistent referenced table
int Variation_33();
// @cmember Add several constraints to the table
int Variation_34();
// @cmember Inexistent table name => DB_E_NOTABLE
int Variation_35();
// @cmember Inexistent column name => DB_E_NOCOLUMN
int Variation_36();
// }} TCW_TESTVARS_END
} ;
// {{ TCW_TESTCASE(TCAddConstraint_Boundary)
#define THE_CLASS TCAddConstraint_Boundary
BEG_TEST_CASE(TCAddConstraint_Boundary, TCITableDefinition, L"General and boundary/null test for ITableDefinitionWithConstraints::AddConstraint")
TEST_VARIATION(1, L"Check the session object (QI for interfaces)")
TEST_VARIATION(2, L"pTableID is NULL => E_INVALIDARG")
TEST_VARIATION(3, L"*pTableID is DB_NULLID => DB_E_NOTABLE")
TEST_VARIATION(4, L"Table name is NULL => DB_E_NOTABLE")
TEST_VARIATION(5, L"Table name is the empty string => DB_E_NOTABLE")
TEST_VARIATION(6, L"Table name has maximum length")
TEST_VARIATION(7, L"Table name exceeds maximum length => DB_E_NOTABLE")
TEST_VARIATION(8, L"Table name contains illegal characters")
TEST_VARIATION(9, L"Invalid DBKIND value for the base table")
TEST_VARIATION(10, L"NULL column list in a constraint, column size is not 0 => E_INVALIDARG")
TEST_VARIATION(11, L"NULL column name in a constraint")
TEST_VARIATION(12, L"Empty string for a column name")
TEST_VARIATION(13, L"Maximum length column name in a constraint")
TEST_VARIATION(14, L"Column name exceeds maximum length")
TEST_VARIATION(15, L"Invalid DBKIND for a column DBID of a constraint")
TEST_VARIATION(16, L"Column ID is DB_NULLID")
TEST_VARIATION(17, L"NULL pReferencedTableID for a foreign key constraint (with and without cForeignKeyColumns being 0)")
TEST_VARIATION(18, L"DBNULL_ID *pReferencedTableID for a foreign key constraint")
TEST_VARIATION(19, L"NULL referenced table name for a foreign key constraint")
TEST_VARIATION(20, L"Emptry string referenced table name for a foreign key constraint")
TEST_VARIATION(21, L"Maximum length referenced table name for a foreign key constraint")
TEST_VARIATION(22, L"Referenced table name longer than allowed for a foreign key constraint")
TEST_VARIATION(23, L"Illegal characters in the referenced table name for a foreign key constraint")
TEST_VARIATION(24, L"Bad constraint type")
TEST_VARIATION(25, L"Empty list of columns for a unique, primay key or foreign key constraint")
TEST_VARIATION(26, L"Non empty list of columns for a check constraint")
TEST_VARIATION(27, L"Not null pwszConstraintText in a unique, PK or FK constraint")
TEST_VARIATION(28, L"NULL pConstraintDesc => E_INVALIDARG")
TEST_VARIATION(29, L"0 < cColumns and NULL == rgColumnList => E_INVALIDARG")
TEST_VARIATION(30, L"0 < cForeignKeyColumns and NULL == rgForeignKeyColumnList => E_INVALIDARG")
TEST_VARIATION(31, L"Constraint is not foreign key and pReferencedTableID is not NULL")
TEST_VARIATION(32, L"Non empty list of foreign keys for a constraint that is not foreign key")
TEST_VARIATION(33, L"Inexistent referenced table")
TEST_VARIATION(34, L"Add several constraints to the table")
TEST_VARIATION(35, L"Inexistent table name => DB_E_NOTABLE")
TEST_VARIATION(36, L"Inexistent column name => DB_E_NOCOLUMN")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCAddConstraint_UNIQUE)
//*-----------------------------------------------------------------------
// @class Testcase for ITableDefinitionWithConstraints::AddConstraint used with DBCONSTRAINTTYPE_UNIQUE
//
class TCAddConstraint_UNIQUE : public TCITableDefinition {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCAddConstraint_UNIQUE,TCITableDefinition);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Create a table and try to apply the constraint on each column
int Variation_1();
// @cmember Set a unique constraint on each type of column
int Variation_2();
// @cmember Create a unique constraint that uses several columns
int Variation_3();
// @cmember Create several unique constraints on a table, no overlapping
int Variation_4();
// @cmember Create multiple, overlapping constraints on a table
int Variation_5();
// @cmember Create a constraint, drop it and recreate it
int Variation_6();
// @cmember Create a constraint on a null column
int Variation_7();
// @cmember Create a contraint on a not nullable column
int Variation_8();
// @cmember Create a constraint on a column that has a default value
int Variation_9();
// @cmember Create a constraint on a column defined as a primary key
int Variation_10();
// @cmember Create a constraint on a column defined as a foreign key
int Variation_11();
// @cmember Create a constraint on a column that is included in an index
int Variation_12();
// @cmember Use the name of an already existing constraint
int Variation_13();
// @cmember Constraint is created in a different catalog
int Variation_14();
// @cmember create a unique constraint on a non empty table
int Variation_15();
// @cmember Create a unique constraints on a column that has doubled values
int Variation_16();
// @cmember Abort retaining
int Variation_17();
// @cmember Abort non retaining
int Variation_18();
// @cmember Commit retaining
int Variation_19();
// @cmember Commit non retaining
int Variation_20();
// @cmember Maximum columns allowed in Unique constraint
int Variation_21();
// }} TCW_TESTVARS_END
} ;
// {{ TCW_TESTCASE(TCAddConstraint_UNIQUE)
#define THE_CLASS TCAddConstraint_UNIQUE
BEG_TEST_CASE(TCAddConstraint_UNIQUE, TCITableDefinition, L"Testcase for ITableDefinitionWithConstraints::AddConstraint used with DBCONSTRAINTTYPE_UNIQUE")
TEST_VARIATION(1, L"Create a table and try to apply the constraint on each column")
TEST_VARIATION(2, L"Set a unique constraint on each type of column")
TEST_VARIATION(3, L"Create a unique constraint that uses several columns")
TEST_VARIATION(4, L"Create several unique constraints on a table, no overlapping")
TEST_VARIATION(5, L"Create multiple, overlapping constraints on a table")
TEST_VARIATION(6, L"Create a constraint, drop it and recreate it")
TEST_VARIATION(7, L"Create a constraint on a null column")
TEST_VARIATION(8, L"Create a contraint on a not nullable column")
TEST_VARIATION(9, L"Create a constraint on a column that has a default value")
TEST_VARIATION(10, L"Create a constraint on a column defined as a primary key")
TEST_VARIATION(11, L"Create a constraint on a column defined as a foreign key")
TEST_VARIATION(12, L"Create a constraint on a column that is included in an index")
TEST_VARIATION(13, L"Use the name of an already existing constraint")
TEST_VARIATION(14, L"Constraint is created in a different catalog")
TEST_VARIATION(15, L"create a unique constraint on a non empty table")
TEST_VARIATION(16, L"Create a unique constraints on a column that has doubled values")
TEST_VARIATION(17, L"Abort retaining")
TEST_VARIATION(18, L"Abort non retaining")
TEST_VARIATION(19, L"Commit retaining")
TEST_VARIATION(20, L"Commit non retaining")
TEST_VARIATION(21, L"Maximum columns allowed in unique constraint")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCAddConstraint_PRIMARYKEY)
//*-----------------------------------------------------------------------
// @class Testcase for ITableDefinitionWithConstraints::AddConstraint used with DBCONSTRAINTTYPE_PRIMARYKEY
//
class TCAddConstraint_PRIMARYKEY : public TCITableDefinition {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCAddConstraint_PRIMARYKEY,TCITableDefinition);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Create a table and try to apply the constraint on each column
int Variation_1();
// @cmember Set a primary key constraint on each type of column
int Variation_2();
// @cmember Create a primary key constraint. Drop it. Create a primary key using the same name as before.
int Variation_3();
// @cmember Create multiple-columned primary key
int Variation_4();
// @cmember Create multiple primary key constraints using successive calls
int Variation_5();
// @cmember Successive calls, lists of columns overlap
int Variation_6();
// @cmember Primary key constraint on a nullable column
int Variation_7();
// @cmember Primary key constraint on a not nullable column
int Variation_8();
// @cmember Primary key constraint on a column with a default value
int Variation_9();
// @cmember Primary key constraint on a column defined as unique
int Variation_10();
// @cmember Primary key constraint on a column defined as primary key => DB_E_DUPLICATECONSTRAINTID
int Variation_11();
// @cmember Primary key constraint on a column that already has a primary key constraint
int Variation_12();
// @cmember Primary key constraint on a column that is part of a foreign key constraint
int Variation_13();
// @cmember Primary key constraint on a column that is part of an index
int Variation_14();
// @cmember Primary key constraint on a column on a not empty table
int Variation_15();
// @cmember Primary key constraint on a column that already has duplicates (for the whole key)
int Variation_16();
// @cmember Primary key constraint that has duplicates for a column in the key, but not for the whole key
int Variation_17();
// @cmember Abort retaining
int Variation_18();
// @cmember Abort non retaining
int Variation_19();
// @cmember Commit retaining
int Variation_20();
// @cmember Commit non retaining
int Variation_21();
// @cmember Create PK in different catalog
int Variation_22();
// @cmember Find maximum limit on PKs
int Variation_23();
// }} TCW_TESTVARS_END
} ;
// {{ TCW_TESTCASE(TCAddConstraint_PRIMARYKEY)
#define THE_CLASS TCAddConstraint_PRIMARYKEY
BEG_TEST_CASE(TCAddConstraint_PRIMARYKEY, TCITableDefinition, L"Testcase for ITableDefinitionWithConstraints::AddConstraint used with DBCONSTRAINTTYPE_PRIMARYKEY")
TEST_VARIATION(1, L"Create a table and try to apply the constraint on each column")
TEST_VARIATION(2, L"Set a primary key constraint on each type of column")
TEST_VARIATION(3, L"Create a primary key constraint. Drop it. Create a primary key using the same name as before.")
TEST_VARIATION(4, L"Create multiple-columned primary key")
TEST_VARIATION(5, L"Create multiple primary key constraints using successive calls")
TEST_VARIATION(6, L"Successive calls, lists of columns overlap")
TEST_VARIATION(7, L"Primary key constraint on a nullable column -> E_FAIL")
TEST_VARIATION(8, L"Primary key constraint on a not nullable column")
TEST_VARIATION(9, L"Primary key constraint on a column with a default value")
TEST_VARIATION(10, L"Primary key constraint on a column defined as unique")
TEST_VARIATION(11, L"Primary key constraint on a column defined as primary key => DB_E_DUPLICATECONSTRAINTID")
TEST_VARIATION(12, L"Primary key constraint on a column that already has a primary key constraint")
TEST_VARIATION(13, L"Primary key constraint on a column that is part of a foreign key constraint")
TEST_VARIATION(14, L"Primary key constraint on a column that is part of an index")
TEST_VARIATION(15, L"Primary key constraint on a column on a not empty table")
TEST_VARIATION(16, L"Primary key constraint on a column that already has duplicates (for the whole key)")
TEST_VARIATION(17, L"Primary key constraint that has duplicates for a column in the key, but not for the whole key")
TEST_VARIATION(18, L"Abort retaining")
TEST_VARIATION(19, L"Abort non retaining")
TEST_VARIATION(20, L"Commit retaining")
TEST_VARIATION(21, L"Commit non retaining")
TEST_VARIATION(22, L"Create primary key in a different catalog")
TEST_VARIATION(23, L"Find how many columns are supported in a PK")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCAddConstraint_FOREIGNKEY)
//*-----------------------------------------------------------------------
// @class Testcase for ITableDefinitionWithConstraints::AddConstraint used with DBCONSTRAINTTYPE_FOREIGNKEY
//
class TCAddConstraint_FOREIGNKEY : public TCITableDefinition {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
CTable *m_pReferenceTable;
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCAddConstraint_FOREIGNKEY,TCITableDefinition);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Simple foreign key constraint
int Variation_1();
// @cmember Foregin key is made of several columns
int Variation_2();
// @cmember Multiple foreign key constraints on a table
int Variation_3();
// @cmember Multiple overlapping foreign key constraints
int Variation_4();
// @cmember Create a foreign key on each column of the table
int Variation_5();
// @cmember Create a foreign key on all columns
int Variation_6();
// @cmember Create foreign key and try to drop the reference table
int Variation_7();
// @cmember On a nullable column
int Variation_8();
// @cmember On a not nullable column
int Variation_9();
// @cmember On a column having a default value
int Variation_10();
// @cmember On a column defined as unique
int Variation_11();
// @cmember On a primary key column
int Variation_12();
// @cmember On a column that is part of the index
int Variation_13();
// @cmember On a table that is in another catalog
int Variation_14();
// @cmember Use different combination for update/delete rules, as well as match type
int Variation_15();
// @cmember Referenced table name and base table names have maximum length
int Variation_16();
// @cmember Columns in the foreign key (base table and reference table) have different names
int Variation_17();
// @cmember Different size in column lists (base table and referenced)
int Variation_18();
// @cmember Column types in base table and reference table are different
int Variation_19();
// @cmember Invalid value for the update rule
int Variation_20();
// @cmember Invalid value for the delete rule
int Variation_21();
// @cmember Invalid value for the MatchType
int Variation_22();
// @cmember Inexistent column names in the referenced table
int Variation_23();
// @cmember Inexistent column name in the base table
int Variation_24();
// @cmember Inexistent base table
int Variation_25();
// @cmember Inexistent reference table
int Variation_26();
// @cmember NULL pConstraintID
int Variation_27();
// @cmember Referenced col list is not a unique / pk constraint => failure
int Variation_28();
// @cmember Create a foreign key and then insert a NULL value for one of the fk columns
int Variation_29();
// @cmember The referenced table and the base table are the same
int Variation_30();
// @cmember The base and referenced tables are temporary tables
int Variation_31();
// @cmember Base table is a temporary table
int Variation_32();
// @cmember Abort retaining
int Variation_33();
// @cmember Abort non retaining
int Variation_34();
// @cmember Commit retaining
int Variation_35();
// @cmember Commit non retaining
int Variation_36();
// @cmember The base table is already populated and the referenced one is empty => DB_E_SCHEMAVIOLATION
int Variation_37();
// @cmember Find maximum columns allowed in foreign keys
int Variation_38();
// }} TCW_TESTVARS_END
} ;
// {{ TCW_TESTCASE(TCAddConstraint_FOREIGNKEY)
#define THE_CLASS TCAddConstraint_FOREIGNKEY
BEG_TEST_CASE(TCAddConstraint_FOREIGNKEY, TCITableDefinition, L"Testcase for ITableDefinitionWithConstraints::AddConstraint used with DBCONSTRAINTTYPE_FOREIGNKEY")
TEST_VARIATION(1, L"Simple foreign key constraint")
TEST_VARIATION(2, L"Foregin key is made of several columns")
TEST_VARIATION(3, L"Multiple foreign key constraints on a table")
TEST_VARIATION(4, L"Multiple overlapping foreign key constraints")
TEST_VARIATION(5, L"Create a foreign key on each column of the table")
TEST_VARIATION(6, L"Create a foreign key on all columns")
TEST_VARIATION(7, L"Create foreign key and try to drop the reference table")
TEST_VARIATION(8, L"On a nullable column")
TEST_VARIATION(9, L"On a not nullable column")
TEST_VARIATION(10, L"On a column having a default value")
TEST_VARIATION(11, L"On a column defined as unique")
TEST_VARIATION(12, L"On a primary key column")
TEST_VARIATION(13, L"On a column that is part of the index")
TEST_VARIATION(14, L"On a table that is in another catalog")
TEST_VARIATION(15, L"Use different combination for update/delete rules, as well as match type")
TEST_VARIATION(16, L"Referenced table name and base table names have maximum length")
TEST_VARIATION(17, L"Columns in the foreign key (base table and reference table) have different names")
TEST_VARIATION(18, L"Different size in column lists (base table and referenced)")
TEST_VARIATION(19, L"Column types in base table and reference table are different")
TEST_VARIATION(20, L"Invalid value for the update rule")
TEST_VARIATION(21, L"Invalid value for the delete rule")
TEST_VARIATION(22, L"Invalid value for the MatchType")
TEST_VARIATION(23, L"Inexistent column names in the referenced table")
TEST_VARIATION(24, L"Inexistent column name in the base table")
TEST_VARIATION(25, L"Inexistent base table")
TEST_VARIATION(26, L"Inexistent reference table")
TEST_VARIATION(27, L"NULL pConstraintID")
TEST_VARIATION(28, L"Referenced col list is not a unique / pk constraint => failure")
TEST_VARIATION(29, L"Create a foreign key and then insert a NULL value for one of the fk columns")
TEST_VARIATION(30, L"The referenced table and the base table are the same")
TEST_VARIATION(31, L"The base and referenced tables are temporary tables")
TEST_VARIATION(32, L"Base table is a temporary table")
TEST_VARIATION(33, L"Abort retaining")
TEST_VARIATION(34, L"Abort non retaining")
TEST_VARIATION(35, L"Commit retaining")
TEST_VARIATION(36, L"Commit non retaining")
TEST_VARIATION(37, L"The base table is already populated and the referenced one is empty => DB_E_SCHEMAVIOLATION")
TEST_VARIATION(38, L"Find maximum columns allowed in foreign keys")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCAddConstraint_CHECK)
//*-----------------------------------------------------------------------
// @class Testcase for ITableDefinitionWithConstraints::AddConstraint used with DBCONSTRAINTTYPE_UNIQUE
//
class TCAddConstraint_CHECK : public TCITableDefinition {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCAddConstraint_CHECK,TCITableDefinition);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Add simple check constraint
int Variation_1();
// @cmember Add 2 check constraints on the same column
int Variation_2();
// @cmember Add check constraint for each column
int Variation_3();
// @cmember Check constraint is always TRUE
int Variation_4();
// @cmember Check constraint is always false
int Variation_5();
// @cmember Long text for the check constraint
int Variation_6();
// @cmember Check constraint is made of white characters
int Variation_7();
// @cmember Maximum length for the table name
int Variation_8();
// @cmember Create the constraint, drop it, readd it with different text
int Variation_9();
// @cmember Use inexistent column names in the check constraint
int Variation_10();
// @cmember Use qualified table column with different table
int Variation_11();
// @cmember Set a check condition on an index column
int Variation_12();
// @cmember pwszConstraintText is NULL
int Variation_13();
// @cmember pwszConstraintText is an empty string
int Variation_14();
// @cmember Abort retaining
int Variation_15();
// @cmember Abort non retaining
int Variation_16();
// @cmember Commit retaining
int Variation_17();
// @cmember Commit non retaining
int Variation_18();
// @cmember Table is populated with rows that break the constraint to be added => DB_E_SCHEMAVIOLATION
int Variation_19();
// @cmember Create check constraint in different catalog
int Variation_20();
// }} TCW_TESTVARS_END
} ;
// {{ TCW_TESTCASE(TCAddConstraint_CHECK)
#define THE_CLASS TCAddConstraint_CHECK
BEG_TEST_CASE(TCAddConstraint_CHECK, TCITableDefinition, L"Testcase for ITableDefinitionWithConstraints::AddConstraint used with DBCONSTRAINTTYPE_UNIQUE")
TEST_VARIATION(1, L"Add simple check constraint")
TEST_VARIATION(2, L"Add 2 check constraints on the same column")
TEST_VARIATION(3, L"Add check constraint for each column")
TEST_VARIATION(4, L"Check constraint is always TRUE")
TEST_VARIATION(5, L"Check constraint is always false")
TEST_VARIATION(6, L"Long text for the check constraint")
TEST_VARIATION(7, L"Check constraint is made of white characters")
TEST_VARIATION(8, L"Maximum length for the table name")
TEST_VARIATION(9, L"Create the constraint, drop it, readd it with different text")
TEST_VARIATION(10, L"Use inexistent column names in the check constraint")
TEST_VARIATION(11, L"Use qualified table column with different table")
TEST_VARIATION(12, L"Set a check condition on an index column")
TEST_VARIATION(13, L"pwszConstraintText is NULL")
TEST_VARIATION(14, L"pwszConstraintText is an empty string")
TEST_VARIATION(15, L"Abort retaining")
TEST_VARIATION(16, L"Abort non retaining")
TEST_VARIATION(17, L"Commit retaining")
TEST_VARIATION(18, L"Commit non retaining")
TEST_VARIATION(19, L"Table is populated with rows that break the constraint to be added => DB_E_SCHEMAVIOLATION")
TEST_VARIATION(20, L"Check constraint is created on a table in different catalog")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCAddConstraint_Deferrability)
//*-----------------------------------------------------------------------
// @class Testcase for ITableDefinitionWithConstraints::AddConstraint used with deferrability setting
//
class TCAddConstraint_Deferrability : public TCITableDefinition {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCAddConstraint_Deferrability,TCITableDefinition);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Immediate unique constraint
int Variation_1();
// @cmember Defferable unique constraint
int Variation_2();
// @cmember Deffered unique constraint
int Variation_3();
// @cmember Bad deferrability value unique constraint
int Variation_4();
// @cmember Immediate primary key constraint
int Variation_5();
// @cmember Deferrable primary key constraint
int Variation_6();
// @cmember Deferred primary key constraint
int Variation_7();
// @cmember Bad deferrability value primary key constraint
int Variation_8();
// @cmember Immediate foreign key constraint
int Variation_9();
// @cmember Deferrable foreign key constraint
int Variation_10();
// @cmember Deferred foreign key constraint
int Variation_11();
// @cmember Bad deferrability value foreign key constraint
int Variation_12();
// @cmember Immediate check constraint
int Variation_13();
// @cmember Deferrable check constraint
int Variation_14();
// @cmember Deferred check constraint
int Variation_15();
// @cmember Bad deferrability value check constraint
int Variation_16();
// }} TCW_TESTVARS_END
} ;
// {{ TCW_TESTCASE(TCAddConstraint_Deferrability)
#define THE_CLASS TCAddConstraint_Deferrability
BEG_TEST_CASE(TCAddConstraint_Deferrability, TCITableDefinition, L"Testcase for ITableDefinitionWithConstraints::AddConstraint used with deferrability setting")
TEST_VARIATION(1, L"Immediate unique constraint")
TEST_VARIATION(2, L"Defferable unique constraint")
TEST_VARIATION(3, L"Deffered unique constraint")
TEST_VARIATION(4, L"Bad deferrability value unique constraint")
TEST_VARIATION(5, L"Immediate primary key constraint")
TEST_VARIATION(6, L"Deferrable primary key constraint")
TEST_VARIATION(7, L"Deferred primary key constraint")
TEST_VARIATION(8, L"Bad deferrability value primary key constraint")
TEST_VARIATION(9, L"Immediate foreign key constraint")
TEST_VARIATION(10, L"Deferrable foreign key constraint")
TEST_VARIATION(11, L"Deferred foreign key constraint")
TEST_VARIATION(12, L"Bad deferrability value foreign key constraint")
TEST_VARIATION(13, L"Immediate check constraint")
TEST_VARIATION(14, L"Deferrable check constraint")
TEST_VARIATION(15, L"Deferred check constraint")
TEST_VARIATION(16, L"Bad deferrability value check constraint")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCCreateTableWithConstraints_NoConstraint)
//*-----------------------------------------------------------------------
// @class Testcase for ITableDefinitionWithConstraints::AddConstraint used with deferrability setting
//
class TCCreateTableWithConstraints_NoConstraint : public TCCreateTable {
public:
//DECLARE_TEST_CASE_DATA();
ITableDefinitionWithConstraints *m_pITableDefinitionWithConstraints;
public:
static const WCHAR m_wszTestCaseName[];
static const WCHAR m_wszTestCaseDesc[];
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCCreateTableWithConstraints_NoConstraint,TCCreateTable);
// }} TCW_DECLARE_FUNCS_END
// @member Create the table using ITableDefinition::CreateTable and check its creation
virtual HRESULT CreateAndCheckTable(
ITableDefinition *pITableDefinitionWithConstraints, // [in] pointer to the ITableDefinition interface to be used
IUnknown *pUnkOuter, // [in] pointer to controlling unknown
DBID *pTableID, // [in] pointer to the input table ID
DBORDINAL cColumnDescs, // [in] the number of columns to be created
DBCOLUMNDESC *rgColumnDesc, // [in/out] array of columns to be created
REFIID riid, // [in] rowset interface to be returned
ULONG cPropertySets, // [in] number of roset property sets asked
DBPROPSET *rgPropertySets, // [in/out] array of rowset property sets
DBID **ppTableID, // [out] returned table ID
IUnknown **ppRowset // [out] pointer to outer interface
);
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// }} TCW_TESTVARS_END
} ;
// {{ TCW_TESTCASE(TCCreateTableWithConstraints_NoConstraint)
//#define THE_CLASS TCCreateTableWithConstraints_NoConstraint
//BEG_TEST_CASE(TCCreateTableWithConstraints_NoConstraint, TCCreateTable, L"Testcase for ITableDefinitionWithConstraints::AddConstraint used with deferrability setting")
//END_TEST_CASE()
//#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
const WCHAR TCCreateTableWithConstraints_NoConstraint::m_wszTestCaseName[] = { L"TCCreateTableWithConstraints_NoConstraint" };
const WCHAR TCCreateTableWithConstraints_NoConstraint::m_wszTestCaseDesc[] = { L"Testcase for ITableDefinitionWithConstraints::CreateTable when no constraints are specified => should expect the same results as for ITableDefinition::CreateTable" };
// {{ TCW_TEST_CASE_MAP(TCCreateTableWithConstraints)
//*-----------------------------------------------------------------------
// @class Testcase for ITableDefinitionWithConstraints::CreateTableWithConstraints when constraints are set
//
class TCCreateTableWithConstraints : public TCITableDefinition {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCCreateTableWithConstraints,TCITableDefinition);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Create a table and multiple constraint of various types
int Variation_1();
// @cmember Table with a unique constraint (on a single column)
int Variation_2();
// @cmember Table with a unique constraint (on multiple columns)
int Variation_3();
// @cmember Table with a primary key constraint (on a single column)
int Variation_4();
// @cmember Table with a primary key constraint (on multiple columns)
int Variation_5();
// @cmember Table with a foreign key constraint (single column)
int Variation_6();
// @cmember Table with foreign key constraint defined on multiple keys
int Variation_7();
// @cmember Table with a simple check constraint
int Variation_8();
// @cmember Table with multiple unique constraints defined
int Variation_9();
// @cmember Table with unique constraint and foreign key
int Variation_10();
// @cmember Table with primary key and check constraint
int Variation_11();
// @cmember Deferrable, immediate constraints
int Variation_12();
// @cmember Deferred constraints
int Variation_13();
// @cmember Abort retain
int Variation_14();
// @cmember Abort non retain
int Variation_15();
// @cmember Commit retain
int Variation_16();
// @cmember Commit non retain
int Variation_17();
// }} TCW_TESTVARS_END
} ;
// {{ TCW_TESTCASE(TCCreateTableWithConstraints)
#define THE_CLASS TCCreateTableWithConstraints
BEG_TEST_CASE(TCCreateTableWithConstraints, TCITableDefinition, L"Testcase for ITableDefinitionWithConstraints::CreateTableWithConstraints when constraints are set")
TEST_VARIATION(1, L"Create a table and multiple constraint of various types")
TEST_VARIATION(2, L"Table with a unique constraint (on a single column)")
TEST_VARIATION(3, L"Table with a unique constraint (on multiple columns)")
TEST_VARIATION(4, L"Table with a primary key constraint (on a single column)")
TEST_VARIATION(5, L"Table with a primary key constraint (on multiple columns)")
TEST_VARIATION(6, L"Table with a foreign key constraint (single column)")
TEST_VARIATION(7, L"Table with foreign key constraint defined on multiple keys")
TEST_VARIATION(8, L"Table with a simple check constraint")
TEST_VARIATION(9, L"Table with multiple unique constraints defined")
TEST_VARIATION(10, L"Table with unique constraint and foreign key")
TEST_VARIATION(11, L"Table with primary key and check constraint")
TEST_VARIATION(12, L"Deferrable, immediate constraints")
TEST_VARIATION(13, L"Deferred constraints")
TEST_VARIATION(14, L"Abort retain")
TEST_VARIATION(15, L"Abort non retain")
TEST_VARIATION(16, L"Commit retain")
TEST_VARIATION(17, L"Commit non retain")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCCreateTableWithConstraints_Boundary)
//*-----------------------------------------------------------------------
// @class Boundary and NULL testcase for ITableDefinitionWithConstraints::CreateTableWithConstraints
//
class TCCreateTableWithConstraints_Boundary : public TCITableDefinition {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCCreateTableWithConstraints_Boundary,TCITableDefinition);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember 0 < cConstraintDescs and NULL == rgConstraintDescs => E_INVALIDARG
int Variation_1();
// @cmember 0 == cConstraintDescs and NULL != rgConstraintDescs => S_OK
int Variation_2();
// @cmember pTableID is NULL ppTableID is not NULL => S_OK
int Variation_3();
// @cmember Bad DBKIND of a constraint ID
int Variation_4();
// @cmember NULL pConstraintID in a constraint
int Variation_5();
// @cmember NULL column list in a constraint, column size is not 0 => E_INVALIDARG
int Variation_6();
// @cmember Empty list of columns for a unique, primay key or foreign key constraint
int Variation_7();
// @cmember Non empty list of columns for a check constraint
int Variation_8();
// @cmember Non empty list of foreign keys for a constraint that is not foreign key
int Variation_9();
// @cmember 0 < cForeignKeyColumns and NULL == rgForeignKeyColumnList => E_INVALIDARG
int Variation_10();
// @cmember Constraint is not foreign key and pReferencedTableID is not NULL
int Variation_11();
// @cmember NULL pReferencedTableID for a foreign key constraint (with and without cForeignKeyColumns being 0)
int Variation_12();
// @cmember NULL referenced table name for a foreign key constraint
int Variation_13();
// @cmember DB_NULLID *pReferencedTableID for a foreign key constraint
int Variation_14();
// @cmember Empty string referenced table name for a foreign key constraint
int Variation_15();
// @cmember Maximum length referenced table name for a foreign key constraint
int Variation_16();
// @cmember Referenced table name longer than allowed for a foreign key constraint
int Variation_17();
// @cmember Illegal characters in the referenced table name for a foreign key constraint
int Variation_18();
// @cmember Bad constraint type
int Variation_19();
// @cmember Inexistent referenced table
int Variation_20();
// @cmember Empty string for a column name
int Variation_21();
// @cmember Maximum length column name in a constraint
int Variation_22();
// @cmember Invalid DBKIND for a column DBID of a constraint
int Variation_23();
// @cmember Column ID is DB_NULLID
int Variation_24();
// @cmember Inexistent column => DB_E_NOCOLUMN
int Variation_25();
// @cmember NULL column name => DB_E_NOCOLUMN
int Variation_26();
// @cmember Column name exceeds maximum length name
int Variation_27();
// @cmember Invalid column name
int Variation_28();
// @cmember Existent table name => DB_E_DUPLICATETABLEID
int Variation_29();
// @cmember Same constraint name in 2 constraints => DB_E_DUPLICATECONSTRAINTID
int Variation_30();
// @cmember NULL pConstraintID in 2 constraints => S_OK
int Variation_31();
// @cmember Try to create table with constraints, but table already exists => DB_E_DUPLICATEDTABLEID
int Variation_32();
// }} TCW_TESTVARS_END
} ;
// {{ TCW_TESTCASE(TCCreateTableWithConstraints_Boundary)
#define THE_CLASS TCCreateTableWithConstraints_Boundary
BEG_TEST_CASE(TCCreateTableWithConstraints_Boundary, TCITableDefinition, L"Boundary and NULL testcase for ITableDefinitionWithConstraints::CreateTableWithConstraints")
TEST_VARIATION(1, L"0 < cConstraintDescs and NULL == rgConstraintDescs => E_INVALIDARG")
TEST_VARIATION(2, L"0 == cConstraintDescs and NULL != rgConstraintDescs => S_OK")
TEST_VARIATION(3, L"pTableID is NULL ppTableID is not NULL => S_OK")
TEST_VARIATION(4, L"Bad DBKIND of a constraint ID")
TEST_VARIATION(5, L"NULL pConstraintID in a constraint")
TEST_VARIATION(6, L"NULL column list in a constraint, column size is not 0 => E_INVALIDARG")
TEST_VARIATION(7, L"Empty list of columns for a unique, primay key or foreign key constraint")
TEST_VARIATION(8, L"Non empty list of columns for a check constraint")
TEST_VARIATION(9, L"Non empty list of foreign keys for a constraint that is not foreign key")
TEST_VARIATION(10, L"0 < cForeignKeyColumns and NULL == rgForeignKeyColumnList => E_INVALIDARG")
TEST_VARIATION(11, L"Constraint is not foreign key and pReferencedTableID is not NULL")
TEST_VARIATION(12, L"NULL pReferencedTableID for a foreign key constraint (with and without cForeignKeyColumns being 0)")
TEST_VARIATION(13, L"NULL referenced table name for a foreign key constraint")
TEST_VARIATION(14, L"DB_NULLID *pReferencedTableID for a foreign key constraint")
TEST_VARIATION(15, L"Empty string referenced table name for a foreign key constraint")
TEST_VARIATION(16, L"Maximum length referenced table name for a foreign key constraint")
TEST_VARIATION(17, L"Referenced table name longer than allowed for a foreign key constraint")
TEST_VARIATION(18, L"Illegal characters in the referenced table name for a foreign key constraint")
TEST_VARIATION(19, L"Bad constraint type")
TEST_VARIATION(20, L"Inexistent referenced table")
TEST_VARIATION(21, L"Empty string for a column name")
TEST_VARIATION(22, L"Maximum length column name in a constraint")
TEST_VARIATION(23, L"Invalid DBKIND for a column DBID of a constraint")
TEST_VARIATION(24, L"Column ID is DB_NULLID")
TEST_VARIATION(25, L"Inexistent column => DB_E_NOCOLUMN")
TEST_VARIATION(26, L"NULL column name => DB_E_NOCOLUMN")
TEST_VARIATION(27, L"Column name exceeds maximum length name")
TEST_VARIATION(28, L"Invalid column name")
TEST_VARIATION(29, L"Existent table name => DB_E_DUPLICATETABLEID")
TEST_VARIATION(30, L"Same constraint name in 2 constraints => DB_E_DUPLICATECONSTRAINTID")
TEST_VARIATION(31, L"NULL pConstraintID in 2 constraints => S_OK")
TEST_VARIATION(32, L"Try to create table with constraints, but table already exists => DB_E_DUPLICATEDTABLEID")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCDropConstraint)
//*-----------------------------------------------------------------------
// @class Testcase for ITableDefinitionWithConstraints::DropConstraint
//
class TCDropConstraint : public TCITableDefinition {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCDropConstraint,TCITableDefinition);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember pTableID is NULL => E_INVALIDARG
int Variation_1();
// @cmember pTableID.uName.pwszName is NULL => DB_E_BADTABLEID
int Variation_2();
// @cmember Table name is empty => DB_E_BADTABLEID
int Variation_3();
// @cmember Table name is not the one on which the column was created
int Variation_4();
// @cmember Inexistent table name => DB_E_NOTABLE
int Variation_5();
// @cmember Maximum table name => S_OK
int Variation_6();
// @cmember Invalid characters in table's name => DB_E_BADTABLEID
int Variation_7();
// @cmember pConstraintID is NUL => E_INVALIDARG
int Variation_8();
// @cmember *pConstraintID is DB_NULLID => DB_E_NOCONSTRAINT
int Variation_9();
// @cmember Invalid DBKIND in the constraint name => DB_E_NOCONSTRAINT
int Variation_10();
// @cmember NULL constraint name => DB_E_NOCONSTRAINT
int Variation_11();
// @cmember Constraint name is empty string => DB_E_NOCONSTRAINT
int Variation_12();
// @cmember Inexistent constraint name => DB_E_NOCONSTRAINT
int Variation_13();
// @cmember Drop a constraint twice
int Variation_14();
// @cmember Drop a unique constraint
int Variation_15();
// @cmember Drop a primary key constraint
int Variation_16();
// @cmember Drop a foreign key constraint
int Variation_17();
// @cmember Drop a check constraint
int Variation_18();
// @cmember Create several constraints, drop a single constraint
int Variation_19();
// @cmember Drop a unique constraint in the referenced table, after the foreign key constraint was added
int Variation_20();
// @cmember Try to drop a unique constraint while a rowset is opened on the table => DB_E_TABLEINUSE
int Variation_21();
// @cmember *pTableID is DB_NULLID => DB_E_BADTABLEID
int Variation_22();
// @cmember Invalid DBKIND in pTableID => DB_E_BADTABLEID
int Variation_23();
// @cmember Try to drop a check constraint while a rowset is opened on the table => DB_E_TABLEINUSE
int Variation_24();
// @cmember Try to drop a pk constraint while a rowset is opened on the table => DB_E_TABLEINUSE
int Variation_25();
// @cmember Try to drop a fk constraint while a rowset is opened on the table => DB_E_TABLEINUSE
int Variation_26();
// @cmember Both pTableID and pConstraintID are NULL => E_INVALIDARG
int Variation_27();
// @cmember Abort retain
int Variation_28();
// @cmember Abort non retain
int Variation_29();
// @cmember Commit retain
int Variation_30();
// @cmember Commit non retain
int Variation_31();
// }} TCW_TESTVARS_END
} ;
// {{ TCW_TESTCASE(TCDropConstraint)
#define THE_CLASS TCDropConstraint
BEG_TEST_CASE(TCDropConstraint, TCITableDefinition, L"Testcase for ITableDefinitionWithConstraints::DropConstraint")
TEST_VARIATION(1, L"pTableID is NULL => E_INVALIDARG")
TEST_VARIATION(2, L"pTableID.uName.pwszName is NULL => DB_E_BADTABLEID")
TEST_VARIATION(3, L"Table name is empty => DB_E_BADTABLEID")
TEST_VARIATION(4, L"Table name is not the one on which the column was created")
TEST_VARIATION(5, L"Inexistent table name => DB_E_NOTABLE")
TEST_VARIATION(6, L"Maximum table name => S_OK")
TEST_VARIATION(7, L"Invalid characters in table's name => DB_E_BADTABLEID")
TEST_VARIATION(8, L"pConstraintID is NUL => E_INVALIDARG")
TEST_VARIATION(9, L"*pConstraintID is DB_NULLID => DB_E_NOCONSTRAINT")
TEST_VARIATION(10, L"Invalid DBKIND in the constraint name => DB_E_NOCONSTRAINT")
TEST_VARIATION(11, L"NULL constraint name => DB_E_NOCONSTRAINT")
TEST_VARIATION(12, L"Constraint name is empty string => DB_E_NOCONSTRAINT")
TEST_VARIATION(13, L"Inexistent constraint name => DB_E_NOCONSTRAINT")
TEST_VARIATION(14, L"Drop a constraint twice")
TEST_VARIATION(15, L"Drop a unique constraint")
TEST_VARIATION(16, L"Drop a primary key constraint")
TEST_VARIATION(17, L"Drop a foreign key constraint")
TEST_VARIATION(18, L"Drop a check constraint")
TEST_VARIATION(19, L"Create several constraints, drop a single constraint")
TEST_VARIATION(20, L"Drop a unique constraint in the referenced table, after the foreign key constraint was added")
TEST_VARIATION(21, L"Try to drop a unique constraint while a rowset is opened on the table => DB_E_TABLEINUSE")
TEST_VARIATION(22, L"*pTableID is DB_NULLID => DB_E_BADTABLEID")
TEST_VARIATION(23, L"Invalid DBKIND in pTableID => DB_E_BADTABLEID")
TEST_VARIATION(24, L"Try to drop a check constraint while a rowset is opened on the table => DB_E_TABLEINUSE")
TEST_VARIATION(25, L"Try to drop a pk constraint while a rowset is opened on the table => DB_E_TABLEINUSE")
TEST_VARIATION(26, L"Try to drop a fk constraint while a rowset is opened on the table => DB_E_TABLEINUSE")
TEST_VARIATION(27, L"Both pTableID and pConstraintID are NULL => E_INVALIDARG")
TEST_VARIATION(28, L"Abort retain")
TEST_VARIATION(29, L"Abort non retain")
TEST_VARIATION(30, L"Commit retain")
TEST_VARIATION(31, L"Commit non retain")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCAddConstraint_Multithreading)
//*-----------------------------------------------------------------------
// @class Testcase for ITableDefinitionWithConstraints::AddConstraint used in multithreaded calls
//
class TCAddConstraint_Multithreading : public TCITableDefinition {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
DBID **m_prgTableID;
DBCONSTRAINTDESC *m_rgConstraintDesc;
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCAddConstraint_Multithreading,TCITableDefinition);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Each thread creates a different constraint
int Variation_1();
// @cmember Some of the threads try to create the same constraint name
int Variation_2();
// @cmember Unique constraints with disjoint columns
int Variation_3();
// @cmember Unique constraints with overlapping columns
int Variation_4();
// @cmember All constraint IDs are generated by the provider
int Variation_5();
// }} TCW_TESTVARS_END
unsigned MyThreadProc(ULONG i);
} ;
// {{ TCW_TESTCASE(TCAddConstraint_Multithreading)
#define THE_CLASS TCAddConstraint_Multithreading
BEG_TEST_CASE(TCAddConstraint_Multithreading, TCITableDefinition, L"Testcase for ITableDefinitionWithConstraints::AddConstraint used in multithreaded calls")
TEST_VARIATION(1, L"Each thread creates a different constraint")
TEST_VARIATION(2, L"Some of the threads try to create the same constraint name")
TEST_VARIATION(3, L"Unique constraints with disjoint columns")
TEST_VARIATION(4, L"Unique constraints with overlapping columns")
TEST_VARIATION(5, L"All constraint IDs are generated by the provider")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCDropConstraint_Multithreading)
//*-----------------------------------------------------------------------
// @class Multithreading test case for ITableDefinitionWithConstraints::DropConstraints
//
class TCDropConstraint_Multithreading : public TCITableDefinition {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
DBID **m_prgTableID;
DBID **m_prgConstraintID;
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCDropConstraint_Multithreading,TCITableDefinition);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Each thread drops a different constraint => all S_OK
int Variation_1();
// @cmember Some threads try to drop the same constraint => S_OK and DB_E_NOCONSTRAINT
int Variation_2();
// }} TCW_TESTVARS_END
unsigned MyThreadProc(ULONG i);
} ;
// {{ TCW_TESTCASE(TCDropConstraint_Multithreading)
#define THE_CLASS TCDropConstraint_Multithreading
BEG_TEST_CASE(TCDropConstraint_Multithreading, TCITableDefinition, L"Multithreading test case for ITableDefinitionWithConstraints::DropConstraints")
TEST_VARIATION(1, L"Each thread drops a different constraint => all S_OK")
TEST_VARIATION(2, L"Some threads try to drop the same constraint => S_OK and DB_E_NOCONSTRAINT")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// {{ TCW_TEST_CASE_MAP(TCCreateTableWithConstraints_Multithreading)
//*-----------------------------------------------------------------------
// @class Multithreading test case for ITableDefinitionWithConstraints::CreateTableWithConstraints
//
class TCCreateTableWithConstraints_Multithreading : public TCITableDefinition {
private:
// @cmember Static array of variations
DECLARE_TEST_CASE_DATA();
CCTWCThreadParam *m_rgThreadParams;
public:
// {{ TCW_DECLARE_FUNCS
// @cmember Execution Routine
DECLARE_TEST_CASE_FUNCS(TCCreateTableWithConstraints_Multithreading,TCITableDefinition);
// }} TCW_DECLARE_FUNCS_END
// @cmember Initialization Routine
virtual BOOL Init();
// @cmember Termination Routine
virtual BOOL Terminate();
// {{ TCW_TESTVARS()
// @cmember Each thread builds different table => all S_OK
int Variation_1();
// @cmember Some threads build the same table => S_OK and DB_E_DUPLICATETABLEID
int Variation_2();
// }} TCW_TESTVARS_END
unsigned MyThreadProc(ULONG i);
} ;
// {{ TCW_TESTCASE(TCCreateTableWithConstraints_Multithreading)
#define THE_CLASS TCCreateTableWithConstraints_Multithreading
BEG_TEST_CASE(TCCreateTableWithConstraints_Multithreading, TCITableDefinition, L"Multithreading test case for ITableDefinitionWithConstraints::CreateTableWithConstraints")
TEST_VARIATION(1, L"Each thread builds different table => all S_OK")
TEST_VARIATION(2, L"Some threads build the same table => S_OK and DB_E_DUPLICATETABLEID")
END_TEST_CASE()
#undef THE_CLASS
// }} TCW_TESTCASE_END
// }} TCW_TEST_CASE_MAP_END
// }} END_DECLARE_TEST_CASES()
// {{ TCW_TESTMODULE(ThisModule)
TEST_MODULE(18, ThisModule, gwszModuleDescrip)
TEST_CASE(1, TCAddColumn)
TEST_CASE(2, TCDropColumn)
TEST_CASE(3, TCDropTable)
TEST_CASE(4, TCCreateTable)
TEST_CASE(5, RODataSource)
TEST_CASE(6, TCAddConstraint_Boundary)
TEST_CASE(7, TCAddConstraint_UNIQUE)
TEST_CASE(8, TCAddConstraint_PRIMARYKEY)
TEST_CASE(9, TCAddConstraint_FOREIGNKEY)
TEST_CASE(10, TCAddConstraint_CHECK)
TEST_CASE(11, TCAddConstraint_Deferrability)
TEST_CASE(12, TCCreateTableWithConstraints_NoConstraint)
TEST_CASE(13, TCCreateTableWithConstraints)
TEST_CASE(14, TCCreateTableWithConstraints_Boundary)
TEST_CASE(15, TCDropConstraint)
TEST_CASE(16, TCAddConstraint_Multithreading)
TEST_CASE(17, TCDropConstraint_Multithreading)
TEST_CASE(18, TCCreateTableWithConstraints_Multithreading)
END_TEST_MODULE()
// }} TCW_TESTMODULE_END
class CTransactionAdapter {
public:
CTransactionAdapter() {}
~CTransactionAdapter() {}
virtual BOOL BeforeTransaction() = 0;
virtual HRESULT InsideTransactionScope() = 0;
virtual HRESULT InsideTransactionOnDDLLock() = 0;
virtual BOOL CheckCompletion() = 0;
virtual BOOL CheckRollBack() = 0;
}; //class CTransactionAdapter
class CAddConstraintTxnAdapter: public CTransactionAdapter {
protected:
TCITableDefinition *m_pTCITableDefinition;
CTable m_Table;
CConstraints *m_pConstraints;
CConsDesc *m_pCons;
// m_TransactedTable will be created inside the transaction
CTable m_TransactedTable;
// constraint on transacted table
CConsDesc *m_pTransactedTableCons;
CConstraints *m_pTxnConstraints;
public:
CAddConstraintTxnAdapter(TCITableDefinition *pTCITableDefinition) :
CTransactionAdapter(),
m_pTCITableDefinition(pTCITableDefinition),
m_pConstraints(NULL), m_pCons(NULL),
m_Table(g_pIOpenRowset, (LPWSTR)gwszModuleName),
m_TransactedTable(g_pIOpenRowset, (LPWSTR)gwszModuleName),
m_pTransactedTableCons(NULL),
m_pTxnConstraints(NULL)
{}
~CAddConstraintTxnAdapter() {
m_Table.DropTable();
m_TransactedTable.DropTable();
delete m_pConstraints;
delete m_pCons;
delete m_pTransactedTableCons;
delete m_pTxnConstraints;
}
TCITableDefinition *pTCITableDefinition() {return m_pTCITableDefinition;}
virtual BOOL BeforeTransaction();
virtual HRESULT InsideTransactionScope() {
return m_pTCITableDefinition->AddConstraintAndCheck(
m_pTCITableDefinition->pITDWC(),
&m_Table.GetTableID(), *m_pCons);
}
virtual HRESULT InsideTransactionOnDDLLock() {
return m_pTCITableDefinition->pITDWC()->AddConstraint(
&m_Table.GetTableID(), *m_pCons);
}
virtual BOOL CheckCompletion() {
TBEGIN
BOOL fTableExisted;
ASSERT(m_pCons);
CHECK(m_pConstraints->CheckAddConstraints(1, *m_pCons), S_OK);
// transacted table exists
ASSERT(m_pTransactedTableCons);
CHECK(m_TransactedTable.DoesTableExist(&m_TransactedTable.GetTableID(), &fTableExisted), S_OK);
COMPARE(fTableExisted, TRUE);
CHECK(m_pTxnConstraints->CheckAddConstraints(1, *m_pTransactedTableCons), S_OK);
TRETURN
}
virtual BOOL CheckRollBack() {
TBEGIN
BOOL fTableExisted;
ASSERT(m_pCons);
CHECK(m_pConstraints->AreConstraintsPreserved(), S_OK);
// transacted table does not exist
ASSERT(m_pTransactedTableCons);
CHECK(m_TransactedTable.DoesTableExist(&m_TransactedTable.GetTableID(), &fTableExisted), S_OK);
COMPARE(fTableExisted, FALSE);
CHECK(m_pTxnConstraints->AreConstraintsPreserved(), S_OK);
TRETURN
}
}; //class CAddConstraintTxnAdapter
class CAddUniqueConsTxnAdapter: public CAddConstraintTxnAdapter {
public:
CAddUniqueConsTxnAdapter(TCITableDefinition *pTCITableDefinition):
CAddConstraintTxnAdapter(pTCITableDefinition) {}
~CAddUniqueConsTxnAdapter() {
}
virtual BOOL BeforeTransaction();
virtual HRESULT InsideTransactionScope();
virtual HRESULT InsideTransactionOnDDLLock();
virtual BOOL CheckCompletion();
virtual BOOL CheckRollBack();
}; //class CAddUniqueConsTxnAdapter
class CAddPrimaryKeyConsTxnAdapter: public CAddUniqueConsTxnAdapter {
public:
CAddPrimaryKeyConsTxnAdapter(TCITableDefinition *pTCITableDefinition):
CAddUniqueConsTxnAdapter(pTCITableDefinition)
{}
~CAddPrimaryKeyConsTxnAdapter() {
}
virtual BOOL BeforeTransaction();
}; //class CAddPrimaryKeyConsTxnAdapter
class CAddFKConsTxnAdapter: public CAddConstraintTxnAdapter {
private:
CTable m_ReferencedTable;
public:
CAddFKConsTxnAdapter(TCITableDefinition *pTCITableDefinition):
CAddConstraintTxnAdapter(pTCITableDefinition),
m_ReferencedTable(g_pIOpenRowset, (LPWSTR)gwszModuleName)
{}
~CAddFKConsTxnAdapter() {
m_Table.DropTable();
m_TransactedTable.DropTable();
m_ReferencedTable.DropTable();
}
virtual BOOL BeforeTransaction();
virtual HRESULT InsideTransactionScope();
virtual HRESULT InsideTransactionOnDDLLock();
virtual BOOL CheckCompletion();
virtual BOOL CheckRollBack();
}; //class CAddFKConsTxnAdapter
class CAddCheckConsTxnAdapter: public CAddConstraintTxnAdapter {
public:
CAddCheckConsTxnAdapter(TCITableDefinition *pTCITableDefinition):
CAddConstraintTxnAdapter(pTCITableDefinition)
{}
~CAddCheckConsTxnAdapter() {}
virtual BOOL BeforeTransaction();
virtual HRESULT InsideTransactionScope();
virtual HRESULT InsideTransactionOnDDLLock();
virtual BOOL CheckCompletion();
virtual BOOL CheckRollBack();
}; //class CAddCheckConsTxnAdapter
class CCreateTableWithConsTxnAdapter: public CTransactionAdapter {
protected:
TCITableDefinition *m_pTCITableDefinition;
CTable m_Table;
CConstraints *m_pConstraints;
CConsDescArray m_ConsDescArray;
// m_TransactedTable will be created inside the transaction
CTable m_RefTable;
DBORDINAL m_cColumnDesc;
DBCOLUMNDESC *m_rgColumnDesc;
public:
CCreateTableWithConsTxnAdapter(TCITableDefinition *pTCITableDefinition) :
CTransactionAdapter(),
m_pTCITableDefinition(pTCITableDefinition),
m_pConstraints(NULL),
m_Table(g_pIOpenRowset, (LPWSTR)gwszModuleName),
m_RefTable(g_pIOpenRowset, (LPWSTR)gwszModuleName),
m_cColumnDesc(0), m_rgColumnDesc(NULL)
{}
~CCreateTableWithConsTxnAdapter() {
m_Table.DropTable();
m_RefTable.DropTable();
delete m_pConstraints;
m_pConstraints = NULL;
ReleaseColumnDesc(m_rgColumnDesc, m_cColumnDesc);
}
TCITableDefinition *pTCITableDefinition() {return m_pTCITableDefinition;}
virtual BOOL BeforeTransaction();
virtual HRESULT InsideTransactionScope() {
return m_pTCITableDefinition->CreateAndCheckTableWithConstraints(
m_pTCITableDefinition->pITDWC(),
NULL,
&m_Table.GetTableID(),
m_cColumnDesc,
m_rgColumnDesc,
m_ConsDescArray,
m_ConsDescArray,
IID_NULL,
0, NULL,
NULL,
NULL);
}
virtual HRESULT InsideTransactionOnDDLLock() {
return m_pTCITableDefinition->pITDWC()->CreateTableWithConstraints(
NULL, &m_Table.GetTableID(),
m_cColumnDesc,
m_rgColumnDesc,
m_ConsDescArray,
m_ConsDescArray,
IID_NULL,
0, NULL,
NULL,
NULL);
}
virtual BOOL CheckCompletion() {
TBEGIN
BOOL fTableExisted;
// check constraints were added
CHECK(m_pConstraints->CheckAddConstraints(m_ConsDescArray, m_ConsDescArray), S_OK);
// transacted table exists
CHECK(m_Table.DoesTableExist(&m_Table.GetTableID(), &fTableExisted), S_OK);
COMPARE(fTableExisted, TRUE);
TRETURN
}
virtual BOOL CheckRollBack() {
TBEGIN
BOOL fTableExisted;
CHECK(m_pConstraints->AreConstraintsPreserved(), S_OK);
// transacted table does not exist
CHECK(m_Table.DoesTableExist(&m_Table.GetTableID(), &fTableExisted), S_OK);
COMPARE(fTableExisted, FALSE);
TRETURN
}
}; //class CCreateTableWithConsTxnAdapter
class CDropConsTxnAdapter: public CTransactionAdapter {
protected:
TCITableDefinition *m_pTCITableDefinition;
CTable m_Table;
CTable m_RefTable;
CConstraints *m_pConstraints;
CPrimaryKeyCons *m_pPKCons;
CForeignKeyCons *m_pFKCons;
CUniqueCons *m_pUniqueCons;
CCheckCons *m_pCheckCons;
public:
CDropConsTxnAdapter(TCITableDefinition *pTCITableDefinition) :
CTransactionAdapter(),
m_pTCITableDefinition(pTCITableDefinition),
m_pConstraints(NULL),
m_Table(g_pIOpenRowset, (LPWSTR)gwszModuleName),
m_RefTable(g_pIOpenRowset, (LPWSTR)gwszModuleName),
m_pPKCons(NULL), m_pFKCons(NULL), m_pUniqueCons(NULL), m_pCheckCons(NULL)
{}
~CDropConsTxnAdapter() {
m_Table.DropTable();
m_RefTable.DropTable();
delete m_pConstraints;
delete m_pPKCons;
delete m_pFKCons;
delete m_pUniqueCons;
delete m_pCheckCons;
}
TCITableDefinition *pTCITableDefinition() {return m_pTCITableDefinition;}
virtual BOOL BeforeTransaction();
virtual HRESULT InsideTransactionScope() {
HRESULT hr = S_OK;
HRESULT hres;
hres = m_pTCITableDefinition->DropConstraintAndCheck(
m_pTCITableDefinition->pITDWC(),
&m_Table.GetTableID(), *m_pPKCons);
hr = (S_OK == hr)? hres: hr;
hres = m_pTCITableDefinition->DropConstraintAndCheck(
m_pTCITableDefinition->pITDWC(),
&m_Table.GetTableID(), *m_pFKCons);
hr = (S_OK == hr)? hres: hr;
hres = m_pTCITableDefinition->DropConstraintAndCheck(
m_pTCITableDefinition->pITDWC(),
&m_Table.GetTableID(), *m_pUniqueCons);
hr = (S_OK == hr)? hres: hr;
hres = m_pTCITableDefinition->DropConstraintAndCheck(
m_pTCITableDefinition->pITDWC(),
&m_Table.GetTableID(), *m_pCheckCons);
hr = (S_OK == hr)? hres: hr;
return hr;
}
virtual HRESULT InsideTransactionOnDDLLock() {
HRESULT hr = S_OK;
HRESULT hres;
hres = m_pTCITableDefinition->pITDWC()->DropConstraint(
&m_Table.GetTableID(), *m_pPKCons);
hr = (S_OK == hr)? hres: hr;
hres = m_pTCITableDefinition->pITDWC()->DropConstraint(
&m_Table.GetTableID(), *m_pFKCons);
hr = (S_OK == hr)? hres: hr;
hres = m_pTCITableDefinition->pITDWC()->DropConstraint(
&m_Table.GetTableID(), *m_pUniqueCons);
hr = (S_OK == hr)? hres: hr;
hres = m_pTCITableDefinition->pITDWC()->DropConstraint(
&m_Table.GetTableID(), *m_pCheckCons);
hr = (S_OK == hr)? hres: hr;
return hr;
}
virtual BOOL CheckCompletion() {
TBEGIN
ASSERT(m_pPKCons);
ASSERT(m_pFKCons);
ASSERT(m_pUniqueCons);
ASSERT(m_pCheckCons);
CHECK(m_pConstraints->CheckDropConstraint(*m_pPKCons), S_OK);
CHECK(m_pConstraints->CheckDropConstraint(*m_pFKCons), S_OK);
CHECK(m_pConstraints->CheckDropConstraint(*m_pUniqueCons), S_OK);
CHECK(m_pConstraints->CheckDropConstraint(*m_pCheckCons), S_OK);
TRETURN
}
virtual BOOL CheckRollBack() {
TBEGIN
ASSERT(m_pPKCons);
ASSERT(m_pFKCons);
ASSERT(m_pUniqueCons);
ASSERT(m_pCheckCons);
CHECK(m_pConstraints->AreConstraintsPreserved(), S_OK);
TRETURN
}
}; //class CDropConsTxnAdapter
class CTransactionLocal {
protected:
CLightDataSource m_DataSource;
CLightSession m_Session;
LONG m_lSupportedTxnDDL;
CTransactionAdapter *m_pTAdapter;
public:
CTransactionLocal(
) {
m_pTAdapter = NULL;
m_lSupportedTxnDDL = DBPROPVAL_TC_NONE;
}
~CTransactionLocal() { }
virtual HRESULT StartTransaction(
IUnknown *pISessionUnknown,
// arguments for ITransactionLocal::StartTransaction
ISOLEVEL isoLevel,
ULONG isoFlags,
ITransactionOptions *pOtherOptions
);
virtual HRESULT Abort(
BOID * pboidReason,
BOOL fRetaining,
BOOL fAsync
) {
return ((ITransactionLocal*)m_Session)->Abort(pboidReason, fRetaining, fAsync);
}
virtual HRESULT Commit(
BOOL fRetaining,
DWORD grfTC,
DWORD grfRM
) {
return ((ITransactionLocal*)m_Session)->Commit(fRetaining, grfTC, grfRM);
}
virtual BOOL DoTransactionTest(
IUnknown *pISessionUnknown,
CTransactionAdapter *pTAdapter,
// arguments for ITransactionLocal::Abort / Commit
BOOL fDDL, // whether or not this is a DDL call
BOOL fAbortCommit, // whether to abort or commit
BOOL fRetaining // if it's retaining or not
);
}; //CTransactionLocal
//---------------------------------------------------------------------
//
// @cmember Initialize the TCIDefinition data members
//---------------------------------------------------------------------
BOOL TCITableDefinition::Init()
{
m_pITDWC = NULL;
m_pITableDefinition = NULL;
m_nTables = 0;
InitializeCriticalSection(&m_CriticalSection);
if(CSessionObject::Init())
{
SetDataSourceObject(m_pThisTestModule->m_pIUnknown);
SetDBSession(m_pThisTestModule->m_pIUnknown2);
// select ITableDefinition as standard table creation method
GetModInfo()->UseITableDefinition(TRUE);
GetProviderTypes();
GetLiteralInfo();
m_nTables = GetNoOfTables();
m_pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
// check for ITableDefinition
if (!(m_hr=VerifyInterface(m_pIOpenRowset, IID_ITableDefinition, SESSION_INTERFACE, (IUnknown**)&m_pITableDefinition)))
return FALSE;
m_pIOpenRowset->QueryInterface(IID_ITableDefinitionWithConstraints, (void**)&m_pITDWC);
if (m_pITDWC)
{
// find out what values of matching types are supported for foreign keys
DBORDINAL rgCol[] = {1};
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable Table2(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
HRESULT hr;
TESTC_(Table.CreateTable(0, 1), S_OK);
CHECK(Table.AddInfoFromColumnsSchemaRowset(m_pITableDefinition), S_OK);
TESTC_(Table2.CreateTable(0, 1), S_OK);
CHECK(Table2.AddInfoFromColumnsSchemaRowset(m_pITableDefinition), S_OK);
m_SupportedMatchType = DBMATCHTYPE_NONE;
TEST2C_(hr = AddForeignKeyConstraint(&Table, NUMELEM(rgCol), rgCol, &Table2, NUMELEM(rgCol), rgCol,
m_SupportedMatchType), S_OK, DB_E_BADMATCHTYPE);
if (S_OK != hr)
{
m_SupportedMatchType = DBMATCHTYPE_PARTIAL;
TEST2C_(hr = AddForeignKeyConstraint(&Table, NUMELEM(rgCol), rgCol, &Table2, NUMELEM(rgCol), rgCol,
m_SupportedMatchType), S_OK, DB_E_BADMATCHTYPE);
if (S_OK != hr)
{
m_SupportedMatchType = DBMATCHTYPE_FULL;
TESTC_(hr = AddForeignKeyConstraint(&Table, NUMELEM(rgCol), rgCol, &Table2, NUMELEM(rgCol), rgCol,
m_SupportedMatchType), S_OK);
}
}
CLEANUP:
Table.DropTable();
Table2.DropTable();
}
return TRUE;
}
return FALSE;
}
//---------------------------------------------------------------------
//
// @cmember constructor
//---------------------------------------------------------------------
TCITableDefinition::TCITableDefinition(WCHAR *wstrTestCaseName):CSessionObject(wstrTestCaseName)
{
m_fIsIDBInfo = NULL;
m_pwszInvalidTableChars = NULL;
m_pwszInvalidColChars = NULL;
m_pITableDefinition = NULL;
m_rgColumnDesc = NULL;
m_cColumnDesc = 0;
} //TCITableDefinition::TCITableDefinition
//-------------------------------------------------------------------------
//
// @cmember Compare two column in the identical position
//-------------------------------------------------------------------------
BOOL TCITableDefinition::AreColEqual
(
DBCOLUMNDESC *oldCD,
DBCOLUMNDESC *newCD
)
{
// when this function is called, it is supposed that m_HasAuto... were set by GetTableColumnInfo
// and unmodified ever since
ULONG cPropSet, cProp;
BOOL fResult = FALSE;
DBPROPSET *pNewPropSet = NULL;
DBPROPSET *pOldPropSet = NULL;
DBPROP *pNewProp = NULL;
DBPROP *pOldProp = NULL;
// compare everything in the stru
ASSERT(oldCD->pTypeInfo == newCD->pTypeInfo);
TESTC(oldCD->pTypeInfo == newCD->pTypeInfo);
TESTC(oldCD->ulColumnSize == newCD->ulColumnSize);
TESTC(oldCD->wType == newCD->wType);
TESTC(!IsNumericType(oldCD->wType) || oldCD->bPrecision == newCD->bPrecision);
TESTC( (oldCD->wType != DBTYPE_NUMERIC && oldCD->wType != DBTYPE_DECIMAL)
|| oldCD->bScale == newCD->bScale);
TESTC(m_hr = CompareDBID(oldCD->dbcid, newCD->dbcid, m_pIDBInitialize));
// invalidated for the time being
// if the CLSID are to be compared for the lists, then a GUID object has to be allocated and mentained;
// during the life of each ColumnDescriptor array
// if a pointer to m_gTypeGUID of a column is stored we'll have troubles as soon as the value of the column changes
//if (m_pTable->GetHasCLSID() && !CHECK(oldCD->pclsid == newCD->pclsid, TRUE))
// return FALSE;
// compare the properties
TESTC(oldCD->cPropertySets == newCD->cPropertySets);
for (cPropSet=0; cPropSet<oldCD->cPropertySets; cPropSet++)
{
pOldPropSet = &(oldCD->rgPropertySets[cPropSet]);
pNewPropSet = &(newCD->rgPropertySets[cPropSet]);
// compare the props in that prop set
TESTC(pOldPropSet->guidPropertySet == pNewPropSet->guidPropertySet);
TESTC(pOldPropSet->cProperties == pNewPropSet->cProperties);
for (cProp = 0; cProp < pOldPropSet->cProperties; cProp++)
{
pOldProp = &(pOldPropSet->rgProperties[cProp]);
pNewProp = &(pNewPropSet->rgProperties[cProp]);
// there are no info for some of the properties
if ( ((pNewProp->dwPropertyID == DBPROP_COL_AUTOINCREMENT) && !m_pTable->GetHasAuto())
|| ((pNewProp->dwPropertyID == DBPROP_COL_DEFAULT) && !m_pTable->GetHasDefault())
|| ((pNewProp->dwPropertyID == DBPROP_COL_UNIQUE) && !m_pTable->GetHasUnique())
)
continue;
TESTC(pOldProp->dwPropertyID == pNewProp->dwPropertyID);
TESTC(CompareVariant(&(pOldProp->vValue), &(pNewProp->vValue)));
}
}
fResult = TRUE;
CLEANUP:
return fResult;
} //TCITableDefinition::AreColEqual
//-------------------------------------------------------------------------
//
// @cmember Compare the list of old columns against the list of new columns
//-------------------------------------------------------------------------
BOOL TCITableDefinition::AreColEqual
(
DBCOLUMNDESC *oldCD,
DBORDINAL oldlen,
DBCOLUMNDESC *newCD,
DBORDINAL newlen
)
{
// when this function is called, it is supposed that m_HasAuto... were set by GetTableColumnInfo
// and unmodified ever since
ULONG i;
BOOL fResult = FALSE;
TESTC(oldlen == newlen);
for (i=0; i<oldlen; i++)
{
TESTC(AreColEqual(&newCD[i], &oldCD[i]));
}
fResult = TRUE;
CLEANUP:
return fResult;
} //TCITableDefinition::AreColEqual
//--------------------------------------------------------------------------
//
// @cmember Check the result and property status
//--------------------------------------------------------------------------
BOOL TCITableDefinition::CheckPropertyStatus(
GUID guidPropertySet, // [in] property set guid
GUID guidExpectedPS, // [in] expected prop set guid
DBPROP *pProp , // [in] property
HRESULT hr // [in] the result
)
{
BOOL fRes = TRUE;
BOOL fSupported;
BOOL fSettable;
VARTYPE vtType;
if (!pProp)
return TRUE;
// general checking
if (DBPROPOPTIONS_REQUIRED == pProp->dwOptions && DBPROPSTATUS_OK != pProp->dwStatus)
fRes = COMPARE(FAILED(hr), TRUE);
if (!(guidPropertySet == guidExpectedPS) )
// 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 && !COMPARE(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) && CHECK(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:
// this could mean not supported property or value
break;
}
// DBPROPSTATUS_BADVALUE can be certainly got only if type of the prop is wrong
// info about supported discret values of the prop cannot be generacally obtained
// before creating an index
vtType = GetPropInfoType(pProp->dwPropertyID, guidPropertySet);
if ( DBPROP_COL_DEFAULT != pProp->dwPropertyID
&& vtType != 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;
} //TCITableDefinition::CheckProperty
//--------------------------------------------------------------------
//
// @cmember Check the prop status of a list of col desc
// returns TRUE if all status are set consistent with prop and result
// FALSE otherwise
//--------------------------------------------------------------------
BOOL TCITableDefinition::CheckColPropStatus(
DBORDINAL cColDesc, // [in]
DBCOLUMNDESC *rgColDesc, // [in] the size of the propset array
HRESULT hr // [in] the result of the previous op
)
{
ULONG cPropSet;
ULONG cProp;
BOOL fRes = TRUE;
DBORDINAL nCol;
if (!rgColDesc)
return TRUE;
for (nCol = 0; nCol < cColDesc; nCol++)
{
if (!rgColDesc[nCol].rgPropertySets)
continue;
for (cPropSet = 0; cPropSet < rgColDesc[nCol].cPropertySets; cPropSet++)
{
if (!rgColDesc[nCol].rgPropertySets[cPropSet].rgProperties)
continue;
for (cProp = 0; cProp < rgColDesc[nCol].rgPropertySets[cPropSet].cProperties; cProp++)
{
fRes = fRes && CheckPropertyStatus(rgColDesc[nCol].rgPropertySets[cPropSet].guidPropertySet,
DBPROPSET_COLUMN, &rgColDesc[nCol].rgPropertySets[cPropSet].rgProperties[cProp], hr);
}
}
}
return fRes;
} // TCITableDefinition::CheckColPropStatus
//--------------------------------------------------------------------
//
// @cmember CompareColumnDesc
// pColumnDesc and pNewCol [IN] parameteres to be compared
// column addition (table creation) is assumed to have succeeded
// returns TRUE or FALSE
//--------------------------------------------------------------------
BOOL TCITableDefinition::CompareColumnDesc(
DBCOLUMNDESC *pColumnDesc, // [in] column descriptor, as passed to ITableDefinition::AddColumn()
DBCOLUMNDESC *pNewCol // [in] column descriptor, as read from the table after addition
)
{
DBPROPSET *pNewPropSet = NULL;
DBPROPSET *pInPropSet = NULL;
DBPROP *pInProp = NULL;
ULONG j;
ULONG cPropSet, cProp;
ULONG n;
POSITION pos, posOld, posFind;
CCol col;
BOOL fRes = FALSE;
GUID gCD;
TESTC(pColumnDesc->pTypeInfo == pNewCol->pTypeInfo);
PRVTRACE("TCITableDefinition::CompareColumnDesc: pColumnDesc->wType = %d, pNewCol->wType = %d\n",
pColumnDesc->wType, pNewCol->wType);
TESTC(pColumnDesc->wType == pNewCol->wType);
TESTC(CompareDBID(pColumnDesc->dbcid, pNewCol->dbcid, m_pIDBInitialize));
// if there is a provider type name, the column size, precision and
// scale of the column can be checked otherwise skip it there could
// be several provider types implemented on the DBTYPE
if (!pColumnDesc->pwszTypeName)
{
// are multiple provider types implemented on the same DBTYPE?
for (posFind = pos = m_ColList.GetHeadPosition(), n=0; pos;)
{
posOld = pos;
col = m_ColList.GetNext(pos);
if (col.GetProviderType() == pNewCol->wType)
{
n++;
posFind = posOld;
}
}
col = m_ColList.GetAt(posFind);
}
else
{
BOOL fExistType;
col = GetType(GetColumnTypeName(pColumnDesc), pNewCol->wType, &fExistType);
n = fExistType ? 1: 0;
}
// see if there are enough data for a compColumnDescrison
if (1 != n)
{
fRes = TRUE;
goto CLEANUP;
}
// CHECK THE COLUMN SIZE
// for DBTYPE_STR, DBTYPE_WSTR, DBTYPE_BSTR check whether the
// size of the column fits with the spec ones or the maximum
if ((pNewCol->wType == DBTYPE_STR) ||
(pNewCol->wType == DBTYPE_WSTR) ||
(pNewCol->wType == DBTYPE_BYTES) )
{
LPWSTR pwszCreateParams = col.GetCreateParams();
if (col.GetColumnSize() >= pColumnDesc->ulColumnSize)
{
if ( 0 != pColumnDesc->ulColumnSize
&& pwszCreateParams
&& NULL != wcsstr(pwszCreateParams, L"length"))
TESTC(pColumnDesc->ulColumnSize == pNewCol->ulColumnSize);
}
else
{
// Check for varchar(max), nvarchar(max), and varbinary(max) types
if ((pColumnDesc->pwszTypeName &&
(wcscmp(pColumnDesc->pwszTypeName, L"varchar") == 0 ||
wcscmp(pColumnDesc->pwszTypeName, L"nvarchar") == 0 ||
wcscmp(pColumnDesc->pwszTypeName, L"varbinary") == 0))
||
(pNewCol->wType == DBTYPE_WSTR || pNewCol->wType == DBTYPE_BYTES)
)
{
//Note: we need to verify column size as read from the table after column addition (pNewCol),
TESTC(pNewCol->ulColumnSize == ~(DBLENGTH)0);
}
else
// column size should be set to the max column size allowed
TESTC(col.GetColumnSize() == pNewCol->ulColumnSize);
}
}
else
if (!IsFixedLength(pNewCol->wType) && DBTYPE_VARNUMERIC != pNewCol->wType)
TESTC(pNewCol->ulColumnSize == (DBLENGTH)~0);
// CHECK THE PRECISION
if (IsNumericType(pColumnDesc->wType) || DBTYPE_DBTIMESTAMP == pColumnDesc->wType)
{
if (0 < pColumnDesc->bPrecision)
if ( DBTYPE_NUMERIC == pColumnDesc->wType
|| DBTYPE_VARNUMERIC == pColumnDesc->wType )
{
if (DBTYPE_VARNUMERIC != pColumnDesc->wType ) //
TESTC(pColumnDesc->bPrecision == pNewCol->bPrecision);
}
else
TESTC(col.GetPrecision() == pNewCol->bPrecision);
}
else
TESTC(pNewCol->bPrecision == (BYTE)~0);
// CHECK SCALE
if ( DBTYPE_NUMERIC == pColumnDesc->wType
|| DBTYPE_VARNUMERIC == pColumnDesc->wType
|| DBTYPE_DECIMAL == pColumnDesc->wType
|| DBTYPE_DBTIMESTAMP == pColumnDesc->wType)
{
if (DBTYPE_VARNUMERIC != pColumnDesc->wType )
if ( DBTYPE_DBTIMESTAMP != pColumnDesc->wType
&& pColumnDesc->bScale >= col.GetMinScale()
&& pColumnDesc->bScale > col.GetMaxScale())
TESTC(pColumnDesc->bScale == pNewCol->bScale);
}
else
TESTC(pNewCol->bScale == (BYTE)~0); // as set trhough col.SetColInfo
// get the psid
if (pColumnDesc->pclsid)
gCD = *pColumnDesc->pclsid;
else
gCD = GUID_NULL;
TESTC(!m_pTable->GetHasCLSID() || gCD == *(GUID*)pNewCol->pclsid);
if (NULL == pColumnDesc->rgPropertySets)
{
fRes = TRUE;
goto CLEANUP;
}
for (cPropSet=0; cPropSet<(pColumnDesc->cPropertySets); cPropSet++)
{
pInPropSet = &(pColumnDesc->rgPropertySets[cPropSet]);
if ( pInPropSet->guidPropertySet != DBPROPSET_COLUMN )
{
for (cProp=0; cProp < pInPropSet->cProperties; cProp++)
TESTC(DBPROPSTATUS_NOTSUPPORTED == pInPropSet->rgProperties[cProp].dwStatus);
continue;
}
// Find matching PropSet
for(j = 0; j < pNewCol->cPropertySets &&
pNewCol->rgPropertySets[j].guidPropertySet != pInPropSet->guidPropertySet; j++);
if (j >= pNewCol->cPropertySets)
continue;
pNewPropSet = &(pNewCol->rgPropertySets[j]);
// compColumnDescre the propPropSet in the column prop set
ASSERT(pNewPropSet->rgProperties);
if (NULL == pInPropSet->rgProperties)
continue;
for (cProp=0; cProp < pInPropSet->cProperties; cProp++)
{
pInProp = &(pInPropSet->rgProperties[cProp]);
if (pInPropSet->guidPropertySet == DBPROPSET_COLUMN)
{
// look for that property inside the resulted column
if (((pInProp->dwPropertyID == DBPROP_COL_AUTOINCREMENT) && !m_pTable->GetHasAuto() ) ||
((pInProp->dwPropertyID == DBPROP_COL_DEFAULT) && !m_pTable->GetHasDefault() ) ||
((pInProp->dwPropertyID == DBPROP_COL_UNIQUE) && !m_pTable->GetHasUnique()) )
// better check the status, it should be DBPROPSTATUS_NOTSUPPORTED
continue;
TESTC( SupportedProperty(pInProp->dwPropertyID, pInPropSet->guidPropertySet)
|| DBPROPSTATUS_NOTSUPPORTED == pInProp->dwStatus);
TESTC( SettableProperty(pInProp->dwPropertyID, pInPropSet->guidPropertySet)
|| DBPROPSTATUS_NOTSUPPORTED == pInProp->dwStatus);
// identify the property
for ( j=0;
j< pNewPropSet->cProperties
&& pNewPropSet->rgProperties[j].dwPropertyID != pInProp->dwPropertyID;
j++);
if (j>=pNewPropSet->cProperties)
continue;
// try to detect the right dbpropstatus
TESTC( (DBPROPSTATUS_OK != pInProp->dwStatus)
|| CompareVariant(&pInProp->vValue, &pNewPropSet->rgProperties[j].vValue));
}
// skipping the testing of other provider-specific property sets
}
}
fRes = TRUE;
CLEANUP:
return fRes;
} //TCITableDefinition::CompColumnDescreColumnDesc
//--------------------------------------------------------------------
//
// @cmember Compare the list of old columns against the list of new columns and the new column
// the place where the newly added column was added is provider specific!
//--------------------------------------------------------------------
BOOL TCITableDefinition::CheckColInfo
(
DBCOLUMNDESC *oldCD,
DBORDINAL oldlen,
DBCOLUMNDESC *newCD,
DBORDINAL newlen,
DBCOLUMNDESC *pColumnDesc // the new column to be add
)
{
// when this function is called, it is supposed that m_HasAuto... were set by GetTableColumnInfo
// and unmodified ever since
BOOL fNewColumn = FALSE;
BOOL fResult = FALSE;
DBORDINAL cOldCol;
DBORDINAL cNewCol;
TESTC(newlen == oldlen+1);
for (cOldCol=cNewCol=0; cNewCol<newlen; cNewCol++)
{
if ( (cOldCol < oldlen)
&& CompareDBID(oldCD[cOldCol].dbcid, newCD[cNewCol].dbcid, m_pIDBInitialize))
{
TESTC(AreColEqual(&oldCD[cOldCol], &newCD[cNewCol]));
cOldCol++;
}
else
{
TESTC(!fNewColumn);
TESTC(CompareColumnDesc(pColumnDesc, &newCD[cOldCol]));
fNewColumn = TRUE;
}
}
fResult = TRUE;
CLEANUP:
return fResult;
} //TCITableDefinition::CheckColInfo
//--------------------------------------------------------------------------
//
// @cmember TCITableDefinition::CheckRowset
//--------------------------------------------------------------------------
BOOL TCITableDefinition::CheckRowset(IUnknown *pIRowset)
{
IRowsetInfo* pInterface = NULL;
BOOL hr;
if (!pIRowset)
return TRUE;
if (hr = DefaultObjectTesting(pIRowset, ROWSET_INTERFACE))
{
// just for curiosity
if (VerifyInterface( pIRowset,
IID_IRowsetInfo,
ROWSET_INTERFACE,
(IUnknown**)&pInterface))
{
IUnknown* tempInterface;
if (pInterface->GetSpecification(IID_IUnknown, &tempInterface) == S_FALSE)
{
// what if table ID doesn't specify a name?
PRVTRACE(L"** No object has created the rowset");
}
else
{
IUnknown *pIID;
if (tempInterface->QueryInterface(IID_IGetDataSource, (void**)&pIID) == S_OK)
{
PRVTRACE(L"** Rowset was created by a session");
SAFE_RELEASE(pIID);
}
else
PRVTRACE(L"** Rowset was created by a command");
SAFE_RELEASE(tempInterface);
}
SAFE_RELEASE(pInterface);
}
}
return hr;
} //CTable::CheckRowset
//--------------------------------------------------------------------------
//
// @cmember Fills in a variant with whatever it needs
//--------------------------------------------------------------------------
BOOL TCITableDefinition::FillVariant(VARIANT *pVariant)
{
BOOL fRes = FALSE;
BSTR pwszValue = L"\'some value\'";
WCHAR *pwszStrValue = L"\'value\'";
TESTC(NULL != pVariant);
switch (pVariant->vt)
{
case DBTYPE_R4:
V_R4(pVariant) = (float)3.1415926;
break;
case DBTYPE_R8:
V_R8(pVariant) = 2.71828;
break;
case DBTYPE_BSTR:
V_BSTR(pVariant) = SysAllocString(pwszValue);
break;
case DBTYPE_STR:
case DBTYPE_WSTR:
pVariant->vt = DBTYPE_BSTR;
V_BSTR(pVariant) = SysAllocString(pwszStrValue);
break;
case DBTYPE_BYTES:
V_BYREF(pVariant) = SysAllocString(pwszStrValue);
break;
}
fRes = TRUE;
CLEANUP:
return fRes;
} // TCITableDefinition::FillVariant
// @cmember Builds a default value for a given column type
BOOL TCITableDefinition::GetDefaultValue(
DBCOLUMNDESC *pColumnDesc, // [in] column descriptor
VARIANT *pVariant, // [out] pointer to the variant that stores the default value
CTable *pTable // [in] CTable to be used (default NULL)
)
{
TBEGIN
CTable *pCTable = NULL;
CList<WCHAR *,WCHAR *> NativeTypesList;
CList<DBTYPE,DBTYPE> ProviderTypesList;
CCol col;
WCHAR *pwszDefVal = NULL;
ULONG ulRowNum = 28;
HRESULT hr;
TESTC(NULL != pColumnDesc); // && NULL != pColumnDesc->pwszTypeName);
TESTC(NULL != pVariant);
VariantInit(pVariant);
if (pTable)
pCTable = pTable;
else
{
pCTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
pCTable->CreateTypeColInfo(NativeTypesList, ProviderTypesList);
}
pCTable->GetColInfo(col, GetColumnTypeName(pColumnDesc));
SAFE_ALLOC(pwszDefVal, WCHAR, MAXDATALEN);
pwszDefVal[0]=L'\0';
TESTC_(hr = col.MakeData(pwszDefVal,ulRowNum,PRIMARY,NONULLS), S_OK);
pVariant->vt = DBTYPE_BSTR; //col.GetProviderType();
V_BSTR(pVariant) = SysAllocString(pwszDefVal);
SAFE_FREE(pwszDefVal);
// Use the US_English LCID first and then the System LCID
hr=VariantChangeTypeEx(pVariant, pVariant, MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), VARIANT_NOVALUEPROP, col.GetProviderType());
if(S_OK != hr)
hr=VariantChangeTypeEx(pVariant, pVariant, GetSystemDefaultLCID(), VARIANT_NOVALUEPROP, col.GetProviderType());
if (S_OK != hr)
{
// try to set it as a VT_BSTR value
VariantClear(pVariant);
TESTC_(pCTable->GetLiteralAndValue(col, &pwszDefVal, ulRowNum, col.GetColNum(), PRIMARY), S_OK);
pVariant->vt = DBTYPE_BSTR;
V_BSTR(pVariant) = SysAllocString(pwszDefVal);
TEST2C_(hr, DISP_E_BADVARTYPE, DISP_E_TYPEMISMATCH);
}
CLEANUP:
SAFE_FREE(pwszDefVal);
if (!pTable)
delete pCTable;
TRETURN
} // TCITableDefinition::GetDefaultValue
//--------------------------------------------------------------------------
//
// @cmember Get the number of tables in a data sources, base on IDBSchemaRowset
//--------------------------------------------------------------------------
ULONG TCITableDefinition::GetNoOfTables()
{
IDBSchemaRowset *pInterface = NULL;
IRowset *pRowset = NULL;
DBCOUNTITEM n=0;
HROW * prghRows = NULL;
if (!VerifyInterface(m_pIOpenRowset,IID_IDBSchemaRowset, SESSION_INTERFACE, (IUnknown**)&pInterface))
{
PRVTRACE(L"** I could not get a pointer to IDBSchemaRowset interface");
return 0;
}
TESTC_(pInterface->GetRowset(NULL, DBSCHEMA_TABLES, 0, NULL, IID_IRowset, 0, NULL, (IUnknown**)&pRowset), S_OK);
TEST2C_(pRowset->GetNextRows(0, 0, LONG_MAX/1024, &n, &prghRows), DB_S_ENDOFROWSET, DB_S_ROWLIMITEXCEEDED );
TESTC_(pRowset->ReleaseRows(n, prghRows, NULL, NULL, NULL), S_OK)
CLEANUP:
SAFE_RELEASE(pRowset);
SAFE_RELEASE(pInterface);
PROVIDER_FREE(prghRows);
// I dont't expect the number of tables to exceed ULONG_MAX
ASSERT(n < ULONG_MAX);
return (ULONG)n;
} //TCITableDefinition::GetNoOfTables
//----------------------------------------------------------------------
//
// @cmember Drops a column and check the result against reallity
//----------------------------------------------------------------------
HRESULT TCITableDefinition::DropColumnAndCheck(
DBID *pTableID, // [in] the table ID
DBID *pColumnID, // [in] the ID of the column to be dropped
ITableDefinition *pITableDefinition,/*=NULL*/ // [in] pointer to ITableDefinition interface
DBID *pBaseTableID/*=NULL*/ // [in] if pTableID is exotic (e.g. fuly qualified) this
// table id is used to get metadata info about the table
)
{
DBCOLUMNDESC *OldColList = NULL, *NewColList = NULL;
DBORDINAL oldlen = 0, newlen = 0;
ULONG i;
LONG nCol = -1L;
HRESULT hr;
BOOL fTableExists = FALSE;
BOOL fColumnExists = FALSE;
IOpenRowset *pIOpenRowset = NULL;
IColumnsInfo *pIColumnsInfo = NULL;
HRESULT rgValidHRes[] = { S_OK,
E_FAIL,
E_INVALIDARG,
DB_E_NOCOLUMN,
DB_E_DROPRESTRICTED,
DB_E_NOTABLE,
DB_E_TABLEINUSE,
DB_SEC_E_PERMISSIONDENIED,
XACT_E_XTIONEXISTS,
DB_E_SCHEMAVIOLATION
};
//NOTE: spec was changed in MDAC 2.6 to replace DB_E_BADCOLUMNID with DB_E_NOCOLUMN
// for ITableDefinition::DropColumn. So when runnning against MDAC 2.5 expect DB_E_BADCOLUMNID
// This is for SQL-specific provider. For other providers, you should modify this to test against your target spec
HRESULT rgValidHResMDAC25[] = { S_OK,
E_FAIL,
E_INVALIDARG,
DB_E_BADCOLUMNID,
DB_E_DROPRESTRICTED,
DB_E_NOTABLE,
DB_E_TABLEINUSE,
DB_SEC_E_PERMISSIONDENIED,
XACT_E_XTIONEXISTS,
DB_E_SCHEMAVIOLATION,
};
ULONG cValidHRes = NUMELEM(rgValidHRes);
if (!pBaseTableID)
pBaseTableID = pTableID;
if (!pITableDefinition)
pITableDefinition = m_pITableDefinition;
// check whether the table and column exist
if (pTableID)
{
TESTC(VerifyInterface(pITableDefinition, IID_IOpenRowset, SESSION_INTERFACE, (IUnknown**)&pIOpenRowset));
TEST2C_(hr = pIOpenRowset->OpenRowset(NULL, pTableID, NULL, IID_IColumnsInfo,
0, NULL, (IUnknown**)&pIColumnsInfo), S_OK, DB_E_NOTABLE);
SAFE_RELEASE(pIOpenRowset);
SAFE_RELEASE(pIColumnsInfo);
fTableExists = S_OK == hr;
}
else
fTableExists = FALSE;
// this function is based on the current table name
if (fTableExists)
{
GetColumnDescOnTable(pBaseTableID, &OldColList, &oldlen);
if (pColumnID)
{
for (fColumnExists = FALSE, i=0; !fColumnExists && (i<oldlen); i++)
{
if (CompareDBID(OldColList[i].dbcid, *pColumnID, m_pIDBInitialize))
fColumnExists = TRUE;
}
}
}
// the CHECK will be done at the caller level, where the expected return is known
if ( (hr = m_pITableDefinition->DropColumn(pTableID, pColumnID)) != S_OK)
{
//NOTE: spec was changed in MDAC 2.6 to replace DB_E_BADCOLUMNID with DB_E_NOCOLUMN
// for ITableDefinition::DropColumn. So when runnning against MDAC 2.5 expect DB_E_BADCOLUMNID
// This is for SQL-specific provider. For other providers, you should modify this to test against your target spec
// check that the result is one of the expected results
TESTC(CheckResult(hr, cValidHRes, g_fSQLOLEDB25 ? rgValidHResMDAC25 : rgValidHRes));
// call failed
if (fTableExists) //pTableID && pTableID->uName.pwszName)
{
GetColumnDescOnTable(pBaseTableID, &NewColList, &newlen);
TESTC(AreColEqual(NewColList, newlen, OldColList, oldlen));
if (!fColumnExists)
{
TESTC_(hr, pColumnID? (g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN): E_INVALIDARG);
}
else
{
HRESULT rgValidHRes[] = {DB_E_DROPRESTRICTED, DB_E_TABLEINUSE, DB_SEC_E_PERMISSIONDENIED, XACT_E_XTIONEXISTS, E_FAIL};
// check the possible results
TESTC(CheckResult(hr, NUMELEM(rgValidHRes), rgValidHRes));
}
}
else
{
if (pTableID)
{
TEST2C_(hr, DB_E_NOTABLE, (g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN));
}
else
TESTC_(hr, E_INVALIDARG);
}
}
else
{
// call succeeded
TESTC(fColumnExists);
GetColumnDescOnTable(pBaseTableID, &NewColList, &newlen);
for (i = 0, nCol = -1; i < oldlen && nCol < 0; i++)
{
if (CompareDBID(OldColList[i].dbcid, *pColumnID, m_pIDBInitialize))
nCol = (ULONG)i;
}
TESTC(0 <= nCol);
// this should work even when the column name is not in the original (old) table
TESTC(CheckColInfo(NewColList, newlen, OldColList, oldlen, &OldColList[nCol]));
}
CLEANUP:
SAFE_RELEASE(pIOpenRowset);
SAFE_RELEASE(pIColumnsInfo);
ReleaseColumnDesc(OldColList, oldlen);
ReleaseColumnDesc(NewColList, newlen);
return hr;
} // TCITableDefinition::DropColumnAndCheck
//--------------------------------------------------------------------------
//
// @cmember Drops a table and check the operation
//--------------------------------------------------------------------------
HRESULT TCITableDefinition::DropTableAndCheck(
DBID *pTableID, // [in] ID of the table to be dropped
ITableDefinition *pITableDefinition /*=NULL*/ // [in] pointer to ITableDefinition interface
)
{
BOOL fExists;
BOOL fTableExisted;
CTable *pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
HRESULT hRes;
ASSERT(pTable);
if (!pITableDefinition)
pITableDefinition = m_pITableDefinition;
// check whether the table existed before
CHECK(pTable->DoesTableExist(pTableID, &fTableExisted), S_OK);
// drop the table
hRes = pITableDefinition->DropTable(pTableID);
// check that if table was dropped it doesn't exist
TESTC(fTableExisted || !SUCCEEDED(hRes));
TESTC_(pTable->DoesTableExist(pTableID, &fExists), S_OK);
TESTC(!fTableExisted || fExists == !SUCCEEDED(hRes));
CLEANUP:
delete pTable;
return hRes;
} //TCITableDefinition::DropTableAndCheck
//--------------------------------------------------------------------------
//
// GetInfo about table identifiers
//--------------------------------------------------------------------------
HRESULT TCITableDefinition::GetLiteralInfo()
{
IDBInfo* pInterface = NULL;
DBLITERAL rgLiteral[2]={DBLITERAL_TABLE_NAME, DBLITERAL_COLUMN_NAME};
DBLITERALINFO* rgLiteralInfo = NULL;
ULONG cLiteralInfo, i;
OLECHAR* pCharBuffer = NULL;
IGetDataSource* pIGetDataSource=NULL; // IGetDataSource interface pointer
m_fIsIDBInfo = FALSE;
if(!VerifyInterface(m_pIOpenRowset, IID_IGetDataSource, SESSION_INTERFACE, (IUnknown**)&pIGetDataSource))
return E_FAIL;
m_hr=pIGetDataSource->GetDataSource(IID_IDBInfo,(IUnknown**)&pInterface);
SAFE_RELEASE(pIGetDataSource);
if (!CHECK(pInterface->GetLiteralInfo(2, rgLiteral, &cLiteralInfo, &rgLiteralInfo, &pCharBuffer), S_OK))
goto CLEANUP;
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;
PROVIDER_FREE(m_pwszInvalidTableChars);
m_pwszInvalidTableChars = wcsDuplicate(rgLiteralInfo[i].pwszInvalidChars?
rgLiteralInfo[i].pwszInvalidChars: L"");
break;
case DBLITERAL_COLUMN_NAME:
m_cMaxColName = rgLiteralInfo[i].cchMaxLen;
PROVIDER_FREE(m_pwszInvalidColChars);
m_pwszInvalidColChars = wcsDuplicate(rgLiteralInfo[i].pwszInvalidChars?
rgLiteralInfo[i].pwszInvalidChars: L"");
break;
}
}
m_fIsIDBInfo = TRUE;
CLEANUP:
SAFE_RELEASE(pInterface);
PROVIDER_FREE(pCharBuffer);
PROVIDER_FREE(rgLiteralInfo);
return m_hr;
} //TCITableDefinition::GetLiteralInfo
// @cmember Gets the catalog and schema name for a given table
BOOL TCITableDefinition::GetCatalogSchemaNames(
LPWSTR pwszTableName, // [in] the name of the table
LPWSTR *ppwszCatalogName, // [out] catalog name
LPWSTR *ppwszSchemaName, // [out] schema name
CTable *pTable // [in] table object (DEFAULT NULL - use m_pTable)
)
{
IRowset *pIRowset = NULL;
HROW hRow = DB_NULL_HROW;
BOOL bFound = FALSE;
WCHAR *pwszTableName1 = NULL;
CRowset Rowset;
if (!pTable)
pTable = m_pTable;
TESTC(NULL != pwszTableName);
TESTC(NULL != ppwszCatalogName);
TESTC(NULL != ppwszSchemaName);
//Obtain Schema TABLES Rowset
//We don't want to put any restrictions, since its not required to support
//restrictions...
TESTC_PROVIDER((Rowset.CreateRowset(SELECT_DBSCHEMA_TABLE,
IID_IRowset, pTable, DBACCESSOR_ROWDATA, DBPART_ALL, ALL_COLS_BOUND)==S_OK));
//Try to find the specified row with this table...
while(!bFound && S_OK == (m_hr = Rowset.GetNextRows(&hRow)))
{
//GetData for this row
TESTC_(Rowset.GetRowData(hRow, &Rowset.m_pData),S_OK);
//TABLE_NAME column
DBBINDING* pCatalogBinding = Rowset.m_rgBinding[0].iOrdinal == 0 ? &Rowset.m_rgBinding[1] : &Rowset.m_rgBinding[0];
DBBINDING* pSchemaBinding = Rowset.m_rgBinding[0].iOrdinal == 0 ? &Rowset.m_rgBinding[2] : &Rowset.m_rgBinding[1];
DBBINDING* pTableBinding = Rowset.m_rgBinding[0].iOrdinal == 0 ? &Rowset.m_rgBinding[3] : &Rowset.m_rgBinding[2];
//See if this is the correct row...
if(STATUS_BINDING(*pTableBinding, Rowset.m_pData)==DBSTATUS_S_OK)
{
//TableName
pwszTableName1 = (WCHAR*)&VALUE_BINDING(*pTableBinding, Rowset.m_pData);
bFound = FALSE;
if(CHECK(CompareID(&bFound, pwszTableName,
pwszTableName1, m_pIDBInitialize), S_OK) && bFound)
{
//Catalog Name
if(STATUS_BINDING(*pCatalogBinding, Rowset.m_pData)==DBSTATUS_S_OK)
*ppwszCatalogName = wcsDuplicate((WCHAR*)&VALUE_BINDING(*pCatalogBinding, Rowset.m_pData));
//Schema Name
if(STATUS_BINDING(*pSchemaBinding, Rowset.m_pData)==DBSTATUS_S_OK)
*ppwszSchemaName = wcsDuplicate((WCHAR*)&VALUE_BINDING(*pSchemaBinding, Rowset.m_pData));
}
}
Rowset.ReleaseRows(hRow);
hRow = DB_NULL_HROW;
}
//Error
if(!bFound)
{
TERROR("Unable to find the table \"" << pwszTableName << "\"in the Schema Rowset?");
QTESTC(bFound);
return FALSE;
}
CLEANUP:
if (DB_NULL_HROW != hRow)
Rowset.ReleaseRows(hRow);
SAFE_RELEASE(pIRowset);
return TRUE;
} //TCITableDefinition::GetCatalogSchemaNames
//--------------------------------------------------------------------------
//
// @cmember Build a valid table name of a certain length
//--------------------------------------------------------------------------
WCHAR* TCITableDefinition::BuildValidName(size_t length, WCHAR* pattern)
{
WCHAR* pwszBuffer = NULL;
size_t cLen = wcslen(pattern), i;
SAFE_ALLOC(pwszBuffer, WCHAR, i=(length+1));
memset(pwszBuffer, 0, i);
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;
} //TCITableDefinition::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* TCITableDefinition::BuildInvalidName(size_t length, WCHAR* pattern, WCHAR* invchars)
{
WCHAR* pwszBuffer=NULL;
size_t cLen = wcslen(pattern), i, cInvLen=wcslen(invchars);
pwszBuffer = (WCHAR*) PROVIDER_ALLOC( (length + 1) * sizeof(WCHAR) );
if (!pwszBuffer)
goto CLEANUP;
if (length > cInvLen+cLen)
{
wcscpy(pwszBuffer, pattern);
wcscat(pwszBuffer, invchars);
}
else
{
wcscpy(pwszBuffer, L"aa");
wcsncat(pwszBuffer, invchars, length-wcslen(pwszBuffer)-1);
pwszBuffer[length] = 0;
assert( wcslen(pwszBuffer) < length );
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;
} //TCITableDefinition::BuildInvalidName
//---------------------------------------------------------------------
//
// @cmember Uses m_pTable to get a column description for all types
//---------------------------------------------------------------------
void TCITableDefinition::GetProviderTypes(void)
{
CList <WCHAR*, WCHAR*> ListNativeTemp;
CList <DBTYPE, DBTYPE> ListDataTypes;
if (m_pTable)
delete m_pTable;
m_pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
// get the provider types list
// all types appear in CreateColList, so I don't have to use CreateTypeColInfo
m_pTable->CreateTypeColInfo(ListNativeTemp, ListDataTypes, ALLTYPES);
m_pTable->DuplicateColList(m_ColList);
// in m_rgColumnDesc I would rather load just the types prepared for table creation
m_pTable->CreateColInfo(ListNativeTemp, ListDataTypes, ALLTYPES);
// build the column description array
m_pTable->BuildColumnDescs(&m_rgColumnDesc);
m_cColumnDesc = m_pTable->CountColumnsOnTable();
m_pTable->SetBuildColumnDesc(FALSE);
ReleaseAllColumnPropSets(m_rgColumnDesc, m_cColumnDesc);
delete m_pTable;
m_pTable = NULL;
} //TCITableDefinition::GetProviderTypes
//---------------------------------------------------------------------
//
// @cmember Sets all the columns to maximum size as got from m_ColList
// (based on information read from PROVIDER_TYPES Rowset)
//
// RESULT:
// TRUE - set for every element in column desc array
// FALSE - could not be set for every element in thee array
//---------------------------------------------------------------------
BOOL TCITableDefinition::SetMaximumColSize
(
DBCOLUMNDESC *rgColumnDesc,
DBORDINAL cColumnDesc
)
{
POSITION pos;
CCol col;
DBORDINAL i;
WCHAR *pwszType;
for (i=0; i<cColumnDesc; i++)
{
pwszType = GetColumnTypeName(&rgColumnDesc[i]);
// look for the type which fits with column type
for ( pos=m_ColList.GetHeadPosition(), col=m_ColList.GetNext(pos);
wcscmp(col.GetProviderTypeName(), pwszType) && pos;
col=m_ColList.GetNext(pos));
if (wcscmp(col.GetProviderTypeName(), pwszType) )
continue;
// set to max column size
rgColumnDesc[i].ulColumnSize = col.GetColumnSize();
}
return TRUE;
} //TCITableDefinition::SetMaximumColSize
//--------------------------------------------------------------------------
//
// @cmember Sets all the column sizes to 0
// RESULT:
// TRUE - set for every element in column desc array
// FALSE - could not be set for every element in thee array
//--------------------------------------------------------------------------
BOOL TCITableDefinition::SetZeroColSize
(
DBCOLUMNDESC *rgColumnDesc,
DBORDINAL cColumnDesc
)
{
DBORDINAL i;
for (i=0; i<cColumnDesc; i++)
{
// set column size to 0
rgColumnDesc[i].ulColumnSize = 0;
}
return TRUE;
} //TCITableDefinition::SetZeroColSize
//--------------------------------------------------------------------------
//
// @cmember CheckReturnedDBID about the columns in the table
// pIndexID - [IN] the DBID asked for
// ppIndexID - [IN] the DBID created
//--------------------------------------------------------------------------
BOOL TCITableDefinition::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;
if (pIndexID->eKind != (*ppIndexID)->eKind)
return TRUE;
return CompareDBID(*pIndexID, **ppIndexID);
} //TCITableDefinition::CheckReturnedDBID
//--------------------------------------------------------------------------
//
// @cmember GetInfo about the columns in the table
// prgInfo - [OUT] the array of column information
// pcColumns - [OUT] the size of the array
// ppStringBuffer - [OUT] memory for info in the array
//--------------------------------------------------------------------------
BOOL TCITableDefinition::GetColumnInfo
(
DBID *pTableID,
DBORDINAL *pcColumns,
DBCOLUMNINFO **prgInfo,
OLECHAR **ppStringBuffer
)
{
IColumnsInfo *pIColumnsInfo;
if ( (m_hr = m_pIOpenRowset->OpenRowset(NULL, pTableID, NULL, IID_IColumnsInfo,
0, NULL, (IUnknown**)&pIColumnsInfo)) != S_OK)
{
*prgInfo = NULL;
*pcColumns = 0;
*ppStringBuffer = NULL;
return FALSE;
}
if (!CHECK(m_hr = pIColumnsInfo->GetColumnInfo(pcColumns, prgInfo, ppStringBuffer), S_OK))
return FALSE;
SAFE_RELEASE(pIColumnsInfo);
return TRUE;
} //TCITableDefinition::GetColumnInfo
//---------------------------------------------------------------------
//
// @cmember Get an array od Column Descriptors on a Table
//---------------------------------------------------------------------
BOOL TCITableDefinition::GetColumnDescOnTable(
DBID *pTableID,
DBCOLUMNDESC **prgColumnDesc,
DBORDINAL *cColumnDesc
)
{
if (!m_pTable)
return FALSE;
// get info in m_pTable->m_ColList
m_pTable->GetTableColumnInfo(pTableID);
m_pTable->AddInfoFromColumnsSchemaRowset(m_pITableDefinition,
pTableID || DBKIND_NAME != pTableID->eKind? pTableID->uName.pwszName: NULL);
m_pTable->ColList2ColumnDesc(prgColumnDesc, cColumnDesc);
return TRUE;
} //TCITableDefinition::GetColumnDescOnTable
//---------------------------------------------------------------------
//
// @cmember Passes a type name and retrieves the column from m_ColList with info about that type
//---------------------------------------------------------------------
CCol TCITableDefinition::GetType(WCHAR *pwszTypeName, DBTYPE wType, BOOL *fExists)
{
POSITION pos;
CCol col;
BOOL fRes = FALSE;
for (pos = m_ColList.GetHeadPosition(); pos && !fRes; )
{
col = m_ColList.GetNext(pos);
fRes = (0 == wcscmp(col.GetProviderTypeName(), pwszTypeName))
&& (wType == col.GetProviderType());
}
if (fExists)
*fExists = fRes;
return fRes? col : m_ColList.GetHead();
} //TCITableDefinition::GetType
//------------------------------------------------------------------------
//
// @mfunc Check whether the array of ColumnDesc sent was preserved
// @rdesc TRUE or FALSE
// All the data should be inside, the only thing that is allowed to be modified <nl>
// is the property status
//------------------------------------------------------------------------
BOOL TCITableDefinition::IsColumnDescPreserved
(
DBCOLUMNDESC *rgInColumnDesc, // the array passed to ITableDefinition::CreateTable
DBCOLUMNDESC *rgOutColumnDesc, // the aray returned by ITableDefinition::CreateTable
DBORDINAL cColumnDesc // the size of the arrays
)
{
// when this function is called, it is supposed that m_HasAuto... were set by GetTableColumnInfo
// and unmodified ever since
ULONG i, cPropSets, cProp;
DBPROPSET *pInPropSet, *pOutPropSet;
if (NULL == rgInColumnDesc || NULL == rgOutColumnDesc)
return (0 == cColumnDesc) || (rgOutColumnDesc == rgInColumnDesc);
for (i=0; i<cColumnDesc; i++)
{
// compare everything in the stru
if (!CHECK(rgInColumnDesc[i].pTypeInfo == rgOutColumnDesc[i].pTypeInfo, TRUE))
return FALSE;
if (!CHECK(rgInColumnDesc[i].ulColumnSize == rgOutColumnDesc[i].ulColumnSize, TRUE))
return FALSE;
if (!CHECK(rgInColumnDesc[i].wType == rgOutColumnDesc[i].wType, TRUE))
return FALSE;
if (!CHECK(rgInColumnDesc[i].bPrecision == rgOutColumnDesc[i].bPrecision, TRUE))
return FALSE;
if (!CHECK(rgInColumnDesc[i].bScale == rgOutColumnDesc[i].bScale, TRUE))
return FALSE;
if (!CHECK(rgInColumnDesc[i].pclsid == rgOutColumnDesc[i].pclsid, TRUE))
return FALSE;
if (INVALID_DBKIND != rgInColumnDesc[i].dbcid.eKind)
{
// CompareDBID with NULL DSO interface since the ids should
// match exactly
if (!CHECK(m_hr = CompareDBID(rgInColumnDesc[i].dbcid,
rgOutColumnDesc[i].dbcid, NULL), TRUE))
return FALSE;
}
else
if (INVALID_DBKIND != rgOutColumnDesc[i].dbcid.eKind)
return FALSE;
// compare the properties
if (!CHECK(rgInColumnDesc[i].cPropertySets == rgOutColumnDesc[i].cPropertySets, TRUE))
return FALSE;
if ( (NULL == rgInColumnDesc[i].rgPropertySets)
|| (NULL == rgOutColumnDesc[i].rgPropertySets))
if ( 0 != rgOutColumnDesc[i].cPropertySets
&& !COMPARE(rgInColumnDesc[i].rgPropertySets, rgOutColumnDesc[i].rgPropertySets))
return FALSE;
else
continue;
for (cPropSets=0; cPropSets<rgInColumnDesc[i].cPropertySets; cPropSets++)
{
// compare the props in that prop set
pInPropSet = &(rgInColumnDesc[i].rgPropertySets[cPropSets]);
pOutPropSet = &(rgOutColumnDesc[i].rgPropertySets[cPropSets]);
if (!CHECK(pInPropSet->guidPropertySet == pOutPropSet->guidPropertySet, TRUE))
return FALSE;
if (!CHECK(pInPropSet->cProperties == pOutPropSet->cProperties, TRUE))
return FALSE;
if ( (NULL == pInPropSet->rgProperties)
|| (NULL == pOutPropSet->rgProperties))
if (0 != pOutPropSet->cProperties
&& !COMPARE(pInPropSet->rgProperties, pOutPropSet->rgProperties))
return FALSE;
else
continue;
// compare the properties
for (cProp=0; cProp<pInPropSet->cProperties; cProp++)
{
if (!CHECK(pInPropSet->rgProperties[cProp].dwPropertyID ==
pOutPropSet->rgProperties[cProp].dwPropertyID, TRUE))
return FALSE;
if (!CHECK(pInPropSet->rgProperties[cProp].dwOptions ==
pOutPropSet->rgProperties[cProp].dwOptions, TRUE))
return FALSE;
// use NULL fr DSO interface
if (!CHECK(m_hr = CompareDBID(pInPropSet->rgProperties[cProp].colid,
pOutPropSet->rgProperties[cProp].colid,
NULL), TRUE))
return FALSE;
// protection against assertion errors in CompareVariant
if (
(rgInColumnDesc[i].wType != DBTYPE_GUID) &&
(rgInColumnDesc[i].wType != DBTYPE_BYTES) &&
(rgInColumnDesc[i].wType != DBTYPE_STR) &&
(rgInColumnDesc[i].wType != DBTYPE_WSTR) &&
(rgInColumnDesc[i].wType != DBTYPE_NUMERIC) &&
(rgInColumnDesc[i].wType != DBTYPE_DBTIMESTAMP)
)
if (!CHECK(CompareVariant(&pInPropSet->rgProperties[cProp].vValue,
&pOutPropSet->rgProperties[cProp].vValue), TRUE))
return FALSE;
}
}
}
return TRUE;
} //TCITableDefinition::IsColumnDescPreserved
//---------------------------------------------------------------------
//
// @cmember Set a property in the property sets of a DBCOLUMNDESC
//---------------------------------------------------------------------
BOOL TCITableDefinition::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/*=DPROPOPTIONS_OPTIONAL*/, // [in] prop options
DBID colid/*=DB_NULLID*/, // [in] col id
GUID guidPropertySet/*DBPROPSET_COLUMN*/,// [in] the GUID of the propset
ULONG *pcPropSet/*=NULL*/, // [out] index of property set
ULONG *pcProp/*=NULL*/ // [out] index in the rgProperties array
)
{
LONG i;
DBPROPSET *pPropSet;
BOOL fRes = FALSE, fFound;
ULONG cPropSet, cProp;
if (wType != DBTYPE_VARIANT)
{
TESTC(::SetProperty(propID, guidPropertySet, pcPropertySets, prgPropertySets, value,
wType, dwOption, colid));
}
else
{
TESTC(::SetProperty(propID, guidPropertySet, pcPropertySets, prgPropertySets, value,
VT_I2, dwOption, colid));
}
fRes = TRUE;
for (i=(int)(*pcPropertySets - 1), fFound = FALSE; i >= 0 && !fFound; i--)
{
fFound = (*prgPropertySets)[i].guidPropertySet == guidPropertySet;
cPropSet = (ULONG)i;
}
TESTC(fFound);
pPropSet = &((*prgPropertySets)[cPropSet]);
for (i=pPropSet->cProperties - 1, fFound = FALSE; i >= 0 && !fFound; i--)
{
if (TRUE == (fFound = pPropSet->rgProperties[i].dwPropertyID == propID))
{
cProp = (ULONG)i;
if (DBTYPE_VARIANT == wType)
{
pPropSet->rgProperties[i].vValue.vt = ((VARIANT*)value)->vt;
FillVariant(&pPropSet->rgProperties[i].vValue);
}
}
}
if (pcPropSet)
*pcPropSet = cPropSet;
if (pcProp)
*pcProp = cProp;
TESTC(fFound);
fRes = TRUE;
CLEANUP:
return fRes;
} //TCITableDefinition::SetProperty
//---------------------------------------------------------------------------
//
// @cmember Set a default property in the property sets of a DBCOLUMNDESC
//---------------------------------------------------------------------------
BOOL TCITableDefinition::SetDefaultProperty(
DBPROPSET **prgPropertySets, // [in/out] array of property sets
ULONG *pcPropertySets, // [in/out] number of property sets
VARIANT *pvalue, // [in] property value
DBPROPOPTIONS dwOption /*= DBPROPOPTIONS_OPTIONAL*/, // [in] prop options
DBID colid /*= DB_NULLID*/, // [in] col id
GUID guidPropertySet /*= DBPROPSET_COLUMN*/, // [in] the GUID of the propset
ULONG *pcPropSet /*= NULL*/, // [out] index of property set
ULONG *pcProp /*=NULL*/ // [out] index in the rgProperties array
)
{
BOOL fRes = FALSE;
ULONG cPropSet;
ULONG cProp;
TESTC(NULL != pvalue);
TESTC(SetProperty(prgPropertySets, pcPropertySets, DBPROP_COL_DEFAULT,
DBTYPE_I2, 0, dwOption, colid, DBPROPSET_COLUMN, &cPropSet, &cProp));
VariantCopy(&((*prgPropertySets)[cPropSet].rgProperties[cProp].vValue), pvalue);
if (pcPropSet)
*pcPropSet = cPropSet;
if (pcProp)
*pcProp = cProp;
fRes = TRUE;
CLEANUP:
return fRes;
} // TCITableDefinition::SetDefaultProperty
//---------------------------------------------------------------------------
// TCITableDefinition::Insert
//
// CTable |
// Insert |
// Inserts 1 row in table using IRowsetNewRow. This function is called
// by the pulic Insert function.
//
// @mfunc Insert
// @rdesc HRESULT indicating success or failure
// @flag S_OK | Function ran without problem
// @flag E_FAIL | No Columns Marked for use or SetNewData failed
//
//---------------------------------------------------------------------------
HRESULT TCITableDefinition::Insert(
DBCOUNTITEM ulRowNumber, // @parm [IN] Row number to insert (0 for next)
IUnknown *pIUnknown, // @parm [IN] Pointer to rowset interface
ULONG cNulls, // @parm [IN] Number of columns to be set to NULL (DEFAULT 0)
DBORDINAL *rgNulls, // @parm [IN] Array of columns to be set to NULL (DEFAULT NULL)
CTable *pTable // @parm [IN] Table (DEFAULT NULL - use m_pTable)
)
{
HRESULT hr = E_FAIL;
HACCESSOR hAccessor = NULL;
BYTE* pData = NULL;
DBCOUNTITEM cBindings = 0;
DBBINDING* rgBindings = NULL;
IDBProperties* pIDBProperties = NULL;
IGetDataSource* pIGetDataSource = NULL;
ULONG nBinding, nNull;
BOOL fFound;
IRowsetChange *pIRowsetChange = NULL;
IAccessor *pIAccessor = NULL;
ULONG cRefCounts = ULONG_MAX;
if (!pTable)
pTable = m_pTable;
// Find row number to use on insert
if (ulRowNumber == 0)
ulRowNumber = pTable->GetNextRowNumber();
TESTC(NULL != pIUnknown);
TESTC(VerifyInterface(pIUnknown, IID_IAccessor, ROWSET_INTERFACE, (IUnknown**)&pIAccessor));
TESTC(VerifyInterface(pIUnknown, IID_IRowsetChange, ROWSET_INTERFACE, (IUnknown**)&pIRowsetChange));
//Get the DataSource
TESTC(VerifyInterface(m_pIOpenRowset, IID_IGetDataSource, SESSION_INTERFACE, (IUnknown**)&pIGetDataSource));
TESTC_(hr = pIGetDataSource->GetDataSource(IID_IDBProperties, (IUnknown**)&pIDBProperties), S_OK);
//Get an accessor with all the writeable columns
TESTC_(hr = GetAccessorAndBindings(pIRowsetChange,
DBACCESSOR_ROWDATA,
&hAccessor, &rgBindings, &cBindings, NULL,
DBPART_VALUE |DBPART_STATUS |DBPART_LENGTH,
UPDATEABLE_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL,
NULL, NULL, DBTYPE_EMPTY, 0, NULL), S_OK);
// Fill buffer with appropriate data for insert of this row number
TESTC_(hr = FillInputBindings(
pTable,
DBACCESSOR_ROWDATA,
cBindings,
rgBindings,
&pData,
ulRowNumber,
0,
NULL),S_OK);
// set the NULL columns
for (nBinding = 0; nBinding < cBindings; nBinding++)
{
for (fFound = FALSE, nNull = 0; nNull < cNulls && !fFound; nNull++)
{
if (rgBindings[nBinding].iOrdinal == rgNulls[nNull])
{
*(DBSTATUS*)(pData+rgBindings[nBinding].obStatus) = DBSTATUS_S_ISNULL;
fFound = TRUE;
}
}
}
// release previous accessor and create a new one
hr = pIRowsetChange->InsertRow(NULL, hAccessor, pData, NULL);
if (DB_E_ERRORSOCCURRED == hr)
{
SHORT *pMyData;
for (ULONG i=0; i<cBindings; i++)
{
pMyData = (SHORT*)(pData+rgBindings[i].obStatus);
if (DBSTATUS_S_OK != *pMyData && DBSTATUS_E_UNAVAILABLE != *pMyData)
odtLog << "bindings " << i << "\n";
}
}
// We have successfully inserted if we got this far
pTable->AddRow(); //increments pTable->m_ulNextRow
CLEANUP:
if(hAccessor && pIAccessor)
{
pIAccessor->ReleaseAccessor(hAccessor, &cRefCounts);
COMPARE(cRefCounts,0);
}
SAFE_RELEASE(pIAccessor);
FreeAccessorBindings(cBindings, rgBindings);
PROVIDER_FREE(pData);
SAFE_RELEASE(pIRowsetChange);
SAFE_RELEASE(pIGetDataSource);
SAFE_RELEASE(pIDBProperties);
return hr;
} //TCITableDefinition::Insert
//--------------------------------------------------------------------------
//
// @cmember StartTransaction method
// RETURN
// S_OK - an isolation level could be set and a transaction started
// E_FAIL - could not start a transaction
//--------------------------------------------------------------------------
HRESULT TCITableDefinition::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;
} //TCITableDefinition::StartTransaction
//---------------------------------------------------------------------
//
// TCITableDefinition::AddColumnAndCheck
//
// Add a column to the table and check the result
// RETURN value is the ret value of ITableDefinition::AddColumn
//---------------------------------------------------------------------
HRESULT TCITableDefinition::AddColumnAndCheck(
DBID *pTableID, // [IN] table ID
DBCOLUMNDESC *pColumnDesc, // [IN] descriptor of the column to be added
DBID **ppColumnID, // [OUT] column ID for the resulted column
ITableDefinition *pITableDefinition,/*= NULL*/// [IN] pointer to ITableDefinition
DBID *pBaseTableID/*= NULL*/ // [IN] if provided, this is the table DBID that should be used
// in metadata comparison (e.g. pTableID might be the qualified name)
)
// sometimes there is not a unique expected result (e.g. one property could be supported or not)
// using Validate == FALSE you can protect the code from getting errors
{
DBCOLUMNDESC *rgOldCD = NULL;
DBORDINAL nOldlen = 0;
DBCOLUMNDESC *rgNewCD = NULL;
DBORDINAL nNewlen = 0;
DBCOLUMNDESC *pOriginalColumnDesc = NULL;
BOOL fRes = TRUE;
HRESULT hr = E_FAIL;
if (!pBaseTableID)
pBaseTableID = pTableID;
pITableDefinition = (NULL == pITableDefinition) ? m_pITableDefinition: pITableDefinition;
TESTC(NULL != pITableDefinition);
GetColumnDescOnTable(pBaseTableID, &rgOldCD, &nOldlen);
if (ppColumnID)
*ppColumnID = NULL;
CHECK(NULL == pColumnDesc
|| NULL != DuplicateColumnDesc(pColumnDesc, 1, &pOriginalColumnDesc), TRUE);
// here use pTableID, everywhere else use pBaseTableID
hr = pITableDefinition->AddColumn(pTableID, pColumnDesc, ppColumnID);
if ( pOriginalColumnDesc
&& !COMPARE(IsColumnDescPreserved(pOriginalColumnDesc, pColumnDesc, 1), TRUE))
{
odtLog << "\tERROR: column desc is not preserved\n";
}
// check the status of the column properties
COMPARE(CheckColPropStatus(1, pColumnDesc, hr), TRUE);
if (FAILED(hr) && ppColumnID)
COMPARE(NULL == *ppColumnID, TRUE);
// get the new stru of the table
GetColumnDescOnTable(pBaseTableID, &rgNewCD, &nNewlen);
// check the result of the operation
if (SUCCEEDED(hr))
// get info about the columns in the altered table and compare them, one by one!
COMPARE(CheckColInfo(rgOldCD, nOldlen, rgNewCD, nNewlen, pColumnDesc), TRUE);
else
// make sure that the table stru remained the same
COMPARE(AreColEqual(rgOldCD, nOldlen, rgNewCD, nNewlen), TRUE);
CLEANUP:
// save old values into the new ones and release the others
ReleaseColumnDesc(rgOldCD, nOldlen);
ReleaseColumnDesc(rgNewCD, nNewlen);
ReleaseColumnDesc(pOriginalColumnDesc, 1);
return hr;
} //TCITableDefinition::AddColumnAndCheck
//---------------------------------------------------------------------
//
// @member Create the table using ITableDefinition::CreateTable and
// check its creation
//---------------------------------------------------------------------
HRESULT TCITableDefinition::CreateAndCheckTable(
ITableDefinition *pITableDefinition, // [in] pointer to the ITableDefinition interface to be used
IUnknown *pUnkOuter, // [in] pointer to controlling unknown
DBID *pTableID, // [in] pointer to the input table ID
DBORDINAL cColumnDescs, // [in] the number of columns to be created
DBCOLUMNDESC *rgColumnDescs, // [in/out] array of columns to be created
REFIID riid, // [in] rowset interface to be returned
ULONG cPropertySets, // [in] number of roset property sets asked
DBPROPSET *rgPropertySets, // [in/out] array of rowset property sets
DBID **ppTableID, // [out] returned table ID
IUnknown **ppRowset // [out] pointer to outer interface
)
{
BOOL fExists;
DBORDINAL cOriginalColumnDescs = 0;
DBCOLUMNDESC *rgOriginalColumnDescs = NULL;
ULONG cOriginalPropertySets = 0;
DBPROPSET *rgOriginalPropertySets = NULL;
HRESULT hres;
DBID *pNewTableID = NULL;
CTable *pTable = new CTable(pITableDefinition, (LPWSTR)gwszModuleName);
IUnknown *pIUnknown = NULL; // used to pass the rowset pointer to AreColumnsCreatedOK
ASSERT(pTable);
ASSERT(pITableDefinition);
// save the original values
CHECK(0 == cColumnDescs || NULL == rgColumnDescs
|| NULL != DuplicateColumnDesc(rgColumnDescs, cColumnDescs, &rgOriginalColumnDescs), TRUE);
cOriginalColumnDescs = cColumnDescs;
CHECK(0 == cPropertySets || NULL == rgPropertySets
|| DuplicatePropertySets(cPropertySets, rgPropertySets, &cOriginalPropertySets, &rgOriginalPropertySets), TRUE);
// go for ITableDefinition::CreateTable
hres = pITableDefinition->CreateTable(pUnkOuter, pTableID, cColumnDescs, rgColumnDescs, riid,
cPropertySets, rgPropertySets, ppTableID, ppRowset);
if (SUCCEEDED(hres))
{
COMPARE(NULL == ppTableID || NULL != *ppTableID, TRUE);
}
else
{
COMPARE(NULL == ppTableID || NULL == *ppTableID, TRUE);
}
if (rgOriginalColumnDescs
&& !COMPARE(IsColumnDescPreserved(rgOriginalColumnDescs, rgColumnDescs, cColumnDescs), TRUE))
{
odtLog << "\tERROR: array of column desc is not preserved\n";
}
if ( rgOriginalPropertySets
&& !COMPARE(IsRowsetPropSetPreserved(rgOriginalPropertySets, rgPropertySets, cPropertySets), TRUE))
{
odtLog << "\tERROR: the rowset property sets are not preserved\n";
}
COMPARE(CheckRwstTblPropStatus(cPropertySets, rgPropertySets, hres), TRUE);
COMPARE(CheckColPropStatus(cColumnDescs, rgColumnDescs, hres), TRUE);
pNewTableID = (ppTableID)? (*ppTableID): pTableID;
// if the table creation was reported as succeding, the table should exist
if ( SUCCEEDED(hres)
&& (!CHECK(pTable->DoesTableExist(pNewTableID, &fExists), S_OK) || !fExists))
{
if (!fExists)
odtLog << "\tERROR: despite the return value reported, the table doesn't exist\n";
}
// if the table creation was reported as failed, the table should not exist
if ( FAILED(hres)
&& DB_E_DUPLICATETABLEID != hres
&& DB_E_NOTABLE != hres
&& pNewTableID
&& (!CHECK(pTable->DoesTableExist(pNewTableID, &fExists), S_OK) || fExists))
{
if (!fExists)
odtLog << "\tERROR: despite the return value reported, the table exists\n";
}
if (SUCCEEDED(hres))
{
pIUnknown = (ppRowset) ? (IUnknown*)(*ppRowset) : NULL;
COMPARE(AreColumnsCreatedOK(rgColumnDescs, cColumnDescs, pNewTableID, pIUnknown), TRUE);
if (ppRowset)
{
COMPARE(IsRowsetPropSetCreatedOK(rgPropertySets, cPropertySets, *ppRowset), TRUE);
COMPARE(!ppRowset || CheckRowset(*ppRowset), TRUE);
}
COMPARE(CheckReturnedDBID(pTableID, ppTableID), TRUE);
}
else
{
COMPARE(ppRowset && NULL == *ppRowset, TRUE);
COMPARE(!ppTableID || NULL == *ppTableID, TRUE);
}
delete pTable;
ReleaseColumnDesc(rgOriginalColumnDescs, cOriginalColumnDescs);
FreeProperties( &cOriginalPropertySets, &rgOriginalPropertySets);
return hres;
} //TCITableDefinition::CreateAndCheckTable
//---------------------------------------------------------------------
//
// @member Create the table using ITableDefinitionWithConstraints::CreateTableWithConstraints and
// check its creation
//---------------------------------------------------------------------
HRESULT TCITableDefinition::CreateAndCheckTableWithConstraints(
ITableDefinitionWithConstraints *pITableDefinitionWithConstraints, // [in] pointer to the ITableDefinitionWithConstraints interface to be used
IUnknown *pUnkOuter, // [in] pointer to controlling unknown
DBID *pTableID, // [in] pointer to the input table ID
DBORDINAL cColumnDescs, // [in] the number of columns to be created
DBCOLUMNDESC *rgColumnDescs, // [in/out] array of columns to be created
ULONG cConstraintDescs, // [in] the number of constraints to be created
DBCONSTRAINTDESC *rgConstraintDescs, // [in/out] array of constraints
REFIID riid, // [in] rowset interface to be returned
ULONG cPropertySets, // [in] number of roset property sets asked
DBPROPSET *rgPropertySets, // [in/out] array of rowset property sets
DBID **ppTableID, // [out] returned table ID
IUnknown **ppRowset // [out] pointer to outer interface
)
{
BOOL fExists;
DBORDINAL cOriginalColumnDescs = 0;
DBCOLUMNDESC *rgOriginalColumnDescs = NULL;
ULONG cOriginalPropertySets = 0;
DBPROPSET *rgOriginalPropertySets = NULL;
HRESULT hres;
DBID *pNewTableID = NULL;
CTable *pTable = new CTable(pITableDefinitionWithConstraints, (LPWSTR)gwszModuleName);
IUnknown *pIUnknown = NULL; // used to pass the rowset pointer to AreColumnsCreatedOK
CConstraints Constraints(pITableDefinitionWithConstraints);
DBORDINAL index;
ASSERT(pTable);
ASSERT(pITableDefinitionWithConstraints);
// save the original values
CHECK(0 == cColumnDescs || NULL == rgColumnDescs
|| NULL != DuplicateColumnDesc(rgColumnDescs, cColumnDescs, &rgOriginalColumnDescs), TRUE);
cOriginalColumnDescs = cColumnDescs;
CHECK(0 == cPropertySets || NULL == rgPropertySets
|| DuplicatePropertySets(cPropertySets, rgPropertySets, &cOriginalPropertySets, &rgOriginalPropertySets), TRUE);
// get original constraint set
if (pTableID && (DBKIND_NAME == pTableID->eKind) && pTableID->uName.pwszName)
{
CHECK(Constraints.GetConstraints(NULL, NULL, pTableID->uName.pwszName, NULL, NULL, NULL), S_OK);
}
// go for ITableDefinition::CreateTable
hres = pITableDefinitionWithConstraints->CreateTableWithConstraints(pUnkOuter,
pTableID, cColumnDescs, rgColumnDescs, cConstraintDescs, rgConstraintDescs,
riid, cPropertySets, rgPropertySets, ppTableID, ppRowset);
if ( rgOriginalColumnDescs
&& !COMPARE(IsColumnDescPreserved(rgOriginalColumnDescs, rgColumnDescs, cColumnDescs), TRUE))
{
odtLog << "\tERROR: array of column desc is not preserved\n";
}
if ( rgOriginalPropertySets
&& !COMPARE(IsRowsetPropSetPreserved(rgOriginalPropertySets, rgPropertySets, cPropertySets), TRUE))
{
odtLog << "\tERROR: the rowset property sets are not preserved\n";
}
COMPARE(CheckRwstTblPropStatus(cPropertySets, rgPropertySets, hres), TRUE);
COMPARE(CheckColPropStatus(cColumnDescs, rgColumnDescs, hres), TRUE);
pNewTableID = (ppTableID)? (*ppTableID): pTableID;
// if the table creation was reported as succeding, the table should exist
if ( SUCCEEDED(hres)
&& (!CHECK(pTable->DoesTableExist(pNewTableID, &fExists), S_OK) || !fExists))
{
if (!fExists)
odtLog << "\tERROR: despite the return value reported, the table doesn't exist\n";
}
// if the table creation was reported as failed, the table should not exist
if ( FAILED(hres)
&& DB_E_DUPLICATETABLEID != hres
&& DB_E_NOTABLE != hres
&& pNewTableID
&& (!CHECK(pTable->DoesTableExist(pNewTableID, &fExists), S_OK) || fExists))
{
if (!fExists)
odtLog << "\tERROR: despite the return value reported, the table exists\n";
}
if (SUCCEEDED(hres))
{
pIUnknown = (ppRowset) ? (IUnknown*)(*ppRowset) : NULL;
COMPARE(AreColumnsCreatedOK(rgColumnDescs, cColumnDescs, pNewTableID, pIUnknown), TRUE);
if (ppRowset)
{
COMPARE(IsRowsetPropSetCreatedOK(rgPropertySets, cPropertySets, *ppRowset), TRUE);
COMPARE(!ppRowset || CheckRowset(*ppRowset), TRUE);
}
COMPARE(CheckReturnedDBID(pTableID, ppTableID), TRUE);
// check constraint creation
if (pNewTableID && (DBKIND_NAME == pNewTableID->eKind) && pNewTableID->uName.pwszName)
{
CHECK(Constraints.GetConstraints(NULL, NULL, pNewTableID->uName.pwszName, NULL, NULL, NULL), S_OK);
// the number of constraints created is greater than or equal to cConstraintDescs
// this happens because the user can ask for some more constraints using column props
COMPARE(Constraints.GetConstrNo() >= cConstraintDescs, TRUE);
for (index = 0; index < cConstraintDescs; index++)
{
// BEWARE: if deferred flag was set without deferrable
// flag being set, constraint should be immediate
if (rgConstraintDescs[index].Deferrability == DBDEFERRABILITY_DEFERRABLE)
rgConstraintDescs[index].Deferrability = 0;
}
CHECK(Constraints.CheckIncludedConstraints(cConstraintDescs, rgConstraintDescs), S_OK);
}
}
else
{
COMPARE(NULL == ppRowset || NULL == *ppRowset, TRUE);
COMPARE(NULL == ppTableID || NULL == *ppTableID, TRUE);
// check no constraints existed on the table
if (DB_E_DUPLICATETABLEID == hres)
{
CHECK(Constraints.AreConstraintsPreserved(), S_OK);
}
else
{
// make sure no constraints exist for this table name (if not invalid)
if (pTableID && (DBKIND_NAME == pTableID->eKind) && pTableID->uName.pwszName)
{
CHECK(Constraints.GetConstraints(NULL, NULL, pTableID->uName.pwszName, NULL, NULL, NULL), S_OK);
COMPARE(Constraints.GetConstrNo(), 0);
}
}
}
delete pTable;
ReleaseColumnDesc(rgOriginalColumnDescs, cOriginalColumnDescs);
FreeProperties( &cOriginalPropertySets, &rgOriginalPropertySets);
return hres;
} //TCITableDefinition::CreateAndCheckTableWithConstraints
// Add a constraint to a table using ITableDefinitionWithConstraints::AddConstraint and check its creation
HRESULT TCITableDefinition::AddConstraintAndCheck(
ITableDefinitionWithConstraints *pITableDefinitionWithConstraints, // [in] pointer to the ITableDefinitionWithConstraints interface to be used
DBID *pTableID, // [in] pointer to the input table ID
DBCONSTRAINTDESC *pConstraintDesc, // [in] new constraint
BOOL fDifferentColTypesInFK
)
{
// this method assumes that the table indicated by pTableID does exist
HRESULT hr = E_FAIL;
HRESULT rgValidHRes[] = { S_OK,
E_FAIL,
E_INVALIDARG,
DB_E_DUPLICATECONSTRAINTID,
DB_E_BADCONSTRAINTID,
DB_E_BADCONSTRAINTTYPE,
DB_E_BADUPDATEDELETERULE,
DB_E_BADMATCHTYPE,
DB_E_BADDEFERRABILITY,
DB_E_BADCONSTRAINTFORM,
DB_E_NOCOLUMN,
DB_E_NOTABLE,
DB_E_TABLEINUSE,
DB_SEC_E_PERMISSIONDENIED,
XACT_E_XTIONEXISTS,
DB_E_SCHEMAVIOLATION
};
ULONG cValidHRes = NUMELEM(rgValidHRes);
CConstraints Constraints(pITableDefinitionWithConstraints);
DBID *pConstraintID;
ULONG index;
// keep trace of whether the constraint DBID was NULL
pConstraintID = pConstraintDesc? pConstraintDesc->pConstraintID: NULL;
TESTC(NULL != pITableDefinitionWithConstraints);
// get all the constraints associated with the table
if (pTableID && DBKIND_NAME == pTableID->eKind)
{
TESTC_(Constraints.GetConstraints(NULL, NULL, pTableID->uName.pwszName, NULL, NULL, NULL), S_OK);
}
else
{
TESTC_(Constraints.GetConstraints(NULL, NULL, NULL, NULL, NULL, NULL), S_OK);
}
hr = pITableDefinitionWithConstraints->AddConstraint(pTableID, pConstraintDesc);
// check that constraint ID is not modified if set to NULL
COMPARE(!pConstraintDesc || (pConstraintID == pConstraintDesc->pConstraintID), TRUE);
// check that the result is one of the expected results
TESTC(CheckResult(hr, cValidHRes, rgValidHRes));
if (FAILED(hr))
{
CHECK(Constraints.AreConstraintsPreserved(), S_OK);
}
else
{
TESTC(NULL != pTableID);
// check that the constraint was added
DBDEFERRABILITY def = pConstraintDesc->Deferrability;
// BEWARE: if deferred flag was set without deferrable
// flag being set, constraint should be immediate
if (pConstraintDesc->Deferrability == DBDEFERRABILITY_DEFERRABLE)
pConstraintDesc->Deferrability = 0;
CHECK(Constraints.CheckAddConstraints(1, pConstraintDesc), S_OK);
pConstraintDesc->Deferrability = def;
}
switch (hr)
{
case S_OK:
break;
case E_INVALIDARG:
// check the returned value condition (assume only one of them was set, if any)
TESTC( NULL == pTableID || NULL == pConstraintDesc
|| 0 < pConstraintDesc->cForeignKeyColumns && NULL == pConstraintDesc->rgForeignKeyColumnList
|| 0 < pConstraintDesc->cForeignKeyColumns && pConstraintDesc->cColumns != pConstraintDesc->cForeignKeyColumns
|| 0 < pConstraintDesc->cColumns && NULL == pConstraintDesc->rgColumnList
|| 0 != pConstraintDesc->cReserved && NULL == pConstraintDesc->rgReserved);
break;
case DB_E_BADCONSTRAINTID:
// conditions for DB_E_BADCONSTRAINTID
break;
case DB_E_DUPLICATECONSTRAINTID:
// condition for DB_E_DUPLICATECONSTRAINTID
if ( (NULL == Constraints[pConstraintDesc->pConstraintID])
&& (pTableID && DBKIND_NAME == pTableID->eKind))
{
DBCONSTRAINTDESC *pConstraintDesc = Constraints.GetConstraints();
// or there is a primary constraint on this table
for (index = 0; index < Constraints.GetConstrNo(); index++)
{
if (DBCONSTRAINTTYPE_PRIMARYKEY == pConstraintDesc->ConstraintType)
break;
}
TESTC(index < Constraints.GetConstrNo());
}
break;
case DB_E_BADCONSTRAINTTYPE:
// condition for DB_E_BADCONSTRAINTTYPE: ConstraintType was invalid or not supported by the provider
TESTC(DBCONSTRAINTTYPE_UNIQUE != pConstraintDesc->ConstraintType);
TESTC(DBCONSTRAINTTYPE_PRIMARYKEY != pConstraintDesc->ConstraintType);
TESTC(DBCONSTRAINTTYPE_FOREIGNKEY != pConstraintDesc->ConstraintType);
TESTC(DBCONSTRAINTTYPE_CHECK != pConstraintDesc->ConstraintType);
break;
case DB_E_BADUPDATEDELETERULE:
TESTC(DBCONSTRAINTTYPE_FOREIGNKEY == pConstraintDesc->ConstraintType);
break;
case DB_E_BADMATCHTYPE:
break;
case DB_E_BADDEFERRABILITY:
break;
case DB_E_BADCONSTRAINTFORM:
if (!( DBCONSTRAINTTYPE_FOREIGNKEY != pConstraintDesc->ConstraintType
&& (0 < pConstraintDesc->cForeignKeyColumns || NULL != pConstraintDesc->pReferencedTableID)
|| DBCONSTRAINTTYPE_CHECK == pConstraintDesc->ConstraintType && NULL == pConstraintDesc->pwszConstraintText
|| DBCONSTRAINTTYPE_CHECK == pConstraintDesc->ConstraintType && 0 != pConstraintDesc->cColumns
|| DBCONSTRAINTTYPE_CHECK != pConstraintDesc->ConstraintType && NULL != pConstraintDesc->pwszConstraintText
|| DBCONSTRAINTTYPE_FOREIGNKEY == pConstraintDesc->ConstraintType && 0 == pConstraintDesc->cForeignKeyColumns
|| ( DBCONSTRAINTTYPE_FOREIGNKEY == pConstraintDesc->ConstraintType
|| DBCONSTRAINTTYPE_PRIMARYKEY == pConstraintDesc->ConstraintType
|| DBCONSTRAINTTYPE_UNIQUE == pConstraintDesc->ConstraintType) && 0 == pConstraintDesc->cColumns
|| DBCONSTRAINTTYPE_FOREIGNKEY == pConstraintDesc->ConstraintType && NULL == pConstraintDesc->pReferencedTableID
))
{
// the only good alternative is that the columns in the referenced table and
// and the ones in the base table have different types
TESTC(fDifferentColTypesInFK);
}
// Note: the case when the column types of corresponding cols do not match in a FK is missing!
break;
case DB_E_NOCOLUMN:
// check that one of the columns referred does not exist in the table
// (either col in the base table or col in the referenced table for FK)
break;
case DB_E_NOTABLE:
// pReferencedTableID (for foreign keys) or pTableID does not exist
break;
case DB_E_TABLEINUSE:
case DB_SEC_E_PERMISSIONDENIED:
case DB_E_SCHEMAVIOLATION:
case XACT_E_XTIONEXISTS:
break;
case E_FAIL:
// this code is legal; caller should catch it if there
// is a more meaningful return value
break;
default:
TESTC(FALSE);
};
CLEANUP:
return hr;
} //TCITableDefinition::AddConstraintAndCheck
//---------------------------------------------------------------------
//
// Drop a constraint to a table using ITableDefinitionWithConstraints::DropConstraint and check its deletion
HRESULT TCITableDefinition::DropConstraintAndCheck(
ITableDefinitionWithConstraints *pITableDefinitionWithConstraints, // [in] pointer to the ITableDefinitionWithConstraints interface to be used
DBID *pTableID, // [in] pointer to the input table ID
DBID *pConstraintID // [in] pointer to the DBID of the constraint
)
{
HRESULT hr = E_FAIL;
HRESULT rgValidHRes[] = { S_OK,
E_FAIL,
E_INVALIDARG,
DB_E_NOCONSTRAINT,
DB_E_BADTABLEID,
DB_E_DROPRESTRICTED,
DB_E_NOTABLE,
DB_E_TABLEINUSE,
DB_SEC_E_PERMISSIONDENIED,
XACT_E_XTIONEXISTS,
DB_E_SCHEMAVIOLATION
};
DBORDINAL ulInitConstraints = 0;
ULONG cValidHRes = NUMELEM(rgValidHRes);
CConstraints Constraints(pITableDefinitionWithConstraints);
TESTC(NULL != pITableDefinitionWithConstraints);
// get all the constraints associated with the table
if (pTableID && DBKIND_NAME == pTableID->eKind)
{
CHECK(Constraints.GetConstraints(NULL, NULL, pTableID->uName.pwszName, NULL, NULL, NULL), S_OK);
ulInitConstraints = Constraints.GetConstrNo();
}
else
{
CHECK(Constraints.GetConstraints(NULL, NULL, NULL, NULL, NULL, NULL), S_OK);
}
// drop the constraint
hr = pITableDefinitionWithConstraints->DropConstraint(pTableID, pConstraintID);
// check that the result is one of the expected results
COMPARE(CheckResult(hr, cValidHRes, rgValidHRes), TRUE);
if (FAILED(hr))
{
CHECK(Constraints.AreConstraintsPreserved(), S_OK);
}
else
{
// check that the constraint was dropped
if (NULL != pTableID && DBKIND_NAME == pTableID->eKind)
{
CConstraints NewConstraints(pITableDefinitionWithConstraints);
CHECK(NewConstraints.GetConstraints(NULL, NULL, pTableID->uName.pwszName, NULL, NULL, NULL), S_OK);
COMPARE(NULL == NewConstraints[pConstraintID], TRUE);
COMPARE(ulInitConstraints-1, NewConstraints.GetConstrNo());
CHECK(Constraints.CheckIncludedConstraints(NewConstraints.GetConstrNo(),
NewConstraints.GetConstraints()), S_OK);
}
}
CLEANUP:
return hr;
} //TCITableDefinition::DropConstraintAndCheck
//---------------------------------------------------------------------
//
// @member Create the table using ITableDefinition::CreateTable,
// check its creation then drops the table and releases the rowset interface
//---------------------------------------------------------------------
HRESULT TCITableDefinition::CCNDropTable(
DBID *pTableID, // [in] pointer to the input table ID
DBORDINAL cColumnDescs, // [in] the number of columns to be created
DBCOLUMNDESC *rgColumnDescs, // [in/out] array of columns to be created
REFIID riid, // [in] rowset interface to be returned
ULONG cPropertySets, // [in] number of roset property sets asked
DBPROPSET *rgPropertySets, // [in/out] array of rowset property sets
BOOL fNullPPTableID/*=FALSE*/ // [in] if TRUE ppTableID will be NULL
)
{
HRESULT hr;
BOOL fExists;
DBID *pNewTableID = NULL;
DBID *pOutTableID = NULL; // [out] returned table ID
DBID **ppTableID = fNullPPTableID? NULL: &pOutTableID;
IUnknown *pRowset = NULL; // [out] pointer to outer interface
CTable *pTable = new CTable(m_pITableDefinition, (LPWSTR)gwszModuleName);
hr = CreateAndCheckTable(m_pITableDefinition, NULL, pTableID, cColumnDescs, rgColumnDescs, riid,
cPropertySets, rgPropertySets, ppTableID, &pRowset);
SAFE_RELEASE(pRowset);
pNewTableID = (ppTableID)? *ppTableID: pTableID;
if ( pNewTableID
&& DB_E_NOTABLE != hr
&& DB_E_DUPLICATETABLEID != hr
&& CHECK(pTable->DoesTableExist(pNewTableID, &fExists), S_OK)
&& fExists)
CHECK(m_pITableDefinition->DropTable(pNewTableID), S_OK);
delete pTable;
ReleaseDBID(pOutTableID);
return hr;
} //TCITableDefinition::CCNDropTable
//--------------------------------------------------------------------------
//
// @cmember Check whether the columns were properly created
// The columns of the m_pTable are checked against the column descriptor array <nl>
// returned by ITableDefinition::CreateTable method.
// RETURNS
// TRUE - everything is created ok
// FALSE - errors
//--------------------------------------------------------------------------
BOOL TCITableDefinition::AreColumnsCreatedOK(
DBCOLUMNDESC *rgOutColumnDesc, // [in] the aray returned by ITableDefinition::CreateTable
DBORDINAL cColumnDesc, // [in] the size of the arrays
DBID *pTableID/*=NULL*/, // [in] Table ID
IUnknown *pIUnknown/*=NULL*/ // [in] pointer to a rowset interface on the table
)
{
DBORDINAL cCDFromTable;
BOOL fTestRes = TRUE;
DBCOLUMNDESC *rgCDFromTable = NULL;
ULONG i;
CTable *pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
// get the descriptions of the columns in the table with DBID == m_pTable->GetTableID()
// the list of columns are stored in m_pTable->m_colList
GetColumnDescOnTable(pTableID? pTableID: &m_pTable->GetTableID(),
&rgCDFromTable, &cCDFromTable);
if (cColumnDesc != cCDFromTable)
{
odtLog << "the number of columns asked and created does not fit";
fTestRes = FALSE;
goto CLEANUP;
}
for (i=0; i<cColumnDesc; i++)
{
fTestRes = fTestRes && CompareColumnDesc(&rgOutColumnDesc[i], &rgCDFromTable[i]);
}
CLEANUP:
ReleaseColumnDesc(rgCDFromTable, cCDFromTable);
delete pTable;
return fTestRes;
} //TCITableDefinition::AreColumnsCreatedOK
//--------------------------------------------------------------------
//
// @member Check properties on rowseet and table
// returns TRUE if the prop set is set correctly
// FALSE otherwise
//--------------------------------------------------------------------
BOOL TCITableDefinition::CheckRwstTblPropStatus(
ULONG cPropSets, // [in] the size of the propset array
DBPROPSET *rgPropSets, // [in] propset array
HRESULT hr // [in] the result of the previous op
)
{
GUID guidExpectedPS;
ULONG cPropSet;
ULONG cProp;
BOOL fRes = TRUE;
if (!rgPropSets)
return TRUE;
for (cPropSet = 0; cPropSet < cPropSets; cPropSet++)
{
if (!rgPropSets[cPropSet].rgProperties)
continue;
guidExpectedPS = rgPropSets[cPropSet].guidPropertySet == DBPROPSET_ROWSET? DBPROPSET_ROWSET: DBPROPSET_TABLE;
for (cProp = 0; cProp < rgPropSets[cPropSet].cProperties; cProp++)
{
fRes = fRes && CheckPropertyStatus(rgPropSets[cPropSet].guidPropertySet, guidExpectedPS,
&rgPropSets[cPropSet].rgProperties[cProp], hr);
}
}
return fRes;
} //TCITableDefinition::CheckRwstTblPropStatus
//--------------------------------------------------------------------------
//
// @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 TCITableDefinition::IsRowsetPropSetPreserved
(
DBPROPSET *rgInPropertySets, // the array passed to ITableDefinition::CreateTable
DBPROPSET *rgOutPropertySets, // the aray returned by ITableDefinition::CreateTable
ULONG cPropertySets // the size of the arrays
)
{
ULONG ps, pc;
if (NULL == rgInPropertySets)
return TRUE;
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;
if (NULL == rgInPropertySets[ps].rgProperties)
continue;
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;
// use NULL for DSO interface
if (!COMPARE(CompareDBID(rgInPropertySets[ps].rgProperties[pc].colid,
rgOutPropertySets[ps].rgProperties[pc].colid,
NULL), TRUE))
return FALSE;
if (!COMPARE(CompareVariant(&rgInPropertySets[ps].rgProperties[pc].vValue,
&rgOutPropertySets[ps].rgProperties[pc].vValue), TRUE))
return FALSE;
}
}
return TRUE;
} //TCITableDefinition::IsRowsetPropSetPreserved
//--------------------------------------------------------------------------
//
// @cmember Check whether the rowset properties were properly created
// The rowset properties of the m_pTable are checked against the property set<nl>
// returned by ITableDefinition::CreateTable method.
//--------------------------------------------------------------------------
BOOL TCITableDefinition::IsRowsetPropSetCreatedOK
(
DBPROPSET *rgOutPropertySets, // the aray returned by ITableDefinition::CreateTable
ULONG cPropertySets, // the size of the arrays
IUnknown *pIUnknown // pointer to the rowset interface
)
{
IRowsetInfo *pIRowsetInfo = NULL;
DBPROPIDSET *rgPropIDSet = NULL;
DBPROPSET *rgPropertySets = NULL;
ULONG n;
BOOL fTestRes = TEST_PASS;
DBPROPSTATUS ulStatus;
DBPROPOPTIONS ulOption;
DBPROPID ulPropID;
BOOL fSupported;
BOOL fSettable;
VARIANT *pvValue;
if (!pIUnknown || 0 == cPropertySets || !rgOutPropertySets)
return TRUE;
rgPropIDSet = (DBPROPIDSET*) PROVIDER_ALLOC(sizeof(DBPROPIDSET)*cPropertySets);
for (n=0; n<cPropertySets; n++)
{
// get propID in the property set
rgPropIDSet[n].guidPropertySet = rgOutPropertySets[n].guidPropertySet;
rgPropIDSet[n].cPropertyIDs = rgOutPropertySets[n].cProperties;
if (0 == rgOutPropertySets[n].rgProperties)
{
rgPropIDSet[n].rgPropertyIDs = NULL;
continue;
}
else
SAFE_ALLOC(rgPropIDSet[n].rgPropertyIDs, DBPROPID, rgOutPropertySets[n].cProperties);
for (ULONG i=0; i<rgOutPropertySets[n].cProperties; i++)
{
rgPropIDSet[n].rgPropertyIDs[i] = rgOutPropertySets[n].rgProperties[i].dwPropertyID;
}
}
// get the properties of the rowset
if (!VerifyInterface(pIUnknown, IID_IRowsetInfo, ROWSET_INTERFACE, (IUnknown**)&pIRowsetInfo))
{
fTestRes = TEST_FAIL;
goto CLEANUP;
}
else
{
m_hr = pIRowsetInfo->GetProperties(cPropertySets, rgPropIDSet, &n, &rgPropertySets);
ASSERT(n==cPropertySets);
}
if (NULL == rgPropertySets)
{
fTestRes = TEST_FAIL;
goto CLEANUP;
}
// check the properties
for (n=0; n<cPropertySets; n++)
{
// get propID in the property set
if (DBPROPSET_TABLE == rgOutPropertySets[n].guidPropertySet)
continue;
if (0 == rgOutPropertySets[n].cProperties)
continue;
if (rgPropertySets[n].cProperties != rgOutPropertySets[n].cProperties)
fTestRes = TEST_FAIL;
if (NULL == rgOutPropertySets[n].rgProperties)
continue;
if (NULL == rgPropertySets[n].rgProperties)
{
fTestRes = TEST_FAIL;
continue;
}
// check dbpropstatus
if (!CHECK(DBPROPSET_ROWSET == rgOutPropertySets[n].guidPropertySet, TRUE))
{
for (ULONG i=0; i<rgOutPropertySets[n].cProperties; i++)
if (!COMPARE(rgOutPropertySets[n].rgProperties[i].dwStatus, DBPROPSTATUS_NOTSUPPORTED))
fTestRes = TEST_FAIL;
continue;
}
for (ULONG i=0; i<rgOutPropertySets[n].cProperties; i++)
{
ulPropID = rgOutPropertySets[n].rgProperties[i].dwPropertyID;
ulOption = rgOutPropertySets[n].rgProperties[i].dwStatus;
ulStatus = rgOutPropertySets[n].rgProperties[i].dwOptions;
fSupported = SupportedProperty(ulPropID, DBPROPSET_ROWSET);
fSettable = SettableProperty(ulPropID, DBPROPSET_ROWSET);
pvValue = &rgOutPropertySets[n].rgProperties[i].vValue;
if (!fSupported)
{
fTestRes = DBPROPSTATUS_NOTSUPPORTED == ulStatus? fTestRes : TEST_FAIL;
continue;
}
// property is supported => cannot be sure that setting a prop will fail
// if is settable, the prop should succeed, unless a bad value is tried
if (DBPROPSTATUS_OK == ulStatus)
{
if (ulPropID != rgOutPropertySets[n].rgProperties[i].dwPropertyID)
fTestRes = TEST_FAIL;
if (!CompareVariant(pvValue, &rgOutPropertySets[n].rgProperties[i].vValue))
{
fTestRes = TEST_FAIL;
odtLog << "Rowset property values missmatch for property propID("
<< rgOutPropertySets[n].rgProperties[i].dwPropertyID << ")\n";
}
}
switch (ulStatus)
{
case DBPROPSTATUS_CONFLICTING:
fTestRes = (DBPROPOPTIONS_OPTIONAL == ulOption || DBPROPOPTIONS_REQUIRED == ulOption)
&& pvValue->vt == GetPropInfoType(ulPropID, DBPROPSET_ROWSET)? fTestRes : TEST_FAIL;
break;
case DBPROPSTATUS_NOTSET:
fTestRes = COMPARE(ulOption, DBPROPOPTIONS_OPTIONAL)
&& pvValue->vt == GetPropInfoType(ulPropID, DBPROPSET_ROWSET)? fTestRes : TEST_FAIL;
break;
case DBPROPSTATUS_BADOPTION:
fTestRes = (DBPROPOPTIONS_OPTIONAL != ulOption)
&& (DBPROPOPTIONS_REQUIRED)? fTestRes : TEST_FAIL;
break;
case DBPROPSTATUS_NOTSETTABLE:
fTestRes = !fSettable? fTestRes: TEST_FAIL;
break;
case DBPROPSTATUS_BADVALUE:
fTestRes = (VT_EMPTY != pvValue->vt)
&& (pvValue->vt != GetPropInfoType(ulPropID, DBPROPSET_ROWSET))
? fTestRes : TEST_FAIL;
}
}
}
CLEANUP:
SAFE_RELEASE(pIRowsetInfo);
for (n=0; n<cPropertySets; n++)
PROVIDER_FREE(rgPropIDSet[n].rgPropertyIDs);
PROVIDER_FREE(rgPropIDSet);
FreeProperties( &cPropertySets, &rgPropertySets);
return fTestRes;
} //TCITableDefinition::IsRowsetPropSetCreatedOK
//--------------------------------------------------------------------------
//
// @cmember Creates a table with a column of each provider type and returns a rowset
// to the new created table. The rowset is created with the property required and it
// is tested
//--------------------------------------------------------------------------
int TCITableDefinition::CreateWithOneRowsetProps
(
DBPROPID PropID, // Property ID
DBTYPE DBType, // type of property value
LPVOID Value, // value to be set
struct _GUID *pRIID // interface asked on rowset
)
{
DBTYPE rgDBTypes[] = {DBType};
LPVOID rgValues[] = {Value};
DBPROPOPTIONS rgOptions[] = {DBPROPOPTIONS_OPTIONAL};
DBPROPOPTIONS rgOptions2[] = {DBPROPOPTIONS_REQUIRED};
return CreateWithRowsetProps(1, &PropID, rgDBTypes, rgValues, rgOptions, pRIID)
&& CreateWithRowsetProps(1, &PropID, rgDBTypes, rgValues, rgOptions2, pRIID);
} //TCITableDefinition::CreateWithOneRowsetProps
//--------------------------------------------------------------------------
//
// @cmember Creates a table with a column of each provider type and returns a rowset
// to the new created table. The rowset is created with the properties required and it
// is tested
//--------------------------------------------------------------------------
BOOL TCITableDefinition::CreateWithRowsetProps
(
ULONG nProperties, // number of the properties to be set
DBPROPID *rgPropID, // array with the propIDs
DBTYPE *rgDBType, // type of property values
LPVOID *rgValue, // values to be set
DBPROPOPTIONS *rgOptions, // options of properties
struct _GUID *pRIID // interface asked on rowset
)
{
BOOL fRes = FALSE;
DBPROPSET *rgPropertySets = NULL;
ULONG n, cPropertySets = 0;
HRESULT hr = E_FAIL;
CCol col;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
BOOL fExists;
DBID *pTableID = NULL;
IUnknown *pRowset = NULL; // [out] pointer to outer interface
CTable *pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
TESTC(nProperties);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
for (n=0; n<nProperties; n++)
{
SetProperty(&rgPropertySets, &cPropertySets, rgPropID[n],
rgDBType[n], rgValue[n], rgOptions[n], DB_NULLID, DBPROPSET_ROWSET);
}
hr = CreateAndCheckTable(m_pITableDefinition, NULL, NULL, cColumnDesc, rgColumnDesc, *pRIID,
cPropertySets, rgPropertySets, &pTableID, &pRowset);
SAFE_RELEASE(pRowset);
if ( pTableID
&& DB_E_NOTABLE != hr
&& DB_E_DUPLICATETABLEID != hr
&& CHECK(pTable->DoesTableExist(pTableID, &fExists), S_OK)
&& fExists)
CHECK(m_pITableDefinition->DropTable(pTableID), S_OK);
delete pTable;
ReleaseDBID(pTableID);
if (FAILED(hr))
{
odtLog << "Could not create a table with a specified property set.\n";
if ( (1 == nProperties)
&& (DBPROPSTATUS_OK != rgPropertySets[0].rgProperties[0].dwStatus)
&& ( (DBPROPOPTIONS_REQUIRED == rgPropertySets[0].rgProperties[0].dwStatus)
&& !CHECK(hr, DB_E_ERRORSOCCURRED)))
{
odtLog << "wrong value for dwStatus in rowset property";
goto CLEANUP;
}
}
else
// check the creation of the rowset
if ( (1 == nProperties)
&& ( ( (DBPROPSTATUS_OK == rgPropertySets[0].rgProperties[0].dwStatus)
&& !CHECK(hr, S_OK))
|| ( (DBPROPSTATUS_OK != rgPropertySets[0].rgProperties[0].dwStatus)
&& !CHECK(hr, DB_S_ERRORSOCCURRED))))
{
odtLog << "wrong value for dwStatus in rowset property";
goto CLEANUP;
}
fRes = TRUE;
CLEANUP:
FreeProperties( &cPropertySets, &rgPropertySets);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
return fRes;
} //TCITableDefinition::CreateWithRowsetProps
//--------------------------------------------------------------------------
//
// creates a table with not nullable column
//--------------------------------------------------------------------------
HRESULT TCITableDefinition::CreateTableWithNoNullableColumns(
CTable *pTable, // @param [IN] pointer to CTable
DBCOUNTITEM ulRowCount, // @parm [IN] # of Rows to insert into table, 1 based
DBORDINAL ulIndex /*=0*/, // @parm [IN] Column Number of index, 1 based (Default=1)
WCHAR *pwszTableName/*=NULL*/, // @parm [IN] TableName, if NULL call MakeTableName() (Default=NULL)
EVALUE eValue/*=PRIMARY*/, // @parm [IN] Insert PRIMARY or SECONDARY data (Default=PRIMARY)
BOOL fFirstUpdateable/*=FALSE*/ // @parm [IN] TRUE means first column will be autoinc (Default=FALSE)
)
{
HRESULT hr = E_FAIL;
// customize the table so that no nullable columns is added
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBORDINAL indexCol;
// create a new table with a NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
for (indexCol = 0; indexCol < m_cColumnDesc; indexCol++)
{
SetProperty(&rgNewColumnDesc[indexCol].rgPropertySets, &rgNewColumnDesc[indexCol].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
}
// by setting DBCOLUMNDESC, all nullable type column are created as nullable
pTable->SetColumnDesc(rgNewColumnDesc, m_cColumnDesc);
pTable->SetBuildColumnDesc(FALSE);
TESTC_(pTable->CreateTable(ulRowCount, ulIndex, pwszTableName, eValue, fFirstUpdateable), S_OK);
pTable->AddInfoFromColumnsSchemaRowset(m_pITableDefinition, pTable->GetTableName());
hr = S_OK;
CLEANUP:
return hr;
} //TCITableDefinition::CreateTableWithNoNullableColumns
HRESULT TCITableDefinition::AddUniqueConstraint(
CTable *pTable,
DBORDINAL ulCol,
DBDEFERRABILITY Deferrability /*= 0*/
)
{
return AddKeyConstraint(DBCONSTRAINTTYPE_UNIQUE, pTable, 1, &ulCol, Deferrability);
} //TCITableDefinition::AddUniqueConstraint
HRESULT TCITableDefinition::AddUniqueConstraint(
CTable *pTable,
DBORDINAL cCol,
DBORDINAL *rgCol,
DBDEFERRABILITY Deferrability /*= 0*/
)
{
return AddKeyConstraint(DBCONSTRAINTTYPE_UNIQUE, pTable, cCol, rgCol, Deferrability);
} //TCITableDefinition::AddUniqueConstraint
HRESULT TCITableDefinition::AddPrimaryKeyConstraint(
CTable *pTable,
DBORDINAL ulCol,
DBDEFERRABILITY Deferrability /*= 0*/
)
{
return AddKeyConstraint(DBCONSTRAINTTYPE_PRIMARYKEY, pTable, 1, &ulCol, Deferrability);
} //TCITableDefinition::AddPrimaryKeyConstraint
HRESULT TCITableDefinition::AddPrimaryKeyConstraint(
CTable *pTable,
DBORDINAL cCol,
DBORDINAL *rgCol,
DBDEFERRABILITY Deferrability /*= 0*/
)
{
return AddKeyConstraint(DBCONSTRAINTTYPE_PRIMARYKEY, pTable, cCol, rgCol, Deferrability);
} //TCITableDefinition::AddPrimaryKeyConstraint
HRESULT TCITableDefinition::AddKeyConstraint(
DBCONSTRAINTTYPE ConstraintType,
CTable *pTable,
DBORDINAL cCol,
DBORDINAL *rgCol,
DBDEFERRABILITY Deferrability /*= 0*/
)
{
HRESULT hr = E_FAIL;
CCol col;
CKeyConstraint cons(ConstraintType);
DBORDINAL ulRow;
TESTC(NULL != m_pITDWC);
TESTC(NULL != pTable);
TESTC(0 == cCol || NULL != rgCol);
TESTC(DBCONSTRAINTTYPE_UNIQUE == ConstraintType || DBCONSTRAINTTYPE_PRIMARYKEY == ConstraintType);
TESTC_(cons.SetConstraint(pTable, cCol, rgCol, Deferrability), S_OK);
TESTC_(pTable->GetColInfo(rgCol[0], col), S_OK);
hr = AddConstraintAndCheck(m_pITDWC, &pTable->GetTableID(), cons);
// check that inserting a row with duplicate key is not accepted
if (SUCCEEDED(hr))
{
ulRow = pTable->GetNextRowNumber();
// check that you can not add a row to the base table (no nulls are inserted, right?)
if (S_OK == pTable->Insert(ulRow))
CHECK(pTable->Insert(ulRow), DB_E_INTEGRITYVIOLATION);
}
CLEANUP:
return hr;
} // TCITableDefinition::AddKeyConstraint
HRESULT TCITableDefinition::AddForeignKeyConstraint(
CTable *pBaseTable,
DBORDINAL cBaseCol,
DBORDINAL *rgBaseCol,
CTable *pReferencedTable,
DBORDINAL cReferencedCol,
DBORDINAL *rgReferencedCol,
DBMATCHTYPE MatchType /*= DBMATCHTYPE_FULL*/,
DBUPDELRULE UpdateRule /*= DBUPDELRULE_NOACTION*/,
DBUPDELRULE DeleteRule /*= DBUPDELRULE_NOACTION*/,
DBDEFERRABILITY Deferrability /*= 0*/
)
{
HRESULT hr = E_FAIL;
CForeignKeyCons cons;
DBORDINAL ulRow;
DBORDINAL index;
DBORDINAL ulMaxCol;
TESTC_(cons.SetConstraint(pBaseTable, cBaseCol, rgBaseCol,
pReferencedTable, cReferencedCol, rgReferencedCol,
MatchType, UpdateRule, DeleteRule, Deferrability), S_OK);
hr = AddConstraintAndCheck(m_pITDWC, &pBaseTable->GetTableID(), cons);
if (S_OK == hr)
{
// find the maximum column of the foreign key
for (index = 1, ulMaxCol = rgBaseCol[0]; index < cBaseCol; index++)
{
ulMaxCol = (ulMaxCol < rgBaseCol[index])? rgBaseCol[index]: ulMaxCol;
}
ulRow = pReferencedTable->GetNextRowNumber();
ulRow = (ulRow <= ulMaxCol)? ulMaxCol + 1: ulRow;
// check that you can not add a row to the base table (no nulls are inserted, right?)
// Note: if there is a NULL column in the foreign key schema this insert
// rightfully succeeds
TEST2C_(pBaseTable->Insert(ulRow), DB_E_INTEGRITYVIOLATION, E_FAIL);
// check that you can add a row to the referenced table
CHECK(pReferencedTable->Insert(ulRow), S_OK);
// check that you can now add a row to the base table
CHECK(pBaseTable->Insert(ulRow), S_OK);
}
CLEANUP:
return hr;
} // TCITableDefinition::AddForeignKeyConstraint
//--------------------------------------------------------------------------
//
// @cmember Termination function
//--------------------------------------------------------------------------
BOOL TCITableDefinition::Terminate()
{
DeleteCriticalSection(&m_CriticalSection);
ULONG nTables;
nTables = GetNoOfTables();
ReleaseColumnDesc(m_rgColumnDesc, m_cColumnDesc);
if (nTables>m_nTables)
odtLog << "Numer of residual tables: " << nTables-m_nTables << "\n";
nResidualTables += nTables-m_nTables;
SAFE_RELEASE(m_pITableDefinition);
SAFE_RELEASE(m_pITDWC);
ReleaseDBSession();
ReleaseDataSourceObject();
m_ColList.RemoveAll();
PROVIDER_FREE(m_pwszInvalidTableChars);
PROVIDER_FREE(m_pwszInvalidColChars);
return(CSessionObject::Terminate());
} //TCITableDefinition::Terminate
// {{ TCW_TC_PROTOTYPE(TCAddColumn)
//*-----------------------------------------------------------------------
//| Test Case: TCAddColumn - Testcase for ITableDefinition::AddColumn
//| Created: 09/10/97
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCAddColumn::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCITableDefinition::Init())
// }}
{
//
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Table doesn't exist => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_1()
{
BOOL fTestRes = TEST_PASS, fExists;
DBID TableID;
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
ULONG cColumnDesc = 1;
DuplicateColumnDesc(m_rgColumnDesc, cColumnDesc, &rgColumnDesc);
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
TableID.eKind = DBKIND_NAME;
// CTable::MakeTableName() generates a name that doesn't exist in the catalog
m_pTable->MakeTableName(NULL);
TableID.uName.pwszName = m_pTable->GetTableName();
// try to add a column on this table that doesn't exist
if (!CHECK(m_hr = m_pITableDefinition->AddColumn(&TableID, rgColumnDesc, &pColumnID), DB_E_NOTABLE))
fTestRes = TEST_FAIL;
if (!CHECK(m_pTable->DoesTableExist(&TableID, &fExists), S_OK) || fExists)
{
odtLog << "Table " << TableID.uName.pwszName << " was added by AddColumn!\n";
fTestRes = TEST_FAIL;
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
return fTestRes;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc The table is in use => DB_E_TABLEINUSE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_2()
{
TBEGIN
DBID *pColumnID = NULL;
IRowset *pIRowset = NULL;
IRowsetChange *pIRowsetChange = NULL;
IRowsetChange *pIRowsetChange2 = NULL;
HRESULT hr;
HACCESSOR hAccessor = NULL;
BYTE *pData = NULL;
DBCOUNTITEM cBindings = 0;
DBBINDING *rgBindings = NULL;
const DBORDINAL cColsToBind = 1;
LONG_PTR rgColsToBind[cColsToBind];
HROW *rghRow = NULL;
DBCOUNTITEM cRowsObtained = 0;
DBPROPSET rgPropSets[1];
DBPROP rgProperties[1];
DBLENGTH ulRowSize;
DBCOUNTITEM nRowNo;
DBCOUNTITEM nRowsInTable = 0;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
const DBCOUNTITEM nRowsToInsert = 10;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
m_pTable->SetBuildColumnDesc(FALSE);
// ask for a IRowsetChange interface
m_pTable->SetRowset((IUnknown**)&pIRowsetChange);
if (SettableProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET))
m_pTable->SetRIID((struct _GUID*)&IID_IRowsetChange);
else
m_pTable->SetRIID((struct _GUID*)&IID_IRowset);
// Set properties
FILL_PROP_SET(rgPropSets[0], 1, rgProperties, DBPROPSET_ROWSET);
FILL_PROP(rgProperties[0], DBPROP_OWNINSERT, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
m_pTable->SetPropertySets(rgPropSets, NUMELEM(rgPropSets));
// creates the table and populates it, using the returned pIRowsetChange
TESTC_(hr = m_pTable->CreateTable(0, 0), S_OK);
// check whether iRowsetChange is available
VerifyInterface(pIRowsetChange, IID_IRowsetChange, ROWSET_INTERFACE, (IUnknown**)&pIRowsetChange2);
if (pIRowsetChange2)
{
for (nRowNo = 0; nRowNo < nRowsToInsert; nRowNo++)
{
if (S_OK == Insert(0, (IUnknown*)pIRowsetChange))
nRowsInTable++;
}
}
TESTC(VerifyInterface(pIRowsetChange, IID_IRowset, ROWSET_INTERFACE, (IUnknown**)&pIRowset));
// get a row
if (0 < nRowsInTable)
{
m_hr = pIRowset->GetNextRows(0, 0, // hChapter & lRowsOffset
1, // number of rows to be retrieved
&cRowsObtained, //number of rows actually get
&rghRow // array of handlers to rows
);
if (!CHECK(m_hr, S_OK))
{
odtLog << "insuccess on initial IRowset::GetNextRows\n";
m_hr = pIRowset->ReleaseRows(cRowsObtained, rghRow, NULL, NULL, NULL);
}
// test the return value of IRowset::RestartPosition
CHECK(m_hr = pIRowset->ReleaseRows(cRowsObtained, rghRow, NULL, NULL, NULL), S_OK);
PROVIDER_FREE(rghRow);
cRowsObtained = 0;
}
else
odtLog << "Could not insert any row in the table\n";
// check if a column can be added, on the table in use (look for S_OK or DB_E_TABLEINUSE)
hr = AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[cColumnDesc-1],
&pColumnID);
if (hr == S_OK)
{
odtLog << "Column was added while a rowset was still open on table.\n";
if (1 > nRowsInTable)
goto CLEANUP;
// see how it reacts to RestartPosition and if the new column can be read
hr = pIRowset->RestartPosition(0); // a non-chaptered rowset
if (hr == DB_S_COLUMNSCHANGED)
{
odtLog << "DB_S_COLUMNSCHANGED returned on pIRowset->RestartPosition\n";
// get the value of the new column in the first row
//Get an accessor with all the writeable columns
rgColsToBind[0] = (LONG_PTR)cColumnDesc-1;
if (!CHECK(hr = GetAccessorAndBindings(
pIRowset, // pIUnknRowsetObject
DBACCESSOR_ROWDATA, // accessor flags
&hAccessor, &rgBindings, &cBindings, // accessor handler, array and number of bindings created
&ulRowSize, // [OUT] row size
DBPART_VALUE |DBPART_STATUS |DBPART_LENGTH, // types of bindings to do
USE_COLS_TO_BIND_ARRAY, // eColsByRef specifies that cols to be bind
// are given as an array
FORWARD, // eBindingOrder
NO_COLS_BY_REF, // eColsByRef
NULL, NULL,
NULL, DBTYPE_EMPTY, // ppStringsBufferOut & dwModifier
1, rgColsToBind // size and array of cols to be bind
), S_OK))
{
odtLog << "problems getting accessor and bindings\n";
}
// alloc memory for the row data
SAFE_ALLOC(pData, BYTE, ulRowSize);
// get the rowset window
m_hr = pIRowset->GetNextRows(0, 0, // hChapter & lRowsOffset
1, // number of rows to be retrieved
&cRowsObtained, //number of rows actually get
&rghRow // array of handlers to rows
);
if (S_OK != m_hr || !COMPARE(1 == cRowsObtained, TRUE))
{
odtLog << "after RestartPosition, could not get the rows\n";
CHECK(m_hr = pIRowset->ReleaseRows(cRowsObtained, rghRow, NULL, NULL, NULL), S_OK);
goto CLEANUP;
}
// read data
CHECK(m_hr = pIRowset->GetData(rghRow[0], hAccessor, pData), S_OK);
if ((S_OK != m_hr) ||
((DBSTATUS_S_OK != ((DATA*)pData)->sStatus) &&
!COMPARE(DBSTATUS_S_ISNULL == ((DATA*)pData)->sStatus, TRUE) ))
{
odtLog << "can't get the data from the newly created column\n";
}
else
odtLog << "data read!\n";
CHECK(m_hr = pIRowset->ReleaseRows(cRowsObtained, rghRow, NULL, NULL, NULL), S_OK);
}
}
else
{
odtLog << "DB_E_TABLEINUSE was returned when a column was to be added on a table whith an open rowset.\n";
CHECK(hr, DB_E_TABLEINUSE);
}
CLEANUP:
m_pTable->SetRowset(NULL);
SAFE_RELEASE(pIRowsetChange2);
SAFE_RELEASE(pIRowset);
SAFE_FREE(pData);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
m_pTable->SetNoOfPropertySets(0);
m_pTable->SetPropertySets(NULL);
CHECK(m_pTable->DropTable(), S_OK);
ReleaseDBID(pColumnID);
FreeAccessorBindings(cBindings, rgBindings);
SAFE_FREE(pData);
SAFE_FREE(rghRow);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc *pTableID = DB_NULLID => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_3()
{
BOOL fTestRes = TEST_PASS;
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
ULONG cColumnDesc = 1;
DuplicateColumnDesc(m_rgColumnDesc, cColumnDesc, &rgColumnDesc);
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// try to add a column from this table that doesn't exist
if (!CHECK(m_pITableDefinition->AddColumn((DBID*)&DB_NULLID, rgColumnDesc, &pColumnID), DB_E_NOTABLE))
fTestRes = TEST_FAIL;
ReleaseDBID(pColumnID);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
return fTestRes;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc pTableID = NULL => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_4()
{
BOOL fTestRes = TEST_PASS;
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
ULONG cColumnDesc = 1;
DuplicateColumnDesc(m_rgColumnDesc, cColumnDesc, &rgColumnDesc);
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// try to add a column from this table that doesn't exist
if (!CHECK(m_hr = m_pITableDefinition->AddColumn(NULL, rgColumnDesc, &pColumnID), E_INVALIDARG))
fTestRes = TEST_FAIL;
ReleaseDBID(pColumnID);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
return fTestRes;
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Maximum length for table name => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_5()
{
TBEGIN
DBID TableID;
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = BuildValidName(m_cMaxTableName, m_pTable->GetTableName());
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
m_pTable->SetBuildColumnDesc(FALSE);
PRVTRACE(L"***TCADDColumn::Variation_5(): TableName=%s, len=%d\n",
TableID.uName.pwszName, wcslen(TableID.uName.pwszName));
TESTC_(m_pTable->CreateTable(0, 0, TableID.uName.pwszName), S_OK);
// try to add a column to this maximum length name table
// prepare the column to be added
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[cColumnDesc-1], &pColumnID), S_OK);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
ReleaseDBID(&TableID, FALSE); // don't want to release the pointer, just the container
ReleaseDBID(pColumnID);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc the table name is 1 char too long => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_6()
{
TBEGIN
DBID TableID;
DBID *pColumnID = NULL;
WCHAR *pwszTableName;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
GetLiteralInfo();
TableID.uName.pwszName = BuildValidName(m_cMaxTableName, m_pTable->GetTableName());
pwszTableName = BuildValidName(m_cMaxTableName+1, m_pTable->GetTableName());
// prepare arguments for table creation
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
m_pTable->SetBuildColumnDesc(FALSE);
PRVTRACE(L"***TCADDColumn::Variation_6(): TableName=%s, len=%d\n", TableID.uName.pwszName,
wcslen(TableID.uName.pwszName));
TESTC_(m_pTable->CreateTable(0, 0, TableID.uName.pwszName), S_OK);
// try to add a column, spec the table name plus a char as a table name
PROVIDER_FREE(TableID.uName.pwszName);
TableID.uName.pwszName = pwszTableName;
TESTC_(AddColumnAndCheck(&TableID, &rgColumnDesc[cColumnDesc-1], &pColumnID), DB_E_NOTABLE);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
ReleaseDBID(pColumnID);
ReleaseDBID(&TableID, FALSE);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc invalid table name => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_7()
{
BOOL fTestRes = TEST_PASS;
DBID TableID;
DBID *pColumnID = NULL;
size_t m, n;
DBCOLUMNDESC *rgColumnDesc = NULL;
ULONG cColumnDesc = 1;
DuplicateColumnDesc(m_rgColumnDesc, cColumnDesc, &rgColumnDesc);
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
m = min(m_cMaxTableName, n=5+wcslen(m_pTable->GetTableName()));
TableID.uName.pwszName = BuildInvalidName(m, m_pTable->GetTableName(), m_pwszInvalidTableChars);
PRVTRACE(L"***TCADDColumn::Variation_7(): TableName=%s, len=%d\n", TableID.uName.pwszName,
wcslen(TableID.uName.pwszName));
if (!CHECK(m_hr = m_pITableDefinition->AddColumn(&TableID, &rgColumnDesc[0], &pColumnID), DB_E_NOTABLE))
fTestRes = TEST_FAIL;
ReleaseDBID(pColumnID);
ReleaseDBID(&TableID, FALSE);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
return fTestRes;
}
// }}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc pColumnDesc->dbcid = DB_NULLID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_8()
{
TBEGIN
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
m_pTable->SetBuildColumnDesc(FALSE);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// try to add a column with a DB_NULLID colid to this table
if (rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName)
PROVIDER_FREE(rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName);
memcpy(&rgColumnDesc[cColumnDesc-1].dbcid, (DBID*)&DB_NULLID, sizeof(DBID));
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[cColumnDesc-1],
&pColumnID), DB_E_BADCOLUMNID);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
ReleaseDBID(pColumnID);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc Column name pointer is NULL => DB_E_BADCOLUMNID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_9()
{
TBEGIN
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// try to add a column with a NULL value for name pointer
if (rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName)
PROVIDER_FREE(rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName);
rgColumnDesc[cColumnDesc-1].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName = NULL;
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), DB_E_BADCOLUMNID);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
ReleaseDBID(pColumnID);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc column name is an empty string => DB_E_BADCOLUMNID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_10()
{
TBEGIN
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
m_pTable->SetBuildColumnDesc(FALSE);
// create a table with cColumnDesc-1 columns
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// try to add a column with a NULL value for name pointer
if (rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName)
PROVIDER_FREE(rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName);
rgColumnDesc[cColumnDesc-1].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName = wcsDuplicate(L"");
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), DB_E_BADCOLUMNID);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
ReleaseDBID(pColumnID);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc Maximum length of column name => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_11()
{
TBEGIN
DBID *pColumnID = NULL;
WCHAR *pwszName = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->MakeTableName(NULL);
pwszName = wcsDuplicate(m_pTable->GetTableName());
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// try to add a column with a maximum size for column name
if (rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName)
PROVIDER_FREE(rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName);
rgColumnDesc[cColumnDesc-1].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName = BuildValidName(m_cMaxColName, pwszName);
odtLog << "A maximum length column name: " << rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName <<
", length=" << wcslen(rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName) << "\n";
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[cColumnDesc-1],
&pColumnID), S_OK);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
ReleaseDBID(pColumnID);
PROVIDER_FREE(pwszName);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc 1-char-too-long column name => DB_E_BADCOLUMNID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_12()
{
TBEGIN
WCHAR *pwszName = NULL;
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->MakeTableName(NULL);
pwszName = wcsDuplicate(m_pTable->GetTableName());
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// try to add a column with a name too long
if (rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName)
PROVIDER_FREE(rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName);
rgColumnDesc[cColumnDesc-1].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName = BuildValidName(m_cMaxColName+1, pwszName);
odtLog << "A 1 char too long column name: " << rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName <<
", length=" << wcslen(rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName) << "\n";
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), DB_E_BADCOLUMNID);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
SAFE_FREE(pwszName);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
ReleaseDBID(pColumnID);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc Add a column for each provider type, maximum column size => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_13()
{
TBEGIN
DBID *pColumnID = NULL;
DBORDINAL i;
DBCOLUMNDESC *pColumnDesc = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
DuplicateColumnDesc(rgColumnDesc, 1, &pColumnDesc);
PROVIDER_FREE(pColumnDesc->dbcid.uName.pwszName);
pColumnDesc->dbcid.uName.pwszName = wcsDuplicate(L"FirstColumn");
// for each type in DBCOLUMNDESC, add a column with maximum column size
SetMaximumColSize(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(pColumnDesc, 1);
for (i=0; i<cColumnDesc; i++)
{
// create a table with a single column, equal to the first one in the row
CHECK(m_hr = m_pTable->CreateTable(0, 0), S_OK);
if (FAILED(m_hr))
continue;
// try to add a column from rgColumnDesc[i]
odtLog << "column name:" << rgColumnDesc[i].dbcid.uName.pwszName <<
" column type:" << rgColumnDesc[i].pwszTypeName << "\n";
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[i],
&pColumnID), S_OK);
CHECK(m_pTable->DropTable(), S_OK);
ReleaseDBID(pColumnID);
pColumnID = NULL;
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(14)
//*-----------------------------------------------------------------------
// @mfunc Add a column for each known type; ulColumnsize == 0 => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_14()
{
TBEGIN
DBID *pColumnID = NULL;
DBORDINAL i;
DBCOLUMNDESC *pColumnDesc = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
DuplicateColumnDesc(rgColumnDesc, 1, &pColumnDesc);
PROVIDER_FREE(pColumnDesc->dbcid.uName.pwszName);
pColumnDesc->dbcid.uName.pwszName = wcsDuplicate(L"FirstColumn");
SetZeroColSize(rgColumnDesc, cColumnDesc);
// for each type in DBCOLUMNDESC, add a column with maximum column size
m_pTable->SetColumnDesc(NULL);
m_pTable->SetColumnDesc(pColumnDesc, 1);
m_pTable->SetBuildColumnDesc(FALSE);
for (i=0; i<cColumnDesc; i++)
{
// create a table with a single column, equal to the first one in the row
CHECK(m_hr = m_pTable->CreateTable(0, 0), S_OK);
if (FAILED(m_hr))
continue;
// try to add a column from rgColumnDesc[i]
odtLog << "column name:" << rgColumnDesc[i].dbcid.uName.pwszName <<
" column type:" << rgColumnDesc[i].pwszTypeName << "\n";
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[i],
&pColumnID), S_OK);
CHECK(m_pTable->DropTable(), S_OK);
ReleaseDBID(pColumnID);
pColumnID = NULL;
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(15)
//--------------------------------------------------------------------
// @mfunc Add a column for each provider type (table is populated) => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_15()
{
TBEGIN
DBID *pColumnID = NULL;
DBORDINAL i;
DBCOLUMNDESC *pColumnDesc = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
DuplicateColumnDesc(rgColumnDesc, 1, &pColumnDesc);
PROVIDER_FREE(pColumnDesc->dbcid.uName.pwszName);
pColumnDesc->dbcid.uName.pwszName = wcsDuplicate(L"FirstColumn");
m_pTable->SetColumnDesc(NULL);
m_pTable->SetColumnDesc(pColumnDesc, 1);
m_pTable->SetBuildColumnDesc(FALSE);
for (i=0; i<cColumnDesc; i++)
{
// try to add a column from rgColumnDesc[i]
odtLog << "column name:" << rgColumnDesc[i].dbcid.uName.pwszName <<
" column type:" << rgColumnDesc[i].pwszTypeName << "\n";
// create a popoulated table
if (!CHECK(m_pTable->CreateTable(10, 0), S_OK))
continue;
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[i],
&pColumnID), S_OK);
ReleaseDBID(pColumnID);
pColumnID = NULL;
CHECK(m_pTable->DropTable(), S_OK);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc Precision testing
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_16()
{
TBEGIN
DBID *pColumnID = NULL;
DBORDINAL i;
WCHAR *pwszColumnName = NULL;
BYTE precision, p[6];
ULONG nmax = 6;
WCHAR *prefix[]={L"zero", L"one", L"half", L"max", L"big", L"extra"};
HRESULT hres;
DBCOLUMNDESC *rgColDesc = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
DuplicateColumnDesc(rgColumnDesc, 1, &rgColDesc);
m_pTable->SetColumnDesc(rgColDesc, 1);
m_pTable->SetBuildColumnDesc(FALSE);
SAFE_FREE(rgColDesc[0].dbcid.uName.pwszName);
rgColDesc[0].dbcid.uName.pwszName = wcsDuplicate(L"initialColumn");
// for each type in DBCOLUMNDESC, add a column with different precision value
for (i=0; i<cColumnDesc; i++)
{
// try to add a column with different precision values
odtLog << "column name:" << rgColumnDesc[i].dbcid.uName.pwszName <<
" column type:" << rgColumnDesc[i].pwszTypeName << "\n";
precision = rgColumnDesc[i].bPrecision; // BuildColumnDesc puts max val in bPrecision!
p[0] = 0;
p[1] = 1;
p[2] = precision/2;
p[3] = precision;
if (precision > 254)
nmax = 4;
p[4] = precision+1;
p[5] = (ULONG)precision+10>255? 255: precision+10;
pwszColumnName = rgColumnDesc[i].dbcid.uName.pwszName;
rgColumnDesc[i].dbcid.uName.pwszName = NULL;
rgColumnDesc[i].bScale = 0;
rgColumnDesc[i].ulColumnSize = 0;
for (ULONG j=0; j<nmax; j++)
{
odtLog << "\t" << p[j];
if (!CHECK(m_hr = m_pTable->CreateTable(0, 0), S_OK))
continue;
// if needed you can limit wcscat with the max length for col size
rgColumnDesc[i].dbcid.uName.pwszName = (WCHAR*) PROVIDER_ALLOC( sizeof(WCHAR) * m_cMaxColName);
wcscpy(rgColumnDesc[i].dbcid.uName.pwszName, prefix[j]);
wcsncat(rgColumnDesc[i].dbcid.uName.pwszName, pwszColumnName, m_cMaxColName-wcslen(prefix[j]));
rgColumnDesc[i].bPrecision = p[j];
hres = S_OK;
if (rgColumnDesc[i].wType == DBTYPE_NUMERIC && ((j>3) || (j==0)) )
hres = DB_E_BADPRECISION;
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[i], &pColumnID), hres);
SAFE_FREE(rgColumnDesc[i].dbcid.uName.pwszName);
rgColumnDesc[i].dbcid.uName.pwszName = NULL;
CHECK(m_pTable->DropTable(), S_OK);
ReleaseDBID(pColumnID);
pColumnID = NULL;
}
odtLog << "\n";
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(17)
//*-----------------------------------------------------------------------
// @mfunc Scale testing
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_17()
{
TBEGIN
DBID *pColumnID = NULL;
DBORDINAL i;
WCHAR *pwszName;
DBCOLUMNDESC *pColumnDesc = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
DuplicateColumnDesc(rgColumnDesc, 1, &pColumnDesc);
//SetZeroColSize(rgColumnDesc, cColumnDesc);
PROVIDER_FREE(pColumnDesc->dbcid.uName.pwszName);
pColumnDesc->dbcid.uName.pwszName = wcsDuplicate(L"Initial_column");
// create a table with a single column, equal to the first one in the row
m_pTable->SetColumnDesc(NULL); // so that m_pTable->rgColumnDesc will not be deallocated next
m_pTable->SetColumnDesc(pColumnDesc, 1);
m_pTable->SetBuildColumnDesc(FALSE);
// for each type in DBCOLUMNDESC, add a column with different precision value
for (i=0; i<cColumnDesc; i++)
{
CHECK(m_hr = m_pTable->CreateTable(0, 0), S_OK);
if (!SUCCEEDED(m_hr))
continue;
odtLog << "column name: " << rgColumnDesc[i].dbcid.uName.pwszName <<
" column type: " << rgColumnDesc[i].pwszTypeName << "\n";
if ( rgColumnDesc[i].wType == DBTYPE_NUMERIC
|| rgColumnDesc[i].wType == DBTYPE_DECIMAL
|| rgColumnDesc[i].wType == DBTYPE_VARNUMERIC )
{
const int nScales = 7;
BYTE smax, smin, p[nScales], s[nScales], precision;
ULONG nmax = 1;
WCHAR *prefix[]={L"zero", L"min", L"half", L"max", L"maxpp", L"prec", L"extra_prec"};
HRESULT hres[nScales] = {S_OK, S_OK, S_OK, S_OK, S_OK, S_OK, S_OK};
CCol col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
// try to add a column with different scale values
smin = (BYTE)col.GetMinScale();
smax = (BYTE)col.GetMaxScale();
precision = (BYTE)col.GetPrecision();
for (ULONG k=0; k<nScales; p[k++]=precision);
s[0] = 0;
hres[0] = (smin==0)? S_OK: DB_E_BADSCALE;
if (smin > 0)
{
s[1] = smin;
nmax++;
}
s[nmax++] = (smin+smax)/2;
s[nmax++] = smax;
if (smax < 255)
{
s[nmax] = smax+1;
hres[nmax++] = DB_E_BADSCALE;
// check matching the precision
s[nmax] = precision;
hres[nmax] = (precision>smax) ? DB_E_BADSCALE: S_OK;
nmax++;
s[nmax] = p[nmax]+1;
hres[nmax++]= DB_E_BADSCALE;
}
pwszName = rgColumnDesc[i].dbcid.uName.pwszName;
rgColumnDesc[i].dbcid.uName.pwszName = NULL; // protection for inside the loop!
for (ULONG j=0; j<nmax; j++)
{
odtLog << "\t" << s[j];
// if needed you can limit wcscat with the max length for col size
if (rgColumnDesc[i].dbcid.uName.pwszName)
SAFE_FREE(rgColumnDesc[i].dbcid.uName.pwszName);
rgColumnDesc[i].dbcid.uName.pwszName = (WCHAR*) PROVIDER_ALLOC( sizeof(WCHAR) * m_cMaxColName);
wcscpy(rgColumnDesc[i].dbcid.uName.pwszName, prefix[j]);
wcsncat(rgColumnDesc[i].dbcid.uName.pwszName, pwszName, m_cMaxColName-wcslen(prefix[j]));
rgColumnDesc[i].bPrecision = p[j];
rgColumnDesc[i].bScale = s[j];
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[i], &pColumnID), hres[j]);
ReleaseDBID(pColumnID);
pColumnID = NULL;
}
odtLog << "\n";
SAFE_FREE(pwszName);
}
else
{
rgColumnDesc[i].bScale = 128;
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[i], &pColumnID), S_OK);
ReleaseDBID(pColumnID);
pColumnID = NULL;
}
CHECK(m_pTable->DropTable(), S_OK);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
m_pTable->SetNoOfColumnDesc(1);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(18)
//*-----------------------------------------------------------------------
// @mfunc Invalid value for the property of a column => DB_E_ERRORSOCCURRED
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_18()
{
TBEGIN
DBID *pColumnID = NULL;
DBPROPID dwPropID = DBPROP_COL_UNIQUE;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// try to add a column with a bad property value (prop of a different type than expected)
SetProperty(&rgColumnDesc[cColumnDesc-1].rgPropertySets,
&rgColumnDesc[cColumnDesc-1].cPropertySets,
dwPropID,
VT_I2, (LPVOID)12,
DBPROPOPTIONS_REQUIRED);
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), DB_E_ERRORSOCCURRED);
TESTC(VerifyPropStatus(rgColumnDesc[cColumnDesc-1].cPropertySets,
rgColumnDesc[cColumnDesc-1].rgPropertySets, dwPropID, DBPROPSET_COLUMN,
DBPROPSTATUS_BADVALUE));
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
ReleaseDBID(pColumnID);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(19)
//*-----------------------------------------------------------------------
// @mfunc Non-column property => DBPROPSTATUS_NOTSUPPORTED
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_19()
{
TBEGIN
DBID *pColumnID = NULL;
DBPROPID dwPropID = DBPROP_COL_UNIQUE;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// try to add a column with a bad property guid (DBPROPSET_INDEX)
SetProperty(
&rgColumnDesc[cColumnDesc-1].rgPropertySets, &rgColumnDesc[cColumnDesc-1].cPropertySets,
dwPropID,
VT_BOOL, (LPVOID)VARIANT_TRUE,
DBPROPOPTIONS_OPTIONAL, DB_NULLID, DBPROPSET_INDEX);
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), DB_S_ERRORSOCCURRED);
TESTC(VerifyPropStatus(rgColumnDesc[cColumnDesc-1].cPropertySets,
rgColumnDesc[cColumnDesc-1].rgPropertySets, dwPropID, DBPROPSET_INDEX, DBPROPSTATUS_NOTSUPPORTED));
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
ReleaseDBID(pColumnID);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(20)
//*-----------------------------------------------------------------------
// @mfunc Inexistent property => DBPROPSTATUS_NOTSUPPORTED
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_20()
{
TBEGIN
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// try to add a column with a bad property id
SetProperty(&rgColumnDesc[cColumnDesc-1].rgPropertySets,
&rgColumnDesc[cColumnDesc-1].cPropertySets, 0xffffffff, VT_BOOL, (LPVOID)VARIANT_TRUE);
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), DB_S_ERRORSOCCURRED);
TESTC(VerifyPropStatus(rgColumnDesc[cColumnDesc-1].cPropertySets,
rgColumnDesc[cColumnDesc-1].rgPropertySets, 0xffffffff,
DBPROPSET_COLUMN, DBPROPSTATUS_NOTSUPPORTED));
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
ReleaseDBID(pColumnID);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(21)
//*-----------------------------------------------------------------------
// @mfunc Bad option => DBPROPSTATUS_BADOPTION
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_21()
{
TBEGIN
DBID *pColumnID = NULL;
DBPROPID dwPropID = DBPROP_COL_NULLABLE;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// try to add a column with a bad option
SetProperty(&rgColumnDesc[cColumnDesc-1].rgPropertySets, &rgColumnDesc[cColumnDesc-1].cPropertySets,
dwPropID,
VT_BOOL, (LPVOID)VARIANT_TRUE,
0xf0);
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), DB_E_ERRORSOCCURRED);
TESTC(VerifyPropStatus(rgColumnDesc[cColumnDesc-1].cPropertySets,
rgColumnDesc[cColumnDesc-1].rgPropertySets, dwPropID,
DBPROPSET_COLUMN,DBPROPSTATUS_BADOPTION));
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
ReleaseDBID(pColumnID);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(22)
//*-----------------------------------------------------------------------
// @mfunc Conflicting property => DBPROPSTATUS_CONFLICTING
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_22()
{
TBEGIN
DBID *pColumnID = NULL;
DBORDINAL i, nCol;
CCol col;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
ULONG nConfStatus = 0;
ULONG nOKStatus = 0;
TESTC_PROVIDER(SettableProperty(DBPROP_COL_PRIMARYKEY, DBPROPSET_COLUMN)
&& SettableProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN));
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
nCol = cColumnDesc;
for (i=0; i< cColumnDesc; i++)
{
col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
if (col.GetNullable()!=0)
nCol = i;
}
TESTC(nCol < cColumnDesc);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// try to add a column with conflicting properties
PROVIDER_FREE(rgColumnDesc[nCol].dbcid.uName.pwszName);
rgColumnDesc[nCol].dbcid.uName.pwszName = wcsDuplicate(L"MyColumn");
SetProperty(&rgColumnDesc[nCol].rgPropertySets, &rgColumnDesc[nCol].cPropertySets,
DBPROP_COL_PRIMARYKEY, VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
SetProperty(&rgColumnDesc[nCol].rgPropertySets, &rgColumnDesc[nCol].cPropertySets,
DBPROP_COL_NULLABLE, VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[nCol], &pColumnID), DB_E_ERRORSOCCURRED);
if (DBPROPSTATUS_CONFLICTING == rgColumnDesc[nCol].rgPropertySets[0].rgProperties[0].dwStatus)
nConfStatus++;
else
{
TESTC(DBPROPSTATUS_OK == rgColumnDesc[nCol].rgPropertySets[0].rgProperties[0].dwStatus);
}
if (DBPROPSTATUS_CONFLICTING == rgColumnDesc[nCol].rgPropertySets[0].rgProperties[1].dwStatus)
nConfStatus++;
else
{
TESTC(DBPROPSTATUS_OK == rgColumnDesc[nCol].rgPropertySets[0].rgProperties[1].dwStatus);
}
TESTC(0 < nConfStatus);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
ReleaseDBID(pColumnID);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(23)
//--------------------------------------------------------------------
// @mfunc Bad column ID for a property => ignored
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_23()
{
TBEGIN
DBID *pColumnID = NULL;
DBID colID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBORDINAL cCol;
CCol col;
BOOL fFound = FALSE;
BOOL fExists;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
for (cCol=0; cCol < m_cColumnDesc; cCol++)
{
col = GetType(GetColumnTypeName(&rgColumnDesc[cCol]), rgColumnDesc[cCol].wType, &fExists);
fFound = fExists && 1 == col.GetNullable();
break;
}
TESTC_PROVIDER(fFound && SupportedProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN));
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// try to add a column with a property that set coldid to smthg different from DB_NULLID
colID.eKind = DBKIND_NAME;
colID.uName.pwszName = wcsDuplicate(L"bogus");
SetProperty(&rgColumnDesc[cCol].rgPropertySets, &rgColumnDesc[cCol].cPropertySets,
DBPROP_COL_NULLABLE, VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL, colID);
if (DBKIND_NAME == rgColumnDesc[cCol].dbcid.eKind && rgColumnDesc[cCol].dbcid.uName.pwszName)
PROVIDER_FREE(rgColumnDesc[cCol].dbcid.uName.pwszName);
rgColumnDesc[cCol].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[cCol].dbcid.uName.pwszName = wcsDuplicate(L"ExtraColumn");
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[cCol],
&pColumnID), S_OK);
TESTC(VerifyPropStatus(rgColumnDesc[cCol].cPropertySets,
rgColumnDesc[cCol].rgPropertySets, DBPROP_COL_NULLABLE,
DBPROPSET_COLUMN, DBPROPSTATUS_OK));
CLEANUP:
ReleaseDBID(pColumnID);
CHECK(m_pTable->DropTable(), S_OK);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(24)
//*-----------------------------------------------------------------------
// @mfunc Bad column type (wType in DBCOLUMNDESC)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_24()
{
TBEGIN
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_pTable->CreateTable(10, 0), S_OK);
// try to add a column with a bad wType
PROVIDER_FREE(rgColumnDesc[cColumnDesc-1].pwszTypeName);
rgColumnDesc[cColumnDesc-1].pwszTypeName = NULL;
rgColumnDesc[cColumnDesc-1].wType = 0xFFFF;
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), DB_E_BADTYPE);
CLEANUP:
ReleaseDBID(pColumnID);
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(25)
//*-----------------------------------------------------------------------
// @mfunc Invalid provider type name for a column => DB_E_BADTYPE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_25()
{
TBEGIN
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_pTable->CreateTable(10, 0), S_OK);
// try to add a column with a bad wType
PROVIDER_FREE(rgColumnDesc[cColumnDesc-1].pwszTypeName);
rgColumnDesc[cColumnDesc-1].pwszTypeName = wcsDuplicate(L"New_type_name");
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), DB_E_BADTYPE);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
ReleaseDBID(pColumnID);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(26)
//*-----------------------------------------------------------------------
// @mfunc NULL ppColumnDesc => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_26()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// try to add a column with a bad wType
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], NULL), S_OK);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(27)
//*-----------------------------------------------------------------------
// @mfunc Autoincrementable column - DBPROP_COL_AUTOINCREMENT
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_27()
{
TBEGIN
DBCOLUMNDESC *pColumnDesc = NULL;
DBORDINAL i;
CCol col;
HRESULT hres1; // for DBPROP_COL_AUTOINCREMENT set to VARIANT_TRUE
HRESULT hres2; // for DBPROP_COL_AUTOINCREMENT set to VARIANT_FALSE
HRESULT hr;
BOOL fReadOnlyAutoInc;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
BOOL fSupported = TRUE;
ULONG ulStatus,
cPropSet,
cProp;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
fReadOnlyAutoInc = !SettableProperty(DBPROP_COL_AUTOINCREMENT, DBPROPSET_COLUMN);
fSupported = SupportedProperty(DBPROP_COL_AUTOINCREMENT, DBPROPSET_COLUMN);
if (!fSupported)
odtLog << "DBPROP_COL_AUTOINCREMENT is NOT SUPPORTED!\n";
DuplicateColumnDesc(&rgColumnDesc[0], 1, &pColumnDesc);
SAFE_FREE(pColumnDesc->dbcid.uName.pwszName)
pColumnDesc->dbcid.uName.pwszName = wcsDuplicate(L"First_column");
m_pTable->SetColumnDesc(pColumnDesc, 1);
for (i=0; i<cColumnDesc; i++)
{
col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
if (fSupported)
{
hres1 = (col.CanAutoInc()) ? S_OK : DB_E_ERRORSOCCURRED;
hres2 = (!col.CanAutoInc() || !fReadOnlyAutoInc) ? S_OK : DB_E_ERRORSOCCURRED;
odtLog << GetColumnTypeName(&rgColumnDesc[i])
<< ((col.CanAutoInc()) ? " is AUTOINCREMENTABLE\n" : " is NOT autoincrementable\n");
}
else
{
hres1 = hres2 = DB_E_ERRORSOCCURRED;
}
if (!CHECK(m_pTable->CreateTable(0, 0), S_OK))
continue;
// try to add the column described by rgColumnDesc[i] to the table
// and set it as an AUTOINCREMENT COLUMN
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets,
DBPROP_COL_AUTOINCREMENT, VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED,
DB_NULLID, DBPROPSET_COLUMN, &cPropSet, &cProp);
rgColumnDesc[i].bScale = 0;
CHECK(hr = AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[i], NULL), hres1);
odtLog << (SUCCEEDED(hr) ? "\tautoinc column added\n" : "\tautoinc column could not be added\n");
//check the state
ulStatus = rgColumnDesc[i].rgPropertySets[cPropSet].rgProperties[cProp].dwStatus;
if (S_OK == hr)
{
COMPARE(ulStatus, DBPROPSTATUS_OK);
COMPARE(fSupported, TRUE);
COMPARE(col.CanAutoInc(), TRUE);
}
else
{
CHECK(hr, DB_E_ERRORSOCCURRED);
if (!fSupported)
COMPARE(ulStatus, DBPROPSTATUS_NOTSUPPORTED);
else if (fReadOnlyAutoInc)
COMPARE(ulStatus, DBPROPSTATUS_NOTSETTABLE);
else
COMPARE(ulStatus, DBPROPSTATUS_BADVALUE);
}
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
CHECK(m_pTable->DropTable(), S_OK);
if (!CHECK(m_pTable->CreateTable(0, 0), S_OK))
continue;
// try to add the column described by rgColumnDesc[i] to the table
// and set it as an non autoincrement column
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets,
DBPROP_COL_AUTOINCREMENT, VT_BOOL, (LPVOID)VARIANT_FALSE, DBPROPOPTIONS_REQUIRED);
rgColumnDesc[i].bScale = 0;
CHECK(hr = AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[i], NULL), hres2);
odtLog << (SUCCEEDED(hr) ? "\tNOT autoinc column added\n" : "\tNOT autoinc column could not be added\n");
// check the returned status
ulStatus = rgColumnDesc[i].rgPropertySets[0].rgProperties[0].dwStatus;
if (S_OK == hr)
{
COMPARE(ulStatus, DBPROPSTATUS_OK);
COMPARE(fSupported, TRUE);
}
else
{
CHECK(hr, DB_E_ERRORSOCCURRED);
COMPARE(!col.CanAutoInc(), TRUE);
if (!fSupported)
COMPARE(ulStatus, DBPROPSTATUS_NOTSUPPORTED);
else if (fReadOnlyAutoInc)
COMPARE(ulStatus, DBPROPSTATUS_NOTSETTABLE);
else
COMPARE(ulStatus, DBPROPSTATUS_BADVALUE);
}
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
CHECK(m_pTable->DropTable(), S_OK);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(28)
//*-----------------------------------------------------------------------
// @mfunc DBPROP_COL_DEFAULT
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_28()
{
TBEGIN
DBCOLUMNDESC *pColumnDesc=NULL;
DBORDINAL i;
HRESULT hr;
VARIANT value;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CTable *pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CList<WCHAR *,WCHAR *> NativeTypesList;
CList<DBTYPE,DBTYPE> ProviderTypesList;
BOOL fSettable = TRUE;
BOOL fSupported = TRUE;
ULONG ulStatus;
pTable->CreateTypeColInfo(NativeTypesList, ProviderTypesList);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
DuplicateColumnDesc(&rgColumnDesc[0], 1, &pColumnDesc);
PROVIDER_FREE(pColumnDesc->dbcid.uName.pwszName);
pColumnDesc->dbcid.uName.pwszName = wcsDuplicate(L"First_column");
ASSERT(pColumnDesc->dbcid.uName.pwszName);
m_pTable->SetColumnDesc(pColumnDesc, 1);
if (!SupportedProperty(DBPROP_COL_DEFAULT, DBPROPSET_COLUMN))
{
odtLog << "DBPROP_COL_DEFAULT is NOT SUPPORTED.\n";
fSettable = FALSE;
fSupported = FALSE;
}
else
{
if (!SettableProperty(DBPROP_COL_DEFAULT, DBPROPSET_COLUMN))
fSettable = FALSE;
}
for (i=0; i<cColumnDesc; i++)
{
odtLog << GetColumnTypeName(&rgColumnDesc[i]);
if (!CHECK(m_hr = m_pTable->CreateTable(0, 0), S_OK))
continue;
// try to add the column described by rgColumnDesc[i] to the table
// and set it as a column with a default value
VariantInit(&value);
GetDefaultValue(&rgColumnDesc[i], &value, pTable);
SetDefaultProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets,
&value, DBPROPOPTIONS_REQUIRED); // might be not supported
VariantClear(&value);
//rgColumnDesc[i].ulColumnSize = 0;
// since the property could be supported, writeable but unavailable for
// certain data types, a return value cannot be enforced
hr = AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[i], NULL);
ulStatus = rgColumnDesc[i].rgPropertySets[0].rgProperties[0].dwStatus;
if (S_OK == hr)
{
odtLog << "\t: column has been added with a DEFAULT VALUE\n";
COMPARE(ulStatus, DBPROPSTATUS_OK);
COMPARE(fSupported, TRUE);
}
else
{
if (CHECK(hr, DB_E_ERRORSOCCURRED))
{
odtLog << "\t: column was added WITHOUT default value\n";
if (!fSupported)
COMPARE(ulStatus, DBPROPSTATUS_NOTSUPPORTED);
// property could be settable but failing for this data type
else if (fSettable)
COMPARE(ulStatus, DBPROPSTATUS_BADVALUE);
else
COMPARE(ulStatus, DBPROPSTATUS_NOTSETTABLE);
}
else
{
odtLog << "\tERROR: column was NOT added\n";
}
}
CHECK(m_pTable->DropTable(), S_OK);
// the vt type of the default property could cause problems in VariantClear
// call PrepareVariantToClear to check and fix
FreeProperties( &rgColumnDesc[i].cPropertySets, &rgColumnDesc[i].rgPropertySets);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
delete pTable;
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(29)
//*-----------------------------------------------------------------------
// @mfunc DBPROP_COL_DESCRIPTION
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_29()
{
TBEGIN
DBORDINAL i;
WCHAR *pwszName = NULL;
HRESULT hr;
BSTR pwszDescription = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
HRESULT hExpRes = S_OK;
BOOL fSettable = TRUE;
BOOL fSupported = TRUE;
ULONG ulStatus,
cPropSet,
cProp;
if (!SupportedProperty(DBPROP_COL_DESCRIPTION, DBPROPSET_COLUMN))
{
odtLog << "DBPROP_COL_DESCRIPTION is NOT SUPPORTED.\n";
hExpRes = DB_S_ERRORSOCCURRED;
fSettable = FALSE;
fSupported = FALSE;
}
else
{
if (!SettableProperty(DBPROP_COL_DESCRIPTION, DBPROPSET_COLUMN))
{
fSettable = FALSE;
odtLog << "Implementing the desricption property as readonly is strange. Please reconsider!\n";
}
}
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
//SetZeroColSize(rgColumnDesc, cColumnDesc);
pwszName = rgColumnDesc[0].dbcid.uName.pwszName;
m_pTable->SetColumnDesc(rgColumnDesc, 1);
pwszDescription = SysAllocString(L"ColumnDescription");
for (i=0; i<cColumnDesc; i++)
{
odtLog << "column of type " << rgColumnDesc[i].pwszTypeName;
rgColumnDesc[0].dbcid.uName.pwszName = L"First_column";
if (!CHECK(m_hr = m_pTable->CreateTable(0, 0), S_OK))
{
if (SUCCEEDED(m_hr))
CHECK(m_pTable->DropTable(), S_OK);
continue;
}
rgColumnDesc[0].dbcid.uName.pwszName = pwszName;
// try to add the column described by rgColumnDesc[i] to the table
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets,
DBPROP_COL_DESCRIPTION, DBTYPE_BSTR, (LPVOID)pwszDescription, DBPROPOPTIONS_OPTIONAL,
DB_NULLID, DBPROPSET_COLUMN, &cPropSet, &cProp);
hr = AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[i], NULL);
if (!fSupported)
CHECK(hr, DB_S_ERRORSOCCURRED);
else if (fSettable)
CHECK(hr, S_OK);
else if (S_OK != hr)
CHECK(hr, DB_S_ERRORSOCCURRED);
if (SUCCEEDED(hr))
odtLog << ((DB_S_ERRORSOCCURRED == hr) ? ": could not add a description\n" :
": description has been added\n");
ulStatus = rgColumnDesc[i].rgPropertySets[cPropSet].rgProperties[cProp].dwStatus;
if (!fSupported)
COMPARE(ulStatus, DBPROPSTATUS_NOTSUPPORTED);
else if (fSettable)
COMPARE(ulStatus, DBPROPSTATUS_OK);
else
COMPARE(ulStatus, DBPROPSTATUS_BADVALUE);
CHECK(m_pTable->DropTable(), S_OK);
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
}
SysFreeString(pwszDescription);
rgColumnDesc[0].dbcid.uName.pwszName = pwszName;
m_pTable->SetNoOfColumnDesc(cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(30)
//*-----------------------------------------------------------------------
// @mfunc DBPROP_COL_FIXEDLENGTH
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_30()
{
TBEGIN
HRESULT hr;
DBCOLUMNDESC *pColumnDesc = NULL;
BOOL fFixedLength;
DBORDINAL i;
CCol col;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
BOOL fSettable = TRUE;
BOOL fSupported = TRUE;
ULONG ulStatus,
cPropSet,
cProp;
if (!SupportedProperty(DBPROP_COL_FIXEDLENGTH, DBPROPSET_COLUMN))
{
odtLog << "DBPROP_COL_FIXEDLENGTH is NOT SUPPORTED\n";
fSettable = FALSE;
fSupported = FALSE;
}
else
{
if (!SettableProperty(DBPROP_COL_FIXEDLENGTH, DBPROPSET_COLUMN))
fSettable = FALSE;
}
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
DuplicateColumnDesc(&rgColumnDesc[0], 1, &pColumnDesc);
SetMaximumColSize(rgColumnDesc, cColumnDesc);
PROVIDER_FREE(pColumnDesc->dbcid.uName.pwszName)
pColumnDesc->dbcid.uName.pwszName = wcsDuplicate(L"First_column");
m_pTable->SetColumnDesc(pColumnDesc, 1);
for (i=0; i<cColumnDesc; i++)
{
if ( DBTYPE_STR != rgColumnDesc[i].wType
&& DBTYPE_WSTR != rgColumnDesc[i].wType
&& DBTYPE_BYTES != rgColumnDesc[i].wType)
continue;
col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
// just not yet implemented
// pending for all providers to adjust the provider types schema rowset
fFixedLength = col.GetIsFixedLength();
if (fFixedLength)
odtLog << GetColumnTypeName(&rgColumnDesc[i]) <<" is fixed length\n";
else
odtLog << GetColumnTypeName(&rgColumnDesc[i]) <<" is variable length\n";
if (!CHECK(m_pTable->CreateTable(0, 0), S_OK))
continue;
// try to add the column described by rgColumnDesc[i] to the table
// and set it as a fixed length column
odtLog << "\ttry to add a fixed length column: ";
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets,
DBPROP_COL_FIXEDLENGTH, VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED,
DB_NULLID, DBPROPSET_COLUMN, &cPropSet, &cProp);
rgColumnDesc[i].bScale = 0;
hr = AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[i], NULL);
ulStatus = rgColumnDesc[i].rgPropertySets[cPropSet].rgProperties[cProp].dwStatus;
if (S_OK == hr)
COMPARE(ulStatus, DBPROPSTATUS_OK);
else
{
CHECK(hr, DB_E_ERRORSOCCURRED);
if (!fSupported)
COMPARE(ulStatus, DBPROPSTATUS_NOTSUPPORTED);
else if (fSettable)
COMPARE(ulStatus, DBPROPSTATUS_BADVALUE);
else if (!fSettable)
COMPARE(ulStatus, DBPROPSTATUS_NOTSETTABLE);
}
odtLog << ((S_OK == hr)? "ok\n" : "failed\n");
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
CHECK(m_pTable->DropTable(), S_OK);
if (!CHECK(m_pTable->CreateTable(0, 0), S_OK))
continue;
// try to add the column described by rgColumnDesc[i] to the table
// and set it as a variable_length
odtLog << "\ttry to add a variable length column: ";
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets,
DBPROP_COL_FIXEDLENGTH, VT_BOOL, (LPVOID)VARIANT_FALSE, DBPROPOPTIONS_REQUIRED,
DB_NULLID, DBPROPSET_COLUMN, &cPropSet, &cProp);
rgColumnDesc[i].bScale = 0;
hr = AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[i], NULL);
ulStatus = rgColumnDesc[i].rgPropertySets[cPropSet].rgProperties[cProp].dwStatus;
if (S_OK == hr)
COMPARE(ulStatus, DBPROPSTATUS_OK);
else
{
CHECK(hr, DB_E_ERRORSOCCURRED);
if (!fSupported)
COMPARE(ulStatus, DBPROPSTATUS_NOTSUPPORTED);
else if (fSettable)
COMPARE(ulStatus, DBPROPSTATUS_BADVALUE);
else
COMPARE(ulStatus, DBPROPSTATUS_NOTSETTABLE);
}
odtLog << ((S_OK == hr)? "ok\n" : "failed\n");
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
CHECK(m_pTable->DropTable(), S_OK);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(31)
//*-----------------------------------------------------------------------
// @mfunc DBPROP_COL_NULLABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_31()
{
TBEGIN
DBCOLUMNDESC *pColumnDesc = NULL;
BOOL fNotNullable, fNullable;
DBORDINAL i;
VARIANT value, defval;
CCol col;
HRESULT hr;
DBPROP *pProp = NULL;
DBPROP *pPropDefault = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CTable *pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CList<WCHAR *,WCHAR *> NativeTypesList;
CList<DBTYPE,DBTYPE> ProviderTypesList;
BOOL fSettable = TRUE;
BOOL fSupported = TRUE;
ULONG ulStatus,
cPropSet,
cProp;
if (!SupportedProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN))
{
odtLog << "DBPROP_COL_NULLABLE is NOT SUPPORTED\n";
fSettable = FALSE;
fSupported = FALSE;
}
else
{
if (!SettableProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN))
fSettable = FALSE;
}
pTable->CreateTypeColInfo(NativeTypesList, ProviderTypesList);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
DuplicateColumnDesc(&rgColumnDesc[0], 1, &pColumnDesc);
PROVIDER_FREE(pColumnDesc->dbcid.uName.pwszName)
pColumnDesc->dbcid.uName.pwszName = wcsDuplicate(L"First_column");
m_pTable->SetColumnDesc(pColumnDesc, 1);
value.vt = VT_BOOL;
for (i=0; i<cColumnDesc; i++)
{
col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
fNotNullable = FALSE;
fNullable = FALSE;
switch (col.GetNullable())
{
case 1:
odtLog << GetColumnTypeName(&rgColumnDesc[i]) <<" is nullable: \n";
fNullable = TRUE;
break;
case 0:
odtLog << GetColumnTypeName(&rgColumnDesc[i]) <<" is not nullable: \n";
fNotNullable = TRUE;
break;
default:
odtLog << GetColumnTypeName(&rgColumnDesc[i]) <<": nullable/not nullable information was not found\n";
break;
}
if (!CHECK(m_hr = m_pTable->CreateTable(0, 0), S_OK))
continue;
// try to add the column described by rgColumnDesc[i] to the table
// and set it as a nullable one
//odtLog << "try to add a nullable column\n";
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets,
DBPROP_COL_NULLABLE, VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED, DB_NULLID,
DBPROPSET_COLUMN, &cPropSet, &cProp);
rgColumnDesc[i].bScale = 0;
// try to add a column but do not require the seccess of the operation
// though the column is declared nullable, adding a column could be unimplemented in the provider
hr = AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[i], NULL);
if (fNullable)
CHECK(hr, S_OK);
ulStatus = rgColumnDesc[i].rgPropertySets[cPropSet].rgProperties[cProp].dwStatus;
if (S_OK == hr)
COMPARE(ulStatus, DBPROPSTATUS_OK);
else
{
CHECK(hr, DB_E_ERRORSOCCURRED);
if (!fSupported)
COMPARE(ulStatus, DBPROPSTATUS_NOTSUPPORTED);
else if (fSettable)
COMPARE(ulStatus, DBPROPSTATUS_BADVALUE);
else
COMPARE(ulStatus, DBPROPSTATUS_NOTSETTABLE);
}
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
CHECK(m_pTable->DropTable(), S_OK);
if (!CHECK(m_hr = m_pTable->CreateTable(0, 0), S_OK))
continue;
// try to add the column described by rgColumnDesc[i] to the table
// and set it as a variable_length
//odtLog << "try to add a non nullable column\n";
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets,
DBPROP_COL_NULLABLE, VT_BOOL, (LPVOID)VARIANT_FALSE, DBPROPOPTIONS_REQUIRED,
DB_NULLID, DBPROPSET_COLUMN, &cPropSet, &cProp);
rgColumnDesc[i].bScale = 0;
// Commenting out the default value
VariantInit(&defval);
GetDefaultValue(&rgColumnDesc[i], &defval, pTable);
if (SettableProperty(DBPROP_COL_DEFAULT, DBPROPSET_COLUMN))
SetDefaultProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets,
&defval, DBPROPOPTIONS_REQUIRED); // might be not supported
VariantClear(&defval);
// it is not necessary that a not nullable column be added
hr = AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[i], NULL);
ulStatus = rgColumnDesc[i].rgPropertySets[cPropSet].rgProperties[cProp].dwStatus;
if (S_OK == hr)
COMPARE(ulStatus, DBPROPSTATUS_OK);
else
{
CHECK(hr, DB_E_ERRORSOCCURRED);
if (DBPROPSTATUS_OK == rgColumnDesc[i].rgPropertySets[cPropSet].rgProperties[cProp + 1].dwStatus)
{
if (!fSupported)
COMPARE(ulStatus, DBPROPSTATUS_NOTSUPPORTED);
else if (fSettable)
COMPARE(ulStatus, DBPROPSTATUS_BADVALUE);
else
COMPARE(ulStatus, DBPROPSTATUS_NOTSETTABLE);
}
}
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
CHECK(m_pTable->DropTable(), S_OK);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
delete pTable;
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(32)
//*-----------------------------------------------------------------------
// @mfunc DBPROP_PRIMARYKEY
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_32()
{
TBEGIN
DBCOLUMNDESC *pColumnDesc = NULL;
DBORDINAL i;
VARIANT value;
CCol col;
HRESULT hr;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CTable *pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CList<WCHAR *,WCHAR *> NativeTypesList;
CList<DBTYPE,DBTYPE> ProviderTypesList;
BOOL fSettable;
BOOL fDefaultIsSettable = SettableProperty(DBPROP_COL_DEFAULT, DBPROPSET_COLUMN);
ULONG cPropSet1, cProp1, cPropSet2, cProp2;
DBPROPSTATUS dwStatus1, dwStatus2;
fSettable = SettableProperty(DBPROP_COL_PRIMARYKEY, DBPROPSET_COLUMN);
pTable->CreateTypeColInfo(NativeTypesList, ProviderTypesList);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
DuplicateColumnDesc(&rgColumnDesc[0], 1, &pColumnDesc);
// this is to prevent SQL Server limiting the size of
// the index it creates for primary key or unique columns
SetZeroColSize(rgColumnDesc, cColumnDesc);
PROVIDER_FREE(pColumnDesc->dbcid.uName.pwszName)
pColumnDesc->dbcid.uName.pwszName = wcsDuplicate(L"First_column");
m_pTable->SetColumnDesc(pColumnDesc, 1);
for (i=0; i<cColumnDesc; i++)
{
col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
odtLog << GetColumnTypeName(&rgColumnDesc[i]) << "\n";
if (!CHECK(m_hr = m_pTable->CreateTable(0, 0), S_OK))
continue;
// try to add the column described by rgColumnDesc[i] to the table
// and set it as a PRIMARY KEY column
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets,
DBPROP_COL_PRIMARYKEY, VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL, DB_NULLID,
DBPROPSET_COLUMN, &cPropSet1, &cProp1);
if (fDefaultIsSettable)
{
VariantInit(&value);
GetDefaultValue(&rgColumnDesc[i], &value, pTable);
SetDefaultProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets,
&value, DBPROPOPTIONS_OPTIONAL, DB_NULLID, DBPROPSET_COLUMN, &cPropSet2, &cProp2); // might be not supported
VariantClear(&value);
}
rgColumnDesc[i].bScale = 0;
hr = AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[i], NULL);
dwStatus1 = rgColumnDesc[i].rgPropertySets[cPropSet1].rgProperties[cProp1].dwStatus;
dwStatus2 = rgColumnDesc[i].rgPropertySets[cPropSet2].rgProperties[cProp2].dwStatus;
if (hr != S_OK)
{
CHECK(hr, DB_S_ERRORSOCCURRED);
COMPARE(dwStatus1==DBPROPSTATUS_NOTSET || dwStatus2==DBPROPSTATUS_NOTSET, TRUE);
if (hr==DB_S_ERRORSOCCURRED && dwStatus1==S_OK)
odtLog << "\tcolumn added as a primary key\n";
if (hr==DB_S_ERRORSOCCURRED && dwStatus2==S_OK)
odtLog << "\tcolumn added with the default\n";
}
else
{
COMPARE(fSettable, TRUE);
odtLog << "\tcolumn added as a primary key\n";
COMPARE(dwStatus1, DBPROPSTATUS_OK);
COMPARE(dwStatus2, DBPROPSTATUS_OK);
}
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
CHECK(m_pTable->DropTable(), S_OK);
if (!CHECK(m_hr = m_pTable->CreateTable(0, 0), S_OK))
continue;
// try to add the column described by rgColumnDesc[i] to the table
// and set it as a PRIMARY KEY column
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets,
DBPROP_COL_PRIMARYKEY, VT_BOOL, (LPVOID)VARIANT_FALSE, DBPROPOPTIONS_OPTIONAL, DB_NULLID,
DBPROPSET_COLUMN, &cPropSet1, &cProp1);
rgColumnDesc[i].bScale = 0;
hr = AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[i], NULL);
dwStatus1 = rgColumnDesc[i].rgPropertySets[cPropSet1].rgProperties[cProp1].dwStatus;
if (hr != S_OK)
{
COMPARE(fSettable, FALSE);
CHECK(hr, DB_S_ERRORSOCCURRED);
COMPARE(dwStatus1==DBPROPSTATUS_NOTSET, TRUE);
}
else
{
COMPARE(fSettable, TRUE);
odtLog << "\tcolumn was added with primary property off\n";
COMPARE(dwStatus1, DBPROPSTATUS_OK);
}
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
CHECK(m_pTable->DropTable(), S_OK);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
SAFE_DELETE(pTable);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(33)
//*-----------------------------------------------------------------------
// @mfunc DBPROP_COL_UNIQUE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_33()
{
TBEGIN
DBCOLUMNDESC *pColumnDesc = NULL;
DBORDINAL i;
CCol col;
HRESULT hr;
DBPROP *pProp;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
BOOL fSettable = FALSE;
BOOL fSupported = FALSE;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
DuplicateColumnDesc(&rgColumnDesc[0], 1, &pColumnDesc);
// this is to prevent SQL Server limiting the size of
// the index it creates for primary key or unique columns
SetZeroColSize(rgColumnDesc, cColumnDesc);
PROVIDER_FREE(pColumnDesc->dbcid.uName.pwszName)
pColumnDesc->dbcid.uName.pwszName = wcsDuplicate(L"First_column");
m_pTable->SetColumnDesc(pColumnDesc, 1);
fSupported = SupportedProperty(DBPROP_COL_UNIQUE, DBPROPSET_COLUMN);
fSettable = SettableProperty(DBPROP_COL_UNIQUE, DBPROPSET_COLUMN);
for (i=0; i<cColumnDesc; i++)
{
col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
if (!CHECK(m_hr = m_pTable->CreateTable(0, 0), S_OK))
continue;
// try to add the column described by rgColumnDesc[i] to the table
// and set it as a UNIQUE column
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets,
DBPROP_COL_UNIQUE, VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
rgColumnDesc[i].bScale = 0;
odtLog << GetColumnTypeName(&rgColumnDesc[i]) << "\n";
odtLog << "\ttry to add a unique column; \n";
hr = AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[i], NULL);
FindProperty(
DBPROP_COL_UNIQUE,
DBPROPSET_COLUMN,
rgColumnDesc[i].cPropertySets,
rgColumnDesc[i].rgPropertySets,
&pProp);
if (S_OK == hr)
{
COMPARE(pProp->dwStatus, DBPROPSTATUS_OK);
COMPARE(fSupported, TRUE);
}
else
{
CHECK(hr, DB_E_ERRORSOCCURRED);
if (!fSupported)
COMPARE(pProp->dwStatus, DBPROPSTATUS_NOTSUPPORTED);
else if (fSettable)
COMPARE(pProp->dwStatus, DBPROPSTATUS_BADVALUE);
else
COMPARE(pProp->dwStatus, DBPROPSTATUS_NOTSETTABLE);
}
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
CHECK(m_pTable->DropTable(), S_OK);
if (!CHECK(m_pTable->CreateTable(0, 0), S_OK))
continue;
// try to add the column described by rgColumnDesc[i] to the table
// and set it as a unique column
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets,
DBPROP_COL_UNIQUE, VT_BOOL, (LPVOID)VARIANT_FALSE, DBPROPOPTIONS_REQUIRED);
rgColumnDesc[i].bScale = 0;
odtLog << "\ttry to add a not unique column; \n";
hr = AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[i], NULL);
FindProperty(
DBPROP_COL_UNIQUE,
DBPROPSET_COLUMN,
rgColumnDesc[i].cPropertySets,
rgColumnDesc[i].rgPropertySets,
&pProp
);
if (S_OK == hr)
{
COMPARE(pProp->dwStatus, DBPROPSTATUS_OK);
COMPARE(fSupported, TRUE);
}
else
{
CHECK(hr, DB_E_ERRORSOCCURRED);
if (!fSupported)
COMPARE(pProp->dwStatus, DBPROPSTATUS_NOTSUPPORTED);
else if (fSettable)
COMPARE(pProp->dwStatus, DBPROPSTATUS_BADVALUE);
else
COMPARE(pProp->dwStatus, DBPROPSTATUS_NOTSETTABLE);
}
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
CHECK(m_pTable->DropTable(), S_OK);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(34)
//*-----------------------------------------------------------------------
// @mfunc Duplicate an existing column => DB_E_DUPLCATECOLUMNID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_34()
{
TBEGIN
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// try to add a column to this maximum length name table
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[cColumnDesc-1],
&pColumnID),DB_E_DUPLICATECOLUMNID);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
ReleaseDBID(pColumnID);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(35)
//*-----------------------------------------------------------------------
// @mfunc Abort retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_35()
{
TBEGIN
ITransactionLocal *pITransactionLocal = NULL;
DBCOLUMNDESC *newCD = NULL;
DBCOLUMNDESC *oldCD = NULL;
DBORDINAL newlen = 0;
DBORDINAL oldlen = 0;
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
VARIANT vSupportedTxnDDL;
BOOL fTxnStarted = FALSE;
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_ITransactionLocal,
SESSION_INTERFACE, (IUnknown**)&pITransactionLocal));
VariantInit(&vSupportedTxnDDL);
TESTC_PROVIDER(GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO,
g_pIDBInitialize, &vSupportedTxnDDL));
TESTC(VT_I4 == vSupportedTxnDDL.vt);
// what values should we accept?
TESTC_PROVIDER(DBPROPVAL_TC_NONE != vSupportedTxnDDL.lVal);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table and populate it
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
GetColumnDescOnTable(&m_pTable->GetTableID(), &oldCD, &oldlen);
// start the transaction
TESTC_(StartTransaction(pITransactionLocal), S_OK);
fTxnStarted = TRUE;
// try to add a column to this maximum length name table
if (rgColumnDesc[0].dbcid.uName.pwszName)
PROVIDER_FREE(rgColumnDesc[0].dbcid.uName.pwszName);
rgColumnDesc[0].dbcid.uName.pwszName = L"transacted_column";
switch(vSupportedTxnDDL.lVal)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(m_hr = m_pITableDefinition->AddColumn(
&m_pTable->GetTableID(),
&rgColumnDesc[0],
&pColumnID), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[0], &pColumnID), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
// error should be returned
CHECK(m_pITableDefinition->AddColumn(
&m_pTable->GetTableID(),
&rgColumnDesc[0],
&pColumnID), S_OK);
break;
default:
TESTC(FALSE);
}
// abort retaining
if (DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal)
{
CHECK(pITransactionLocal->Abort(NULL, TRUE, FALSE), S_OK);
// check that it is retaining (another transaction is available)
CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK);
}
GetColumnDescOnTable(&m_pTable->GetTableID(), &newCD, &newlen);
if ( DBPROPVAL_TC_DDL_IGNORE == vSupportedTxnDDL.lVal
|| DBPROPVAL_TC_DDL_COMMIT == vSupportedTxnDDL.lVal)
{ // check column was added
COMPARE(CheckColInfo(oldCD, oldlen, newCD, newlen, &rgColumnDesc[0]), TRUE);
}
else
{ // check column was not added
COMPARE(AreColEqual(oldCD, oldlen, newCD, newlen), TRUE);
}
ReleaseColumnDesc(newCD, newlen);
newCD = NULL;
newlen = 0;
CLEANUP:
ReleaseColumnDesc(oldCD, oldlen);
m_hr = m_pTable->DropTable();
SAFE_RELEASE(pITransactionLocal);
if (rgColumnDesc)
rgColumnDesc[0].dbcid.uName.pwszName = NULL;
ReleaseDBID(pColumnID);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(36)
//*-----------------------------------------------------------------------
// @mfunc Abort without retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_36()
{
TBEGIN
ITransactionLocal *pITransactionLocal = NULL;
DBCOLUMNDESC *newCD = NULL;
DBCOLUMNDESC *oldCD = NULL;
DBORDINAL newlen = 0;
DBORDINAL oldlen = 0;
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
VARIANT vSupportedTxnDDL;
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_ITransactionLocal,
SESSION_INTERFACE, (IUnknown**)&pITransactionLocal));
VariantInit(&vSupportedTxnDDL);
TESTC_PROVIDER(GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO,
g_pIDBInitialize, &vSupportedTxnDDL));
TESTC(VT_I4 == vSupportedTxnDDL.vt);
// what values should we accept?
TESTC_PROVIDER(DBPROPVAL_TC_NONE != vSupportedTxnDDL.lVal);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table and populate it
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
GetColumnDescOnTable(&m_pTable->GetTableID(), &oldCD, &oldlen);
// start the transaction
TESTC_(StartTransaction(pITransactionLocal), S_OK);
// try to add a column to this maximum length name table
if (rgColumnDesc[0].dbcid.uName.pwszName)
PROVIDER_FREE(rgColumnDesc[0].dbcid.uName.pwszName);
rgColumnDesc[0].dbcid.uName.pwszName = L"transacted_column";
switch(vSupportedTxnDDL.lVal)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(m_hr = m_pITableDefinition->AddColumn(
&m_pTable->GetTableID(),
&rgColumnDesc[0],
&pColumnID), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[0], &pColumnID), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
// error should be returned
CHECK(m_pITableDefinition->AddColumn(
&m_pTable->GetTableID(),
&rgColumnDesc[0],
&pColumnID), S_OK);
break;
default:
TESTC(FALSE);
}
// abort without retaining
if (DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal)
{
// abort without retaining
CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK);
CHECK(pITransactionLocal->Abort(NULL, FALSE, FALSE),
SUCCEEDED(m_hr)? XACT_E_NOTRANSACTION : S_OK);
}
// check column was not added
GetColumnDescOnTable(&m_pTable->GetTableID(), &newCD, &newlen);
if ( DBPROPVAL_TC_DDL_IGNORE == vSupportedTxnDDL.lVal
|| DBPROPVAL_TC_DDL_COMMIT == vSupportedTxnDDL.lVal)
{ // check column was added
COMPARE(CheckColInfo(oldCD, oldlen, newCD, newlen, &rgColumnDesc[0]), TRUE);
}
else
{ // check column was not added
COMPARE(AreColEqual(oldCD, oldlen, newCD, newlen), TRUE);
}
ReleaseColumnDesc(newCD, newlen);
newCD = NULL;
newlen = 0;
CLEANUP:
ReleaseColumnDesc(oldCD, oldlen);
m_hr = m_pTable->DropTable();
SAFE_RELEASE(pITransactionLocal);
if (rgColumnDesc)
rgColumnDesc[0].dbcid.uName.pwszName = NULL;
ReleaseDBID(pColumnID);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(37)
//*-----------------------------------------------------------------------
// @mfunc Commit with retain
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_37()
{
TBEGIN
ITransactionLocal *pITransactionLocal = NULL;
DBCOLUMNDESC *newCD = NULL, *oldCD = NULL;
DBORDINAL newlen = 0, oldlen = 0;
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
VARIANT vSupportedTxnDDL;
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_ITransactionLocal,
SESSION_INTERFACE, (IUnknown**)&pITransactionLocal));
VariantInit(&vSupportedTxnDDL);
TESTC_PROVIDER(GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO,
g_pIDBInitialize, &vSupportedTxnDDL));
TESTC(VT_I4 == vSupportedTxnDDL.vt);
// what values should we accept?
TESTC_PROVIDER(DBPROPVAL_TC_NONE != vSupportedTxnDDL.lVal);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table and populate it
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
GetColumnDescOnTable(&m_pTable->GetTableID(), &oldCD, &oldlen);
// start the transaction
TESTC_(StartTransaction(pITransactionLocal), S_OK);
// try to add a column to this maximum length name table
if (rgColumnDesc[0].dbcid.uName.pwszName)
PROVIDER_FREE(rgColumnDesc[0].dbcid.uName.pwszName);
rgColumnDesc[0].dbcid.uName.pwszName = wcsDuplicate(L"transacted_column");
switch(vSupportedTxnDDL.lVal)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(m_hr = m_pITableDefinition->AddColumn(
&m_pTable->GetTableID(),
&rgColumnDesc[0],
&pColumnID), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[0], &pColumnID), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
// error should be returned
CHECK(m_pITableDefinition->AddColumn(
&m_pTable->GetTableID(),
&rgColumnDesc[0],
&pColumnID), S_OK);
break;
default:
TESTC(FALSE);
}
// commit with retaining
if (DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal)
{
CHECK(pITransactionLocal->Commit(TRUE, 0, 0), S_OK); //XACTTC_SYNC, 0), S_OK))
//check the commit with retaining
CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK);
}
GetColumnDescOnTable(&m_pTable->GetTableID(), &newCD, &newlen);
if (DBPROPVAL_TC_DML == vSupportedTxnDDL.lVal)
{ // check column was not added
COMPARE(AreColEqual(oldCD, oldlen, newCD, newlen), TRUE);
}
else
{ // check column was added
COMPARE(CheckColInfo(oldCD, oldlen, newCD, newlen, &rgColumnDesc[0]), TRUE);
}
ReleaseColumnDesc(newCD, newlen);
newCD = NULL;
newlen = 0;
CLEANUP:
if (rgColumnDesc)
rgColumnDesc[0].dbcid.uName.pwszName = NULL;
SAFE_RELEASE(pITransactionLocal);
ReleaseColumnDesc(oldCD, oldlen);
m_hr = m_pTable->DropTable();
ReleaseDBID(pColumnID);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(38)
//*-----------------------------------------------------------------------
// @mfunc Commit without retain
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_38()
{
TBEGIN
ITransactionLocal *pITransactionLocal = NULL;
DBCOLUMNDESC *newCD = NULL, *oldCD = NULL;
DBORDINAL newlen = 0, oldlen = 0;
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
VARIANT vSupportedTxnDDL;
BOOL fDDL_LOCK = FALSE;
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_ITransactionLocal,
SESSION_INTERFACE, (IUnknown**)&pITransactionLocal));
VariantInit(&vSupportedTxnDDL);
TESTC_PROVIDER(GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO,
g_pIDBInitialize, &vSupportedTxnDDL));
TESTC(VT_I4 == vSupportedTxnDDL.vt);
// what values should we accept?
TESTC_PROVIDER(DBPROPVAL_TC_NONE != vSupportedTxnDDL.lVal);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create a table and populate it
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
GetColumnDescOnTable(&m_pTable->GetTableID(), &oldCD, &oldlen);
// start the transaction
TESTC_(StartTransaction(pITransactionLocal), S_OK);
// try to add a column to this maximum length name table
if (rgColumnDesc[0].dbcid.uName.pwszName)
PROVIDER_FREE(rgColumnDesc[0].dbcid.uName.pwszName);
rgColumnDesc[0].dbcid.uName.pwszName = L"transacted_column";
switch(vSupportedTxnDDL.lVal)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(m_hr = m_pITableDefinition->AddColumn(
&m_pTable->GetTableID(),
&rgColumnDesc[0],
&pColumnID), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[0], &pColumnID), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
// error should be returned
CHECK(m_pITableDefinition->AddColumn(
&m_pTable->GetTableID(),
&rgColumnDesc[0],
&pColumnID), S_OK);
break;
default:
TESTC(FALSE);
}
if (DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal)
{
// commit without retaining
CHECK(m_hr = pITransactionLocal->Commit(FALSE, XACTTC_SYNC, 0), S_OK);
//check the commit without retaining
CHECK(pITransactionLocal->Abort(NULL, FALSE, FALSE), FAILED(m_hr)? S_OK: XACT_E_NOTRANSACTION);
}
GetColumnDescOnTable(&m_pTable->GetTableID(), &newCD, &newlen);
if (DBPROPVAL_TC_DML == vSupportedTxnDDL.lVal)
{ // check column was not added
COMPARE(AreColEqual(oldCD, oldlen, newCD, newlen), TRUE);
}
else
{ // check column was added
COMPARE(CheckColInfo(oldCD, oldlen, newCD, newlen, &rgColumnDesc[0]), TRUE);
}
ReleaseColumnDesc(newCD, newlen);
CLEANUP:
if (rgColumnDesc)
rgColumnDesc[0].dbcid.uName.pwszName = NULL;
ReleaseColumnDesc(oldCD, oldlen);
m_hr = m_pTable->DropTable();
SAFE_RELEASE(pITransactionLocal);
ReleaseDBID(pColumnID);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(39)
//*-----------------------------------------------------------------------
// @mfunc Add a column for each provider type in an empty table => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_39()
{
TBEGIN
DBORDINAL i;
WCHAR *pwszName;
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
pwszName = rgColumnDesc[0].dbcid.uName.pwszName;
m_pTable->SetColumnDesc(rgColumnDesc, 1);
// for each type in DBCOLUMNDESC, add a column with maximum column size
rgColumnDesc[0].dbcid.uName.pwszName = pwszName;
for (i=0; i<cColumnDesc; i++)
{
// try to add a column from rgColumnDesc[i]
odtLog << "column name:" << rgColumnDesc[i].dbcid.uName.pwszName <<
" column type:" << rgColumnDesc[i].pwszTypeName << "\n";
rgColumnDesc[0].dbcid.uName.pwszName = L"Initial_column";
// create a table with a single column, equal to the first one in the row
if (!CHECK(m_pTable->CreateTable(0, 0), S_OK))
continue;
rgColumnDesc[0].dbcid.uName.pwszName = pwszName;
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[i], &pColumnID), S_OK);
CHECK(m_pTable->DropTable(), S_OK);
ReleaseDBID(pColumnID);
pColumnID = NULL;
}
rgColumnDesc[0].dbcid.uName.pwszName = pwszName;
m_pTable->SetNoOfColumnDesc(cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(40)
//*-----------------------------------------------------------------------
// @mfunc Add a column to a table created with a SQL command => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_40()
{
TBEGIN
DBID *pColumnID = NULL;
BOOL fTableCreation;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
IDBCreateCommand *pIDBCreateCommand = NULL;
// check wheter the commands are supported
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_IDBCreateCommand,
SESSION_INTERFACE, (IUnknown**)&pIDBCreateCommand));
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
// set order for table creation
fTableCreation = GetModInfo()->UseITableDefinition(FALSE);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// try to add a column to this maximum length name table
SAFE_FREE(rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName);
rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName = wcsDuplicate(L"new_column");
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[cColumnDesc-1], &pColumnID), S_OK);
CLEANUP:
m_pTable->DropTable();
m_pTable->SetNoOfColumnDesc(cColumnDesc);
GetModInfo()->UseITableDefinition(fTableCreation);
ReleaseDBID(pColumnID);
SAFE_RELEASE(pIDBCreateCommand);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(41)
//*-----------------------------------------------------------------------
// @mfunc Drop all the column of a table (via SQL stmt) and then try to add a column => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_41()
{
TBEGIN
DBID *pColumnID = NULL;
BOOL fTableCreation;
DB_LORDINAL rgCol[1] = {1};
DB_LORDINAL *prgCol = rgCol;
DBORDINAL nCol = 1;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 1;
IDBCreateCommand *pIDBCreateCommand = NULL;
// check whether commands are supported
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_IDBCreateCommand,
SESSION_INTERFACE, (IUnknown**)&pIDBCreateCommand));
DuplicateColumnDesc(m_rgColumnDesc, cColumnDesc, &rgColumnDesc);
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// create a table with a single column, using a SQL command
fTableCreation = GetModInfo()->UseITableDefinition(FALSE);
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// drop the only existing column from the table
TESTC_PROVIDER(S_OK == m_pTable->ExecuteCommand(
ALTER_TABLE_DROP_COLUMN,
IID_NULL,
NULL, // the table name will be the implicit one
NULL, // don't return the command statement
&nCol,
(DB_LORDINAL**)&prgCol,
EXECUTE_IFNOERROR // execute the command
));
// try to add a column to this table
SAFE_FREE(rgColumnDesc[0].dbcid.uName.pwszName);
rgColumnDesc[0].dbcid.uName.pwszName = wcsDuplicate(L"new_column");
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[0], &pColumnID), S_OK);
CHECK(m_pTable->DropTable(), S_OK);
CLEANUP:
GetModInfo()->UseITableDefinition(fTableCreation);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pColumnID);
SAFE_RELEASE(pIDBCreateCommand);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(42)
//*-----------------------------------------------------------------------
// @mfunc Non NULL pTypeInfo in DBCOLUMNDESC => DB_E_BADTYPE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_42()
{
TBEGIN
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// try to add a column with a NULL value for name pointer
rgColumnDesc[cColumnDesc-1].pTypeInfo = (ITypeInfo*)m_pITableDefinition;
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[cColumnDesc-1],
&pColumnID), DB_E_BADTYPE);
CLEANUP:
m_pTable->DropTable();
rgColumnDesc[cColumnDesc-1].pTypeInfo = NULL;
m_pTable->SetNoOfColumnDesc(cColumnDesc);
ReleaseDBID(pColumnID);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(43)
//*-----------------------------------------------------------------------
// @mfunc Missmatch between wType and pwszTypeName => DB_E_BADTYPE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_43()
{
TBEGIN
DBORDINAL i;
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
// try to add a column with a NULL value for name pointer
for (i=0; i<cColumnDesc-1 && rgColumnDesc[i].wType == rgColumnDesc[cColumnDesc-1].wType; i++);
TESTC_PROVIDER(i < cColumnDesc-2);
if (rgColumnDesc[cColumnDesc-1].pwszTypeName)
PROVIDER_FREE(rgColumnDesc[cColumnDesc-1].pwszTypeName);
rgColumnDesc[cColumnDesc-1].pwszTypeName = wcsDuplicate(rgColumnDesc[i].pwszTypeName);
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[cColumnDesc-1],
&pColumnID), DB_E_BADTYPE);
CLEANUP:
m_pTable->DropTable();
m_pTable->SetNoOfColumnDesc(cColumnDesc);
ReleaseDBID(pColumnID);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(44)
//*-----------------------------------------------------------------------
// @mfunc Add a not nullable column and try to insert a null value for it
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_44()
{
TBEGIN
HRESULT hr;
DBID *pColumnID = NULL;
DBORDINAL i;
DBORDINAL nCol[1];
CCol col;
IRowsetChange *pIRowsetChange = NULL;
BOOL fFound;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
VARIANT defval;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
if (!SettableProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN) && 2 > m_cColumnDesc)
{
TESTB = TEST_SKIPPED;
goto CLEANUP1;
}
m_pTable->SetBuildColumnDesc(FALSE);
// use all the types from the not nullable one (exclusive)
m_pTable->SetColumnDesc(&rgColumnDesc[1], cColumnDesc-1);
TESTC_(m_pTable->CreateTable(10, 0), S_OK);
if (rgColumnDesc[0].dbcid.uName.pwszName)
PROVIDER_FREE(rgColumnDesc[0].dbcid.uName.pwszName);
rgColumnDesc[0].dbcid.uName.pwszName = L"NewColumn";
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets, DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE, DBPROPOPTIONS_REQUIRED, DB_NULLID, DBPROPSET_COLUMN);
if (SettableProperty(DBPROP_COL_DEFAULT, DBPROPSET_COLUMN))
{
VariantInit(&defval);
GetDefaultValue(&rgColumnDesc[0], &defval);
SetDefaultProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
&defval, DBPROPOPTIONS_OPTIONAL); // might be not supported
VariantClear(&defval);
}
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[0], &pColumnID), S_OK);
// must update info about table in m_pTable
m_pTable->GetTableColumnInfo(&m_pTable->GetTableID());
m_pTable->AddInfoFromColumnsSchemaRowset(m_pITableDefinition,
DBKIND_NAME != m_pTable->GetTableID().eKind? m_pTable->GetTableID().uName.pwszName: NULL);
for (i=0, fFound=FALSE; !fFound && i<m_pTable->CountColumnsOnTable(); i++)
{
col = m_pTable->GetColInfoForUpdate(i+1);
if (CompareDBID(rgColumnDesc[0].dbcid, *col.GetColID(), m_pIDBInitialize))
{
nCol[0] = col.GetColNum();
fFound = TRUE;
}
}
TESTC(fFound);
TEST2C_(hr = m_pIOpenRowset->OpenRowset(NULL, &m_pTable->GetTableID(), NULL,
IID_IRowsetChange, 0, NULL, (IUnknown**)&pIRowsetChange), S_OK, E_NOINTERFACE);
TESTC_PROVIDER(S_OK == hr);
// try to insert a null value in a not null column
hr = Insert(0, pIRowsetChange, NUMELEM(nCol), nCol);
if (DB_E_NOTSUPPORTED != hr)
CHECK(hr, DB_E_ERRORSOCCURRED);
CLEANUP:
m_pTable->SetColumnDesc(NULL);
CLEANUP1:
SAFE_RELEASE(pIRowsetChange);
CHECK(m_pTable->DropTable(), S_OK);
if (rgColumnDesc)
rgColumnDesc[0].dbcid.uName.pwszName = NULL;
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pColumnID);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(45)
//*-----------------------------------------------------------------------
// @mfunc Add a column on a view
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_45()
{
TBEGIN
DBID TableID;
DBID *pColumnID = NULL;
LPWSTR pwszViewName = L"VirTab";
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
IDBCreateCommand *pIDBCreateCommand = NULL;
// check whether commands are supported
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_IDBCreateCommand,
SESSION_INTERFACE, (IUnknown**)&pIDBCreateCommand));
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_pTable->CreateTable(10, 1), S_OK);
m_pTable->SetViewName(pwszViewName);
if ( !CHECK(m_pTable->ExecuteCommand(
CREATE_VIEW,
IID_NULL,
pwszViewName, // the table name will be the implicit one
NULL, // don't return the command statement
0,
NULL,
EXECUTE_IFNOERROR // execute the command
), S_OK)
)
{
odtLog << "\tA view on the table could not be created\n";
goto CLEANUP;
}
// try to add a column to this maximum length name table
PROVIDER_FREE(rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName);
rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName = wcsDuplicate(L"new_column");
// prepare the DBID to reflect the view
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = pwszViewName;
TEST3C_(AddColumnAndCheck(&TableID, &rgColumnDesc[cColumnDesc-1], &pColumnID),
E_FAIL, DB_E_NOTABLE, DB_SEC_E_PERMISSIONDENIED)
CLEANUP:
SAFE_RELEASE(pIDBCreateCommand);
ReleaseDBID(pColumnID);
// drop the view!
if (m_pTable->GetTableName())
m_pTable->ExecuteCommand(
DROP_VIEW,
IID_NULL,
pwszViewName, // the table name will be the implicit one
NULL, // don't return the command statement
0,
NULL,
EXECUTE_IFNOERROR // execute the command
);
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(46)
//*-----------------------------------------------------------------------
// @mfunc eKind != DBKIND_NAME for a column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_46()
// try to use all the DBKIND values
{
TBEGIN
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_hr = m_pTable->CreateTable(10, 0), S_OK);
// try to add a column with different DBKIND values
odtLog << "Add DBKIND_GUID_NAME column\n";
if (rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName)
PROVIDER_FREE(rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName);
rgColumnDesc[cColumnDesc-1].dbcid.eKind = DBKIND_GUID_NAME;
rgColumnDesc[cColumnDesc-1].dbcid.uGuid.guid = guidModule;
rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName = L"DBKIND_GUID_NAME";
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), DB_E_BADCOLUMNID);
ReleaseDBID(pColumnID);
pColumnID = NULL;
odtLog << "Add DBKIND_GUID_PROPID column\n";
rgColumnDesc[cColumnDesc-1].dbcid.eKind = DBKIND_GUID_PROPID;
rgColumnDesc[cColumnDesc-1].dbcid.uName.ulPropid = 0;
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), DB_E_BADCOLUMNID);
ReleaseDBID(pColumnID);
pColumnID = NULL;
odtLog << "Add DBKIND_NAME column\n";
rgColumnDesc[cColumnDesc-1].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName = L"DBKIND_NAME";
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), S_OK);
ReleaseDBID(pColumnID);
pColumnID = NULL;
odtLog << "Add DBKIND_PGUID_NAME column\n";
rgColumnDesc[cColumnDesc-1].dbcid.eKind = DBKIND_PGUID_NAME;
rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName = L"DBKIND_PGUID_NAME";
rgColumnDesc[cColumnDesc-1].dbcid.uGuid.pguid = &guidModule;
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), DB_E_BADCOLUMNID);
ReleaseDBID(pColumnID);
pColumnID = NULL;
odtLog << "Add DBKIND_PGUID_PROPID column\n";
rgColumnDesc[cColumnDesc-1].dbcid.eKind = DBKIND_PGUID_PROPID;
rgColumnDesc[cColumnDesc-1].dbcid.uName.ulPropid = 0;
rgColumnDesc[cColumnDesc-1].dbcid.uGuid.pguid = &guidModule;
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), DB_E_BADCOLUMNID);
ReleaseDBID(pColumnID);
pColumnID = NULL;
odtLog << "Add DBKIND_PROPID column\n";
rgColumnDesc[cColumnDesc-1].dbcid.eKind = DBKIND_PROPID;
rgColumnDesc[cColumnDesc-1].dbcid.uName.ulPropid = 0;
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), DB_E_BADCOLUMNID);
ReleaseDBID(pColumnID);
pColumnID = NULL;
odtLog << "Add DBKIND_GUID column\n";
rgColumnDesc[cColumnDesc-1].dbcid.eKind = DBKIND_GUID;
rgColumnDesc[cColumnDesc-1].dbcid.uName.ulPropid = 0;
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), DB_E_BADCOLUMNID);
ReleaseDBID(pColumnID);
pColumnID = NULL;
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
rgColumnDesc[cColumnDesc-1].dbcid.uName.pwszName = NULL;
m_pTable->SetNoOfColumnDesc(cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
//---------------------------------------------------------------------
//
// @cmember Thread funtion for TCAddColumn
//---------------------------------------------------------------------
unsigned TCAddColumn::MyThreadProc(ULONG i)
{
DBCOLUMNDESC *pColumnDesc = NULL;
HRESULT hr;
if (i>= nThreads)
return 0;
DuplicateColumnDesc(m_rgColumnDesc, 1, &pColumnDesc);
ReleaseDBID(&pColumnDesc->dbcid, FALSE);
pColumnDesc->dbcid.eKind = DBKIND_NAME;
pColumnDesc->dbcid.uName.pwszName = m_rgName[i];
Sleep(0); // switch the context
hr = m_pITableDefinition->AddColumn(&m_pTable->GetTableID(), pColumnDesc, NULL);
Sleep(0); // switch the context
pColumnDesc->dbcid.uName.pwszName = NULL;
ReleaseColumnDesc(pColumnDesc, 1);
m_rgResult[i] = hr;
return 1;
} //TCAddColumn::MyThreadProc
// {{ TCW_VAR_PROTOTYPE(47)
//*-----------------------------------------------------------------------
// @mfunc threads with different column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_47()
{
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
BOOL fTestResult = TEST_FAIL;
ULONG i;
LPWSTR pwszBaseName = NULL;
WCHAR number[3];
DBCOLUMNDESC *rgColumnDesc = NULL;
ULONG cColumnDesc = 1;
DuplicateColumnDesc(m_rgColumnDesc, cColumnDesc, &rgColumnDesc);
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
// create n names and init the results
for (i=0; i<nThreads; i++)
m_rgName[i] = NULL;
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
pwszBaseName = m_pTable->GetTableName();
for (i=0; i< nThreads; i++)
{
m_rgResult[i] = -1;
m_rgName[i] = (WCHAR*)PROVIDER_ALLOC((3+wcslen(pwszBaseName))*sizeof(WCHAR));
ASSERT(m_rgName[i]);
wcscpy(m_rgName[i], pwszBaseName);
swprintf(number, L"%02d", i);
wcscat(m_rgName[i], number);
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
}
// creates a table, build rgColumnDesc by it
for (i=0; i<nThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(nThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< nThreads; i++)
CloseHandle(hrgThread[i]);
for (i=0; i<nThreads; i++)
TESTC_(m_rgResult[i], S_OK);
fTestResult = TEST_PASS;
CLEANUP:
DropTableAndCheck(&m_pTable->GetTableID());
for (i=0; i<nThreads; i++)
PROVIDER_FREE(m_rgName[i]);
return fTestResult;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(48)
//*-----------------------------------------------------------------------
// @mfunc threads on the same column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_48()
{
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
BOOL fTestResult = TEST_FAIL;
ULONG i, nS_OK, nDB_E_DUPLICATECOLUMNID;
DBCOLUMNDESC *rgColumnDesc = NULL;
ULONG cColumnDesc = 1;
DuplicateColumnDesc(m_rgColumnDesc, cColumnDesc, &rgColumnDesc);
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
for (i=0; i< nThreads; i++)
{
m_rgResult[i] = -1;
m_rgName[i] = L"someOtherColumn";
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
}
// creates a table, build rgColumnDesc by it
for (i=0; i<nThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(nThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< nThreads; i++)
CloseHandle(hrgThread[i]);
for (i=nS_OK=nDB_E_DUPLICATECOLUMNID=0; i<nThreads; i++)
{
if (m_rgResult[i] == S_OK)
nS_OK++;
else if (CHECK(m_rgResult[i], DB_E_DUPLICATECOLUMNID))
nDB_E_DUPLICATECOLUMNID++;
else
goto CLEANUP;
}
TESTC(nS_OK== 1 && nDB_E_DUPLICATECOLUMNID == nThreads-1);
fTestResult = TEST_PASS;
CLEANUP:
DropTableAndCheck(&m_pTable->GetTableID());
return fTestResult;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(49)
//*-----------------------------------------------------------------------
// @mfunc add columns of alll known wType => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_49()
{
TBEGIN
DBORDINAL i;
DBID *pColumnID = NULL;
DBCOLUMNDESC *pColumnDesc = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
DuplicateColumnDesc(&rgColumnDesc[0], 1, &pColumnDesc);
PROVIDER_FREE(pColumnDesc[0].dbcid.uName.pwszName);
pColumnDesc[0].dbcid.uName.pwszName = wcsDuplicate(L"ColoanaInitiala");
m_pTable->SetColumnDesc(pColumnDesc, 1);
for (i=0; i<cColumnDesc; i++)
{
// create a table with a single column, equal to the first one in the row
if (!CHECK(m_hr = m_pTable->CreateTable(0, 0), S_OK))
continue;
// try to add a column from rgColumnDesc[i] with a NULL name and a valid wType
PROVIDER_FREE(rgColumnDesc[i].pwszTypeName);
odtLog << "column name: " << rgColumnDesc[i].dbcid.uName.pwszName << "\n";
CHECK(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[i], &pColumnID), S_OK);
CHECK(m_pTable->DropTable(), S_OK);
ReleaseDBID(pColumnID);
pColumnID = NULL;
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(50)
//*-----------------------------------------------------------------------
// @mfunc Fully Qualified table name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_50()
{
TBEGIN
DBID TableID;
DBID BaseTableID;
WCHAR *pwszQualTableName = NULL;
WCHAR *pwszCatalogName = NULL;
WCHAR *pwszSchemaName = NULL;
WCHAR *pwszTableName = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
// create a regular table
TESTC(NULL != m_pTable);
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
pwszTableName = m_pTable->GetTableName();
TableID.eKind = DBKIND_NAME;
BaseTableID.eKind = DBKIND_NAME;
BaseTableID.uName.pwszName = pwszTableName;
TESTC(GetCatalogSchemaNames(pwszTableName, &pwszCatalogName, &pwszSchemaName));
//Construct a fully Qualified TableName...
TESTC_(m_pTable->GetQualifiedName(pwszCatalogName, pwszSchemaName, pwszTableName, &pwszQualTableName),S_OK);
TableID.uName.pwszName = pwszQualTableName;
m_pTable->BuildColumnDescs(&rgColumnDesc);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc=m_pTable->CountColumnsOnTable());
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
ReleaseDBID(&rgColumnDesc[0].dbcid, FALSE);
rgColumnDesc[0].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[0].dbcid.uName.pwszName = wcsDuplicate(L"AltaColoana");
TESTC_(AddColumnAndCheck(&TableID, &rgColumnDesc[0], NULL, NULL, &BaseTableID), S_OK);
CLEANUP:
SAFE_FREE(pwszCatalogName);
SAFE_FREE(pwszSchemaName);
SAFE_FREE(pwszQualTableName);
m_pTable->DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(51)
//*-----------------------------------------------------------------------
// @mfunc Quoted Table Name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_51()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = NULL;
TESTC(NULL != m_pTable);
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
m_pTable->GetQuotedName(m_pTable->GetTableName(), &TableID.uName.pwszName);
m_pTable->BuildColumnDescs(&rgColumnDesc);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc=m_pTable->CountColumnsOnTable());
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
ReleaseDBID(&rgColumnDesc[0].dbcid, FALSE);
rgColumnDesc[0].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[0].dbcid.uName.pwszName = wcsDuplicate(L"AltaColoana");
TESTC_(AddColumnAndCheck(&TableID, &rgColumnDesc[0], NULL), S_OK);
CLEANUP:
ReleaseDBID(&TableID, FALSE);
m_pTable->DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(52)
//*-----------------------------------------------------------------------
// @mfunc pColumnDesc == NULL => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_52()
{
TBEGIN
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
m_pTable->SetBuildColumnDesc(FALSE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(), NULL, &pColumnID), E_INVALIDARG);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
ReleaseDBID(pColumnID);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(53)
//*-----------------------------------------------------------------------
// @mfunc cPropertySets != 0 and rgPropertySets == NULL in pColumnDesc => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_53()
{
TBEGIN
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_hr = m_pTable->CreateTable(10, 0), S_OK);
// try to add a column with a bad wType
rgColumnDesc[cColumnDesc-1].cPropertySets = (BYTE)(rand()%255+1);
rgColumnDesc[cColumnDesc-1].rgPropertySets = NULL;
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[cColumnDesc-1],
&pColumnID), E_INVALIDARG);
CLEANUP:
ReleaseDBID(pColumnID);
CHECK(m_pTable->DropTable(), S_OK);
// restore the proper number of properties for the column
rgColumnDesc[cColumnDesc-1].cPropertySets = 0;
m_pTable->SetNoOfColumnDesc(cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(54)
//*-----------------------------------------------------------------------
// @mfunc cPropertySets == 0 and rgPropertySets != NULL in pColumnDesc => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_54()
{
TBEGIN
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBPROPSET rgPropertySets[1];
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_hr = m_pTable->CreateTable(10, 0), S_OK);
// try to add a column with a bad wType
rgColumnDesc[cColumnDesc-1].cPropertySets = 0;
rgColumnDesc[cColumnDesc-1].rgPropertySets = rgPropertySets;
memset(rgPropertySets, 0, sizeof(DBPROPSET));
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[cColumnDesc-1],
&pColumnID), S_OK);
CLEANUP:
rgColumnDesc[cColumnDesc-1].rgPropertySets = NULL;
ReleaseDBID(pColumnID);
CHECK(m_pTable->DropTable(), S_OK);
// restore the property set array
rgColumnDesc[cColumnDesc-1].rgPropertySets = NULL;
m_pTable->SetNoOfColumnDesc(cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(55)
//*-----------------------------------------------------------------------
// @mfunc cProperties == 0 and rgProperties != NULL in pColumnDesc's propset => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_55()
{
TBEGIN
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBPROPSET rgPropertySets[1];
DBPROP rgProperties[1];
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_hr = m_pTable->CreateTable(10, 0), S_OK);
// try to add a column with a bad wType
rgColumnDesc[cColumnDesc-1].cPropertySets = NUMELEM(rgPropertySets);
rgColumnDesc[cColumnDesc-1].rgPropertySets = rgPropertySets;
memset(rgPropertySets, 0, sizeof(DBPROPSET));
rgPropertySets[0].guidPropertySet = DBPROPSET_COLUMN;
rgPropertySets[0].cProperties = 0;
rgPropertySets[0].rgProperties = rgProperties;
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), S_OK);
CLEANUP:
rgColumnDesc[cColumnDesc-1].rgPropertySets = NULL;
ReleaseDBID(pColumnID);
CHECK(m_pTable->DropTable(), S_OK);
// restore the prop array
rgPropertySets[0].rgProperties = NULL;
m_pTable->SetNoOfColumnDesc(cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(56)
//*-----------------------------------------------------------------------
// @mfunc cProperties != 0 and rgProperties == NULL in pColumnDesc's propset => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_56()
{
TBEGIN
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBPROPSET rgPropertySets[1];
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_pTable->CreateTable(10, 0), S_OK);
// built the property set array
rgColumnDesc[cColumnDesc-1].cPropertySets = NUMELEM(rgPropertySets);
rgColumnDesc[cColumnDesc-1].rgPropertySets = rgPropertySets;
memset(rgPropertySets, 0, sizeof(DBPROPSET));
rgPropertySets[0].guidPropertySet = DBPROPSET_COLUMN;
rgPropertySets[0].cProperties = (BYTE)(rand()%255+1);
rgPropertySets[0].rgProperties = NULL;
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID), E_INVALIDARG);
CLEANUP:
rgColumnDesc[cColumnDesc-1].rgPropertySets = NULL;
ReleaseDBID(pColumnID);
CHECK(m_pTable->DropTable(), S_OK);
// restore the prop counter
rgPropertySets[0].cProperties = 0;
m_pTable->SetNoOfColumnDesc(cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(57)
//*-----------------------------------------------------------------------
// @mfunc pclsid not null
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_57()
{
TBEGIN
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
HRESULT hr;
POSITION pos;
CCol col;
BOOL fOleSupported = FALSE;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_pTable->CreateTable(10, 0), S_OK);
// set pclsid to IID_NULL
rgColumnDesc[cColumnDesc-1].pclsid = (GUID*)&IID_NULL;
// check that pclsid is ignored
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(),
&rgColumnDesc[cColumnDesc-1], &pColumnID),S_OK);
TESTC_(m_pTable->DropTable(), S_OK);
TESTC_(m_pTable->CreateTable(10, 0), S_OK);
// check DBTYPE_IUNKNOWN is supported
for (pos = m_ColList.GetHeadPosition(); pos; )
{
col = m_ColList.GetNext(pos);
if (DBTYPE_IUNKNOWN == col.GetProviderType())
{
fOleSupported = TRUE;
break;
}
}
// check whether a DBTYPE_IUNKNOWN column can be created in the table
rgColumnDesc[cColumnDesc-1].wType = DBTYPE_IUNKNOWN;
PROVIDER_FREE(rgColumnDesc[cColumnDesc-1].pwszTypeName);
if (fOleSupported)
rgColumnDesc[cColumnDesc-1].pwszTypeName = wcsDuplicate(col.GetProviderTypeName());
hr = fOleSupported ? S_OK : DB_E_BADTYPE;
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[cColumnDesc-1],
&pColumnID), hr);
CLEANUP:
ReleaseDBID(pColumnID);
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(58)
//*-----------------------------------------------------------------------
// @mfunc NULL pwszTypeName => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddColumn::Variation_58()
{
TBEGIN
DBID *pColumnID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
TESTC_(m_hr = m_pTable->CreateTable(10, 0), S_OK);
// try to add a column with a bad wType
PROVIDER_FREE(rgColumnDesc[cColumnDesc-1].pwszTypeName);
rgColumnDesc[cColumnDesc-1].pwszTypeName = NULL;
TESTC_(AddColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[cColumnDesc-1],
&pColumnID), S_OK);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
m_pTable->SetNoOfColumnDesc(cColumnDesc);
ReleaseDBID(pColumnID);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCAddColumn::Terminate()
{
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCITableDefinition::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(TCDropColumn)
//*-----------------------------------------------------------------------
//| Test Case: TCDropColumn - Test case for dropping columns
//| Created: 09/11/97
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCDropColumn::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCITableDefinition::Init())
// }}
{
return TRUE;
}
return FALSE;
}
/*
//----------------------------------------------------------------------
//
// @cmember Check whether the 2 list of columns are identical,
// excepting column n
//----------------------------------------------------------------------
BOOL TCDropColumn::IsColumnDifferention(
DBCOLUMNDESC *newlist,
ULONG newlen,
DBCOLUMNDESC *oldlist,
ULONG oldlen,
ULONG n
)
{
ULONG nNewCol;
ULONG nOldCol;
if (!newlist || !oldlist)
return oldlist == newlist;
if (newlen != oldlen - 1)
return FALSE;
// it is assumed that the columns should be identical up to column n
// the new column n will be the oldcolumn n+1, the new column n+1
// should be identical to the old column n+2, etc
for (nNewCol = nOldCol = 0; nNewCol < newlen; nNewCol++)
{
if (nNewCol == n)
nOldCol++;
if (!CompareDBID(newlist[nNewCol].dbcid, oldlist[nOldCol++].dbcid, m_pIDBInitialize))
return FALSE;
}
return TRUE;
} //TCDropColumn::IsColumnDifferention
//----------------------------------------------------------------------
//
// @cmember Check whether the 2 list of columns are identical
//----------------------------------------------------------------------
BOOL TCDropColumn::ListEqual(DBCOLUMNDESC *newlist, ULONG newlen, DBCOLUMNDESC *oldlist, ULONG oldlen)
{
ULONG i;
if (!newlist || !oldlist)
return newlist == oldlist;
if (newlen != oldlen)
return FALSE;
for (i=0; i<newlen; i++)
if (!CompareDBID(newlist[i].dbcid, oldlist[i].dbcid, m_pIDBInitialize))
return FALSE;
return TRUE;
} //TCDropColumn::ListEqual
*/
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc pTableID is NULL => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_1()
{
TBEGIN
DBID ColumnID;
ColumnID.eKind = DBKIND_NAME;
ColumnID.uName.pwszName = L"Gateway2001";
TESTC_(DropColumnAndCheck(NULL, &ColumnID), E_INVALIDARG);
CLEANUP:
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc pColumnID in NULL => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_2()
{
TBEGIN
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
TESTC_(DropColumnAndCheck(&m_pTable->GetTableID(), NULL), E_INVALIDARG);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc *pTableID is DB_NULLID => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_3()
{
TBEGIN
DBID ColumnID;
DBID TableID = DB_NULLID;
ColumnID.eKind = DBKIND_NAME;
ColumnID.uName.pwszName = L"Gateway2001";
TESTC_(DropColumnAndCheck(&TableID, &ColumnID), DB_E_NOTABLE);
CLEANUP:
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc *pColumnID is DB_NULLID => DB_E_NOCOLUMN
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_4()
{
TBEGIN
DBID ColumnID;
memset(&ColumnID, 0, sizeof(DBID));
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
//NOTE: spec was changed in MDAC 2.6 to replace DB_E_BADCOLUMNID with DB_E_NOCOLUMN
// for ITableDefinition::DropColumn. So when runnning against MDAC 2.5 expect DB_E_BADCOLUMNID
// This is for SQL-specific provider. For other providers, you should modify this to test against your target spec
TESTC_(DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID), g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Maximum length table name => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_5()
{
TBEGIN
DBID ColumnID;
DBID TableID;
DBORDINAL n, cColumns;
DBCOLUMNINFO *rgColInfo = NULL;
LPWSTR pwszTableName;
OLECHAR *pStringBuffer = NULL;
DBORDINAL ulOrdinal = 0;
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = pwszTableName = BuildValidName(m_cMaxTableName, m_pTable->GetTableName());
PRVTRACE(L"** TCDropColumn::Variation_5(): create a table with max table name: %s, %d\n",
pwszTableName, n=wcslen(pwszTableName));
TESTC_(m_hr = m_pTable->CreateTable(0, 0, pwszTableName), S_OK);
GetColumnInfo(&TableID, &cColumns, &rgColInfo, &pStringBuffer);
TESTC(0 < cColumns);
// check if the first column is bookmark or not
if (0 == rgColInfo[0].iOrdinal)
ulOrdinal = 1;
TESTC(ulOrdinal < cColumns);
ColumnID.eKind = DBKIND_NAME;
ColumnID.uName.pwszName = rgColInfo[ulOrdinal].pwszName;
TESTC_(DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID), S_OK);
CLEANUP:
CHECK(m_hr = m_pTable->DropTable(), S_OK);
PROVIDER_FREE(pStringBuffer);
PROVIDER_FREE(rgColInfo);
PROVIDER_FREE(pwszTableName);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc 1-char-too long table name => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_6()
{
BOOL fTestRes = TEST_FAIL;
DBID ColumnID;
DBID TableID;
DBCOLUMNDESC *oldCD=NULL;
DBORDINAL oldlen;
LPWSTR pwszTableName;
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = BuildValidName(m_cMaxTableName+1, m_pTable->GetTableName());
pwszTableName = BuildValidName(m_cMaxTableName, m_pTable->GetTableName());
TESTC_(m_hr = m_pTable->CreateTable(0, 0, pwszTableName), S_OK);
GetColumnDescOnTable(&m_pTable->GetTableID(), &oldCD, &oldlen);
ColumnID.eKind = DBKIND_NAME;
ColumnID.uName.pwszName = wcsDuplicate(oldCD[0].dbcid.uName.pwszName);
TESTC_(DropColumnAndCheck(&TableID, &ColumnID), DB_E_NOTABLE);
CLEANUP:
ReleaseColumnDesc(oldCD, oldlen);
CHECK(m_pTable->DropTable(), S_OK);
ReleaseDBID(&ColumnID, FALSE);
ReleaseDBID(&TableID, FALSE);
PROVIDER_FREE(pwszTableName);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc *pTableID contains a NULL table name => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_7()
{
TBEGIN
DBID ColumnID;
DBID TableID;
ColumnID.eKind = DBKIND_NAME;
ColumnID.uName.pwszName = L"Gateway2001";
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = NULL;
TESTC_(DropColumnAndCheck(&TableID, &ColumnID), DB_E_NOTABLE);
CLEANUP:
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc *pTableID contains an invalid name => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_8()
{
TBEGIN
DBID ColumnID;
DBID TableID;
size_t n;
m_pTable->MakeTableName(NULL);
n = min(wcslen(m_pwszInvalidTableChars)+wcslen(m_pTable->GetTableName()), m_cMaxTableName);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = BuildInvalidName(n, m_pTable->GetTableName(), m_pwszInvalidTableChars);
ColumnID.eKind = DBKIND_NAME;
ColumnID.uName.pwszName = L"foca";
TESTC_(DropColumnAndCheck(&TableID, &ColumnID), DB_E_NOTABLE);
CLEANUP:
ReleaseDBID(&TableID, FALSE);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc Maximum length for a column name => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_9()
{
TBEGIN
DBID ColumnID;
LPWSTR pwszColumnName;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->MakeTableName(NULL);
ColumnID.eKind = DBKIND_NAME;
ColumnID.uName.pwszName = pwszColumnName = BuildValidName(m_cMaxColName, L"aaabcdef");
ReleaseDBID(&rgColumnDesc[0].dbcid, FALSE);
rgColumnDesc[0].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[0].dbcid.uName.pwszName = pwszColumnName;
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
TESTC_(DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID), S_OK);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc 1-char-too-long column name => DB_E_NOCOLUMN
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_10()
{
TBEGIN
DBID ColumnID;
LPWSTR pwszColumnName = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
m_pTable->MakeTableName(NULL);
ColumnID.eKind = DBKIND_NAME;
ColumnID.uName.pwszName = pwszColumnName = BuildValidName(m_cMaxColName, L"aaabcdef");
ColumnID.uName.pwszName = BuildValidName(m_cMaxColName+1, m_pTable->GetTableName());
ReleaseDBID(&rgColumnDesc[0].dbcid, FALSE);
rgColumnDesc[0].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[0].dbcid.uName.pwszName = pwszColumnName;
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
//NOTE: spec was changed in MDAC 2.6 to replace DB_E_BADCOLUMNID with DB_E_NOCOLUMN
// for ITableDefinition::DropColumn. So when runnning against MDAC 2.5 expect DB_E_BADCOLUMNID
// This is for SQL-specific provider. For other providers, you should modify this to test against your target spec
TESTC_(DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID), g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
PROVIDER_FREE(ColumnID.uName.pwszName);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc *pColumnID contains a NULL column name pointer => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_11()
{
TBEGIN
DBID ColumnID;
// create a table, which contains a maximum size table length
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
ColumnID.eKind = DBKIND_NAME;
ColumnID.uName.pwszName = NULL;
//NOTE: spec was changed in MDAC 2.6 to replace DB_E_BADCOLUMNID with DB_E_NOCOLUMN
// for ITableDefinition::DropColumn. So when runnning against MDAC 2.5 expect DB_E_BADCOLUMNID
// This is for SQL-specific provider. For other providers, you should modify this to test against your target spec
TESTC_(DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID), g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc *pColumnID contains an invalid column name => E_INVALID ARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_12()
{
TBEGIN
DBID ColumnID;
LPWSTR pwszColumnName;
size_t n;
m_pTable->SetBuildColumnDesc(TRUE);
m_pTable->MakeTableName(NULL);
n = min(wcslen(m_pTable->GetTableName())+wcslen(m_pwszInvalidColChars), m_cMaxColName);
pwszColumnName = BuildInvalidName(n, m_pTable->GetTableName(), m_pwszInvalidColChars);
// create a table, which contains a maximum size table length
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
ColumnID.eKind = DBKIND_NAME;
ColumnID.uName.pwszName = pwszColumnName;
//NOTE: spec was changed in MDAC 2.6 to replace DB_E_BADCOLUMNID with DB_E_NOCOLUMN
// for ITableDefinition::DropColumn. So when runnning against MDAC 2.5 expect DB_E_BADCOLUMNID
// This is for SQL-specific provider. For other providers, you should modify this to test against your target spec
TESTC_(DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID), g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
PROVIDER_FREE(pwszColumnName);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc Drop all the columns of a table => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_13()
{
TBEGIN
HRESULT hr;
DBID ColumnID;
DBORDINAL n, cColumns;
DBCOLUMNDESC *rgColumnDesc = NULL;
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
//GetColumnInfo(&m_pTable->GetTableID(), &cColumns, &rgColInfo, &pStringBuffer);
TESTC(GetColumnDescOnTable(&m_pTable->GetTableID(), &rgColumnDesc, &cColumns));
// check for bookmarks
n = 0;
for (; n < cColumns-1; n++)
{
// drop column i
//DuplicateDBID(rgColInfo[n].columnid, &ColumnID);
DuplicateDBID(rgColumnDesc[n].dbcid, &ColumnID);
if ( !CHECK(hr = DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID),
S_OK))
{
if (DBKIND_NAME == rgColumnDesc[n].dbcid.eKind)
odtLog << "cannot drop column " << rgColumnDesc[n].dbcid.uName.pwszName << "!\n";
}
else if (DBKIND_NAME == rgColumnDesc[n].dbcid.eKind)
odtLog << "Column "<< rgColumnDesc[n].dbcid.uName.pwszName << " was successfully dropped\n";
ReleaseDBID(&ColumnID, FALSE);
}
// try to drop the last column
DuplicateDBID(rgColumnDesc[cColumns-1].dbcid, &ColumnID);
hr = DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID);
if (FAILED(hr))
{
if (DBKIND_NAME == rgColumnDesc[cColumns-1].dbcid.eKind)
odtLog << "cannot drop column " << rgColumnDesc[cColumns-1].dbcid.uName.pwszName << " (the last one)!\n";
}
else if (DBKIND_NAME == rgColumnDesc[cColumns-1].dbcid.eKind)
odtLog << "Column "<< rgColumnDesc[cColumns-1].dbcid.uName.pwszName << " (the last column) was successfully dropped\n";
ReleaseDBID(&ColumnID, FALSE);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
//PROVIDER_FREE(rgColInfo);
//PROVIDER_FREE(pStringBuffer);
ReleaseColumnDesc(rgColumnDesc, cColumns, TRUE);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(14)
//*-----------------------------------------------------------------------
// @mfunc Try to delete an inexistent column => DB_E_NOCOLUMN
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_14()
{
TBEGIN
DBID ColumnID;
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
ColumnID.eKind = DBKIND_NAME;
ColumnID.uName.pwszName = L"inexistentColumn";
//NOTE: spec was changed in MDAC 2.6 to replace DB_E_BADCOLUMNID with DB_E_NOCOLUMN
// for ITableDefinition::DropColumn. So when runnning against MDAC 2.5 expect DB_E_BADCOLUMNID
// This is for SQL-specific provider. For other providers, you should modify this to test against your target spec
TESTC_(DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID), g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(15)
//*-----------------------------------------------------------------------
// @mfunc Table in use => DB_E_TABLEINUSE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_15()
{
TBEGIN
IRowset *pIRowset=NULL;
CCol col;
m_pTable->SetRowset((IUnknown**)&pIRowset);
m_pTable->SetRIID((struct _GUID*)&IID_IRowset);
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
m_pTable->AddInfoFromColumnsSchemaRowset(m_pITableDefinition,
DBKIND_NAME != m_pTable->GetTableID().eKind? m_pTable->GetTableID().uName.pwszName: NULL);
col = m_pTable->GetColInfoForUpdate(1);
TEST2C_(m_hr = DropColumnAndCheck(&m_pTable->GetTableID(),
col.GetColID()), S_OK, DB_E_TABLEINUSE);
odtLog << ((S_OK == m_hr)? "column was dropped\n": "column has been preserved\n");
CLEANUP:
m_pTable->SetRowset(NULL);
CHECK(m_pTable->DropTable(), S_OK);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc Valid name of an inexistent table => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_16()
{
TBEGIN
DBID ColumnID, TableID;
m_pTable->MakeTableName(NULL);
DuplicateDBID(m_rgColumnDesc[0].dbcid, &ColumnID);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
//NOTE: spec was changed in MDAC 2.6 to replace DB_E_BADCOLUMNID with DB_E_NOCOLUMN
// for ITableDefinition::DropColumn. So when runnning against MDAC 2.5 expect DB_E_BADCOLUMNID
// This is for SQL-specific provider. For other providers, you should modify this to test against your target spec
TEST2C_(m_hr = DropColumnAndCheck(&TableID, &ColumnID), DB_E_NOTABLE, g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN);
ReleaseDBID(&ColumnID, FALSE);
CLEANUP:
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(17)
//*-----------------------------------------------------------------------
// @mfunc Abort with retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_17()
{
TBEGIN
ITransactionLocal *pITransactionLocal = NULL;
DBCOLUMNDESC *newCD = NULL, *oldCD = NULL;
DBORDINAL newlen = 0, oldlen = 0;
CCol col;
DBORDINAL nCol;
VARIANT vSupportedTxnDDL;
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_ITransactionLocal,
SESSION_INTERFACE, (IUnknown**)&pITransactionLocal));
VariantInit(&vSupportedTxnDDL);
TESTC_PROVIDER(GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO,
g_pIDBInitialize, &vSupportedTxnDDL));
TESTC(VT_I4 == vSupportedTxnDDL.vt);
// what values should we accept?
TESTC_PROVIDER(DBPROPVAL_TC_NONE != vSupportedTxnDDL.lVal);
// create a table
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
GetColumnDescOnTable(&m_pTable->GetTableID(), &oldCD, &oldlen);
// start the transaction
TESTC_(m_hr = StartTransaction(pITransactionLocal), S_OK);
// try to drop a column from table
nCol = (ULONG)rand()%m_pTable->CountColumnsOnTable()+1;
col = m_pTable->GetColInfoForUpdate(nCol);
switch(vSupportedTxnDDL.lVal)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(m_pITableDefinition->DropColumn(&m_pTable->GetTableID(),
col.GetColID()), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
CHECK(DropColumnAndCheck(&m_pTable->GetTableID(), col.GetColID()), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
CHECK(m_pITableDefinition->DropColumn(&m_pTable->GetTableID(),
col.GetColID()), S_OK);
break;
default:
TESTC(FALSE);
}
// abort retaining
if (DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal)
{
CHECK(pITransactionLocal->Abort(NULL, TRUE, FALSE), S_OK);
//check the retaining propriety
CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK);
}
GetColumnDescOnTable(&m_pTable->GetTableID(), &newCD, &newlen);
if ( DBPROPVAL_TC_DDL_IGNORE == vSupportedTxnDDL.lVal
|| DBPROPVAL_TC_DDL_COMMIT == vSupportedTxnDDL.lVal)
{ // check column was dropped
COMPARE(CheckColInfo(newCD, newlen, oldCD, oldlen, &oldCD[nCol-1]), TRUE);
}
else
{ // check column was not dropped
COMPARE(AreColEqual(oldCD, oldlen, newCD, newlen), TRUE);
}
ReleaseColumnDesc(newCD, newlen);
CLEANUP:
ReleaseColumnDesc(oldCD, oldlen);
SAFE_RELEASE(pITransactionLocal);
m_hr = m_pTable->DropTable();
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(18)
//*-----------------------------------------------------------------------
// @mfunc Abort without retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_18()
{
TBEGIN
ITransactionLocal *pITransactionLocal = NULL;
DBCOLUMNDESC *newCD = NULL, *oldCD = NULL;
DBORDINAL newlen = 0, oldlen = 0;
CCol col;
DBORDINAL nCol;
VARIANT vSupportedTxnDDL;
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_ITransactionLocal,
SESSION_INTERFACE, (IUnknown**)&pITransactionLocal));
VariantInit(&vSupportedTxnDDL);
TESTC_PROVIDER(GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO,
g_pIDBInitialize, &vSupportedTxnDDL));
TESTC(VT_I4 == vSupportedTxnDDL.vt);
// what values should we accept?
TESTC_PROVIDER(DBPROPVAL_TC_NONE != vSupportedTxnDDL.lVal);
// create a table
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
GetColumnDescOnTable(&m_pTable->GetTableID(), &oldCD, &oldlen);
// start the transaction
TESTC_(m_hr = StartTransaction(pITransactionLocal), S_OK);
// try to drop a column from table
nCol = (DBORDINAL)rand()%m_pTable->CountColumnsOnTable()+1;
col = m_pTable->GetColInfoForUpdate(nCol);
switch(vSupportedTxnDDL.lVal)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(m_pITableDefinition->DropColumn(&m_pTable->GetTableID(),
col.GetColID()), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
CHECK(DropColumnAndCheck(&m_pTable->GetTableID(), col.GetColID()), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
CHECK(m_pITableDefinition->DropColumn(&m_pTable->GetTableID(),
col.GetColID()), S_OK);
break;
default:
TESTC(FALSE);
}
if (DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal)
{
// abort non retaining
CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK);
//check the non-retaining propriety
CHECK(pITransactionLocal->Abort(NULL, FALSE, FALSE),
SUCCEEDED(m_hr)? XACT_E_NOTRANSACTION: S_OK);
}
GetColumnDescOnTable(&m_pTable->GetTableID(), &newCD, &newlen);
if ( DBPROPVAL_TC_DDL_IGNORE == vSupportedTxnDDL.lVal
|| DBPROPVAL_TC_DDL_COMMIT == vSupportedTxnDDL.lVal)
{ // check column was dropped
COMPARE(CheckColInfo(newCD, newlen, oldCD, oldlen, &oldCD[nCol-1]), TRUE);
}
else
{ // check column was not dropped
COMPARE(AreColEqual(oldCD, oldlen, newCD, newlen), TRUE);
}
ReleaseColumnDesc(newCD, newlen);
CLEANUP:
ReleaseColumnDesc(oldCD, oldlen);
SAFE_RELEASE(pITransactionLocal);
m_hr = m_pTable->DropTable();
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(19)
//*-----------------------------------------------------------------------
// @mfunc Commit with retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_19()
{
TBEGIN
ITransactionLocal *pITransactionLocal = NULL;
DBCOLUMNDESC *newCD = NULL, *oldCD = NULL;
DBORDINAL newlen = 0, oldlen = 0;
CCol col;
DBORDINAL nCol;
VARIANT vSupportedTxnDDL;
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_ITransactionLocal,
SESSION_INTERFACE, (IUnknown**)&pITransactionLocal));
VariantInit(&vSupportedTxnDDL);
TESTC_PROVIDER(GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO,
g_pIDBInitialize, &vSupportedTxnDDL));
TESTC(VT_I4 == vSupportedTxnDDL.vt);
// what values should we accept?
TESTC_PROVIDER(DBPROPVAL_TC_NONE != vSupportedTxnDDL.lVal);
// create a table
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
GetColumnDescOnTable(&m_pTable->GetTableID(), &oldCD, &oldlen);
// start the transaction
TESTC_(m_hr = StartTransaction(pITransactionLocal), S_OK);
// try to drop a column from table
nCol = (ULONG)rand()%m_pTable->CountColumnsOnTable()+1;
col = m_pTable->GetColInfoForUpdate(nCol);
switch(vSupportedTxnDDL.lVal)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(m_pITableDefinition->DropColumn(&m_pTable->GetTableID(),
col.GetColID()), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
CHECK(DropColumnAndCheck(&m_pTable->GetTableID(), col.GetColID()), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
CHECK(m_pITableDefinition->DropColumn(&m_pTable->GetTableID(),
col.GetColID()), S_OK);
break;
default:
TESTC(FALSE);
}
// abort retaining
if (DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal)
{
// commit retaining
CHECK(pITransactionLocal->Commit(TRUE, 0, 0), S_OK);
// check retain property
CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK);
}
// check column was dropped (oldCD must contains new CD and rgColumnDesc[0])
GetColumnDescOnTable(&m_pTable->GetTableID(), &newCD, &newlen);
if (DBPROPVAL_TC_DML == vSupportedTxnDDL.lVal)
{ // check column was not dropped
COMPARE(AreColEqual(oldCD, oldlen, newCD, newlen), TRUE);
}
else
{ // check column was dropped
COMPARE(CheckColInfo(newCD, newlen, oldCD, oldlen, &oldCD[nCol-1]), TRUE);
}
ReleaseColumnDesc(newCD, newlen);
CLEANUP:
ReleaseColumnDesc(oldCD, oldlen);
m_hr = m_pTable->DropTable();
SAFE_RELEASE(pITransactionLocal);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(20)
//*-----------------------------------------------------------------------
// @mfunc Commit without retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_20()
{
TBEGIN
ITransactionLocal *pITransactionLocal = NULL;
DBCOLUMNDESC *newCD = NULL, *oldCD = NULL;
DBORDINAL newlen = 0, oldlen = 0;
CCol col;
DBORDINAL nCol;
VARIANT vSupportedTxnDDL;
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_ITransactionLocal,
SESSION_INTERFACE, (IUnknown**)&pITransactionLocal));
VariantInit(&vSupportedTxnDDL);
TESTC_PROVIDER(GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO,
g_pIDBInitialize, &vSupportedTxnDDL));
TESTC(VT_I4 == vSupportedTxnDDL.vt);
// what values should we accept?
TESTC_PROVIDER(DBPROPVAL_TC_NONE != vSupportedTxnDDL.lVal);
// create a table
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
GetColumnDescOnTable(&m_pTable->GetTableID(), &oldCD, &oldlen);
// start the transaction
TESTC_(m_hr = StartTransaction(pITransactionLocal), S_OK);
// try to drop a column from table
nCol = (ULONG)rand()%m_pTable->CountColumnsOnTable()+1;
col = m_pTable->GetColInfoForUpdate(nCol);
switch(vSupportedTxnDDL.lVal)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(m_pITableDefinition->DropColumn(&m_pTable->GetTableID(),
col.GetColID()), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
CHECK(DropColumnAndCheck(&m_pTable->GetTableID(), col.GetColID()), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
CHECK(m_pITableDefinition->DropColumn(&m_pTable->GetTableID(),
col.GetColID()), S_OK);
break;
default:
TESTC(FALSE);
}
if (DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal)
{
// commit without retaining
CHECK(m_hr = pITransactionLocal->Commit(FALSE, 0, 0), S_OK);
// check retaining / nont retaining prop
CHECK(pITransactionLocal->Abort(NULL, FALSE, FALSE),
FAILED(m_hr)? S_OK: XACT_E_NOTRANSACTION);
}
// check column was dropped (oldCD must contains new CD and rgColumnDesc[0])
GetColumnDescOnTable(&m_pTable->GetTableID(), &newCD, &newlen);
if (DBPROPVAL_TC_DML == vSupportedTxnDDL.lVal)
{ // check column was not dropped
COMPARE(AreColEqual(oldCD, oldlen, newCD, newlen), TRUE);
}
else
{ // check column was dropped
COMPARE(CheckColInfo(newCD, newlen, oldCD, oldlen, &oldCD[nCol-1]), TRUE);
}
ReleaseColumnDesc(newCD, newlen);
CLEANUP:
ReleaseColumnDesc(oldCD, oldlen);
m_hr = m_pTable->DropTable();
SAFE_RELEASE(pITransactionLocal);
TRETURN
}
// }}
//----------------------------------------------------------------------
//
// @cmember Thread function for TCDropColumn
//----------------------------------------------------------------------
unsigned TCDropColumn::MyThreadProc(ULONG i)
{
DBID ColumnID;
HRESULT hr;
if (i>= nThreads)
return 0;
ColumnID.eKind = DBKIND_NAME;
ColumnID.uName.pwszName = m_rgName[i];
Sleep(0); // switch the context
hr = m_pITableDefinition->DropColumn(&m_pTable->GetTableID(), &ColumnID);
Sleep(0); // switch the context
m_rgResult[i] = hr;
return 1;
} //TCDropColumn::MyThreadProc
// {{ TCW_VAR_PROTOTYPE(21)
//*-----------------------------------------------------------------------
// @mfunc threads on different columns
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_21()
{
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
BOOL fTestResult = TEST_FAIL;
ULONG i;
ULONG newnThreads;
CCol col;
// create nThreads names and init the results
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
if (m_cColumnDesc < 2)
{
odtLog << "There are too few columns in the table\n";
goto CLEANUP;
}
newnThreads = (nThreads <= (ULONG)m_cColumnDesc) ? nThreads: (ULONG)m_cColumnDesc;
for (i=0; i< newnThreads; i++)
{
m_rgResult[i] = -1;
col = m_pTable->GetColInfoForUpdate(i+1);
m_rgName[i] = wcsDuplicate(col.GetColName());
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
}
// creates a table, build m_rgColumnDesc by it
for (i=0; i<newnThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(newnThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< newnThreads; i++)
{
CloseHandle(hrgThread[i]);
SAFE_FREE(m_rgName[i]);
}
for (i=0; i<newnThreads; i++)
TESTC_(m_rgResult[i], S_OK);
fTestResult = TEST_PASS;
CLEANUP:
DropTableAndCheck(&m_pTable->GetTableID());
return fTestResult;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(22)
//*-----------------------------------------------------------------------
// @mfunc threads on the same column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_22()
{
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
BOOL fTestResult = TEST_FAIL;
ULONG i, nS_OK, nDB_E_NOCOLUMN;
CCol col;
DBORDINAL nCol;
// create n names and init the results
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
if (m_cColumnDesc < 1)
{
odtLog << "There are too few columns in the table\n";
goto CLEANUP;
}
nCol = (ULONG)rand()%m_pTable->CountColumnsOnTable()+1;
for (i=0; i< nThreads; i++)
{
m_rgResult[i] = -1;
col = m_pTable->GetColInfoForUpdate(nCol);
m_rgName[i] = wcsDuplicate(col.GetColName());
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
}
// creates a table, build m_rgColumnDesc by it
for (i=0; i<nThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(nThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< nThreads; i++)
{
CloseHandle(hrgThread[i]);
SAFE_FREE(m_rgName[i]);
}
//NOTE: spec was changed in MDAC 2.6 to replace DB_E_BADCOLUMNID with DB_E_NOCOLUMN
// for ITableDefinition::DropColumn. So when runnning against MDAC 2.5 expect DB_E_BADCOLUMNID
// This is for SQL-specific provider. For other providers, you should modify this to test against your target spec
for (i=nS_OK=nDB_E_NOCOLUMN=0; i<nThreads; i++)
{
if (m_rgResult[i] == S_OK)
nS_OK++;
else if (CHECK(m_rgResult[i], g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN))
nDB_E_NOCOLUMN++;
else
goto CLEANUP;
}
TESTC(nS_OK == 1 && nDB_E_NOCOLUMN == nThreads-1);
fTestResult = TEST_PASS;
CLEANUP:
DropTableAndCheck(&m_pTable->GetTableID());
return fTestResult;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(23)
//*-----------------------------------------------------------------------
// @mfunc Drop a column twice => DB_E_NOCOLUMN
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_23()
{
TBEGIN
CCol col;
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
m_pTable->AddInfoFromColumnsSchemaRowset(m_pITableDefinition,
DBKIND_NAME != m_pTable->GetTableID().eKind? m_pTable->GetTableID().uName.pwszName: NULL);
col = m_pTable->GetColInfoForUpdate((ULONG)rand()%m_pTable->CountColumnsOnTable()+1);
TESTC_(DropColumnAndCheck(&m_pTable->GetTableID(), col.GetColID()), S_OK);
//NOTE: spec was changed in MDAC 2.6 to replace DB_E_BADCOLUMNID with DB_E_NOCOLUMN
// for ITableDefinition::DropColumn. So when runnning against MDAC 2.5 expect DB_E_BADCOLUMNID
// This is for SQL-specific provider. For other providers, you should modify this to test against your target spec
TESTC_(DropColumnAndCheck(&m_pTable->GetTableID(), col.GetColID()), g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(24)
//*-----------------------------------------------------------------------
// @mfunc 2 TableDefinition interfaces on the same table, try to drop 2 different columns => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_24()
{
TBEGIN
ITableDefinition *pITableDefinition = NULL;
CCol col;
TESTC(VerifyInterface(m_pIOpenRowset, IID_ITableDefinition, SESSION_INTERFACE, (IUnknown**)&pITableDefinition));
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
m_pTable->AddInfoFromColumnsSchemaRowset(m_pITableDefinition,
DBKIND_NAME != m_pTable->GetTableID().eKind? m_pTable->GetTableID().uName.pwszName: NULL);
col = m_pTable->GetColInfoForUpdate(1);
TESTC_(DropColumnAndCheck(&m_pTable->GetTableID(), col.GetColID()), S_OK);
col = m_pTable->GetColInfoForUpdate(2);
TESTC_(DropColumnAndCheck(&m_pTable->GetTableID(), col.GetColID(), pITableDefinition), S_OK);
CLEANUP:
SAFE_RELEASE(pITableDefinition);
m_hr = m_pTable->DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(25)
//*-----------------------------------------------------------------------
// @mfunc Drop as many column as possible from a table created with a SQL statement
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_25()
{
TBEGIN
DBORDINAL i, cColumns;
BOOL fOldTableCreation = GetModInfo()->UseITableDefinition(FALSE);
DBCOLUMNDESC *rgColumnDesc = NULL;
IDBCreateCommand *pIDBCreateCommand = NULL;
// check whether commands are supported
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_IDBCreateCommand,
SESSION_INTERFACE, (IUnknown**)&pIDBCreateCommand));
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
TESTC(GetColumnDescOnTable(&m_pTable->GetTableID(), &rgColumnDesc, &cColumns));
for (i=0; i<cColumns-1; i++)
{
if ( !CHECK(m_hr = DropColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[i].dbcid), S_OK) )
odtLog << "could not drop the column \n";
}
m_hr = DropColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[cColumns-1].dbcid);
odtLog << ((SUCCEEDED(m_hr)) ? "\tlast column was dropped\n" : "\t could not drop the last column\n");
CHECK(m_pTable->DropTable(), S_OK);
CLEANUP:
SAFE_RELEASE(pIDBCreateCommand);
GetModInfo()->UseITableDefinition(fOldTableCreation);
ReleaseColumnDesc(rgColumnDesc, cColumns, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(26)
//*-----------------------------------------------------------------------
// @mfunc Drop a column from a 2 column table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_26()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
ULONG cColumnDesc = 2;
DuplicateColumnDesc(m_rgColumnDesc, cColumnDesc, &rgColumnDesc);
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
TESTC_(DropColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[0].dbcid), S_OK);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(27)
//*-----------------------------------------------------------------------
// @mfunc drop a column from a 1 column table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_27()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
ULONG cColumnDesc = 1;
DuplicateColumnDesc(m_rgColumnDesc, cColumnDesc, &rgColumnDesc);
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
m_hr = DropColumnAndCheck(&m_pTable->GetTableID(), &rgColumnDesc[0].dbcid);
if (S_OK == m_hr)
odtLog << "the only column of the table was dropped\n";
else
odtLog << "could not drop the only column of the table\n";
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(28)
//*-----------------------------------------------------------------------
// @mfunc drop a column from a non empty table => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_28()
{
TBEGIN
CCol col;
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(10, 0), S_OK);
m_pTable->AddInfoFromColumnsSchemaRowset(m_pITableDefinition,
DBKIND_NAME != m_pTable->GetTableID().eKind? m_pTable->GetTableID().uName.pwszName: NULL);
col = m_pTable->GetColInfoForUpdate((ULONG)rand()%m_pTable->CountColumnsOnTable()+1);
TESTC_(DropColumnAndCheck(&m_pTable->GetTableID(), col.GetColID()), S_OK);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(29)
//*-----------------------------------------------------------------------
// @mfunc drop a column from an empty table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_29()
{
TBEGIN
CCol col;
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
m_pTable->AddInfoFromColumnsSchemaRowset(m_pITableDefinition,
DBKIND_NAME != m_pTable->GetTableID().eKind? m_pTable->GetTableID().uName.pwszName: NULL);
col = m_pTable->GetColInfoForUpdate((ULONG)rand()%m_pTable->CountColumnsOnTable()+1);
TESTC_(DropColumnAndCheck(&m_pTable->GetTableID(), col.GetColID()), S_OK);
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(30)
//*-----------------------------------------------------------------------
// @mfunc drop a nullable, an autoincrementable and a default value column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_30()
{
TBEGIN
DBORDINAL nAutoInc;
DBORDINAL nNull;
DBORDINAL nDefault;
DBORDINAL i;
BOOL fFound = FALSE;
VARIANT defVal;
DBID ColumnID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CCol col;
CTable *pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CList<WCHAR *,WCHAR *> NativeTypesList;
CList<DBTYPE,DBTYPE> ProviderTypesList;
TESTC_PROVIDER(SettableProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN));
TESTC_PROVIDER(SettableProperty(DBPROP_COL_AUTOINCREMENT, DBPROPSET_COLUMN));
TESTC_PROVIDER(SettableProperty(DBPROP_COL_DEFAULT, DBPROPSET_COLUMN));
pTable->CreateTypeColInfo(NativeTypesList, ProviderTypesList);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// get an autoincrementable column
nAutoInc = cColumnDesc;
for (i=0; i < cColumnDesc && !fFound; i++)
{
col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
if (TRUE == (fFound = col.CanAutoInc()))
nAutoInc = i;
}
TESTC(nAutoInc < cColumnDesc);
// get the nullable and default columns
nNull = (nAutoInc+1) % cColumnDesc;
nDefault = (nAutoInc+2) % cColumnDesc;
// set autoincrementable property on a column
SetProperty(&rgColumnDesc[nAutoInc].rgPropertySets, &rgColumnDesc[nAutoInc].cPropertySets,
DBPROP_COL_AUTOINCREMENT, VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
// set nullable property on a column (also add default for it)
SetProperty(&rgColumnDesc[nNull].rgPropertySets, &rgColumnDesc[nNull].cPropertySets,
DBPROP_COL_NULLABLE, VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
VariantInit(&defVal);
GetDefaultValue(&rgColumnDesc[nNull], &defVal, pTable);
SetDefaultProperty(&rgColumnDesc[nNull].rgPropertySets, &rgColumnDesc[nNull].cPropertySets,
&defVal, DBPROPOPTIONS_REQUIRED); // might be not supported
VariantClear(&defVal);
// set default column
GetDefaultValue(&rgColumnDesc[nDefault], &defVal, pTable);
SetDefaultProperty(&rgColumnDesc[nDefault].rgPropertySets, &rgColumnDesc[nDefault].cPropertySets,
&defVal, DBPROPOPTIONS_REQUIRED); // might be not supported
VariantClear(&defVal);
// create the table with a autoinc column, a nullable one and a default one
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
DuplicateDBID(rgColumnDesc[nAutoInc].dbcid, &ColumnID);
m_hr = DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID);
if (S_OK != m_hr)
odtLog << "could not drop the autoincrementable column\n";
else
odtLog << "the autoincrementable column was dropped \n";
ReleaseDBID(&ColumnID, FALSE);
DuplicateDBID(rgColumnDesc[nNull].dbcid, &ColumnID);
m_hr = DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID);
if (S_OK != m_hr)
odtLog << "could not drop the nullable column\n";
else
odtLog << "the nullable column was dropped \n";
ReleaseDBID(&ColumnID, FALSE);
DuplicateDBID(m_rgColumnDesc[nDefault].dbcid, &ColumnID);
m_hr = DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID);
if (S_OK != m_hr)
odtLog << "could not drop the default value column\n";
else
odtLog << "the default value column was dropped \n";
ReleaseDBID(&ColumnID, FALSE);
CHECK(m_pTable->DropTable(), S_OK);
CLEANUP:
delete pTable;
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(31)
//*-----------------------------------------------------------------------
// @mfunc try to drop a column from a view
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_31()
{
TBEGIN
LPWSTR pwszViewName = L"HagiView"; // just a view name
DBID TableID;
CCol col;
IDBCreateCommand *pIDBCreateCommand = NULL;
// check whether commands are supported
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_IDBCreateCommand,
SESSION_INTERFACE, (IUnknown**)&pIDBCreateCommand));
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
m_pTable->AddInfoFromColumnsSchemaRowset(m_pITableDefinition, m_pTable->GetTableName());
// create the view
m_pTable->SetViewName(pwszViewName);
if ( S_OK != (m_hr = m_pTable->ExecuteCommand(
CREATE_VIEW,
IID_NULL,
pwszViewName, // the table name will be the implicit one
NULL, // don't return the command statement
0,
NULL,
EXECUTE_IFNOERROR // execute the command
))
)
{
odtLog << "\t the view cannot be created\n";
goto CLEANUP;
}
TESTC_(m_hr, S_OK);
// try to drop a column from the view
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = L"HagiTable";
col = m_pTable->GetColInfoForUpdate((ULONG)rand()%m_pTable->CountColumnsOnTable()+1);
m_hr = DropColumnAndCheck(&TableID, col.GetColID());
odtLog << ((S_OK == m_hr) ? "column was dropped from view\n" : "could not drop column from view\n");
CLEANUP:
SAFE_RELEASE(pIDBCreateCommand);
// drop the view!
if (m_pTable->GetTableName())
m_hr = m_pTable->ExecuteCommand(
DROP_VIEW,
IID_NULL,
pwszViewName, // the table name will be the implicit one
NULL, // don't return the command statement
0,
NULL,
EXECUTE_IFNOERROR // execute the command
);
CHECK(m_hr = m_pTable->DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(32)
//*-----------------------------------------------------------------------
// @mfunc drop a column added with an alter table command => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_32()
{
TBEGIN
DBID ColumnID;
LPWSTR pwszColumnName = L"intHagi"; // the name of the integer column
LPWSTR pwszColNameAndType = NULL;
IDBCreateCommand *pIDBCreateCommand = NULL;
// check whether commands are supported
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_IDBCreateCommand,
SESSION_INTERFACE, (IUnknown**)&pIDBCreateCommand));
TESTC(NULL != m_rgColumnDesc[0].pwszTypeName); // it should be a numeric type
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
// build the column name and type argument of the command
SAFE_ALLOC(pwszColNameAndType, WCHAR, wcslen(pwszColumnName)+wcslen(m_rgColumnDesc[0].pwszTypeName)+2);
wcscpy(pwszColNameAndType, pwszColumnName);
wcscat(pwszColNameAndType, L" ");
wcscat(pwszColNameAndType, m_rgColumnDesc[0].pwszTypeName);
// create the ALTER SQL statement
if ( S_OK != (m_hr = m_pTable->ExecuteCommand(
ALTER_TABLE_ADD,
IID_NULL,
pwszColNameAndType, // the table name will be the implicit one
NULL, // don't return the command statement
0,
NULL,
EXECUTE_IFNOERROR // execute the command
))
)
{
odtLog << "Could not add a column in the table, using commands\n";
goto CLEANUP;
}
// try to drop the new column from the table
ColumnID.eKind = DBKIND_NAME;
ColumnID.uName.pwszName = pwszColumnName;
TESTC_(DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID), S_OK);
CLEANUP:
SAFE_RELEASE(pIDBCreateCommand);
SAFE_FREE(pwszColNameAndType);
CHECK(m_pTable->DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(33)
//*-----------------------------------------------------------------------
// @mfunc try to drop columns using different DBKIND pattern
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_33()
{
TBEGIN
DBID ColumnID;
CCol col;
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
// try to drop a column
col = m_pTable->GetColInfoForUpdate(2);
ColumnID.eKind = DBKIND_NAME;
ColumnID.uName.pwszName = wcsDuplicate(col.GetColName());
if (m_cColumnDesc > 2)
{
CHECK(DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID), S_OK);
}
else
{
odtLog << "too few columns, skipped the drop column given by name case \n";
}
ReleaseDBID(&ColumnID, FALSE);
col = m_pTable->GetColInfoForUpdate(4);
ColumnID.eKind = DBKIND_GUID;
memset(&ColumnID.uGuid.guid, 0, sizeof(GUID));
//NOTE: spec was changed in MDAC 2.6 to replace DB_E_BADCOLUMNID with DB_E_NOCOLUMN
// for ITableDefinition::DropColumn. So when runnning against MDAC 2.5 expect DB_E_BADCOLUMNID
// This is for SQL-specific provider. For other providers, you should modify this to test against your target spec
if (!CHECK(DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID), g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN))
{
odtLog << "error at the guid case\n";
}
col = m_pTable->GetColInfoForUpdate(3);
ColumnID.eKind = DBKIND_GUID_NAME;
ColumnID.uGuid.guid = guidModule;
ColumnID.uName.pwszName = col.GetColName();
m_hr = DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID);
if (!CHECK(m_hr, g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN))
{
odtLog << "error at the guid name case\n";
}
ColumnID.eKind = DBKIND_GUID_PROPID;
memset(&ColumnID.uGuid.guid, 0, sizeof(GUID));
ColumnID.uName.ulPropid = 0L;
m_hr = DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID);
if (!CHECK(m_hr, g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN) )
{
odtLog << "error at the guid propid case\n";
}
ColumnID.eKind = DBKIND_PGUID_NAME;
ColumnID.uGuid.pguid = &guidModule;
ColumnID.uName.pwszName = NULL;
m_hr = DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID);
if (!CHECK(m_hr, g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN))
{
odtLog << "error at the pguid name case\n";
}
ColumnID.eKind = DBKIND_PGUID_PROPID;
ColumnID.uGuid.pguid = &guidModule;
ColumnID.uName.ulPropid = 0L;
m_hr = DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID);
if (!CHECK(m_hr, g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN) )
{
odtLog << "error at the pguid propid case\n";
}
ColumnID.eKind = DBKIND_PROPID;
ColumnID.uName.ulPropid = 0L;
m_hr = DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID);
if (!CHECK(m_hr, g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN))
{
odtLog << "error at the propid case\n";
}
ColumnID.eKind = 0xff;
m_hr = DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID);
if (!CHECK(m_hr, g_fSQLOLEDB25 ? DB_E_BADCOLUMNID : DB_E_NOCOLUMN))
{
odtLog << "error at the inexistent value for eKind case\n";
}
CLEANUP:
CHECK(m_hr = m_pTable->DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(34)
//*-----------------------------------------------------------------------
// @mfunc Fully Qualified Table Name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_34()
{
TBEGIN
DBID TableID;
WCHAR *pwszQualTableName = NULL;
WCHAR *pwszCatalogName = NULL;
WCHAR *pwszSchemaName = NULL;
WCHAR *pwszTableName = NULL;
CCol col;
// create a regular table
TESTC(NULL != m_pTable);
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
pwszTableName = m_pTable->GetTableName();
TableID.eKind = DBKIND_NAME;
TESTC(GetCatalogSchemaNames(pwszTableName, &pwszCatalogName, &pwszSchemaName));
//Construct a fully Qualified TableName...
TESTC_(m_pTable->GetQualifiedName(pwszCatalogName, pwszSchemaName, pwszTableName, &pwszQualTableName),S_OK);
TableID.uName.pwszName = pwszQualTableName;
m_pTable->AddInfoFromColumnsSchemaRowset(m_pITableDefinition,
DBKIND_NAME != m_pTable->GetTableID().eKind? m_pTable->GetTableID().uName.pwszName: NULL);
col = m_pTable->GetColInfoForUpdate(1);
TESTC_(DropColumnAndCheck(&TableID, col.GetColID(), NULL, &m_pTable->GetTableID()), S_OK);
CLEANUP:
m_pTable->DropTable();
SAFE_FREE(pwszCatalogName);
SAFE_FREE(pwszSchemaName);
SAFE_FREE(pwszQualTableName);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(35)
//*-----------------------------------------------------------------------
// @mfunc Quoted Table Name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropColumn::Variation_35()
{
TBEGIN
DBID TableID;
CCol col;
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = NULL;
TESTC(NULL != m_pTable);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
m_pTable->GetQuotedName(m_pTable->GetTableName(), &TableID.uName.pwszName);
m_pTable->AddInfoFromColumnsSchemaRowset(m_pITableDefinition,
DBKIND_NAME != m_pTable->GetTableID().eKind? m_pTable->GetTableID().uName.pwszName: NULL);
col = m_pTable->GetColInfoForUpdate(1);
TESTC_(DropColumnAndCheck(&TableID, col.GetColID()), S_OK);
CLEANUP:
m_pTable->DropTable();
ReleaseDBID(&TableID, FALSE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCDropColumn::Terminate()
{
// TO DO: Add your own code here
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCITableDefinition::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(TCDropTable)
//*-----------------------------------------------------------------------
//| Test Case: TCDropTable - Test Case fo dropping a table
//| Created: 09/11/97
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCDropTable::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCITableDefinition::Init())
// }}
{
// TO DO: Add your own code here
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc pTableID is NULL => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_1()
{
if ( !CHECK(m_hr = m_pITableDefinition->DropTable(NULL), E_INVALIDARG))
return TEST_FAIL;
else
return TEST_PASS;
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc *pTableID is DB_NULLID => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_2()
{
DBID TableID;
TableID = DB_NULLID;
if ( !CHECK(m_hr = m_pITableDefinition->DropTable(&TableID), DB_E_NOTABLE))
return TEST_FAIL;
else
return TEST_PASS;
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Maximum length for table name => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_3()
{
BOOL fTestRes = TEST_FAIL;
WCHAR* pwszTableName = NULL;
DBID TableID;
// create a maximum size table name
m_pTable->MakeTableName(NULL);
GetLiteralInfo();
pwszTableName = BuildValidName(m_cMaxTableName, m_pTable->GetTableName());
odtLog << "king size table name: " << pwszTableName << ", i.e." << (wcslen(pwszTableName)) << " characters\n";
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0, pwszTableName), S_OK);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = pwszTableName;
TESTC_(m_hr = m_pITableDefinition->DropTable(&TableID), S_OK);
fTestRes = TEST_PASS;
CLEANUP:
m_pTable->DropTable();
PROVIDER_FREE(pwszTableName);
return fTestRes;
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc 1-char-too-long table name => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_4()
{
BOOL fTestRes = TEST_FAIL;
WCHAR* pwszTableName = NULL, *pwszTableName1 = NULL;
DBID TableID;
// create a maximum size table name
m_pTable->MakeTableName(NULL);
GetLiteralInfo();
pwszTableName = BuildValidName(m_cMaxTableName, m_pTable->GetTableName());
pwszTableName1 = BuildValidName(m_cMaxTableName+1, m_pTable->GetTableName());
odtLog << "1 char too long table name: " << pwszTableName1 << ", i.e."
<< wcslen(pwszTableName1) << " characters\n";
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0, pwszTableName), S_OK);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = pwszTableName1;
TESTC_(m_hr = m_pITableDefinition->DropTable(&TableID), DB_E_NOTABLE);
fTestRes = TEST_PASS;
CLEANUP:
CHECK(m_pTable->DropTable(), S_OK);
PROVIDER_FREE(pwszTableName);
PROVIDER_FREE(pwszTableName1);
m_pTable->DropTable();
return fTestRes;
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc The pointer to the table name is NULL => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_5()
{
DBID TableID;
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = NULL;
if ( !CHECK(m_hr = m_pITableDefinition->DropTable(&TableID), DB_E_NOTABLE))
return TEST_FAIL;
else
return TEST_PASS;
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Table name is empty => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_6()
{
DBID TableID;
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = L"";
if ( !CHECK(m_hr = m_pITableDefinition->DropTable(&TableID), DB_E_NOTABLE))
return TEST_FAIL;
else
return TEST_PASS;
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Invalid table name => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_7()
{
BOOL fTestRes = TEST_FAIL;
WCHAR* pwszTableName = NULL;
size_t m;
DBID TableID;
// create an invalid table name
m_pTable->MakeTableName(NULL);
GetLiteralInfo();
m = min(wcslen(m_pTable->GetTableName())+5, m_cMaxTableName);
pwszTableName = BuildInvalidName(m, m_pTable->GetTableName(), m_pwszInvalidTableChars);
odtLog << "invalid table name: " << pwszTableName << ", i.e." << wcslen(pwszTableName) << " characters\n";
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = pwszTableName;
TESTC_(m_hr = m_pITableDefinition->DropTable(&TableID), DB_E_NOTABLE);
fTestRes = TEST_PASS;
CLEANUP:
PROVIDER_FREE(pwszTableName);
return fTestRes;
}
// }}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc A rowset is opened on table => DB_E_TABLEINUSE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_8()
{
BOOL fTestRes = TEST_FAIL, fExists;
IRowset* pIRowset = NULL;
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
TESTC_(m_pIOpenRowset->OpenRowset(NULL, &m_pTable->GetTableID(), NULL, IID_IRowset,
0, NULL, (IUnknown**)&pIRowset), S_OK);
fTestRes = TEST_PASS;
//try to drop the table
m_hr = m_pITableDefinition->DropTable(&m_pTable->GetTableID());
if (DB_E_TABLEINUSE != m_hr && !CHECK(m_hr, S_OK))
{
odtLog << "The table was dropped, though in use \n";
fTestRes = TEST_FAIL;
}
else
{
odtLog << ((DB_E_TABLEINUSE == m_hr) ? "DB_E_TABLEINUSE returned\n": "S_OK returned\n");
//check the table still exist
if (!CHECK(m_pTable->DoesTableExist(&m_pTable->GetTableID(), &fExists), S_OK) ||
(fExists==(S_OK == m_hr)))
fTestRes = TEST_FAIL;
}
CLEANUP:
SAFE_RELEASE(pIRowset);
m_pTable->DropTable();
return fTestRes;
}
// }}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc Table in use => DB_E_TABLEINUSE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_9()
{
BOOL fTestRes = TEST_FAIL, fExists;
IRowset* pIRowset = NULL;
m_pTable->SetRIID((struct _GUID*)&IID_IRowset);
m_pTable->SetRowset((IUnknown**)&pIRowset);
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_pTable->CreateTable(10, 1), S_OK);
fTestRes = TEST_PASS;
//try to release drop the table
m_hr = m_pITableDefinition->DropTable(&m_pTable->GetTableID());
if (DB_E_TABLEINUSE != m_hr && S_OK != m_hr)
{
odtLog << "The table was dropped, though in use \n";
fTestRes = TEST_FAIL;
}
else
{
odtLog << ((DB_E_TABLEINUSE == m_hr) ? "DB_E_TABLEINUSE returned\n" : "S_OK returned\n");
//check the table still exist
if (!CHECK(m_pTable->DoesTableExist(&m_pTable->GetTableID(), &fExists), S_OK) || (fExists==(S_OK == m_hr)))
fTestRes = TEST_FAIL;
}
CLEANUP:
m_pTable->SetRowset(NULL);
m_pTable->DropTable();
return fTestRes;
}
// }}
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc Inexistent table => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_10()
{
WCHAR* pwszTableName = NULL;
DBID TableID;
// create a new valid table name
m_pTable->MakeTableName(NULL);
pwszTableName = m_pTable->GetTableName();
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = pwszTableName;
if (!CHECK(m_hr = m_pITableDefinition->DropTable(&TableID), DB_E_NOTABLE))
return TEST_FAIL;
else
return TEST_PASS;
}
// }}
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc Abort with retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_11()
{
TBEGIN
BOOL fExists;
ITransactionLocal *pITransactionLocal = NULL;
VARIANT vSupportedTxnDDL;
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_ITransactionLocal,
SESSION_INTERFACE, (IUnknown**)&pITransactionLocal));
VariantInit(&vSupportedTxnDDL);
TESTC_PROVIDER(GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO,
g_pIDBInitialize, &vSupportedTxnDDL));
TESTC(VT_I4 == vSupportedTxnDDL.vt);
// what values should we accept?
TESTC_PROVIDER(DBPROPVAL_TC_NONE != vSupportedTxnDDL.lVal);
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0,0), S_OK);
TESTC_(m_hr = StartTransaction(pITransactionLocal), S_OK);
switch(vSupportedTxnDDL.lVal)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(m_hr = m_pITableDefinition->DropTable(&m_pTable->GetTableID()), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
CHECK(DropTableAndCheck(&m_pTable->GetTableID()), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
// error should be returned on further table access
TESTC_(DropTableAndCheck(&m_pTable->GetTableID()), S_OK);
break;
default:
TESTC(FALSE);
}
if (DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal)
{
// abort retaining
CHECK(m_hr = pITransactionLocal->Abort(NULL, TRUE, FALSE), S_OK);
// check retaining
CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK);
}
// check table existence
CHECK(m_hr = m_pTable->DoesTableExist(&m_pTable->GetTableID(), &fExists), S_OK);
COMPARE(fExists, DBPROPVAL_TC_DDL_IGNORE != vSupportedTxnDDL.lVal
&& DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal);
CLEANUP:
SAFE_RELEASE(pITransactionLocal);
m_pTable->DropTable();
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc Abort without retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_12()
{
TBEGIN
BOOL fExists;
ITransactionLocal *pITransactionLocal = NULL;
VARIANT vSupportedTxnDDL;
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_ITransactionLocal,
SESSION_INTERFACE, (IUnknown**)&pITransactionLocal));
VariantInit(&vSupportedTxnDDL);
TESTC_PROVIDER(GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO,
g_pIDBInitialize, &vSupportedTxnDDL));
TESTC(VT_I4 == vSupportedTxnDDL.vt);
// what values should we accept?
TESTC_PROVIDER(DBPROPVAL_TC_NONE != vSupportedTxnDDL.lVal);
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0,0), S_OK);
TESTC_(m_hr = StartTransaction(pITransactionLocal), S_OK);
switch(vSupportedTxnDDL.lVal)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(m_hr = m_pITableDefinition->DropTable(&m_pTable->GetTableID()), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
TESTC_(DropTableAndCheck(&m_pTable->GetTableID()), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
// error should be returned on further table operations
TESTC_(DropTableAndCheck(&m_pTable->GetTableID()), S_OK);
break;
default:
TESTC(FALSE);
}
if (DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal)
{
// abort non retaining
CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK);
// check not retaining
CHECK(pITransactionLocal->Abort(NULL, FALSE, FALSE),
FAILED(m_hr)? S_OK : XACT_E_NOTRANSACTION);
}
// check table existence
CHECK(m_hr = m_pTable->DoesTableExist(&m_pTable->GetTableID(), &fExists), S_OK);
COMPARE(fExists, DBPROPVAL_TC_DDL_IGNORE != vSupportedTxnDDL.lVal
&& DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal);
CLEANUP:
SAFE_RELEASE(pITransactionLocal);
m_pTable->DropTable();
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc Commit with retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_13()
{
TBEGIN
BOOL fExists;
ITransactionLocal *pITransactionLocal = NULL;
VARIANT vSupportedTxnDDL;
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_ITransactionLocal,
SESSION_INTERFACE, (IUnknown**)&pITransactionLocal));
VariantInit(&vSupportedTxnDDL);
TESTC_PROVIDER(GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO,
g_pIDBInitialize, &vSupportedTxnDDL));
TESTC(VT_I4 == vSupportedTxnDDL.vt);
// what values should we accept?
TESTC_PROVIDER(DBPROPVAL_TC_NONE != vSupportedTxnDDL.lVal);
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0,0), S_OK);
TESTC_(m_hr = StartTransaction(pITransactionLocal), S_OK);
switch(vSupportedTxnDDL.lVal)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(m_hr = m_pITableDefinition->DropTable(&m_pTable->GetTableID()), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
TESTC_(DropTableAndCheck(&m_pTable->GetTableID()), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
// error should be returned
TESTC_(DropTableAndCheck(&m_pTable->GetTableID()), S_OK);
break;
default:
TESTC(FALSE);
}
if (DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal)
{
// commit retaining
CHECK(m_hr = pITransactionLocal->Commit(TRUE, 0, 0), S_OK);
// check retaining
CHECK(pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK);
}
// check table existence
CHECK(m_hr = m_pTable->DoesTableExist(&m_pTable->GetTableID(), &fExists), S_OK);
COMPARE(fExists, DBPROPVAL_TC_DML == vSupportedTxnDDL.lVal);
CLEANUP:
SAFE_RELEASE(pITransactionLocal);
m_pTable->DropTable();
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(14)
//*-----------------------------------------------------------------------
// @mfunc Commit without retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_14()
{
TBEGIN
BOOL fExists;
ITransactionLocal *pITransactionLocal = NULL;
VARIANT vSupportedTxnDDL;
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_ITransactionLocal,
SESSION_INTERFACE, (IUnknown**)&pITransactionLocal));
VariantInit(&vSupportedTxnDDL);
TESTC_PROVIDER(GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO,
g_pIDBInitialize, &vSupportedTxnDDL));
TESTC(VT_I4 == vSupportedTxnDDL.vt);
// what values should we accept?
TESTC_PROVIDER(DBPROPVAL_TC_NONE != vSupportedTxnDDL.lVal);
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0,0), S_OK);
TESTC_(m_hr = StartTransaction(pITransactionLocal), S_OK);
switch(vSupportedTxnDDL.lVal)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(m_hr = m_pITableDefinition->DropTable(&m_pTable->GetTableID()), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
TESTC_(DropTableAndCheck(&m_pTable->GetTableID()), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
// error should be returned
TESTC_(DropTableAndCheck(&m_pTable->GetTableID()), S_OK);
break;
default:
TESTC(FALSE);
}
if (DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal)
{
// commit not retaining
CHECK(m_hr = pITransactionLocal->Commit(FALSE, 0, 0), S_OK);
// check not retaining
CHECK(pITransactionLocal->Abort(NULL, FALSE, FALSE),
FAILED(m_hr)? S_OK: XACT_E_NOTRANSACTION);
}
// check whether the transaction was aborted
CHECK(m_hr = m_pTable->DoesTableExist(&m_pTable->GetTableID(), &fExists), S_OK);
COMPARE(fExists, DBPROPVAL_TC_DML == vSupportedTxnDDL.lVal);
CLEANUP:
SAFE_RELEASE(pITransactionLocal);
m_pTable->DropTable();
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(15)
//*-----------------------------------------------------------------------
// @mfunc Drop a table created with an SQL command => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_15()
{
TBEGIN
IDBCreateCommand *pIDBCreateCommand = NULL;
// check whether commands are supported
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_IDBCreateCommand,
SESSION_INTERFACE, (IUnknown**)&pIDBCreateCommand));
GetModInfo()->UseITableDefinition(FALSE);
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
TESTC_(m_hr = m_pITableDefinition->DropTable(&m_pTable->GetTableID()), S_OK);
CLEANUP:
SAFE_RELEASE(pIDBCreateCommand);
GetModInfo()->UseITableDefinition(TRUE);
m_pTable->DropTable();
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc Drop a table created with ITableDefinition, no rowset created => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_16()
{
BOOL fTestRes = TEST_FAIL;
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(10, 0), S_OK);
TESTC_(m_hr = m_pITableDefinition->DropTable(&m_pTable->GetTableID()), S_OK);
fTestRes = TEST_PASS;
CLEANUP:
m_pTable->DropTable();
return fTestRes;
}
// }}
// {{ TCW_VAR_PROTOTYPE(17)
//*-----------------------------------------------------------------------
// @mfunc Drop a table created with ITableDefinition, rowset released => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_17()
{
BOOL fTestRes = TEST_FAIL;
IRowset *pIRowset = NULL;
m_pTable->SetRowset((IUnknown**)&pIRowset);
m_pTable->SetRIID((struct _GUID*)&IID_IRowset);
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
SAFE_RELEASE(pIRowset);
TESTC_(m_hr = m_pITableDefinition->DropTable(&m_pTable->GetTableID()), S_OK);
fTestRes = TEST_PASS;
CLEANUP:
m_pTable->SetRowset(NULL);
m_pTable->DropTable();
return fTestRes;
}
// }}
// {{ TCW_VAR_PROTOTYPE(18)
//*-----------------------------------------------------------------------
// @mfunc ITableDefinition::CreateTable, insert 10 rows, release rowset, drop the table => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_18()
{
BOOL fTestRes = TEST_FAIL;
IRowset *pIRowset = NULL;
m_pTable->SetRowset((IUnknown**)&pIRowset);
m_pTable->SetRIID((struct _GUID*)&IID_IRowset);
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(10, 0), S_OK);
SAFE_RELEASE(pIRowset);
TESTC_(m_hr = m_pITableDefinition->DropTable(&m_pTable->GetTableID()), S_OK);
fTestRes = TEST_PASS;
CLEANUP:
m_pTable->SetRowset(NULL);
m_pTable->DropTable();
return fTestRes;
}
// }}
// {{ TCW_VAR_PROTOTYPE(19)
//*-----------------------------------------------------------------------
// @mfunc For each provider type, create a table with a single column and then drop it => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_19()
{
BOOL fTestRes = TEST_PASS;
DBORDINAL i;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->SetBuildColumnDesc(FALSE);
m_pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
for (i=0; i<cColumnDesc; i++)
{
odtLog << "\t" << rgColumnDesc[i].pwszTypeName;
m_pTable->SetColumnDesc(NULL);
m_pTable->SetColumnDesc(&rgColumnDesc[i], 1);
if (!CHECK(m_hr = m_pTable->CreateTable(0, 0), S_OK))
{
fTestRes = TEST_FAIL;
continue;
}
if (!CHECK(m_hr = m_pITableDefinition->DropTable(&m_pTable->GetTableID()), S_OK))
{
odtLog << "\n Error for type" << rgColumnDesc[i].pwszTypeName << "\n";
fTestRes = TEST_FAIL;
}
m_pTable->DropTable();
}
odtLog << "\n";
m_pTable->SetColumnDesc(NULL);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
return fTestRes;
}
// }}
// {{ TCW_VAR_PROTOTYPE(20)
//*-----------------------------------------------------------------------
// @mfunc Drop a table twice => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_20()
{
BOOL fTestRes = TEST_FAIL;
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
TESTC_(m_hr = m_pITableDefinition->DropTable(&m_pTable->GetTableID()), S_OK);
TESTC_(m_hr = m_pITableDefinition->DropTable(&m_pTable->GetTableID()), DB_E_NOTABLE);
fTestRes = TEST_PASS;
CLEANUP:
return fTestRes;
}
// }}
//----------------------------------------------------------------------
//
// @cmember Thread procedure for TCDropTable
//----------------------------------------------------------------------
unsigned TCDropTable::MyThreadProc(ULONG i)
{
DBID TableID;
HRESULT hr;
if (i>= nThreads)
return 0;
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_rgName[i];
Sleep(0); // switch the context
hr = m_pITableDefinition->DropTable(&TableID);
Sleep(0); // switch the context
m_rgResult[i] = hr;
return 1;
} //TCDropTable::MyThreadProc
// {{ TCW_VAR_PROTOTYPE(21)
//*-----------------------------------------------------------------------
// @mfunc threads on different tables
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_21()
{
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
BOOL fTestResult = TEST_FAIL;
ULONG i;
DBID TableID;
// create n names and init the results
for (i=0; i<nThreads; i++)
{
m_rgName[i] = NULL;
m_rgResult[i] = E_FAIL;
}
for (i=0; i< nThreads; i++)
{
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
m_rgName[i] = wcsDuplicate(m_pTable->GetTableName());
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
}
// creates a table, build rgColumnDesc by it
for (i=0; i<nThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(nThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< nThreads; i++)
CloseHandle(hrgThread[i]);
for (i=0; i<nThreads; i++)
TESTC_(m_rgResult[i], S_OK);
fTestResult = TEST_PASS;
CLEANUP:
TableID.eKind = DBKIND_NAME;
for (i=0; i<nThreads; i++)
{
TableID.uName.pwszName = m_rgName[i];
// if the table was not dropped by the corresponding thread, try again
if (FAILED(m_rgResult[i]))
CHECK(DropTableAndCheck(&TableID), S_OK);
PROVIDER_FREE(m_rgName[i]);
}
return fTestResult;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(22)
//*-----------------------------------------------------------------------
// @mfunc threads on same table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_22()
{
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
BOOL fTestResult = TEST_FAIL;
ULONG i;
ULONG nS_OK = 0;
ULONG nDB_E_NOTABLE = 0;
LPWSTR pwszBaseName = NULL;
DBID TableID;
// create n names and init the results
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
pwszBaseName = m_pTable->GetTableName();
for (i=0; i< nThreads; i++)
{
m_rgResult[i] = E_FAIL;
m_rgName[i] = pwszBaseName;
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
}
// creates a table, build rgColumnDesc by it
for (i=0; i<nThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(nThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< nThreads; i++)
CloseHandle(hrgThread[i]);
for (i=nS_OK=nDB_E_NOTABLE=0; i<nThreads; i++)
{
if (m_rgResult[i] == S_OK)
nS_OK++;
else if (CHECK(m_rgResult[i], DB_E_NOTABLE))
nDB_E_NOTABLE++;
else
{
odtLog << "Thread " << i << ": unexpected result " << m_rgResult[i] << "\n";
goto CLEANUP;
}
}
TESTC(nS_OK == 1 && nDB_E_NOTABLE == nThreads-1);
fTestResult = TEST_PASS;
CLEANUP:
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = pwszBaseName;
if (nS_OK < 1)
CHECK(DropTableAndCheck(&TableID), S_OK);
return fTestResult;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(23)
//*-----------------------------------------------------------------------
// @mfunc Fully Qualified Table Name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_23()
{
BOOL fTestRes = TEST_FAIL;
DBID TableID;
WCHAR *pwszQualTableName = NULL;
WCHAR *pwszCatalogName = NULL;
WCHAR *pwszSchemaName = NULL;
WCHAR *pwszTableName = NULL;
// create a regular table
TESTC(NULL != m_pTable);
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
pwszTableName = m_pTable->GetTableName();
TableID.eKind = DBKIND_NAME;
TESTC(GetCatalogSchemaNames(pwszTableName, &pwszCatalogName, &pwszSchemaName));
//Construct a fully Qualified TableName...
TESTC_(m_pTable->GetQualifiedName(pwszCatalogName, pwszSchemaName, pwszTableName, &pwszQualTableName),S_OK);
TableID.uName.pwszName = pwszQualTableName;
// drop the table
TESTC_(DropTableAndCheck(&TableID), S_OK);
fTestRes = TEST_PASS;
CLEANUP:
SAFE_FREE(pwszCatalogName);
SAFE_FREE(pwszSchemaName);
SAFE_FREE(pwszQualTableName);
m_pTable->DropTable();
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(24)
//*-----------------------------------------------------------------------
// @mfunc Quoted Table Name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_24()
{
BOOL fTestRes = TEST_FAIL;
DBID TableID;
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = NULL;
TESTC(NULL != m_pTable);
m_pTable->SetBuildColumnDesc(TRUE);
TESTC_(m_pTable->CreateTable(0, 0), S_OK);
m_pTable->GetQuotedName(m_pTable->GetTableName(), &TableID.uName.pwszName);
TESTC_(DropTableAndCheck(&TableID), S_OK);
fTestRes = TEST_PASS;
CLEANUP:
ReleaseDBID(&TableID, FALSE);
m_pTable->DropTable();
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(25)
//*-----------------------------------------------------------------------
// @mfunc Different DBKINDs for pTableID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropTable::Variation_25()
{
TBEGIN
DBID TableID;
m_pTable->SetBuildColumnDesc(TRUE);
// try to drop a column
TableID.eKind = DBKIND_NAME;
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
TableID.uName.pwszName = m_pTable->GetTableID().uName.pwszName;
TableID.eKind = DBKIND_GUID;
TableID.uGuid.guid = guidModule;
if (!CHECK(DropTableAndCheck(&TableID), DB_E_NOTABLE))
{
odtLog << "error at the guid case\n";
}
CHECK(m_hr = m_pTable->DropTable(), S_OK);
TableID.eKind = DBKIND_GUID_NAME;
TableID.uGuid.guid = guidModule;
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
TableID.uName.pwszName = m_pTable->GetTableID().uName.pwszName;
if (!CHECK(DropTableAndCheck(&TableID), DB_E_NOTABLE))
{
odtLog << "error at the guid name case\n";
}
CHECK(m_hr = m_pTable->DropTable(), S_OK);
TableID.eKind = DBKIND_GUID_PROPID;
TableID.uGuid.guid = guidModule;
TableID.uName.ulPropid = 0L;
if (!CHECK(DropTableAndCheck(&TableID), DB_E_NOTABLE))
{
odtLog << "error at the guid propid case\n";
}
TableID.eKind = DBKIND_PGUID_NAME;
TableID.uGuid.pguid = &guidModule;
TESTC_(m_hr = m_pTable->CreateTable(0, 0), S_OK);
TableID.uName.pwszName = m_pTable->GetTableID().uName.pwszName;
if (!CHECK(DropTableAndCheck(&TableID), DB_E_NOTABLE))
{
odtLog << "error at the pguid name case\n";
}
CHECK(m_hr = m_pTable->DropTable(), S_OK);
TableID.eKind = DBKIND_PGUID_PROPID;
TableID.uGuid.pguid = &guidModule;
TableID.uName.ulPropid = 0L;
if (!CHECK(DropTableAndCheck(&TableID), DB_E_NOTABLE))
{
odtLog << "error at the pguid propid case\n";
}
TableID.eKind = DBKIND_PROPID;
TableID.uName.ulPropid = 0L;
if (!CHECK(DropTableAndCheck(&TableID), DB_E_NOTABLE))
{
odtLog << "error at the propid case\n";
}
TableID.eKind = 0xff;
if (!CHECK(DropTableAndCheck(&TableID), DB_E_NOTABLE))
{
odtLog << "error at the inexistent value for eKind case\n";
}
CLEANUP:
CHECK(m_hr = m_pTable->DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCDropTable::Terminate()
{
// TO DO: Add your own code here
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCITableDefinition::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(TCCreateTable)
//*-----------------------------------------------------------------------
//| Test Case: TCCreateTable - TestCase for table creation
//| Created: 09/11/97
//*-----------------------------------------------------------------------
//--------------------------------------------------------------------
//
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//--------------------------------------------------------------------------
BOOL TCCreateTable::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCITableDefinition::Init())
// }}
{
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Session interfaces
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_1()
{
return DefaultObjectTesting(m_pITableDefinition, SESSION_INTERFACE);
}
// }}
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc pTableID is NULL => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_2()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK);
CLEANUP:
// checkings, etc
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc ppTableID is a NULL pointer => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_3()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
TESTC_(CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset,
0, NULL), S_OK);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc pTableID and ppTableID both NULL => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_4()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset,
0, NULL, TRUE), E_INVALIDARG);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc *pTableID == DB_NULLID => DB_E_BADTABLEID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_5()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
TESTC_(CCNDropTable((DBID*)&DB_NULLID, cColumnDesc, rgColumnDesc, IID_IRowset,
0, NULL), DB_E_BADTABLEID);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc cColumnDesc == 0 => E_INVALIDARG or S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_6()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
TEST2C_(CCNDropTable(NULL, 0, rgColumnDesc, IID_IRowset, 0, NULL),
S_OK, E_INVALIDARG);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc rgColumnDesc == NULL => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_7()
{
TBEGIN
TESTC_(CCNDropTable(NULL, m_cColumnDesc, NULL, IID_IRowset,
0, NULL), E_INVALIDARG);
CLEANUP:
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc cPropertySets != 0 and rgPropertySets == NULL => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_8()
{
TBEGIN
ULONG ulNonZero = 2;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset,
ulNonZero, NULL), E_INVALIDARG);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc cPropertySets is 0 and rgPropertySets != NULL => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_9()
{
TBEGIN
DBPROPSET rgPropertySets[1];
DBPROP rgProp[1];
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
FILL_PROP_SET(rgPropertySets[0], 1, rgProp, DBPROPSET_ROWSET)
FILL_PROP(rgProp[0], DBPROP_IAccessor, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED)
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset,
0, rgPropertySets), S_OK);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc for a property sets, cProperties != 0 and rgProperties == NULL => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_10()
{
TBEGIN
DBPROPSET rgPropertySets[1];
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
FILL_PROP_SET(rgPropertySets[0], 3, NULL, DBPROPSET_ROWSET)
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset,
1, rgPropertySets), E_INVALIDARG);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc cProperties == 0 on a property set => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_11()
{
TBEGIN
DBPROPSET rgPropertySets[1];
DBPROP rgProp[1];
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// FILL_PROP_SET(rgPropertySets[0], 0, rgProp, DBPROPSET_ROWSET)
rgPropertySets[0].cProperties = 0;
rgPropertySets[0].rgProperties = rgProp;
rgPropertySets[0].guidPropertySet = DBPROPSET_ROWSET;
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 1, rgPropertySets), S_OK);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc for a column, rgPropertySets is NULL though cPropertySets != 0 => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_12()
{
TBEGIN
ULONG cProp = 3;
DBPROPSET rgPropSets[1];
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
rgColumnDesc[0].rgPropertySets = rgPropSets;
rgColumnDesc[0].cPropertySets = NUMELEM(rgPropSets);
FILL_PROP_SET(rgPropSets[0], cProp, NULL, DBPROPSET_COLUMN)
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), E_INVALIDARG);
CLEANUP:
// it is not required to release the memory for rgColumnDesc; it will be release in table destructor
rgColumnDesc[0].rgPropertySets = NULL;
rgColumnDesc[0].cPropertySets = 0;
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc dbcid in an element of rgColumnDesc is DB_NULLID => DB_E_BADCOLUMNID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_13()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// set a dbcid of an element in rgColumnDesc to DB_NULLID
ReleaseDBID(&rgColumnDesc[0].dbcid, FALSE); // cleans the container
memcpy(&rgColumnDesc[0].dbcid, &DB_NULLID, sizeof(DBID));
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_BADCOLUMNID);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(14)
//*-----------------------------------------------------------------------
// @mfunc dbcid in an element of rgColumnDesc is NULL => DB_E_BADCOLUMNID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_14()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// set a dbcid of an element in rgColumnDesc to DB_NULLID
ReleaseDBID(&rgColumnDesc[0].dbcid, FALSE); // cleans the container
rgColumnDesc[0].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[0].dbcid.uName.pwszName = NULL;
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_BADCOLUMNID);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(15)
//*-----------------------------------------------------------------------
// @mfunc not null pclsid in a DBCOLUMNDESC element
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_15()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
POSITION pos;
CCol col;
HRESULT hr;
BOOL fOleSupported = FALSE;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// set pclsid to IID_NULL
rgColumnDesc[0].pclsid = (GUID*)&IID_NULL;
// check whether this is ignored for a non-DBTYPE_IUNKNOWN column
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK);
// check DBTYPE_IUNKNOWN is supported
for (pos = m_ColList.GetHeadPosition(); pos; )
{
col = m_ColList.GetNext(pos);
if (DBTYPE_IUNKNOWN == col.GetProviderType())
{
fOleSupported = TRUE;
break;
}
}
// check whether a DBTYPE_IUNKNOWN column can be created in the table
rgColumnDesc[0].wType = DBTYPE_IUNKNOWN;
PROVIDER_FREE(rgColumnDesc[0].pwszTypeName);
if (fOleSupported)
rgColumnDesc[0].pwszTypeName = wcsDuplicate(col.GetProviderTypeName());
hr = fOleSupported ? S_OK : DB_E_BADTYPE;
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), hr);
CLEANUP:
rgColumnDesc[0].pclsid = NULL;
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc empty column name => DB_E_BADCOLUMNID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_16()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// set a dbcid of an element in rgColumnDesc to DB_NULLID
rgColumnDesc[0].dbcid.eKind = DBKIND_NAME;
ReleaseDBID(&rgColumnDesc[0].dbcid, FALSE); // cleans the container
rgColumnDesc[0].dbcid.uName.pwszName = wcsDuplicate(L"");
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_BADCOLUMNID);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(17)
//*-----------------------------------------------------------------------
// @mfunc empty table name => DB_E_BADTABLEID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_17()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = L"";
// create the empty name table
TESTC_(CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_BADTABLEID);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(18)
//*-----------------------------------------------------------------------
// @mfunc Maximum length for table name => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_18()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// create a maximum size table name
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = BuildValidName(m_cMaxTableName, m_pTable->GetTableName());
TESTC_(CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK);
CLEANUP:
ReleaseDBID(&TableID, FALSE);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(19)
//*-----------------------------------------------------------------------
// @mfunc 1 char too long table name => DB_E_BADTABLEID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_19()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// create a maximum size table name
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = BuildValidName(m_cMaxTableName+1, m_pTable->GetTableName());
TESTC_(CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_BADTABLEID);
CLEANUP:
ReleaseDBID(&TableID, FALSE);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(20)
//*-----------------------------------------------------------------------
// @mfunc Maximum length column name => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_20()
{
TBEGIN
LPWSTR pwszColumnName = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// set a dbcid of an element in rgColumnDesc to DB_NULLID
pwszColumnName = rgColumnDesc[0].dbcid.uName.pwszName;
rgColumnDesc[0].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[0].dbcid.uName.pwszName = BuildValidName(m_cMaxColName, pwszColumnName);
// save the number of propertySets, to be able to release it ok
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK);
CLEANUP:
PROVIDER_FREE(pwszColumnName);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(21)
//*-----------------------------------------------------------------------
// @mfunc 1 char too long column name => DB_E_BADCOLUMNID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_21()
{
TBEGIN
WCHAR *pwszColumnName = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
if (DBKIND_NAME == rgColumnDesc[0].dbcid.eKind)
pwszColumnName = rgColumnDesc[0].dbcid.uName.pwszName;
else
pwszColumnName = wcsDuplicate(L"ColumnName");
rgColumnDesc[0].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[0].dbcid.uName.pwszName = BuildValidName(m_cMaxColName+1, pwszColumnName);
// save the number of propertySets, to be able to release it ok
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_BADCOLUMNID);
CLEANUP:
PROVIDER_FREE(pwszColumnName);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(22)
//*-----------------------------------------------------------------------
// @mfunc ulColumnSize 0 for a variable-length column => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_22()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// go through the list of column and set the column size to 0 for all variable-length columns
for (ULONG i=0; i<cColumnDesc; i++)
{
if (!IsFixedLength(rgColumnDesc[i].wType))
{
rgColumnDesc[i].ulColumnSize = 0;
odtLog << "Column " << rgColumnDesc[i].dbcid.uName.pwszName << " is set to length 0!\n";
}
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(23)
//*-----------------------------------------------------------------------
// @mfunc For each provider type create and drop a table with a single column => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_23()
{
TBEGIN
DBCOLUMNDESC *tempColumnDesc;
DBORDINAL i;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// go through the list of column and set the column size to 0 for all variable-length columns
for (i=0, tempColumnDesc=rgColumnDesc; i<cColumnDesc; i++, tempColumnDesc++)
{
odtLog << "Create a table with a single column " << tempColumnDesc->dbcid.uName.pwszName << "\n";
CHECK(CCNDropTable(NULL, 1, tempColumnDesc, IID_IRowset, 0, NULL), S_OK);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(24)
//*-----------------------------------------------------------------------
// @mfunc invalid table name => DB_E_BADTABLEID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_24()
{
TBEGIN
WCHAR *pwszTableName = NULL;
size_t n, m;
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
m = min(n=wcslen(m_pTable->GetTableName())+5, m_cMaxTableName);
pwszTableName = BuildInvalidName(m, m_pTable->GetTableName(), m_pwszInvalidTableChars);
TableID.uName.pwszName = pwszTableName;
TESTC_(CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_BADTABLEID);
CLEANUP:
PROVIDER_FREE(pwszTableName);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(25)
//*-----------------------------------------------------------------------
// @mfunc pTableID provides the name of an existing table => DB_E_DUPLICATETABLEID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_25()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
TESTC_(CreateAndCheckTable(m_pITableDefinition, NULL, &TableID,
cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL, NULL, NULL), S_OK);
TESTC_(CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_DUPLICATETABLEID);
CLEANUP:
CHECK(DropTableAndCheck(&TableID), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(26)
//*-----------------------------------------------------------------------
// @mfunc valid riid and NULL ppRowset => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_26()
{
TBEGIN
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
TESTC_(CreateAndCheckTable(m_pITableDefinition, NULL, NULL,
cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL, &pTableID, NULL), S_OK);
CLEANUP:
CHECK(DropTableAndCheck(pTableID), S_OK);
ReleaseDBID(pTableID);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(27)
//*-----------------------------------------------------------------------
// @mfunc invalid column name => DB_E_BADCOLUMNID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_27()
{
TBEGIN
WCHAR *pwszColName = NULL;
size_t n, m;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// create an invalid column name
m = min(n=wcslen(rgColumnDesc[0].dbcid.uName.pwszName)+5, m_cMaxColName);
if (DBKIND_NAME == rgColumnDesc[0].dbcid.eKind)
pwszColName = rgColumnDesc[0].dbcid.uName.pwszName;
else
pwszColName = wcsDuplicate(L"ColumnName");
rgColumnDesc[0].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[0].dbcid.uName.pwszName = BuildInvalidName(m,
pwszColName, m_pwszInvalidColChars);
SAFE_FREE(pwszColName);
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_BADCOLUMNID);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(28)
//*-----------------------------------------------------------------------
// @mfunc invalid type name for a column (NULL, empty or inexistent
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_28()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// build the column type name
SAFE_FREE(rgColumnDesc[0].pwszTypeName);
odtLog << "NULL type name\n";
rgColumnDesc[0].pwszTypeName = NULL;
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK);
// verify empty string (bug 26380, empty string for type name should be equivalent to specifying a NULL pointer)
odtLog << "empty type name for a column\n";
rgColumnDesc[0].pwszTypeName = wcsDuplicate(L"");
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK);
rgColumnDesc[0].pwszTypeName = wcsDuplicate(L"Pay a trip to Europe");
odtLog << "invalid type name (" << rgColumnDesc[0].pwszTypeName <<")\n";
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_BADTYPE);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(29)
//*-----------------------------------------------------------------------
// @mfunc invalid wType for a column => DB_E_BADTYPE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_29()
{
TBEGIN
DBTYPE wInvalidType = 0xffff;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
PROVIDER_FREE(rgColumnDesc[0].pwszTypeName);
rgColumnDesc[0].pwszTypeName = NULL;
rgColumnDesc[0].wType = wInvalidType;
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_BADTYPE);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(30)
//*-----------------------------------------------------------------------
// @mfunc wType and pswzTypeName mismatch in a column description => DB_E_BADTYPE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_30()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// set an invalid wType
TESTC_PROVIDER(cColumnDesc >= 7);
// each column was assigned a different type; try to mismatch a pwszTypeName and wType for the first col
PROVIDER_FREE(rgColumnDesc[0].pwszTypeName);
rgColumnDesc[0].pwszTypeName = rgColumnDesc[7].pwszTypeName;
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_BADTYPE);
CLEANUP:
if (cColumnDesc > 1)
rgColumnDesc[0].pwszTypeName = NULL;
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(31)
//*-----------------------------------------------------------------------
// @mfunc not null pTypeInfo => DB_E_BADTYPE (for the time being
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_31()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// set a not NULL pTypeInfo
rgColumnDesc[0].pTypeInfo = (ITypeInfo*)pITableDefinition();
TEST2C_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), E_NOINTERFACE, DB_E_BADTYPE);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(32)
//*-----------------------------------------------------------------------
// @mfunc duplicate column identifiers => DB_E_DUPLICATECOLUMNID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_32()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// set an invalid wType
TESTC_PROVIDER(2 < cColumnDesc);
// each column was assigned a different type; try to mismatch a pwszTypeName and wType for the first col
ReleaseDBID(&rgColumnDesc[0].dbcid, FALSE);
DuplicateDBID(rgColumnDesc[1].dbcid, &rgColumnDesc[0].dbcid);
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_DUPLICATECOLUMNID);
CLEANUP:
memset(&rgColumnDesc[0].dbcid, 0, sizeof(DBID));
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(33)
//*-----------------------------------------------------------------------
// @mfunc improper eKind value in a DBID => DB_E_BADCOLUMNID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_33()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// set improper eKind in a column DBID
ReleaseDBID(&rgColumnDesc[0].dbcid, FALSE);
rgColumnDesc[0].dbcid.eKind = INVALID_DBKIND;
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_BADCOLUMNID);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(34)
//*-----------------------------------------------------------------------
// @mfunc invalid property value on column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_34()
{
TBEGIN
DBPROPSET rgPropSet[1];
DBPROP rgProp[1];
LONG lValue = 12;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// set improper value (different type than required) for a property value of a column
// DBPROPOPTIONS_REQUIRED
rgColumnDesc[0].cPropertySets = NUMELEM(rgPropSet);
rgColumnDesc[0].rgPropertySets = rgPropSet;
FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_COLUMN)
FILL_PROP(rgProp[0], DBPROP_COL_UNIQUE, DBTYPE_I4, V_I4, lValue, DBPROPOPTIONS_REQUIRED)
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_ERRORSOCCURRED);
// set improper value (different type) for a column DBPROPOPTIONS_OPTIONAL
// try to set the property value of the rowset trough a column
rgColumnDesc[0].cPropertySets = NUMELEM(rgPropSet);
rgColumnDesc[0].rgPropertySets = rgPropSet;
FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_COLUMN)
FILL_PROP(rgProp[0], DBPROP_COL_UNIQUE, DBTYPE_I4, V_I4, lValue, DBPROPOPTIONS_OPTIONAL)
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_S_ERRORSOCCURRED);
// try to set a rowset property through a column, DBPROPOPTIONS_REQUIRED
rgColumnDesc[0].cPropertySets = NUMELEM(rgPropSet);
rgColumnDesc[0].rgPropertySets = rgPropSet;
FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_ROWSET)
FILL_PROP(rgProp[0], DBPROP_BOOKMARKS, DBTYPE_I4, V_I4, lValue, DBPROPOPTIONS_REQUIRED)
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_ERRORSOCCURRED);
// try to set a rowset property through a column, DBPROPOPTIONS_OPTIONAL
rgColumnDesc[0].cPropertySets = NUMELEM(rgPropSet);
rgColumnDesc[0].rgPropertySets = rgPropSet;
FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_ROWSET)
FILL_PROP(rgProp[0], DBPROP_BOOKMARKS, DBTYPE_I4, V_I4, lValue, DBPROPOPTIONS_OPTIONAL)
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_S_ERRORSOCCURRED);
CLEANUP:
rgColumnDesc[0].cPropertySets = 0;
rgColumnDesc[0].rgPropertySets = NULL;
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(35)
//*-----------------------------------------------------------------------
// @mfunc Invalid column precision => DB_E_BADPRECISION
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_35()
{
TBEGIN
const int n=8;
BYTE testValues[n];
HRESULT testResult[n]={S_OK, S_OK, S_OK, S_OK, S_OK, S_OK, DB_E_BADPRECISION, DB_E_BADPRECISION};
CCol Col;
ULONG cPrecision;
DBORDINAL i;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
testValues[0] = 0;
testValues[1] = 1;
for (i=0; i<cColumnDesc; i++)
{
Col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
ASSERT(0 == wcscmp(Col.GetProviderTypeName(), GetColumnTypeName(&rgColumnDesc[i])));
if (rgColumnDesc[i].wType == DBTYPE_NUMERIC)
testResult[0] = DB_E_BADPRECISION;
else
testResult[0] = S_OK;
testResult[6] = S_OK;
testResult[7] = S_OK;
if (rgColumnDesc[i].wType == DBTYPE_NUMERIC)
{
testResult[6] = DB_E_BADPRECISION;
testResult[7] = DB_E_BADPRECISION;
}
testValues[2] = (BYTE)(Col.GetPrecision()/3);
testValues[3] = (BYTE)(2*Col.GetPrecision()/3);
testValues[4] = (BYTE)Col.GetPrecision()-1;
testValues[5] = (BYTE)Col.GetPrecision();
testValues[6] = (BYTE)Col.GetPrecision()+1;
testValues[7] = (BYTE)Col.GetPrecision()+10;
odtLog << rgColumnDesc[i].pwszTypeName <<" ("
<< rgColumnDesc[i].dbcid.uName.pwszName << ") max precision =" << testValues[5] << "\n";
odtLog << "\t" << "precisions tested :";
for (cPrecision=0; cPrecision<n; cPrecision++)
odtLog << "\t" << (ULONG)testValues[cPrecision];
odtLog << "\n";
for (cPrecision=0; cPrecision<n; cPrecision++)
{
rgColumnDesc[i].bPrecision = (BYTE)testValues[cPrecision];
rgColumnDesc[i].ulColumnSize = 0;
rgColumnDesc[i].bScale = 0;
if (!CHECK(CCNDropTable(NULL, 1, &rgColumnDesc[i], IID_IRowset, 0, NULL), testResult[cPrecision]))
{
odtLog << "Error for precision " << testValues[cPrecision] << "\n";
}
}
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(36)
//*-----------------------------------------------------------------------
// @mfunc invalid scale on column => DB_E_BADSCALE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_36()
{
TBEGIN
const int n=7;
BYTE testValues[n];
HRESULT testResult[n]={S_OK, S_OK, S_OK, S_OK, S_OK, DB_E_BADSCALE, DB_E_BADSCALE};
CCol Col;
ULONG cScale, m;
DBORDINAL i;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
testValues[0] = 0;
testValues[1] = 1;
for (i=0; i<cColumnDesc; i++)
{
Col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
ASSERT(0 == wcscmp(Col.GetProviderTypeName(), GetColumnTypeName(&rgColumnDesc[i])));
odtLog << rgColumnDesc[i].pwszTypeName << "\n";
testResult[0] = S_OK;
testResult[1] = S_OK;
testValues[0] = 0;
testValues[1] = 1;
testValues[2] = 100;
testValues[3] = (BYTE)Col.GetPrecision()+1;
m = 4;
if ((rgColumnDesc[i].wType == DBTYPE_NUMERIC) || (rgColumnDesc[i].wType == DBTYPE_DECIMAL))
{
m = 7;
if (Col.GetMinScale()>0)
{
testResult[0] = DB_E_BADSCALE;
testResult[1] = DB_E_BADSCALE;
}
testResult[4] = S_OK;
testValues[1] = (BYTE)max(Col.GetMinScale()-1, 0);
testValues[2] = (BYTE)Col.GetMinScale();
testValues[3] = (BYTE)((Col.GetMinScale()+Col.GetMaxScale())/2);
testValues[4] = (BYTE)Col.GetMaxScale();
testValues[5] = (BYTE)Col.GetMaxScale()+1;
testValues[6] = (BYTE)Col.GetMaxScale();
// tests
for (cScale=0; cScale<m; cScale++)
{
rgColumnDesc[i].bScale = (BYTE)testValues[cScale];
if (cScale+1 == m)
{
rgColumnDesc[i].bPrecision = max(1, Col.GetMaxScale()-2);
odtLog << "\nprecision: " << rgColumnDesc[i].bPrecision
<< ", scale: " << testValues[cScale] <<"\n";
}
else
odtLog << "\t" << testValues[cScale];
if (!CHECK(CCNDropTable(NULL, 1, &rgColumnDesc[i], IID_IRowset, 0, NULL), testResult[cScale]))
{
odtLog << "Error for scale " << testValues[cScale] << "\n";
}
}
odtLog << "\n";
}
else
{
testResult[4] = S_OK;
for (cScale=0; cScale<m; cScale++)
{
rgColumnDesc[i].bScale = (BYTE)testValues[cScale];
if (cScale+1 == m)
rgColumnDesc[cScale].bPrecision = Col.GetMaxScale()-1;
if (!CHECK(CCNDropTable(NULL, 1, &rgColumnDesc[i],
IID_IRowset, 0, NULL), testResult[cScale]))
{
odtLog << "Error for scale " << testValues[cScale] << "\n";
}
}
}
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(37)
//*-----------------------------------------------------------------------
// @mfunc col prop is not in the Column, Rowset or Table property group and dwOption is DBPROP_SETIFCHEAP => DB_S_ERRORSOCCURRED
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_37()
{
TBEGIN
DBPROPSET rgPropSet[1];
DBPROP rgProp[1];
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// set a column property that doesn't belong to the column, rowset or table propriety group
rgColumnDesc[0].cPropertySets = NUMELEM(rgPropSet);
rgColumnDesc[0].rgPropertySets = rgPropSet;
FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_DBINIT)
FILL_PROP(rgProp[0], DBPROP_AUTH_PASSWORD, DBTYPE_BSTR, V_BSTR,
SysAllocString(L"passwd"), DBPROPOPTIONS_OPTIONAL)
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_S_ERRORSOCCURRED);
CLEANUP:
SysFreeString(V_BSTR(&rgProp[0].vValue));
rgColumnDesc[0].cPropertySets = 0;
rgColumnDesc[0].rgPropertySets = NULL;
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(38)
//*-----------------------------------------------------------------------
// @mfunc col prop is not in the Column, Rowset or Table property group and dwOption is DBPROP_REQUIRED => DB_E_ERRORSOCCURRED
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_38()
{
TBEGIN
DBPROPSET rgPropSet[1];
DBPROP rgProp[1];
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// set a column property ID that is not valid
rgColumnDesc[0].cPropertySets = NUMELEM(rgPropSet);
rgColumnDesc[0].rgPropertySets = rgPropSet;
FILL_PROP_SET(rgPropSet[0], NUMELEM(rgProp), rgProp, DBPROPSET_DBINIT)
FILL_PROP(rgProp[0], DBPROP_AUTH_PASSWORD, DBTYPE_BSTR, V_BSTR,
SysAllocString(L"passwd"), DBPROPOPTIONS_REQUIRED)
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_ERRORSOCCURRED);
CLEANUP:
SysFreeString(V_BSTR(&rgProp[0].vValue));
rgColumnDesc[0].cPropertySets = 0;
rgColumnDesc[0].rgPropertySets = NULL;
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(39)
//*-----------------------------------------------------------------------
// @mfunc invalid propID for a column propriety
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_39()
{
TBEGIN
DBPROPSET rgPropSet[1];
DBPROP rgProp[1];
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// set an inexistent column property with DBPROPOPTIONS_OPTIONAL
rgColumnDesc[0].cPropertySets = NUMELEM(rgPropSet);
rgColumnDesc[0].rgPropertySets = rgPropSet;
FILL_PROP_SET(rgPropSet[0], 1, rgProp, DBPROPSET_COLUMN)
FILL_PROP(rgProp[0], 0xffff, DBTYPE_I4, V_I4, 42, DBPROPOPTIONS_OPTIONAL)
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_S_ERRORSOCCURRED);
// set an inexistent column property with DBPROPOPTIONS_REQUIRED
rgColumnDesc[0].cPropertySets = NUMELEM(rgPropSet);
rgColumnDesc[0].rgPropertySets = rgPropSet;
FILL_PROP_SET(rgPropSet[0], 1, rgProp, DBPROPSET_COLUMN)
FILL_PROP(rgProp[0], 0xffff, DBTYPE_I4, V_I4, 42, DBPROPOPTIONS_REQUIRED)
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_ERRORSOCCURRED);
CLEANUP:
rgColumnDesc[0].cPropertySets = 0;
rgColumnDesc[0].rgPropertySets = NULL;
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(40)
//*-----------------------------------------------------------------------
// @mfunc colid in DBPROP of a column property is ignored
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_40()
{
TBEGIN
DBPROPSET rgPropSet[1];
DBPROP rgProp[1];
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBPROPID rgPropID[] = { DBPROP_COL_AUTOINCREMENT, DBPROP_COL_NULLABLE};
ULONG i;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
rgColumnDesc[0].cPropertySets = 0;
rgColumnDesc[0].rgPropertySets = NULL;
// set a column property that is not ...
for (i=0; i<NUMELEM(rgPropID); i++)
{
if (SettableProperty(rgPropID[i], DBPROPSET_COLUMN))
break;
}
TESTC_PROVIDER(i<NUMELEM(rgPropID));
rgColumnDesc[0].cPropertySets = 1;
rgColumnDesc[0].rgPropertySets = rgPropSet;
FILL_PROP_SET(rgPropSet[0], 1, rgProp, DBPROPSET_COLUMN)
FILL_PROP(rgProp[0], rgPropID[i], 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 = wcsDuplicate(L"someColumn");
// check colid is ignored for the column property
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK);
COMPARE(DBPROPSTATUS_OK == rgProp[0].dwStatus, TRUE);
// check colid is ignored for the column property
rgProp[0].dwOptions = DBPROPOPTIONS_REQUIRED;
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK);
COMPARE(DBPROPSTATUS_OK == rgProp[0].dwStatus, TRUE);
CLEANUP:
PROVIDER_FREE(rgProp[0].colid.uName.pwszName);
rgColumnDesc[0].cPropertySets = 0;
rgColumnDesc[0].rgPropertySets = NULL;
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }}
// {{ TCW_VAR_PROTOTYPE(41)
//*-----------------------------------------------------------------------
// @mfunc Abort retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_41()
{
TBEGIN
BOOL fExists;
ITransactionLocal *pITransactionLocal = NULL;
DBID *pTableID = NULL;
DBPROPSET *rgPropSet = NULL;
ULONG cPropSet = 0;
IRowsetInfo *pIRowsetInfo = NULL;
BOOL fAbortPreserve = TRUE;
ULONG cReadPropSet = 0;
DBPROPSET *rgReadPropSet = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
VARIANT vSupportedTxnDDL;
HRESULT hr;
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_ITransactionLocal,
SESSION_INTERFACE, (IUnknown**)&pITransactionLocal));
VariantInit(&vSupportedTxnDDL);
TESTC_PROVIDER(GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO,
g_pIDBInitialize, &vSupportedTxnDDL));
TESTC(VT_I4 == vSupportedTxnDDL.vt);
// what values should we accept?
TESTC_PROVIDER(DBPROPVAL_TC_NONE != vSupportedTxnDDL.lVal);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
TESTC_(StartTransaction(pITransactionLocal), S_OK);
// if possible, prepare to ask DBPROP_ABORTPRESERVE to be set to VARIANT_FALSE
if (SettableProperty(DBPROP_ABORTPRESERVE, DBPROPSET_ROWSET))
{
::SetProperty(DBPROP_ABORTPRESERVE, DBPROPSET_ROWSET, &cPropSet, &rgPropSet,
(LPVOID)VARIANT_FALSE, VT_BOOL, DBPROPOPTIONS_REQUIRED, DB_NULLID);
}
switch(vSupportedTxnDDL.lVal)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(hr = m_pITableDefinition->CreateTable(NULL, NULL, cColumnDesc, rgColumnDesc,
IID_IRowsetInfo, cPropSet, rgPropSet, &pTableID,
(IUnknown**)&pIRowsetInfo), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
CHECK(hr = CreateAndCheckTable(m_pITableDefinition, NULL, NULL,
cColumnDesc, rgColumnDesc, IID_IRowsetInfo,
cPropSet, rgPropSet, &pTableID,
(IUnknown**)&pIRowsetInfo), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
// error should be returned
CHECK(hr = m_pITableDefinition->CreateTable(NULL, NULL, cColumnDesc, rgColumnDesc,
IID_IRowsetInfo, cPropSet, rgPropSet, &pTableID,
(IUnknown**)&pIRowsetInfo), S_OK);
break;
default:
TESTC(FALSE);
}
if (DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal)
{
if (pIRowsetInfo)
fAbortPreserve = GetProperty(DBPROP_ABORTPRESERVE, DBPROPSET_ROWSET, pIRowsetInfo, VARIANT_TRUE);
// abort retaining
CHECK(pITransactionLocal->Abort(NULL, TRUE, FALSE), S_OK);
// check that it is retaining (another transaction is available)
CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK);
}
// abort retaining and check that the table doesn't exist anymore
CHECK(m_hr = m_pTable->DoesTableExist(pTableID, &fExists), S_OK);
COMPARE(fExists, DBPROPVAL_TC_DDL_IGNORE == vSupportedTxnDDL.lVal
|| DBPROPVAL_TC_DDL_COMMIT == vSupportedTxnDDL.lVal);
if (fExists)
{
CHECK(DropTableAndCheck(pTableID), S_OK);
}
// test zombie rowset
if (pIRowsetInfo)
TESTC_(pIRowsetInfo->GetProperties(0, NULL, &cReadPropSet, &rgReadPropSet), fAbortPreserve? S_OK: E_UNEXPECTED);
CLEANUP:
SAFE_RELEASE(pITransactionLocal);
SAFE_RELEASE(pIRowsetInfo);
ReleaseDBID(pTableID);
FreeProperties( &cPropSet, &rgPropSet);
FreeProperties( &cReadPropSet, &rgReadPropSet);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(42)
//*-----------------------------------------------------------------------
// @mfunc Abort without retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_42()
{
TBEGIN
BOOL fExists;
ITransactionLocal *pITransactionLocal = NULL;
DBID *pTableID = NULL;
DBPROPSET *rgPropSet = NULL;
ULONG cPropSet = 0;
IRowsetInfo *pIRowsetInfo = NULL;
BOOL fAbortPreserve = TRUE;
ULONG cReadPropSet = 0;
DBPROPSET *rgReadPropSet = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
VARIANT vSupportedTxnDDL;
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_ITransactionLocal,
SESSION_INTERFACE, (IUnknown**)&pITransactionLocal));
VariantInit(&vSupportedTxnDDL);
TESTC_PROVIDER(GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO,
g_pIDBInitialize, &vSupportedTxnDDL));
TESTC(VT_I4 == vSupportedTxnDDL.vt);
// what values should we accept?
TESTC_PROVIDER(DBPROPVAL_TC_NONE != vSupportedTxnDDL.lVal);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
TESTC_(StartTransaction(pITransactionLocal), S_OK);
// if possible, prepare to ask DBPROP_ABORTPRESERVE to be set to VARIANT_FALSE
if (SettableProperty(DBPROP_ABORTPRESERVE, DBPROPSET_ROWSET))
{
::SetProperty(DBPROP_ABORTPRESERVE, DBPROPSET_ROWSET, &cPropSet, &rgPropSet,
(LPVOID)VARIANT_FALSE, VT_BOOL, DBPROPOPTIONS_REQUIRED, DB_NULLID);
}
switch(vSupportedTxnDDL.lVal)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(m_hr = m_pITableDefinition->CreateTable(NULL, NULL, cColumnDesc, rgColumnDesc,
IID_IRowsetInfo, cPropSet, rgPropSet, &pTableID,
(IUnknown**)&pIRowsetInfo), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
CHECK(CreateAndCheckTable(m_pITableDefinition, NULL, NULL,
cColumnDesc, rgColumnDesc, IID_IRowsetInfo,
cPropSet, rgPropSet, &pTableID,
(IUnknown**)&pIRowsetInfo), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
// error should be returned
CHECK(m_hr = m_pITableDefinition->CreateTable(NULL, NULL, cColumnDesc, rgColumnDesc,
IID_IRowsetInfo, cPropSet, rgPropSet, &pTableID,
(IUnknown**)&pIRowsetInfo), S_OK);
break;
default:
TESTC(FALSE);
}
if (DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal)
{
fAbortPreserve = GetProperty(DBPROP_ABORTPRESERVE, DBPROPSET_ROWSET, pIRowsetInfo, VARIANT_TRUE);
// abort non retaining
CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK);
// check that it is retaining (another transaction is available)
CHECK(pITransactionLocal->Abort(NULL, FALSE, FALSE),
FAILED(m_hr)? S_OK : XACT_E_NOTRANSACTION);
}
// abort retaining and check that the table doesn't exist anymore
CHECK(m_hr = m_pTable->DoesTableExist(pTableID, &fExists), S_OK);
COMPARE(fExists, DBPROPVAL_TC_DDL_IGNORE == vSupportedTxnDDL.lVal
|| DBPROPVAL_TC_DDL_COMMIT == vSupportedTxnDDL.lVal);
if (fExists)
{
CHECK(DropTableAndCheck(pTableID), S_OK);
}
// test zombie rowset
TESTC_(pIRowsetInfo->GetProperties(0, NULL, &cReadPropSet, &rgReadPropSet), fAbortPreserve? S_OK: E_UNEXPECTED);
CLEANUP:
SAFE_RELEASE(pITransactionLocal);
SAFE_RELEASE(pIRowsetInfo);
ReleaseDBID(pTableID);
FreeProperties( &cPropSet, &rgPropSet);
FreeProperties(&cReadPropSet, &rgReadPropSet);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(43)
//*-----------------------------------------------------------------------
// @mfunc Commit retain
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_43()
{
TBEGIN
BOOL fExists;
ITransactionLocal *pITransactionLocal = NULL;
DBID *pTableID = NULL;
DBPROPSET *rgPropSet = NULL;
ULONG cPropSet = 0;
IRowsetInfo *pIRowsetInfo = NULL;
BOOL fCommitPreserve = TRUE;
ULONG cReadPropSet = 0;
DBPROPSET *rgReadPropSet = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
VARIANT vSupportedTxnDDL;
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_ITransactionLocal,
SESSION_INTERFACE, (IUnknown**)&pITransactionLocal));
VariantInit(&vSupportedTxnDDL);
TESTC_PROVIDER(GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO,
g_pIDBInitialize, &vSupportedTxnDDL));
TESTC(VT_I4 == vSupportedTxnDDL.vt);
// what values should we accept?
TESTC_PROVIDER(DBPROPVAL_TC_NONE != vSupportedTxnDDL.lVal);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
TESTC_(StartTransaction(pITransactionLocal), S_OK);
// if possible, prepare to ask DBPROP_ABORTPRESERVE to be set to VARIANT_FALSE
if (SettableProperty(DBPROP_COMMITPRESERVE, DBPROPSET_ROWSET))
{
::SetProperty(DBPROP_COMMITPRESERVE, DBPROPSET_ROWSET, &cPropSet, &rgPropSet,
(LPVOID)VARIANT_FALSE, VT_BOOL, DBPROPOPTIONS_REQUIRED, DB_NULLID);
}
switch(vSupportedTxnDDL.lVal)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(m_hr = m_pITableDefinition->CreateTable(NULL, NULL, cColumnDesc, rgColumnDesc,
IID_IRowsetInfo, cPropSet, rgPropSet, &pTableID,
(IUnknown**)&pIRowsetInfo), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
CHECK(CreateAndCheckTable(m_pITableDefinition, NULL, NULL,
cColumnDesc, rgColumnDesc, IID_IRowsetInfo,
cPropSet, rgPropSet, &pTableID,
(IUnknown**)&pIRowsetInfo), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
// error should be returned
CHECK(m_hr = m_pITableDefinition->CreateTable(NULL, NULL, cColumnDesc, rgColumnDesc,
IID_IRowsetInfo, cPropSet, rgPropSet, &pTableID,
(IUnknown**)&pIRowsetInfo), S_OK);
break;
default:
TESTC(FALSE);
}
if (DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal)
{
fCommitPreserve = GetProperty(DBPROP_COMMITPRESERVE, DBPROPSET_ROWSET, pIRowsetInfo, VARIANT_TRUE);
// commit retaining
CHECK(m_hr = pITransactionLocal->Commit(TRUE, 0, 0), S_OK);
// check that it is retaining (another transaction is available)
CHECK(m_hr = pITransactionLocal->Abort(NULL, FALSE, FALSE), S_OK);
}
// abort retaining and check that the table doesn't exist anymore
CHECK(m_hr = m_pTable->DoesTableExist(pTableID, &fExists), S_OK);
COMPARE(fExists, DBPROPVAL_TC_DML != vSupportedTxnDDL.lVal);
if (fExists)
{
CHECK(DropTableAndCheck(pTableID), S_OK);
}
// test zombie rowset
TESTC_(pIRowsetInfo->GetProperties(0, NULL, &cReadPropSet, &rgReadPropSet), fCommitPreserve? S_OK: E_UNEXPECTED);
CLEANUP:
SAFE_RELEASE(pITransactionLocal);
SAFE_RELEASE(pIRowsetInfo);
DropTableAndCheck(pTableID);
ReleaseDBID(pTableID);
FreeProperties( &cPropSet, &rgPropSet);
FreeProperties(&cReadPropSet, &rgReadPropSet);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(44)
//*-----------------------------------------------------------------------
// @mfunc Commit non-retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_44()
{
TBEGIN
BOOL fExists;
ITransactionLocal *pITransactionLocal = NULL;
DBID *pTableID = NULL;
DBPROPSET *rgPropSet = NULL;
ULONG cPropSet = 0;
IRowsetInfo *pIRowsetInfo = NULL;
BOOL fCommitPreserve = TRUE;
ULONG cReadPropSet = 0;
DBPROPSET *rgReadPropSet = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
VARIANT vSupportedTxnDDL;
TESTC_PROVIDER(VerifyInterface(m_pITableDefinition, IID_ITransactionLocal,
SESSION_INTERFACE, (IUnknown**)&pITransactionLocal));
VariantInit(&vSupportedTxnDDL);
TESTC_PROVIDER(GetProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO,
g_pIDBInitialize, &vSupportedTxnDDL));
TESTC(VT_I4 == vSupportedTxnDDL.vt);
// what values should we accept?
TESTC_PROVIDER(DBPROPVAL_TC_NONE != vSupportedTxnDDL.lVal);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
TESTC_(StartTransaction(pITransactionLocal), S_OK);
// if possible, prepare to ask DBPROP_ABORTPRESERVE to be set to VARIANT_FALSE
if (SettableProperty(DBPROP_COMMITPRESERVE, DBPROPSET_ROWSET))
{
::SetProperty(DBPROP_COMMITPRESERVE, DBPROPSET_ROWSET, &cPropSet, &rgPropSet,
(LPVOID)VARIANT_FALSE, VT_BOOL, DBPROPOPTIONS_REQUIRED, DB_NULLID);
}
switch(vSupportedTxnDDL.lVal)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(m_hr = m_pITableDefinition->CreateTable(NULL, NULL, cColumnDesc, rgColumnDesc,
IID_IRowsetInfo, cPropSet, rgPropSet, &pTableID,
(IUnknown**)&pIRowsetInfo), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
CHECK(CreateAndCheckTable(m_pITableDefinition, NULL, NULL,
cColumnDesc, rgColumnDesc, IID_IRowsetInfo,
cPropSet, rgPropSet, &pTableID,
(IUnknown**)&pIRowsetInfo), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
// error should be returned
CHECK(m_hr = m_pITableDefinition->CreateTable(NULL, NULL, cColumnDesc, rgColumnDesc,
IID_IRowsetInfo, cPropSet, rgPropSet, &pTableID,
(IUnknown**)&pIRowsetInfo), S_OK);
break;
default:
TESTC(FALSE);
}
if (DBPROPVAL_TC_DDL_COMMIT != vSupportedTxnDDL.lVal)
{
fCommitPreserve = GetProperty(DBPROP_COMMITPRESERVE, DBPROPSET_ROWSET, pIRowsetInfo, VARIANT_TRUE);
// commit non retaining
CHECK(m_hr = pITransactionLocal->Commit(FALSE, 0, 0), S_OK);
// check that it is retaining (another transaction is available)
CHECK(pITransactionLocal->Abort(NULL, FALSE, FALSE),
FAILED(m_hr)? S_OK: XACT_E_NOTRANSACTION);
}
// abort retaining and check that the table doesn't exist anymore
CHECK(m_hr = m_pTable->DoesTableExist(pTableID, &fExists), S_OK);
COMPARE(fExists, DBPROPVAL_TC_DML != vSupportedTxnDDL.lVal);
if (fExists)
{
CHECK(DropTableAndCheck(pTableID), S_OK);
goto CLEANUP;
}
// test zombie rowset
TESTC_(pIRowsetInfo->GetProperties(0, NULL, &cReadPropSet, &rgReadPropSet), fCommitPreserve? S_OK: E_UNEXPECTED);
CLEANUP:
SAFE_RELEASE(pITransactionLocal);
SAFE_RELEASE(pIRowsetInfo);
DropTableAndCheck(pTableID);
ReleaseDBID(pTableID);
FreeProperties( &cPropSet, &rgPropSet);
FreeProperties(&cReadPropSet, &rgReadPropSet);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(45)
//*-----------------------------------------------------------------------
// @mfunc Autoincrementable columns
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_45()
{
TBEGIN
DBORDINAL i;
HRESULT resA, resB;
CCol col;
BOOL fReadWriteAutoInc;
HRESULT hr;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
ULONG cPropSet, cProp;
fReadWriteAutoInc = (GetPropInfoFlags(DBPROP_COL_AUTOINCREMENT, DBPROPSET_COLUMN,
m_pThisTestModule->m_pIUnknown, DATASOURCE_INTERFACE) & DBPROPFLAGS_WRITE);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
//SetZeroColSize(rgColumnDesc, cColumnDesc);
// try all data types
for (i=0; i<cColumnDesc; i++)
{
odtLog << "Type " << GetColumnTypeName(&rgColumnDesc[i]) << "\n";
// try to create a table in which column rgColumnDesc[i].pwszTypeName is:
// a) autoincrementable
// b) not autoincrementable
col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
resA = col.CanAutoInc()? S_OK: DB_E_ERRORSOCCURRED;
resB = !col.CanAutoInc() || fReadWriteAutoInc? S_OK : DB_E_ERRORSOCCURRED;
// create a table with an autoincrementable column
rgColumnDesc[i].bScale = 0;
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets, DBPROP_COL_AUTOINCREMENT,
VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED, DB_NULLID,
DBPROPSET_COLUMN, &cPropSet, &cProp);
CHECK(hr = CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset,
0, NULL), resA);
if (S_OK == hr)
{
COMPARE(rgColumnDesc[i].rgPropertySets[cPropSet].rgProperties[cProp].dwStatus, DBPROPSTATUS_OK);
}
else
{
CHECK(hr, DB_E_ERRORSOCCURRED);
if (!fReadWriteAutoInc && !col.CanAutoInc())
COMPARE(rgColumnDesc[i].rgPropertySets[0].rgProperties[0].dwStatus, DBPROPSTATUS_NOTSETTABLE);
}
odtLog << ((hr == S_OK) ? "\tcolumn added for DBPROPCOL_AUTOINCREMENT set to VARIANT_TRUE\n":
"\tcolumn NOT added for DBPROPCOL_AUTOINCREMENT set to VARIANT_TRUE\n");
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
// create a table with a column property value to VARIANT_FALSE for DBPROP_COL_AUTOINCREMENT
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets, DBPROP_COL_AUTOINCREMENT,
VT_BOOL, (LPVOID)VARIANT_FALSE, DBPROPOPTIONS_REQUIRED, DB_NULLID,
DBPROPSET_COLUMN, &cPropSet, &cProp);
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), resB);
odtLog << ((S_OK == hr) ? "\tcolumn added for DBPROPCOL_AUTOINCREMENT set to VARIANT_FALSE\n":
"\tcolumn NOT added for DBPROPCOL_AUTOINCREMENT set to VARIANT_FALSE\n");
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(46)
//*-----------------------------------------------------------------------
// @mfunc Default values
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_46()
{
TBEGIN
DBORDINAL i;
CCol col;
VARIANT value;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CTable *pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CList<WCHAR *,WCHAR *> NativeTypesList;
CList<DBTYPE,DBTYPE> ProviderTypesList;
BOOL fSettable = TRUE;
BOOL fSupported = TRUE;
HRESULT hr;
ULONG cPropSet, cProp;
if (!SupportedProperty(DBPROP_COL_DEFAULT, DBPROPSET_COLUMN))
{
fSettable = FALSE;
fSupported = FALSE;
}
else
if (!SettableProperty(DBPROP_COL_DEFAULT, DBPROPSET_COLUMN))
fSettable = FALSE;
pTable->CreateTypeColInfo(NativeTypesList, ProviderTypesList);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
for (i=0; i<cColumnDesc; i++)
{
odtLog << "Type " << GetColumnTypeName(&rgColumnDesc[i]) << "\n";
// try to create a table in which column rgColumnDesc[i].pwszTypeName has a default value
col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
// create a table with a default value column
VariantInit(&value);
GetDefaultValue(&rgColumnDesc[i], &value, pTable);
SetDefaultProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets,
&value, DBPROPOPTIONS_REQUIRED, DB_NULLID, DBPROPSET_COLUMN, &cPropSet, &cProp); // might be not supported
VariantClear(&value);
hr = CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL);
if (S_OK == hr)
{
COMPARE(rgColumnDesc[i].rgPropertySets[0].rgProperties[0].dwStatus, DBPROPSTATUS_OK);
}
else
{
odtLog << "Failed on creating a table with a DBPROP_COL_DEFAULT property value set for this type.\n";
CHECK(hr, DB_E_ERRORSOCCURRED);
if (!fSupported)
{
COMPARE(rgColumnDesc[i].rgPropertySets[cPropSet].rgProperties[cProp].dwStatus, DBPROPSTATUS_NOTSUPPORTED);
}
else
if (!fSettable)
{
COMPARE(rgColumnDesc[i].rgPropertySets[cPropSet].rgProperties[cProp].dwStatus, DBPROPSTATUS_BADVALUE);
}
else
COMPARE(rgColumnDesc[i].rgPropertySets[cPropSet].rgProperties[cProp].dwStatus, DBPROPSTATUS_BADVALUE);
}
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
delete pTable;
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(47)
//*-----------------------------------------------------------------------
// @mfunc Column descriptions
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_47()
{
TBEGIN
DBORDINAL i;
CCol col;
HRESULT hr;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
//SetZeroColSize(rgColumnDesc, cColumnDesc);
for (i=0; i<cColumnDesc; i++)
{
odtLog << "Type " << GetColumnTypeName(&rgColumnDesc[i]) << "\n";
// try to create a table in which column rgColumnDesc[i].pwszTypeName has a description
col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
// create a table with a described column
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets, DBPROP_COL_DESCRIPTION,
VT_BSTR, (LPVOID)L"description");
hr = CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL);
if (S_OK != hr && !CHECK(hr, DB_S_ERRORSOCCURRED))
{
odtLog << "Could not create a table with DBPROP_COL_DESCRIPTION property value set for this type.\n";
}
else
{
if (DB_S_ERRORSOCCURRED == hr)
odtLog << "DB_S_ERRORSOCCURRED\n";
}
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(48)
//*-----------------------------------------------------------------------
// @mfunc Variable length columns
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_48()
{
TBEGIN
DBORDINAL i;
VARIANT value;
CCol col;
HRESULT hr;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
value.vt = VT_BOOL;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
//SetZeroColSize(rgColumnDesc, cColumnDesc);
for (i=0; i<cColumnDesc; i++)
{
if ( DBTYPE_STR != rgColumnDesc[i].wType
&& DBTYPE_WSTR != rgColumnDesc[i].wType
&& DBTYPE_BYTES != rgColumnDesc[i].wType)
continue;
odtLog << "Type " << rgColumnDesc[i].pwszTypeName << "\n";
// try to create a table in which column rgColumnDesc[i].pwszTypeName is:
// a) fixed length
// b) variable length
col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
// create a table with an fixed length column
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets, DBPROP_COL_FIXEDLENGTH,
VT_BOOL, (LPVOID)VARIANT_TRUE);
odtLog << "\ttry to create a table with a fixed length column of type "
<< rgColumnDesc[i].pwszTypeName << "\n";
hr = CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL);
if (S_OK != hr && !CHECK(hr, DB_S_ERRORSOCCURRED))
{
odtLog << "\t\tProblems in creating a table with DBPROP_COL_FIXEDLENGTH property value set to VARIANT_TRUE for this column.\n";
}
FreeProperties( &rgColumnDesc[i].cPropertySets, &rgColumnDesc[i].rgPropertySets);
// create a table with a column property value set to VARIANT_FALSE for DBPROP_COL_FIXEDLENGTH
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets, DBPROP_COL_FIXEDLENGTH,
VT_BOOL, (LPVOID)VARIANT_FALSE);
odtLog << "\ttry to create a table with a variable length column of type "
<< rgColumnDesc[i].pwszTypeName << "\n";
hr = CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL);
if (S_OK != hr && !CHECK(hr, DB_S_ERRORSOCCURRED))
{
odtLog << "\t\tCould not create a table with DBPROP_COL_FIXEDLENGTH property value set to VARIANT_FALSE for this column.\n";
}
FreeProperties( &rgColumnDesc[i].cPropertySets, &rgColumnDesc[i].rgPropertySets);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(49)
//*-----------------------------------------------------------------------
// @mfunc Nullable/non nullable columns
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_49()
{
BOOL fTestRes = TEST_PASS;
DBORDINAL i;
CCol col;
VARIANT defval;
HRESULT hr;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CTable *pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CList<WCHAR *,WCHAR *> NativeTypesList;
CList<DBTYPE,DBTYPE> ProviderTypesList;
HRESULT hExpRes = S_OK;
BOOL fSettable = TRUE;
BOOL fSupported = TRUE;
DBPROP *pPropDefault = NULL;
DBPROPSTATUS ulStatus;
ULONG cPropSet, cProp;
if (!SupportedProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN))
{
hExpRes = DB_S_ERRORSOCCURRED;
fSettable = FALSE;
fSupported = FALSE;
}
else
if (!SettableProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN))
fSettable = FALSE;
pTable->CreateTypeColInfo(NativeTypesList, ProviderTypesList);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
//SetZeroColSize(rgColumnDesc, cColumnDesc);
for (i=0; i<cColumnDesc; i++)
{
odtLog << "Type " << GetColumnTypeName(&rgColumnDesc[i]);
// try to create a table in which column i is:
// a) nullable
// b) not nullable
col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
switch (col.GetNullable())
{
case 0:
odtLog << " (not nullable)\n";
break;
case 1:
odtLog << " (NULLable)\n";
break;
default:
odtLog << "\n";
}
// create a table with a nullable column
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets, DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED, DB_NULLID, DBPROPSET_COLUMN,
&cPropSet, &cProp);
odtLog << "\tcreate table with a nullable column: ";
// create a table with a column property value set to VARIANT_TRUE for DBPROP_COL_NULLABLE
hr = CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL);
ulStatus = rgColumnDesc[i].rgPropertySets[cPropSet].rgProperties[cProp].dwStatus;
if ( (S_OK == hr && !COMPARE(ulStatus, DBPROPSTATUS_OK))
|| (!fSupported && !COMPARE(ulStatus, DBPROPSTATUS_NOTSUPPORTED))
|| (S_OK != hr && fSettable && !COMPARE(ulStatus, DBPROPSTATUS_BADVALUE))
|| (S_OK != hr && !fSettable && !COMPARE(ulStatus, DBPROPSTATUS_NOTSETTABLE))
|| (!fSupported && !CHECK(hr, DB_E_ERRORSOCCURRED))
|| (S_OK != hr && !CHECK(hr, DB_E_ERRORSOCCURRED)))
fTestRes = TEST_FAIL;
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
switch (col.GetNullable())
{
case 0:
if (!CHECK(hr, DB_E_ERRORSOCCURRED))
fTestRes = TEST_FAIL;
break;
case 1:
if (!CHECK(hr, S_OK))
fTestRes = TEST_FAIL;
break;
case -1:
if (S_OK != hr && !CHECK(hr, DB_E_ERRORSOCCURRED))
fTestRes = TEST_FAIL;
break;
default:
ASSERT(FALSE);
break;
}
odtLog << ((SUCCEEDED(hr)) ? "CREATED\n" : "INSUCCESS\n");
// create a table with a column property value set to VARIANT_FALSE for DBPROP_COL_NULLABLE
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets, DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE, DBPROPOPTIONS_REQUIRED, DB_NULLID, DBPROPSET_COLUMN,
&cPropSet, &cProp);
if (SettableProperty(DBPROP_COL_DEFAULT, DBPROPSET_COLUMN))
{
VariantInit(&defval);
GetDefaultValue(&rgColumnDesc[i], &defval, pTable);
if (SettableProperty(DBPROP_COL_DEFAULT, DBPROPSET_COLUMN))
SetDefaultProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets,
&defval, DBPROPOPTIONS_REQUIRED); // might be not supported
VariantClear(&defval);
}
odtLog << "\tcreate table with a not nullable column\n";
hr = CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL);
ulStatus = rgColumnDesc[i].rgPropertySets[cPropSet].rgProperties[cProp].dwStatus;
FindProperty(
DBPROP_COL_DEFAULT,
DBPROPSET_COLUMN,
rgColumnDesc[i].cPropertySets,
rgColumnDesc[i].rgPropertySets,
&pPropDefault
);
if ( (!pPropDefault || DBPROPSTATUS_OK == pPropDefault->dwStatus)
&& ( (S_OK == hr && !COMPARE(ulStatus, DBPROPSTATUS_OK))
|| (!fSupported && !COMPARE(ulStatus, DBPROPSTATUS_NOTSUPPORTED))
|| (S_OK != hr && fSettable && !COMPARE(ulStatus, DBPROPSTATUS_BADVALUE))
|| (S_OK != hr && !fSettable && !COMPARE(ulStatus, DBPROPSTATUS_NOTSETTABLE))
|| (!fSupported && !CHECK(hr, DB_E_ERRORSOCCURRED))
|| (S_OK != hr && !CHECK(hr, DB_E_ERRORSOCCURRED))))
fTestRes = TEST_FAIL;
if (FAILED(hr))
odtLog << "Could not create a table with DBPROP_COL_NULLABLE property value set to VARIANT_FALSE.\n";
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
delete pTable;
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(50)
//*-----------------------------------------------------------------------
// @mfunc Primary key column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_50()
{
TBEGIN
DBORDINAL i;
CCol col;
HRESULT hr;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
HRESULT hExpRes = S_OK;
if (!SupportedProperty(DBPROP_COL_DEFAULT, DBPROPSET_COLUMN))
hExpRes = DB_S_ERRORSOCCURRED;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// this is to prevent SQL Server limiting the size of
// the index it creates for primary key or unique columns
SetZeroColSize(rgColumnDesc, cColumnDesc);
for (i=0; i<cColumnDesc; i++)
{
odtLog << "Type " << GetColumnTypeName(&rgColumnDesc[i]) << "\n";
// try to create a table in which column _rgColumnDesc[i].pwszTypeName is:
// a) primary key
// b) not primary key
col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
// create a table with an primary key column
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets, DBPROP_COL_PRIMARYKEY,
VT_BOOL, (LPVOID)VARIANT_FALSE, DBPROPOPTIONS_OPTIONAL);
if (S_OK != (hr = CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL)))
{
CHECK(hr, DB_S_ERRORSOCCURRED);
}
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
// create a table with a column property value set to VARIANT_FALSE for DBPROP_COL_PRIMARYKEY
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets, DBPROP_COL_PRIMARYKEY,
VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL);
if (1 != col.GetNullable())
hExpRes = DB_S_ERRORSOCCURRED;
if (S_OK != (hr = CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL)))
{
CHECK(hr, DB_S_ERRORSOCCURRED);
}
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(51)
//*-----------------------------------------------------------------------
// @mfunc Unique columns
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_51()
{
TBEGIN
DBORDINAL i;
CCol col;
HRESULT hr;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
BOOL fSupported = FALSE;
fSupported = SupportedProperty(DBPROP_COL_DEFAULT, DBPROPSET_COLUMN);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// this is to prevent SQL Server limiting the size of
// the index it creates for primary key or unique columns
SetZeroColSize(rgColumnDesc, cColumnDesc);
for (i=0; i<cColumnDesc; i++)
{
odtLog << "Type " << GetColumnTypeName(&rgColumnDesc[i]) << "\n";
// try to create a table in which column rgColumnDesc[i].pwszTypeName is:
// a) unique
// b) non-unique
// there is no info whether a type can or cannot be unique
col = GetType(GetColumnTypeName(&rgColumnDesc[i]), rgColumnDesc[i].wType);
// create a table with an unique column
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets, DBPROP_COL_UNIQUE,
VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
hr = CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL);
if (S_OK != hr)
{
odtLog << "Could not create a table with DBPROP_COL_UNIQUE property value set to VARIANT_TRUE for this column.\n";
CHECK(hr, DB_E_ERRORSOCCURRED);
}
else
{
COMPARE(fSupported, TRUE);
}
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
// create a table with a column property value set to VARIANT_FALSE for DBPROP_COL_UNIQUE
SetProperty(&rgColumnDesc[i].rgPropertySets, &rgColumnDesc[i].cPropertySets, DBPROP_COL_UNIQUE,
VT_BOOL, (LPVOID)VARIANT_FALSE, DBPROPOPTIONS_OPTIONAL);
hr = CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL);
if (S_OK != hr)
{
odtLog << "Could not create a table with DBPROP_COL_UNIQUE property value set to VARIANT_FALSE for this column.\n";
CHECK(hr, DB_S_ERRORSOCCURRED);
}
else
{
COMPARE(fSupported, TRUE);
}
ReleaseAllColumnPropSets(&rgColumnDesc[i], 1);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(52)
//*-----------------------------------------------------------------------
// @mfunc Test conflicting properties
// a column that is both nullable and primary key
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_52()
{
TBEGIN
CCol col;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
TESTC_PROVIDER(SettableProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN)
&& SettableProperty(DBPROP_COL_PRIMARYKEY, DBPROPSET_COLUMN));
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
//SetZeroColSize(rgColumnDesc, cColumnDesc);
// create a table with a column showing contradiction in properties
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets, DBPROP_COL_PRIMARYKEY,
VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets, DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), DB_E_ERRORSOCCURRED);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(53)
//*-----------------------------------------------------------------------
// @mfunc Create a table and ask for a rowset, setting DBPROP_ABORTPRESERVE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_53()
{
TBEGIN
DBPROPSET *rgPropertySets = NULL;
ULONG cPropertySets = 0;
CCol col;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
//SetZeroColSize(rgColumnDesc, cColumnDesc);
TESTC_PROVIDER(SupportedProperty(DBPROP_ABORTPRESERVE, DBPROPSET_ROWSET)
&& SettableProperty(DBPROP_ABORTPRESERVE, DBPROPSET_ROWSET));
SetProperty(&rgPropertySets, &cPropertySets, DBPROP_ABORTPRESERVE,
VT_BOOL, (LPVOID)VARIANT_TRUE, DBPROPOPTIONS_REQUIRED, DB_NULLID, DBPROPSET_ROWSET);
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowsetInfo,
cPropertySets, rgPropertySets), S_OK);
CLEANUP:
FreeProperties( &cPropertySets, &rgPropertySets);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(54)
//*-----------------------------------------------------------------------
// @mfunc Inserting rows after table creation, using the resulting rowset
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_54()
{
IRowsetChange *pIRowsetChange = NULL;
BOOL fTestRes = TEST_FAIL;
BOOL fMayWrite;
DBORDINAL i;
const ULONG nRows = 10;
DBID *pTableID = NULL;
ULONG cPropSets = 0;
DBPROPSET *rgPropSets = NULL;
LONG lUpdateInsert = DBPROPVAL_UP_INSERT;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CList <WCHAR*, WCHAR*> ListNativeTemp;
CList <DBTYPE, DBTYPE> ListDataTypes;
CTable *pTable = NULL;
pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
// get the provider types list
pTable->CreateColInfo(ListNativeTemp, ListDataTypes, ALLTYPES);
// build the column description array
pTable->BuildColumnDescs(&rgColumnDesc);
cColumnDesc = pTable->CountColumnsOnTable();
pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
//Need to set DBPROP_UPDATABILITY: InsertRow is supported
if ( !SupportedProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET)
|| !SettableProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET))
{
fTestRes = TEST_SKIPPED;
goto CLEANUP;
}
//Need to set DBPROP_UPDATABILITY: InsertRow is supported
if ( !SupportedProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET)
|| !SettableProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET))
{
fTestRes = TEST_SKIPPED;
goto CLEANUP;
}
::SetProperty( DBPROP_UPDATABILITY, DBPROPSET_ROWSET, &cPropSets, &rgPropSets,
DBTYPE_I4, (LPVOID)&lUpdateInsert);
TESTC_(CreateAndCheckTable(m_pITableDefinition, NULL, NULL, cColumnDesc, rgColumnDesc, IID_IRowsetChange,
cPropSets, rgPropSets, &pTableID, (IUnknown**)&pIRowsetChange), S_OK);
fTestRes = TEST_PASS;
// find out if one can write to that table
pTable->SetTableID(*pTableID);
pTable->MayWrite(&fMayWrite);
for (i=0; i<nRows; i++)
{
m_hr = Insert(0, pIRowsetChange, 0, NULL, pTable);
if (DB_E_NOTSUPPORTED != m_hr)
{
if (!CHECK(m_hr, S_OK))
fTestRes = TEST_FAIL;
}
else
fTestRes = TEST_SKIPPED;
}
CLEANUP:
SAFE_RELEASE(pIRowsetChange);
if (pTableID)
CHECK(DropTableAndCheck(pTableID), S_OK);
ReleaseDBID(pTableID);
FreeProperties( &cPropSets, &rgPropSets);
delete pTable;
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(55)
//*-----------------------------------------------------------------------
// @mfunc Delete rows in the created rowset
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_55()
{
IRowsetChange *pIRowsetChange = NULL;
IRowset *pIRowset = NULL;
BOOL fTestRes = TEST_FAIL;
ULONG i, nSuccess;
const ULONG nRows = 10;
const int nProps = 3;
DBPROPSET rgPropSets[1];
DBPROP rgProperties[nProps];
HROW *rghRow = NULL;
DBCOUNTITEM cRowsObtained = 0;
DBROWSTATUS rgRowStatus[nRows];
DBID *pTableID = NULL;
BOOL fMayWrite;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CList <WCHAR*, WCHAR*> ListNativeTemp;
CList <DBTYPE, DBTYPE> ListDataTypes;
CTable *pTable = NULL;
pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
// get the provider types list
pTable->CreateColInfo(ListNativeTemp, ListDataTypes, ALLTYPES);
// build the column description array
pTable->BuildColumnDescs(&rgColumnDesc);
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc=pTable->CountColumnsOnTable());
pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
FILL_PROP_SET(rgPropSets[0], NUMELEM(rgProperties), rgProperties, DBPROPSET_ROWSET)
FILL_PROP(rgProperties[0], DBPROP_IRowsetChange, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL)
FILL_PROP(rgProperties[1], DBPROP_OWNINSERT, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED)
FILL_PROP(rgProperties[2], DBPROP_OWNUPDATEDELETE, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL)
TESTC_(CreateAndCheckTable(m_pITableDefinition, NULL, NULL, cColumnDesc, rgColumnDesc, IID_IRowsetChange,
NUMELEM(rgPropSets), rgPropSets, &pTableID, (IUnknown**)&pIRowsetChange), S_OK);
pTable->SetTableID(*pTableID);
pTable->MayWrite(&fMayWrite);
for (i=0; i<nRows; i++)
{
m_hr = Insert(0, pIRowsetChange, 0, NULL, pTable);
if (DB_E_NOTSUPPORTED == m_hr)
{
odtLog << "IRowsetChange->Insert() is not supported\n";
fTestRes = TEST_SKIPPED;
goto CLEANUP;
}
else
TESTC_(m_hr, S_OK);
}
// get a pointer to IRoewset interface
if (!VerifyInterface(pIRowsetChange, IID_IRowset, ROWSET_INTERFACE, (IUnknown**)&pIRowset))
{
odtLog << "could not get IRowsetChange\n";
goto CLEANUP;
}
m_hr = pIRowset->RestartPosition(NULL);
if (!CHECK(m_hr = pIRowset->GetNextRows(
0, 0, // hChapter & lRowsOffset
nRows, // number of rows to be retrieved
&cRowsObtained, //number of rows actually get
&rghRow // array of handlers to rows
), S_OK) || nRows != cRowsObtained)
{
odtLog << "insuccess on IRowset::GetNextRows\n";
goto CLEANUP;
}
TESTC_(m_hr = pIRowsetChange->DeleteRows(0, cRowsObtained, rghRow, rgRowStatus), S_OK);
for (i=nSuccess=0; i<nRows; i++)
if (DBROWSTATUS_S_OK == rgRowStatus[i])
nSuccess ++;
if (nSuccess != nRows)
odtLog << "delete succeeded for " << nRows-nSuccess << " rows out of " << nRows << "\n";
else
fTestRes = TEST_PASS;
CLEANUP:
if (cRowsObtained)
CHECK(m_hr = pIRowset->ReleaseRows(cRowsObtained, rghRow, NULL, NULL, NULL), S_OK);
PROVIDER_FREE(rghRow);
SAFE_RELEASE(pIRowsetChange);
SAFE_RELEASE(pIRowset);
if (pTableID)
{
CHECK(DropTableAndCheck(pTableID), S_OK);
ReleaseDBID(pTableID);
}
delete pTable;
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(56)
//*-----------------------------------------------------------------------
// @mfunc Aggregation, ask for IID_IUnknown
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_56()
{
TBEGIN
HRESULT hr;
DBID *pTableID = NULL;
CAggregate Aggregate(m_pIOpenRowset);
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
TEST2C_(hr = CreateAndCheckTable(m_pITableDefinition, &Aggregate, NULL, cColumnDesc, rgColumnDesc,
IID_IUnknown, 0, NULL, &pTableID, (IUnknown**)&Aggregate.m_pIUnkInner),
S_OK, DB_E_NOAGGREGATION);
TESTC_PROVIDER(S_OK == hr);
// Verify Aggregation for this rowset...
TESTC(Aggregate.VerifyAggregationQI(hr, IID_IRowset));
CLEANUP:
Aggregate.ReleaseInner();
// checkings, etc
CHECK(DropTableAndCheck(pTableID), pTableID? S_OK: E_INVALIDARG);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(57)
//*-----------------------------------------------------------------------
// @mfunc Create a table and ask for a rowset, setting DBPROP_COMMITPRESERVE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_57()
{
TBEGIN
DBPROPID rgPropID=DBPROP_COMMITPRESERVE;
COMPARE(CreateWithOneRowsetProps(rgPropID, VT_BOOL, (LPVOID)VARIANT_TRUE,
(struct _GUID*)&IID_IRowsetInfo), TRUE);
TESTC(CreateWithOneRowsetProps(rgPropID, VT_BOOL, (LPVOID)VARIANT_FALSE,
(struct _GUID*)&IID_IRowsetInfo));
CLEANUP:
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(58)
//*-----------------------------------------------------------------------
// @mfunc Create a table and ask for a rowset, setting DBPROP_OWNINSERT
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_58()
{
TBEGIN
DBPROPID rgPropID=DBPROP_OWNINSERT;
COMPARE(CreateWithOneRowsetProps(rgPropID, VT_BOOL, (LPVOID)VARIANT_TRUE,
(struct _GUID*)&IID_IRowsetInfo), TRUE);
TESTC(CreateWithOneRowsetProps(rgPropID, VT_BOOL, (LPVOID)VARIANT_FALSE,
(struct _GUID*)&IID_IRowsetInfo));
CLEANUP:
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(59)
//*-----------------------------------------------------------------------
// @mfunc Create a table and ask for a rowset, setting DBPROP_BOOKMARKS
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_59()
{
TBEGIN
DBPROPID rgPropID=DBPROP_BOOKMARKS;
COMPARE(CreateWithOneRowsetProps(rgPropID, VT_BOOL, (LPVOID)VARIANT_TRUE,
(struct _GUID*)&IID_IRowsetInfo), TRUE);
TESTC(CreateWithOneRowsetProps(rgPropID, VT_BOOL, (LPVOID)VARIANT_FALSE,
(struct _GUID*)&IID_IRowsetInfo));
CLEANUP:
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(60)
//*-----------------------------------------------------------------------
// @mfunc Create a table and ask for a rowset, setting DBPROP_CANHOLDROWS
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_60()
{
TBEGIN
DBPROPID rgPropID=DBPROP_CANHOLDROWS;
COMPARE(CreateWithOneRowsetProps(rgPropID, VT_BOOL, (LPVOID)VARIANT_TRUE,
(struct _GUID*)&IID_IRowsetInfo), TRUE);
TESTC(CreateWithOneRowsetProps(rgPropID, VT_BOOL, (LPVOID)VARIANT_FALSE,
(struct _GUID*)&IID_IRowsetInfo));
CLEANUP:
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(61)
//*-----------------------------------------------------------------------
// @mfunc Create a table and ask for a rowset, setting DBPROP_MAYWRITECOLUMN
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_61()
{
TBEGIN
DBPROPID rgPropID=DBPROP_MAYWRITECOLUMN;
COMPARE(CreateWithOneRowsetProps(rgPropID, VT_BOOL, (LPVOID)VARIANT_TRUE,
(struct _GUID*)&IID_IRowsetInfo), TRUE);
TESTC(CreateWithOneRowsetProps(rgPropID, VT_BOOL, (LPVOID)VARIANT_FALSE,
(struct _GUID*)&IID_IRowsetInfo));
CLEANUP:
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(62)
//*-----------------------------------------------------------------------
// @mfunc Ask for a rowset mandatory/optional interface when table creation => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_62()
{
BOOL fTestRes = TEST_FAIL;
IUnknown *pIRowset = NULL;
DBID *pTableID = NULL;
BOOL fMayWrite;
HRESULT hr;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CList <WCHAR*, WCHAR*> ListNativeTemp;
CList <DBTYPE, DBTYPE> ListDataTypes;
CTable *pTable = NULL;
pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
// get the provider types list
pTable->CreateColInfo(ListNativeTemp, ListDataTypes, ALLTYPES);
// build the column description array
pTable->BuildColumnDescs(&rgColumnDesc);
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc=pTable->CountColumnsOnTable());
pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
odtLog << "CreateTable and ask for a pointer to IRowset (mandatory)\n";
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset,
0, NULL), S_OK);
odtLog << "CreateTable and ask for a pointer to IRowsetChange (optional)\n";
CHECK(hr = CreateAndCheckTable(m_pITableDefinition, NULL, NULL, cColumnDesc, rgColumnDesc,
IID_IRowsetChange, 0, NULL, &pTableID, (IUnknown**)&pIRowset), S_OK);
// try to use the IRowsetChange interface to insert a row
if (SUCCEEDED(hr))
{
pTable->SetTableID(*pTableID);
pTable->MayWrite(&fMayWrite);
m_hr = Insert(0, (IRowsetChange*)pIRowset, 0, NULL, pTable);
if (DB_E_NOTSUPPORTED != m_hr)
{
TESTC_(m_hr, S_OK);
}
else
{
fTestRes = TEST_SKIPPED;
goto CLEANUP;
}
}
fTestRes = TEST_PASS;
CLEANUP:
// checkings, etc
SAFE_RELEASE(pIRowset);
if (pTableID)
{
CHECK(DropTableAndCheck(pTableID), S_OK);
ReleaseDBID(pTableID);
}
delete pTable;
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
unsigned TCCreateTable::MyThreadProc(ULONG i)
{
DBCOLUMNDESC *rgColumnDesc = NULL;
DBID TableID;
DBID *pTableID = NULL;
HRESULT hr;
if (i>= nThreads)
return 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
ReleaseAllColumnPropSets(rgColumnDesc, m_cColumnDesc);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_rgName[i];
Sleep(0); // switch the context
hr = m_pITableDefinition->CreateTable(NULL, m_rgName[i]? &TableID: NULL,
m_cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL,
m_rgName[i] ? NULL: &pTableID, NULL);
Sleep(0); // switch the context
m_rgResult[i] = hr;
if (!m_rgName[i] && pTableID && DBKIND_NAME == pTableID->eKind)
{
m_rgName[i] = pTableID->uName.pwszName;
SAFE_FREE(pTableID);
}
else
ReleaseDBID(pTableID);
ReleaseColumnDesc(rgColumnDesc, m_cColumnDesc);
return 1;
} //TCCreateTable::MyThreadProc
// {{ TCW_VAR_PROTOTYPE(63)
//*-----------------------------------------------------------------------
// @mfunc threads on different tables
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_63()
{
TBEGIN
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
ULONG i;
WCHAR number[3];
LPWSTR pwszBaseName = NULL;
DBID TableID;
odtLog << "All table names are generated by user\n";
m_pTable->MakeTableName(NULL);
pwszBaseName = m_pTable->GetTableName();
for (i=0; i< nThreads; i++)
{
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
m_rgResult[i] = E_FAIL;
m_rgName[i] = (WCHAR*)PROVIDER_ALLOC((3+wcslen(pwszBaseName))*sizeof(WCHAR));
ASSERT(m_rgName[i]);
wcscpy(m_rgName[i], pwszBaseName);
swprintf(number, L"%02d", i);
wcscat(m_rgName[i], number);
}
for (i=0; i<nThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(nThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< nThreads; i++)
CloseHandle(hrgThread[i]);
TableID.eKind = DBKIND_NAME;
for (i=0; i<nThreads; i++)
{
if (CHECK(m_rgResult[i], S_OK))
{
TableID.uName.pwszName = m_rgName[i];
CHECK(DropTableAndCheck(&TableID), S_OK);
}
}
odtLog << "All table names are provider generated\n";
for (i=0; i< nThreads; i++)
{
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
m_rgResult[i] = E_FAIL;
m_rgName[i] = NULL;
}
for (i=0; i<nThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(nThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< nThreads; i++)
CloseHandle(hrgThread[i]);
for (i=0; i<nThreads; i++)
CHECK(m_rgResult[i], S_OK);
CLEANUP:
TableID.eKind = DBKIND_NAME;
for (i=0; i<nThreads; i++)
{
TableID.uName.pwszName = m_rgName[i];
if (SUCCEEDED(m_rgResult[i]))
CHECK(DropTableAndCheck(&TableID), S_OK);
PROVIDER_FREE(m_rgName[i]);
}
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(64)
//*-----------------------------------------------------------------------
// @mfunc threads on the same table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_64()
{
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
BOOL fTestResult = TEST_FAIL;
ULONG i, nS_OK, nDB_E_DUPLICATETABLEID;
LPWSTR pwszBaseName = NULL;
DBID TableID;
m_pTable->MakeTableName(NULL);
pwszBaseName = m_pTable->GetTableName();
for (i=0; i< nThreads; i++)
{
m_rgResult[i] = E_FAIL;
m_rgName[i] = pwszBaseName;
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
}
// creates a table, build rgColumnDesc by it
for (i=0; i<nThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(nThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< nThreads; i++)
CloseHandle(hrgThread[i]);
for (i=nS_OK=nDB_E_DUPLICATETABLEID=0; i<nThreads; i++)
{
if (m_rgResult[i] == S_OK)
nS_OK++;
else if (CHECK(m_rgResult[i], DB_E_DUPLICATETABLEID))
nDB_E_DUPLICATETABLEID++;
else
{
odtLog << "Thread " << i << ": unexpected result " << m_rgResult[i] << "\n";
goto CLEANUP;
}
}
TESTC(nS_OK == 1 && nDB_E_DUPLICATETABLEID == nThreads-1);
fTestResult = TEST_PASS;
CLEANUP:
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = pwszBaseName;
CHECK(DropTableAndCheck(&TableID), S_OK);
return fTestResult;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(65)
//*-----------------------------------------------------------------------
// @mfunc try all interfaces on rowset that can be returned
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_65()
{
TBEGIN
const ULONG nInterfaces = 19; // number of total interfaces
const ULONG nMandatoryInterfaces = 6; // the number of mandatory interfaces
const IID* rgRIIDInterfaces[nInterfaces] = {&IID_IUnknown, &IID_IAccessor, &IID_IColumnsInfo,
&IID_IConvertType, &IID_IRowset, &IID_IRowsetInfo, &IID_IChapteredRowset,
&IID_IColumnsRowset, &IID_IConnectionPointContainer, &IID_IDBAsynchStatus,
&IID_IRowsetChange, &IID_IRowsetFind, &IID_IRowsetIdentity, &IID_IRowsetLocate,
&IID_IRowsetResynch, &IID_IRowsetScroll, &IID_IRowsetUpdate, &IID_IRowsetView,
&IID_ISupportErrorInfo};
LPWSTR rgInterfaceNames[nInterfaces] = {L"IUnknown", L"IAccessor", L"IColumnsInfo",
L"IConvertType", L"IRowset", L"IRowsetInfo", L"IChapteredRowset",
L"IColumnsRowset", L"IConnectionPointContainer", L"IDBAsynchStatus",
L"IRowsetChange", L"IRowsetFind", L"IRowsetIdentity", L"IRowsetLocate",
L"IRowsetResynch", L"IRowsetScroll", L"IRowsetUpdate", L"IRowsetView",
L"ISupportErrorInfo"};
const DBPROPID rgInterfaceID[nInterfaces-1] = {DBPROP_IAccessor, DBPROP_IColumnsInfo,
DBPROP_IConvertType, DBPROP_IRowset, DBPROP_IRowsetInfo, DBPROP_IChapteredRowset,
DBPROP_IColumnsRowset, DBPROP_IConnectionPointContainer, DBPROP_IDBAsynchStatus,
DBPROP_IRowsetChange, DBPROP_IRowsetFind, DBPROP_IRowsetIdentity, DBPROP_IRowsetLocate,
DBPROP_IRowsetResynch, DBPROP_IRowsetScroll, DBPROP_IRowsetUpdate, DBPROP_IRowsetView,
DBPROP_ISupportErrorInfo};
// BOOL fTestRes = TEST_PASS;
ULONG i, j;
IUnknown *pRowset = NULL;
IUnknown *pIUnknown = NULL;
DBPROPSET rgPropertySets[2];
DBPROP rgProperties[nInterfaces-1];
DBPROP rgProp2[1];
DBID *pTableID = NULL;
HRESULT hr;
HRESULT hRes = S_OK;
HRESULT hExpectedRes = S_OK;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
BOOL fRetrieve = true;
BOOL fPropSupported;
FILL_PROP_SET(rgPropertySets[0], NUMELEM(rgProperties), rgProperties, DBPROPSET_ROWSET);
for (i=0; i<nInterfaces-1; i++)
{
FILL_PROP(rgProperties[i], rgInterfaceID[i], VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL);
if (!SupportedProperty(rgInterfaceID[i], DBPROPSET_ROWSET))
hRes = DB_S_ERRORSOCCURRED;
}
FILL_PROP_SET(rgPropertySets[1], NUMELEM(rgProp2), rgProp2, DBPROPSET_ROWSET);
FILL_PROP(rgProp2[0], DBPROP_ISequentialStream, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL);
if (!SupportedProperty(DBPROP_ISequentialStream, DBPROPSET_ROWSET))
hRes = DB_S_ERRORSOCCURRED;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
for (i=0; i<nInterfaces; i++)
{
odtLog << "\t" << rgInterfaceNames[i] << ((i<nMandatoryInterfaces)? "(mandatory)\n" : "\n");
PRVTRACE(L"TCCreateTable::Variation_65(): iteration %d (%s)\n",
i, ((i>0) ? rgInterfaceNames[i] : L"IUnknown"));
fPropSupported = (i>0)? SupportedProperty(rgInterfaceID[i-1], DBPROPSET_ROWSET): TRUE;
hExpectedRes = ((i>0) && !fPropSupported)? E_NOINTERFACE: hRes;
// This interface is only supported if user sets DBPROP_ROWSET_ASYNCH in the
// rowset properties otherwise its unsupported.
if (i>0 && rgInterfaceID[i-1] == DBPROP_IDBAsynchStatus)
{
fPropSupported = FALSE;
hExpectedRes = E_NOINTERFACE;
}
// if the interface is mandatory, it has to be supported
// note that there is not a DBPROP_IUnknown, so the condition is i>nMandatoryInterfaces
COMPARE(i==0 || fPropSupported || i>=nMandatoryInterfaces, TRUE);
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc,
*rgRIIDInterfaces[i], 0, NULL,
FALSE), fPropSupported? S_OK: E_NOINTERFACE);
pRowset = NULL;
CHECK(hr = CreateAndCheckTable(m_pITableDefinition, NULL, NULL, cColumnDesc, rgColumnDesc,
*rgRIIDInterfaces[i], NUMELEM(rgPropertySets), rgPropertySets,
&pTableID, &pRowset), hExpectedRes);
if (S_OK != hr && DB_S_ERRORSOCCURRED != hr)
{
if (i<nMandatoryInterfaces)
{
odtLog << "could not get the mandatory interface " << rgInterfaceNames[i] << "\n";
COMPARE(TRUE, FALSE);
}
}
else
{
// try to get all the other interfaces
if (pRowset)
{
fRetrieve = CHECK(pRowset->QueryInterface(IID_IUnknown,
(void**)&pIUnknown), S_OK) ? fRetrieve: FALSE;
SAFE_RELEASE(pIUnknown);
// all the other interfaces considered
for (j=1; j<nInterfaces; j++)
{
odtLog << "\tTesting: " << rgInterfaceNames[j] << "\n";
if ( (j<nMandatoryInterfaces)
&& ( !COMPARE(rgProperties[j-1].dwStatus, DBPROPSTATUS_OK)
|| !CHECK(pRowset->QueryInterface(*rgRIIDInterfaces[j], (void**)&pIUnknown), S_OK)))
{
odtLog << "Could not retrieve mandatory interface " << rgInterfaceNames[j] << "\n";
continue;
}
SAFE_RELEASE(pIUnknown);
fRetrieve = TRUE;
// the interface should be retrievable if and only if the propstatus is ok
if (DBPROPSTATUS_OK == rgProperties[j-1].dwStatus)
{
fRetrieve = CHECK(pRowset->QueryInterface(*rgRIIDInterfaces[j],
(void**)&pIUnknown), S_OK) ? fRetrieve: FALSE;
SAFE_RELEASE(pIUnknown);
}
else
{
fRetrieve = CHECK(pRowset->QueryInterface(*rgRIIDInterfaces[j],
(void**)&pIUnknown), E_NOINTERFACE) ? fRetrieve: FALSE;
}
// check on prop status
if (SupportedProperty(rgInterfaceID[j-1], DBPROPSET_ROWSET))
{
if (SettableProperty(rgInterfaceID[j-1], DBPROPSET_ROWSET))
fRetrieve = ((DBPROPSTATUS_NOTSET != rgProperties[j-1].dwStatus
&& !COMPARE(rgProperties[j-1].dwStatus, DBPROPSTATUS_OK))) ? FALSE: fRetrieve;
else
fRetrieve = (DBPROPSTATUS_OK != rgProperties[j-1].dwStatus
&& !COMPARE(rgProperties[j-1].dwStatus, DBPROPSTATUS_NOTSETTABLE)) ? FALSE: fRetrieve;
}
else
{
fRetrieve = (!COMPARE(rgProperties[j-1].dwStatus, DBPROPSTATUS_NOTSUPPORTED))? FALSE: fRetrieve;
}
if (!fRetrieve)
{
odtLog << "ERROR: retrieving interface " << rgInterfaceNames[j] << "\n";
}
}
}
}
if (pRowset)
SAFE_RELEASE(pRowset);
if (pTableID)
CHECK(DropTableAndCheck(pTableID), S_OK);
ReleaseDBID(pTableID);
}
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(66)
//*-----------------------------------------------------------------------
// @mfunc create with a table property => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_66()
// just try the creation of a table with the specified property
// there is not any method to retrieve the property of the table
{
TBEGIN
DBPROPSET rgPropSets[1];
DBPROP rgProp[1];
HRESULT hr;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBID TableID;
BOOL fSupported;
BOOL fSettable;
BOOL fValidate;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = NULL;
fSupported = SupportedProperty(DBPROP_TBL_TEMPTABLE, DBPROPSET_TABLE);
fSettable = SettableProperty(DBPROP_TBL_TEMPTABLE, DBPROPSET_TABLE);
fValidate = fSettable || !fSupported;
hr = fSettable? S_OK : DB_E_ERRORSOCCURRED;
odtLog << "Property is REQUIRED\n";
// temp table, TableID generated by provider
odtLog << "\tProvider generated TableID\n";
FILL_PROP_SET(rgPropSets[0], NUMELEM(rgProp), rgProp, DBPROPSET_TABLE);
FILL_PROP(rgProp[0], DBPROP_TBL_TEMPTABLE, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
hr = CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, NUMELEM(rgPropSets), rgPropSets);
if (fValidate && fSettable || S_OK == hr)
{
CHECK(hr, S_OK);
COMPARE(rgProp[0].dwStatus, DBPROPSTATUS_OK);
}
else
{
CHECK(hr, DB_E_ERRORSOCCURRED);
if (fSupported)
{ COMPARE(DBPROPSTATUS_NOTSETTABLE == rgProp[0].dwStatus, TRUE);}
else
{ COMPARE(DBPROPSTATUS_NOTSUPPORTED == rgProp[0].dwStatus, TRUE);}
}
// perm table, TableID generated by provider
FILL_PROP(rgProp[0], DBPROP_TBL_TEMPTABLE, VT_BOOL, V_BOOL, VARIANT_FALSE, DBPROPOPTIONS_REQUIRED);
hr = (S_OK!=hr)? DB_E_ERRORSOCCURRED : S_OK;
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset,
NUMELEM(rgPropSets), rgPropSets), hr);
// temp table, consumer generated TableID
odtLog << "\tConsumer generated TableID\n";
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = wcsDuplicate(m_pTable->GetTableName());
FILL_PROP_SET(rgPropSets[0], NUMELEM(rgProp), rgProp, DBPROPSET_TABLE);
FILL_PROP(rgProp[0], DBPROP_TBL_TEMPTABLE, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
hr = CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset, NUMELEM(rgPropSets), rgPropSets);
// perm table, consumer generated TableID
FILL_PROP(rgProp[0], DBPROP_TBL_TEMPTABLE, VT_BOOL, V_BOOL, VARIANT_FALSE, DBPROPOPTIONS_REQUIRED);
hr = (S_OK!=hr)? DB_E_ERRORSOCCURRED : S_OK;
CHECK(CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset,
NUMELEM(rgPropSets), rgPropSets), hr);
hr = fSettable? S_OK : DB_S_ERRORSOCCURRED;
odtLog << "Property is OPTIONAL\n";
// temp table, TableID generated by provider
odtLog << "\tProvider generated TableID\n";
FILL_PROP_SET(rgPropSets[0], NUMELEM(rgProp), rgProp, DBPROPSET_TABLE);
FILL_PROP(rgProp[0], DBPROP_TBL_TEMPTABLE, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL);
TEST2C_(hr = CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset,
NUMELEM(rgPropSets), rgPropSets), S_OK, DB_S_ERRORSOCCURRED);
// perm table, TableID generated by provider
FILL_PROP(rgProp[0], DBPROP_TBL_TEMPTABLE, VT_BOOL, V_BOOL, VARIANT_FALSE, DBPROPOPTIONS_OPTIONAL);
hr = (S_OK!=hr)? DB_S_ERRORSOCCURRED : S_OK;
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset,
NUMELEM(rgPropSets), rgPropSets), hr);
// temp table, consumer generated TableID
odtLog << "\tConsumer generated TableID\n";
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = wcsDuplicate(m_pTable->GetTableName());
FILL_PROP_SET(rgPropSets[0], NUMELEM(rgProp), rgProp, DBPROPSET_TABLE);
FILL_PROP(rgProp[0], DBPROP_TBL_TEMPTABLE, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL);
TEST2C_(hr = CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset,
NUMELEM(rgPropSets), rgPropSets), S_OK, DB_S_ERRORSOCCURRED);
// perm table, consumer generated TableID
FILL_PROP(rgProp[0], DBPROP_TBL_TEMPTABLE, VT_BOOL, V_BOOL, VARIANT_FALSE, DBPROPOPTIONS_OPTIONAL);
hr = (S_OK!=hr)? DB_S_ERRORSOCCURRED : S_OK;
TESTC_(CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset,
NUMELEM(rgPropSets), rgPropSets), hr);
CLEANUP:
// checkings, etc
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(&TableID, FALSE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(67)
//*-----------------------------------------------------------------------
// @mfunc create a table and update a row, using the rowset interface got => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_67()
{
IRowsetChange *pIRowsetChange = NULL;
IRowset *pIRowset = NULL;
IAccessor *pIAccessor = NULL;
BOOL fTestRes = TEST_FAIL;
ULONG i;
const ULONG nInsertRows = 10;
BOOL fMayWrite;
const ULONG nRows = 3;
DBPROPSET rgPropSets[1];
const ULONG nProps = 3;
DBPROP rgProperties[nProps];
HROW *rghRow = NULL;
DBCOUNTITEM cRowsObtained = 0;
HACCESSOR hAccessor = NULL;
BYTE *pData = NULL;
DBCOUNTITEM cBindings = 0;
DBBINDING *rgBindings = NULL;
const LONG cColsToBind = 1;
LONG_PTR rgColsToBind[cColsToBind];
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CList <WCHAR*, WCHAR*> ListNativeTemp;
CList <DBTYPE, DBTYPE> ListDataTypes;
CTable *pTable = NULL;
pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
// get the provider types list
pTable->CreateColInfo(ListNativeTemp, ListDataTypes, ALLTYPES);
// build the column description array
pTable->BuildColumnDescs(&rgColumnDesc);
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc=pTable->CountColumnsOnTable());
pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
FILL_PROP_SET(rgPropSets[0], NUMELEM(rgProperties), rgProperties, DBPROPSET_ROWSET);
FILL_PROP(rgProperties[0], DBPROP_IRowsetChange, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
FILL_PROP(rgProperties[1], DBPROP_OWNINSERT, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
FILL_PROP(rgProperties[2], DBPROP_OWNUPDATEDELETE, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL);
TESTC_(CreateAndCheckTable(m_pITableDefinition, NULL, NULL, cColumnDesc, rgColumnDesc, IID_IRowsetChange, 1, rgPropSets,
&pTableID, (IUnknown**)&pIRowsetChange), S_OK);
pTable->SetTableID(*pTableID);
pTable->MayWrite(&fMayWrite);
for (i=0; i<nInsertRows; i++)
{
m_hr = Insert(0, pIRowsetChange, 0, NULL, pTable);
if (DB_E_NOTSUPPORTED != m_hr)
{
TESTC_(m_hr, S_OK);
}
else
{
fTestRes = TEST_SKIPPED;
goto CLEANUP;
}
}
// get a pointer to IRoewset interface
if (!VerifyInterface(pIRowsetChange, IID_IRowset, ROWSET_INTERFACE, (IUnknown**)&pIRowset))
{
odtLog << "could not get IRowsetChange\n";
goto CLEANUP;
}
if (!VerifyInterface(pIRowset, IID_IAccessor, ROWSET_INTERFACE, (IUnknown**)&pIAccessor))
{
odtLog << "could not get IAccessor\n";
goto CLEANUP;
}
m_hr = pIRowset->RestartPosition(NULL);
if (!CHECK(m_hr = pIRowset->GetNextRows(0, 0, // hChapter & lRowsOffset
nRows, // number of rows to be retrieved
&cRowsObtained, //number of rows actually get
&rghRow // array of handlers to rows
), S_OK) || nRows != cRowsObtained)
{
odtLog << "insuccess on IRowset::GetNextRows\n";
goto CLEANUP;
}
rgColsToBind[0] = 1;
if (!CHECK(m_hr = GetAccessorAndBindings(pIRowset, // pIUnknRowsetObject
DBACCESSOR_ROWDATA, // accessor flags
&hAccessor, &rgBindings, &cBindings, NULL, // accessor handler, array and number of bindings created
DBPART_VALUE |DBPART_STATUS |DBPART_LENGTH, // types of bindings to do
USE_COLS_TO_BIND_ARRAY, // eColsByRef specifies that cols to be bind
//are gien as an array
FORWARD, // eBindingOrder
NO_COLS_BY_REF, // eColsByRef
NULL, NULL,
NULL, DBTYPE_EMPTY, // ppStringsBufferOut & dwModifier
cColsToBind, rgColsToBind), S_OK))
{
odtLog << "problems getting accessor and bindings\n";
goto CLEANUP;
}
// Fill buffer with appropriate data for insert of this row number
TESTC_(m_hr = FillInputBindings(
pTable,
DBACCESSOR_ROWDATA,
cBindings,
rgBindings,
&pData,
37,
0,
NULL),S_OK);
if (!CHECK(m_hr = pIRowsetChange->SetData(rghRow[0], hAccessor, pData), S_OK))
{
odtLog << "could not update the row\n";
goto CLEANUP;
}
fTestRes = TEST_PASS;
CLEANUP:
if (pIAccessor && hAccessor)
{
CHECK(m_hr = pIAccessor->ReleaseAccessor(hAccessor, NULL), S_OK);
}
SAFE_RELEASE(pIAccessor);
if (pIRowset)
CHECK(m_hr = pIRowset->ReleaseRows(cRowsObtained, rghRow, NULL, NULL, NULL), S_OK);
PROVIDER_FREE(rghRow);
SAFE_RELEASE(pIRowsetChange);
SAFE_RELEASE(pIRowset);
if (pTableID)
{
CHECK(DropTableAndCheck(pTableID), S_OK);
ReleaseDBID(pTableID);
}
delete pTable;
FreeAccessorBindings(cBindings, rgBindings);
PROVIDER_FREE(pData);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(68)
//*-----------------------------------------------------------------------
// @mfunc Fully Qualified Table Name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_68()
{
BOOL fTestRes = TEST_FAIL;
DBID TableID;
WCHAR *pwszQualTableName = NULL;
WCHAR *pwszCatalogName = NULL;
WCHAR *pwszSchemaName = NULL;
WCHAR *pwszTableName = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CTable *pTable = NULL;
// create a regular table
pTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
TESTC(NULL != pTable);
TESTC_(pTable->CreateTable(0, 0), S_OK);
pwszTableName = pTable->GetTableName();
TableID.eKind = DBKIND_NAME;
TESTC(GetCatalogSchemaNames(pwszTableName, &pwszCatalogName, &pwszSchemaName, pTable));
//Construct a fully Qualified TableName...
TESTC_(pTable->GetQualifiedName(pwszCatalogName, pwszSchemaName, pwszTableName, &pwszQualTableName),S_OK);
TableID.uName.pwszName = pwszQualTableName;
// get rid of the previous table; keep info about "the empty shell"
m_pITableDefinition->DropTable(&pTable->GetTableID());
// create the table with the qualified name
pTable->BuildColumnDescs(&rgColumnDesc);
pTable->SetColumnDesc(rgColumnDesc, cColumnDesc=pTable->CountColumnsOnTable());
TESTC_(CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK);
fTestRes = TEST_PASS;
CLEANUP:
SAFE_FREE(pwszCatalogName);
SAFE_FREE(pwszSchemaName);
SAFE_FREE(pwszQualTableName);
pTable->DropTable();
delete pTable;
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(69)
//*-----------------------------------------------------------------------
// @mfunc Quoted table name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_69()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = NULL;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
m_pTable->MakeTableName(NULL);
m_pTable->GetQuotedName(m_pTable->GetTableName(), &TableID.uName.pwszName);
TESTC_(CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK);
CLEANUP:
ReleaseDBID(&TableID, FALSE);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(70)
//*-----------------------------------------------------------------------
// @mfunc Aggregation, non IID_IUnknown
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_70()
{
TBEGIN
DBID *pTableID = NULL;
CAggregate Aggregate(m_pIOpenRowset);
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
TESTC_(CreateAndCheckTable(m_pITableDefinition, &Aggregate, NULL, cColumnDesc, rgColumnDesc,
IID_IRowsetChange, 0, NULL, &pTableID, (IUnknown**)&Aggregate.m_pIUnkInner),
DB_E_NOAGGREGATION);
// Verrify Aggregation for this rowset...
TESTC(NULL == Aggregate.m_pIUnkInner);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
Aggregate.ReleaseInner();
// checkings, etc
DropTableAndCheck(pTableID);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(71)
//*-----------------------------------------------------------------------
// @mfunc Aggregation -> IRowsetInfo::GetReferencedRowset
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_71()
{
TBEGIN
HRESULT hr;
DBID *pTableID = NULL;
CAggregate Aggregate(m_pIOpenRowset);
IRowsetInfo *pIRowsetInfo = NULL;
IUnknown *pIAggregate = NULL;
IUnknown *pIUnkOuter = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
ULONG cPropSet = 0;
DBPROPSET *prgPropSet = NULL;
DBPROPSET rgPropSet[1];
DBPROP rgProp[1];
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// create a table and open a bookmark rowset on it
if (SettableProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET))
{
FILL_PROP_SET(rgPropSet[0], 1, rgProp, DBPROPSET_ROWSET);
FILL_PROP(rgProp[0], DBPROP_BOOKMARKS, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
prgPropSet = rgPropSet;
cPropSet = 1;
}
TEST2C_(hr = CreateAndCheckTable(m_pITableDefinition, &Aggregate, NULL, cColumnDesc, rgColumnDesc, IID_IUnknown, cPropSet, prgPropSet,
&pTableID, (IUnknown**)&Aggregate.m_pIUnkInner), S_OK, DB_E_NOAGGREGATION);
TEST_PROVIDER(S_OK == hr);
//Verify Aggregation for this rowset...
TESTC(Aggregate.VerifyAggregationQI(hr, IID_IRowsetInfo, (IUnknown**)&pIRowsetInfo));
//Verify we are hooked up...
//This call we are using the Rowset and asking for IID_IAggregate,
//which is the outer object and should succeed!!! Kind of cool huh!
hr = pIRowsetInfo->GetReferencedRowset(0, IID_IAggregate, (IUnknown**)&pIAggregate);
TESTC(hr==S_OK || hr==DB_E_BADORDINAL ||hr==DB_E_NOTAREFERENCECOLUMN);
if(hr==DB_E_NOTAREFERENCECOLUMN || hr==DB_E_BADORDINAL)
TESTC(!GetProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET, Aggregate.m_pIUnkInner, VARIANT_TRUE));
TESTC_PROVIDER(hr==S_OK);
//Now make sure the Rowset QI for IUnknown give me the outer
TESTC_(hr = pIRowsetInfo->GetReferencedRowset(0, IID_IUnknown, (IUnknown**)&pIUnkOuter),S_OK);
TESTC(VerifyEqualInterface(pIAggregate, pIUnkOuter));
CLEANUP:
SAFE_RELEASE(pIAggregate);
SAFE_RELEASE(pIRowsetInfo);
SAFE_RELEASE(pIUnkOuter);
Aggregate.ReleaseInner();
// checkings, etc
CHECK(DropTableAndCheck(pTableID), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(72)
//*-----------------------------------------------------------------------
// @mfunc Agg session -> IRowsetInfo::GetSpecification
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_72()
{
CAggregate Aggregate(g_pIDBCreateSession);
ULONG fTestRes = TEST_FAIL;
IRowsetInfo *pIRowsetInfo = NULL;
ITableDefinition *pITableDefinition = NULL;
IUnknown *pIAggregate = NULL;
ULONG ulRefCountBefore;
ULONG ulRefCountAfter;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBID *pTableID = NULL;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
//Aggregation
HRESULT hr = CreateNewSession(g_pIDBInitialize, IID_IUnknown, (IUnknown**)&Aggregate.m_pIUnkInner, &Aggregate);
TEST_PROVIDER(S_OK == hr);
//Verify Aggregation for this session...
TESTC(Aggregate.VerifyAggregationQI(hr, IID_ITableDefinition, (IUnknown**)&pITableDefinition));
//Now Create the Rowset
ulRefCountBefore = Aggregate.GetRefCount();
// create a table and open a bookmark rowset on it
TESTC_(CreateAndCheckTable(pITableDefinition, NULL, NULL, cColumnDesc, rgColumnDesc,
IID_IRowsetInfo, 0, NULL, &pTableID, (IUnknown**)&pIRowsetInfo), S_OK);
ulRefCountAfter = Aggregate.GetRefCount();
//GetSpecification
TEST2C_(hr = pIRowsetInfo->GetSpecification(IID_IAggregate, (IUnknown**)&pIAggregate),S_OK,S_FALSE);
if(hr==S_OK)
{
TESTC(VerifyEqualInterface(pIAggregate, pITableDefinition));
//Verify the child correctly addref'd the parent outer.
//The is an absolute requirement that the child keep the parent outer alive.
//If it doesn't addref the outer, the outer can be released externally since
//its not being used anymore due to the fact the outer controls the refcount
//of the inner. Many providers incorrectly addref the inner, which does nothing
//but guareentee the inner survives, but the inner will delegate to the outer
//and crash since it no longer exists...
TCOMPARE_(ulRefCountAfter > ulRefCountBefore);
}
else
{
TWARNING(L"IRowsetInfo::GetSpecification unable to retrieve Parent object!");
}
fTestRes = TEST_PASS;
CLEANUP:
SAFE_RELEASE(pIAggregate);
SAFE_RELEASE(pIRowsetInfo);
Aggregate.ReleaseInner();
// checkings, etc
if (pITableDefinition)
CHECK(DropTableAndCheck(pTableID, pITableDefinition), S_OK);
SAFE_RELEASE(pITableDefinition);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(73)
//*-----------------------------------------------------------------------
// @mfunc Table -> Agg ColumnRowset, ask for non IID_IUnknown
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_73()
{
TBEGIN
DBID *pTableID = NULL;
CAggregate Aggregate(m_pIOpenRowset);
IRowset *pIRowset = NULL;
IColumnsRowset *pIColumnsRowset = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBPROPSET *rgPropSet = NULL;
ULONG cPropSet = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetSettableProperty(DBPROP_IColumnsRowset, DBPROPSET_ROWSET, &cPropSet, &rgPropSet);
TESTC_(CreateAndCheckTable(m_pITableDefinition, NULL, NULL, cColumnDesc, rgColumnDesc,
IID_IRowset, cPropSet, rgPropSet, &pTableID, (IUnknown**)&pIRowset), S_OK);
//Obtain the ColumnsRowset interface [OPTIONAL] interface
TESTC_PROVIDER(VerifyInterface(pIRowset, IID_IColumnsRowset, ROWSET_INTERFACE, (IUnknown**)&pIColumnsRowset));
//Try to obtain anything but IID_IUnknown.
//This should fail, this is a requirement for COM Aggregation...
TESTC_(pIColumnsRowset->GetColumnsRowset(&Aggregate, 0, NULL, IID_IRowset, 0, NULL,
(IUnknown**)&Aggregate.m_pIUnkInner),DB_E_NOAGGREGATION);
//Inner object cannot RefCount the outer object - COM rule for CircularRef
TESTC(Aggregate.GetRefCount() == 1);
TESTC(Aggregate.m_pIUnkInner == NULL);
CLEANUP:
SAFE_RELEASE(pIColumnsRowset);
SAFE_RELEASE(pIRowset);
Aggregate.ReleaseInner();
DropTableAndCheck(pTableID);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(74)
//*-----------------------------------------------------------------------
// @mfunc Table -> Agg ColumnRowset, ask for IID_IUnknown
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_74()
{
TBEGIN
HRESULT hr;
DBID *pTableID = NULL;
CAggregate Aggregate(m_pIOpenRowset);
IRowset *pIRowset = NULL;
IColumnsRowset *pIColumnsRowset = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBPROPSET *rgPropSet = NULL;
ULONG cPropSet = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetSettableProperty(DBPROP_IColumnsRowset, DBPROPSET_ROWSET, &cPropSet, &rgPropSet);
TEST2C_(hr = CreateAndCheckTable(m_pITableDefinition, NULL, NULL, cColumnDesc, rgColumnDesc,
IID_IRowset, cPropSet, rgPropSet, &pTableID, (IUnknown**)&pIRowset), S_OK, DB_E_ERRORSOCCURRED);
if (DB_E_ERRORSOCCURRED == hr)
TESTC(!GetProperty(DBPROP_IColumnsRowset, DBPROPSET_ROWSET, pIRowset, VARIANT_TRUE));
TESTC_PROVIDER(S_OK == hr);
//Obtain the ColumnsRowset interface [OPTIONAL] interface
TESTC_PROVIDER(VerifyInterface(pIRowset, IID_IColumnsRowset, ROWSET_INTERFACE, (IUnknown**)&pIColumnsRowset));
//Try to obtain IID_IUnknown.
TEST2C_(hr = pIColumnsRowset->GetColumnsRowset(&Aggregate, 0, NULL, IID_IUnknown, 0, NULL,
(IUnknown**)&Aggregate.m_pIUnkInner), S_OK, DB_E_NOAGGREGATION);
TESTC_PROVIDER(S_OK == hr);
//Verify Aggregation for this session...
TESTC(Aggregate.VerifyAggregationQI(hr, IID_IRowset));
CLEANUP:
SAFE_RELEASE(pIColumnsRowset);
SAFE_RELEASE(pIRowset);
Aggregate.ReleaseInner();
// checkings, etc
DropTableAndCheck(pTableID);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(75)
//*-----------------------------------------------------------------------
// @mfunc Table -> Agg ColumnRowset -> IRowsetInfo::GetSpecification
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_75()
{
TBEGIN
CAggregate Aggregate(m_pIOpenRowset);
ULONG fTestRes = TEST_FAIL;
IRowset *pIRowset = NULL;
IColumnsRowset *pIColumnsRowset = NULL;
IUnknown *pIAggregate = NULL;
IRowsetInfo *pIRowsetInfo = NULL;
ULONG ulRefCountBefore;
ULONG ulRefCountAfter;
HRESULT hr = S_OK;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBPROPSET *rgPropSet = NULL;
ULONG cPropSet = 0;
DBID *pTableID = NULL;
BOOL fCreatedTable = FALSE;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetSettableProperty(DBPROP_IColumnsRowset, DBPROPSET_ROWSET, &cPropSet, &rgPropSet);
TEST3C_(hr = CreateAndCheckTable(m_pITableDefinition, &Aggregate, NULL, cColumnDesc, rgColumnDesc,
IID_IUnknown, cPropSet, rgPropSet, &pTableID, (IUnknown**)&Aggregate.m_pIUnkInner),
S_OK, DB_E_ERRORSOCCURRED, DB_E_NOAGGREGATION);
if (DB_E_ERRORSOCCURRED == hr)
TESTC(!GetProperty(DBPROP_IColumnsRowset, DBPROPSET_ROWSET, pIRowset, VARIANT_TRUE));
TESTC_PROVIDER(S_OK == hr);
fCreatedTable = TRUE;
//Verify Aggregation
TESTC(Aggregate.VerifyAggregationQI(hr, IID_IRowset, (IUnknown**)&pIRowset));
//Obtain the ColumnsRowset interface [OPTIONAL] interface
TESTC_PROVIDER(VerifyInterface(pIRowset, IID_IColumnsRowset, ROWSET_INTERFACE, (IUnknown**)&pIColumnsRowset));
//IColumnsRowset::GetRowset
ulRefCountBefore = Aggregate.GetRefCount();
TESTC_(hr = pIColumnsRowset->GetColumnsRowset(NULL, 0, NULL, IID_IRowsetInfo, 0, NULL, (IUnknown**)&pIRowsetInfo),S_OK);
ulRefCountAfter = Aggregate.GetRefCount();
//GetSpecification
TEST2C_(hr = pIRowsetInfo->GetSpecification(IID_IAggregate, (IUnknown**)&pIAggregate),S_OK,S_FALSE);
if(hr==S_OK)
{
TESTC(VerifyEqualInterface(pIAggregate, pIRowset));
//Verify the child correctly addref'd the parent outer.
//The is an absolute requirement that the child keep the parent outer alive.
//If it doesn't addref the outer, the outer can be released externally since
//its not being used anymore due to the fact the outer controls the refcount
//of the inner. Many providers incorrectly addref the inner, which does nothing
//but guareentee the inner survives, but the inner will delegate to the outer
//and crash since it no longer exists...
TCOMPARE_(ulRefCountAfter > ulRefCountBefore);
}
else
{
TWARNING(L"IRowsetInfo::GetSpecification unable to retrieve Parent object!");
}
CLEANUP:
SAFE_RELEASE(pIRowsetInfo);
SAFE_RELEASE(pIAggregate);
SAFE_RELEASE(pIColumnsRowset);
SAFE_RELEASE(pIRowset);
Aggregate.ReleaseInner();
// checkings, etc
CHECK(DropTableAndCheck(pTableID), fCreatedTable? S_OK : E_INVALIDARG);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(76)
//*-----------------------------------------------------------------------
// @mfunc colid is ignored in a non column specific rowset property
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_76()
{
TBEGIN
DBPROPSET rgPropSet[1];
DBPROP rgProp[1];
DBPROPID dwPropID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
HRESULT hr;
DBPROPSTATUS dwStatus;
// make sure there is a non column specific rowset property that is settable
TESTC_PROVIDER(GetNonColSpecProp(DBPROPSET_ROWSET, &dwPropID));
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
rgColumnDesc[0].cPropertySets = 0;
rgColumnDesc[0].rgPropertySets = NULL;
FILL_PROP_SET(rgPropSet[0], 1, rgProp, DBPROPSET_ROWSET)
FILL_PROP(rgProp[0], dwPropID, DBTYPE_BOOL, V_BOOL,
VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL)
// get the result with DB_NULLID
hr = CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 1, rgPropSet);
dwStatus = rgProp[0].dwStatus;
if (S_OK != hr)
{
TESTC_(hr, DB_S_ERRORSOCCURRED);
TESTC(DBPROPSTATUS_NOTSUPPORTED == dwStatus);
}
else
{
TESTC(DBPROPSTATUS_OK == dwStatus);
}
// 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_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 1, rgPropSet), hr);
TESTC(dwStatus == rgProp[0].dwStatus);
// check colid is ignored for the column property
rgProp[0].dwOptions = DBPROPOPTIONS_REQUIRED;
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset,
1, rgPropSet), S_OK == hr? S_OK: DB_E_ERRORSOCCURRED);
TESTC(dwStatus == rgProp[0].dwStatus);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(77)
//*-----------------------------------------------------------------------
// @mfunc colid is DB_NULLID in a column specific rowset property => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_77()
{
TBEGIN
DBPROPSET rgPropSet[1];
DBPROP rgProp[1];
DBPROPID dwPropID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
HRESULT hr;
// make sure there is a column specific rowset property that is settable
TESTC_PROVIDER(GetColSpecProp(DBPROPSET_ROWSET, &dwPropID));
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
rgColumnDesc[0].cPropertySets = 0;
rgColumnDesc[0].rgPropertySets = NULL;
FILL_PROP_SET(rgPropSet[0], 1, rgProp, DBPROPSET_ROWSET)
FILL_PROP(rgProp[0], dwPropID, DBTYPE_BOOL, V_BOOL,
VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL)
// explicitly set colID to DB_NULLID
rgProp[0].colid = DB_NULLID;
// check colid is ignored for the rowset property
hr = CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 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;
// check colid is ignored for the rowset property
hr = CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 1, rgPropSet);
if (DB_E_ERRORSOCCURRED == hr)
{
TESTC(DBPROPSTATUS_NOTALLSETTABLE == rgProp[0].dwStatus);
}
else
{
TESTC_(hr, S_OK);
TESTC(DBPROPSTATUS_OK == rgProp[0].dwStatus);
}
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(78)
//*-----------------------------------------------------------------------
// @mfunc valid, non DB_NULLID colid for a column specific rowset property
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_78()
{
TBEGIN
DBPROPSET rgPropSet[1];
DBPROP rgProp[1];
DBPROPID dwPropID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
memset(&rgProp[0].colid, 0, sizeof(DBID));
// make sure there is a column specific rowset property that is settable
TESTC_PROVIDER(GetColSpecProp(DBPROPSET_ROWSET, &dwPropID));
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
rgColumnDesc[0].cPropertySets = 0;
rgColumnDesc[0].rgPropertySets = NULL;
FILL_PROP_SET(rgPropSet[0], 1, rgProp, DBPROPSET_ROWSET)
FILL_PROP(rgProp[0], dwPropID, DBTYPE_BOOL, V_BOOL,
VARIANT_TRUE, DBPROPOPTIONS_OPTIONAL)
// explicitly set colID to DB_NULLID
DuplicateDBID(m_rgColumnDesc[0].dbcid, &rgProp[0].colid);
// check colid is ignored for the rowset property
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 1, rgPropSet), S_OK);
COMPARE(DBPROPSTATUS_OK == rgProp[0].dwStatus, TRUE);
// check colid is ignored for the column property
rgProp[0].dwOptions = DBPROPOPTIONS_REQUIRED;
// check colid is ignored for the rowset property
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 1, rgPropSet), S_OK);
COMPARE(DBPROPSTATUS_OK == rgProp[0].dwStatus, TRUE);
CLEANUP:
ReleaseDBID(&rgProp[0].colid, FALSE);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(79)
//*-----------------------------------------------------------------------
// @mfunc invalid colid for a column specific rowset property
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_79()
{
TBEGIN
DBPROPSET rgPropSet[1];
DBPROP rgProp[1];
DBPROPID dwPropID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
// make sure there is a column specific rowset property that is settable
TESTC_PROVIDER(GetColSpecProp(DBPROPSET_ROWSET, &dwPropID));
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
rgColumnDesc[0].cPropertySets = 0;
rgColumnDesc[0].rgPropertySets = NULL;
FILL_PROP_SET(rgPropSet[0], 1, rgProp, DBPROPSET_ROWSET)
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
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 1, rgPropSet), DB_S_ERRORSOCCURRED);
COMPARE(DBPROPSTATUS_BADCOLUMN == rgProp[0].dwStatus, TRUE);
// check colid is ignored for the column property
rgProp[0].dwOptions = DBPROPOPTIONS_REQUIRED;
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 1, rgPropSet), DB_E_ERRORSOCCURRED);
COMPARE(DBPROPSTATUS_BADCOLUMN == rgProp[0].dwStatus, TRUE);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(80)
//*-----------------------------------------------------------------------
// @mfunc Create a table. Retrieve a rowset on it (IRowsetInfo). Check GetSpecification()
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_80()
{
IRowsetInfo *pIRowsetInfo = NULL;
IOpenRowset *pIOpenRowset = NULL;
BOOL fTestRes = TEST_FAIL;
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
HRESULT hr;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
TESTC_(CreateAndCheckTable(m_pITableDefinition, NULL, NULL, cColumnDesc, rgColumnDesc, IID_IRowsetInfo,
0, NULL, &pTableID, (IUnknown**)&pIRowsetInfo), S_OK);
hr = pIRowsetInfo->GetSpecification(IID_IOpenRowset, (IUnknown**)&pIOpenRowset);
if (S_FALSE != hr)
{
TESTC_(hr, S_OK);
TESTC(VerifyEqualInterface(m_pITableDefinition, pIOpenRowset));
}
fTestRes = TEST_PASS;
CLEANUP:
SAFE_RELEASE(pIRowsetInfo);
SAFE_RELEASE(pIOpenRowset);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
if (pTableID)
CHECK(DropTableAndCheck(pTableID), S_OK);
ReleaseDBID(pTableID);
return fTestRes;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(81)
//*-----------------------------------------------------------------------
// @mfunc DB_NULLID is ignored for non column-related table properties
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_81()
{
TBEGIN
DBPROPSET rgPropSets[1];
DBPROP rgProp[1];
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBPROPID dwPropID;
// make sure there is a non column specific rowset property that is settable
TESTC_PROVIDER(GetNonColSpecProp(DBPROPSET_TABLE, &dwPropID));
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
FILL_PROP_SET(rgPropSets[0], NUMELEM(rgProp), rgProp, DBPROPSET_TABLE);
FILL_PROP(rgProp[0], dwPropID, VT_BOOL, V_BOOL,
VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
// setting a colid != DB_NULLID for a table property should result in error
rgProp[0].colid.eKind = DBKIND_NAME;
rgProp[0].colid.uName.pwszName = L"AliBaba";
CHECK(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset,
NUMELEM(rgPropSets), rgPropSets), S_OK);
// TableID generated by provider
FILL_PROP(rgProp[0], dwPropID, VT_BOOL, V_BOOL,
VARIANT_FALSE, DBPROPOPTIONS_REQUIRED);
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset,
NUMELEM(rgPropSets), rgPropSets), S_OK);
CLEANUP:
// checkings, etc
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(82)
//*-----------------------------------------------------------------------
// @mfunc Column related table property set to bad colid
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_82()
{
TBEGIN
DBPROPSET rgPropSets[1];
DBPROP rgProp[1];
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBPROPID dwPropID;
// make sure there is a non column specific rowset property that is settable
TESTC_PROVIDER(GetColSpecProp(DBPROPSET_TABLE, &dwPropID));
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
FILL_PROP_SET(rgPropSets[0], NUMELEM(rgProp), rgProp, DBPROPSET_TABLE);
FILL_PROP(rgProp[0], dwPropID, VT_BOOL, V_BOOL,
VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
// setting a colid != DB_NULLID for a table property should result in error
rgProp[0].colid.eKind = DBKIND_NAME;
rgProp[0].colid.uName.pwszName = L"AliBaba";
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset,
NUMELEM(rgPropSets), rgPropSets), DB_S_ERRORSOCCURRED);
// TableID generated by provider
FILL_PROP(rgProp[0], dwPropID, VT_BOOL, V_BOOL,
VARIANT_FALSE, DBPROPOPTIONS_REQUIRED);
TESTC_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset,
NUMELEM(rgPropSets), rgPropSets), DB_E_ERRORSOCCURRED);
CLEANUP:
// checkings, etc
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(83)
//*-----------------------------------------------------------------------
// @mfunc How many DBTYPE_I4 columns?
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_83()
{
return TEST_PASS;
/*
TBEGIN
CTable *pCTable = new CTable(m_pThisTestModule->m_pIUnknown2,
(LPWSTR)gwszModuleName);
DBTYPE dbType = DBTYPE_I4;
BYTE precision = 0;
BYTE scale = 0;
HRESULT hr;
DBCOLUMNDESC *rgColumnDesc = NULL;
const ULONG MAX_VAL = 2048;
ULONG cColumnDesc = MAX_VAL / 2;
ULONG iCol;
ULONG offset = MAX_VAL / 4;
pCTable->SetBuildColumnDesc(FALSE);
for (;0 < offset;)
{
SAFE_ALLOC(rgColumnDesc, DBCOLUMNDESC, cColumnDesc);
memset(rgColumnDesc, 0, cColumnDesc*sizeof(DBCOLUMNDESC));
for (iCol = 0; iCol < cColumnDesc; iCol++)
{
// fill in a column
rgColumnDesc[iCol].wType = dbType;
rgColumnDesc[iCol].bPrecision = precision;
rgColumnDesc[iCol].bScale = scale;
rgColumnDesc[iCol].dbcid.eKind = DBKIND_NAME;
SAFE_ALLOC(rgColumnDesc[iCol].dbcid.uName.pwszName, WCHAR, 10);
swprintf(rgColumnDesc[iCol].dbcid.uName.pwszName, L"C%dCol", iCol);
}
pCTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
hr = pCTable->CreateTable(100, 0);
if (SUCCEEDED(hr))
{
pCTable->DropTable();
if (cColumnDesc < MAX_VAL)
cColumnDesc += offset;
else
break;
}
else
{
if (cColumnDesc < offset)
break;
cColumnDesc -= offset;
}
offset /= 2;
}
odtLog << "Max no of columns : " << cColumnDesc << "\n";
CLEANUP:
pCTable->DropTable();
SAFE_DELETE(pCTable);
TRETURN
*/
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(84)
//*-----------------------------------------------------------------------
// @mfunc Open a rowset with CE, call IColumnRowset with an aggregated pIUnk
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_84()
{
TBEGIN
IRowsetFind *pIRowsetFind = NULL;
IColumnsRowset *pIColumnsRowset= NULL;
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
HRESULT hr;
CAggregate Aggregate(NULL);
TESTC_PROVIDER(SettableProperty(DBPROP_IRowsetFind, DBPROPSET_ROWSET));
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
TEST2C_(hr = CreateAndCheckTable(m_pITableDefinition, NULL, NULL, cColumnDesc, rgColumnDesc,
IID_IRowsetFind, 0, NULL, &pTableID, (IUnknown**)&pIRowsetFind), S_OK, E_NOINTERFACE);
TESTC_PROVIDER(S_OK == hr);
TESTC_(pIRowsetFind->QueryInterface(IID_IColumnsRowset, (LPVOID*)&pIColumnsRowset), S_OK);
TESTC_(hr = pIColumnsRowset->GetColumnsRowset(&Aggregate, 0, NULL, IID_IUnknown,
0, NULL, (IUnknown**)&Aggregate.m_pIUnkInner), S_OK);
// Verify Aggregation for this rowset...
TESTC(Aggregate.VerifyAggregationQI(hr, IID_IRowset));
CLEANUP:
Aggregate.ReleaseInner();
SAFE_RELEASE(pIRowsetFind);
SAFE_RELEASE(pIColumnsRowset);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
if (pTableID)
CHECK(DropTableAndCheck(pTableID), S_OK);
ReleaseDBID(pTableID);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(85)
//*-----------------------------------------------------------------------
// @mfunc Different DBKINDs for pTableID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_85()
{
TBEGIN
LPWSTR pwszColumnName = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBID TableID;
HRESULT hr;
// DBKIND_GUID_NAME
// DBKIND_GUID_PROPID
// DBKIND_NAME
// DBKIND_PGUID_NAME
// DBKIND_PGUID_PROPID
// DBKIND_PROPID
// DBKIND_GUID
m_pTable->MakeTableName(NULL);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
TEST2C_(hr = CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IUnknown,
0, NULL, TRUE), S_OK, DB_E_BADTABLEID);
TableID.eKind = DBKIND_GUID_NAME;
TableID.uGuid.guid = guidModule;
m_pTable->MakeTableName(NULL);
TableID.uName.pwszName = m_pTable->GetTableName();
TEST2C_(CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL, TRUE), S_OK, DB_E_BADTABLEID);
TableID.eKind = DBKIND_PGUID_NAME;
TableID.uGuid.pguid = &guidModule;
m_pTable->MakeTableName(NULL);
TableID.uName.pwszName = m_pTable->GetTableName();
TEST2C_(CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL, TRUE), S_OK, DB_E_BADTABLEID);
TableID.eKind = DBKIND_GUID;
TableID.uGuid.guid = guidModule;
m_pTable->MakeTableName(NULL);
TableID.uName.pwszName = m_pTable->GetTableName();
TEST2C_(CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL, TRUE), S_OK, DB_E_BADTABLEID);
TableID.eKind = DBKIND_GUID_PROPID;
TableID.uGuid.guid = guidModule;
TableID.uName.ulPropid = 0xffL;
TEST2C_(CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL, TRUE), S_OK, DB_E_BADTABLEID);
TableID.eKind = DBKIND_PGUID_PROPID;
TableID.uGuid.pguid = &guidModule;
TableID.uName.ulPropid = 0xffL;
TEST2C_(CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL, TRUE), S_OK, DB_E_BADTABLEID);
TableID.eKind = DBKIND_PROPID;
TableID.uGuid.pguid = &guidModule;
TableID.uName.ulPropid = 0xffL;
TEST2C_(CCNDropTable(&TableID, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL, TRUE), S_OK, DB_E_BADTABLEID);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(86)
//*-----------------------------------------------------------------------
// @mfunc Different DBKINDs for column IDs
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTable::Variation_86()
{
TBEGIN
LPWSTR pwszColumnName = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
// DBKIND_GUID_NAME
// DBKIND_GUID_PROPID
// DBKIND_NAME
// DBKIND_PGUID_NAME
// DBKIND_PGUID_PROPID
// DBKIND_PROPID
// DBKIND_GUID
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
pwszColumnName = rgColumnDesc[0].dbcid.uName.pwszName;
rgColumnDesc[0].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[0].dbcid.uName.pwszName = pwszColumnName;
TEST2C_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK, DB_E_BADCOLUMNID);
rgColumnDesc[0].dbcid.eKind = DBKIND_GUID_NAME;
rgColumnDesc[0].dbcid.uGuid.guid = guidModule;
rgColumnDesc[0].dbcid.uName.pwszName = pwszColumnName;
TEST2C_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK, DB_E_BADCOLUMNID);
rgColumnDesc[0].dbcid.eKind = DBKIND_PGUID_NAME;
rgColumnDesc[0].dbcid.uGuid.pguid = &guidModule;
rgColumnDesc[0].dbcid.uName.pwszName = pwszColumnName;
TEST2C_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK, DB_E_BADCOLUMNID);
rgColumnDesc[0].dbcid.eKind = DBKIND_GUID;
rgColumnDesc[0].dbcid.uGuid.guid = guidModule;
rgColumnDesc[0].dbcid.uName.pwszName = pwszColumnName;
TEST2C_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK, DB_E_BADCOLUMNID);
rgColumnDesc[0].dbcid.eKind = DBKIND_GUID_PROPID;
rgColumnDesc[0].dbcid.uGuid.guid = guidModule;
rgColumnDesc[0].dbcid.uName.ulPropid = 0xffL;
TEST2C_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK, DB_E_BADCOLUMNID);
rgColumnDesc[0].dbcid.eKind = DBKIND_PGUID_PROPID;
rgColumnDesc[0].dbcid.uGuid.pguid = &guidModule;
rgColumnDesc[0].dbcid.uName.ulPropid = 0xffL;
TEST2C_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK, DB_E_BADCOLUMNID);
rgColumnDesc[0].dbcid.eKind = DBKIND_PROPID;
rgColumnDesc[0].dbcid.uGuid.pguid = &guidModule;
rgColumnDesc[0].dbcid.uName.ulPropid = 0xffL;
TEST2C_(CCNDropTable(NULL, cColumnDesc, rgColumnDesc, IID_IRowset, 0, NULL), S_OK, DB_E_BADCOLUMNID);
rgColumnDesc[0].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[0].dbcid.uName.pwszName = pwszColumnName;
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
CLEANUP:
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//--------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCCreateTable::Terminate()
{
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCITableDefinition::Terminate());
} // }}
// }}
// }}
// {{ TCW_TC_PROTOTYPE(RODataSource)
//*-----------------------------------------------------------------------
//| Test Case: RODataSource - Test case for operating on a read only data source
//| Created: 10/13/97
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL RODataSource::Init()
{
BOOL fResults = TEST_SKIPPED;
IDBInitialize *pIDBInitialize = NULL;
IDBProperties *pIDBProperties = NULL;
DBPROPSET *rgPropSets = NULL;
ULONG cPropSets = 0;
HRESULT hr = NOERROR;
DBPROP *rgProperties = NULL;
const int n=1;
const ULONG nINIT_MODE = 0;
DBPROPIDSET rgPropIDSet[n];
DBPROPID rgPropID1[1];
ULONG nActualSize = n;
m_pIUnknown = NULL;
m_pIUnknown2 = NULL;
m_pITableDefinition2 = NULL;
m_pTable = NULL;
// {{ TCW_INIT_BASECLASS_CHECK
if(!TCDropColumn::Init())
// }}
goto CLEANUP2;
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 CLEANUP2;
}
// create a spare table on the read-write datasource
m_hr = m_pTable->CreateTable(10, 0);
m_pITableDefinition2 = m_pITableDefinition;
m_pITableDefinition = NULL;
fResults = FALSE;
if (!CHECK(m_hr, S_OK))
{
odtLog << "could not create atable 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;
// Get our initial connection to the provider, asking for IDBInitialize since
// we must initialize before anything else
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;
SetProperty(&rgPropSets, &cPropSets, DBPROP_INIT_MODE, VT_I4, (LPVOID)DB_MODE_READ, DBPROPOPTIONS_REQUIRED, DB_NULLID,
DBPROPSET_DBINIT);
// 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;
}
else
{
PRVTRACE("RODataSource::Init(): Apparently the read only property was set\n");
FindProperty(
DBPROP_INIT_MODE,
DBPROPSET_DBINIT,
cPropSets,
rgPropSets,
&rgProperties);
if (DBPROPSTATUS_OK != rgProperties->dwStatus)
odtLog << "ERROR: Read only property could not be initialized in fact!\n";
}
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
// switch the interface on ItableDefinition
if (!(m_hr=VerifyInterface(m_pIUnknown2, IID_ITableDefinition, SESSION_INTERFACE,
(IUnknown**)&m_pITableDefinition)))
goto CLEANUP1;
fResults = TRUE;
CLEANUP1:
FreeProperties( &cPropSets, &rgPropSets);
CLEANUP:
SAFE_RELEASE(pIDBProperties);
SAFE_RELEASE(pIDBInitialize);
return fResults;
CLEANUP2:
if (m_pITableDefinition)
{
m_pITableDefinition2 = m_pITableDefinition;
m_pITableDefinition = NULL;
}
return fResults;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Add a column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int RODataSource::Variation_1()
{
BOOL fResults = TEST_PASS;
DBID *pColumnID = NULL;
HRESULT hr;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = m_pTable->CountColumnsOnTable();
m_pTable->BuildColumnDescs(&rgColumnDesc);
TESTC(0 < cColumnDesc);
PROVIDER_FREE(rgColumnDesc->dbcid.uName.pwszName);
FreeProperties( &rgColumnDesc->cPropertySets, &rgColumnDesc->rgPropertySets);
rgColumnDesc[0].dbcid.uName.pwszName = wcsDuplicate(L"newColumn");
if (!CHECK(hr = m_pITableDefinition->AddColumn(&m_pTable->GetTableID(), rgColumnDesc, &pColumnID),
DB_SEC_E_PERMISSIONDENIED))
fResults = TEST_FAIL;
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
CLEANUP:
return fResults;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Drop a column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int RODataSource::Variation_2()
{
TBEGIN;
DBID ColumnID;
DBCOLUMNDESC *oldCD = NULL;
DBORDINAL oldlen = 0;
GetColumnDescOnTable(&m_pTable->GetTableID(), &oldCD, &oldlen);
TESTC_PROVIDER(1 < oldlen);
ColumnID.eKind = DBKIND_NAME;
ColumnID.uName.pwszName = oldCD[0].dbcid.uName.pwszName;
TEST2C_(DropColumnAndCheck(&m_pTable->GetTableID(), &ColumnID), S_OK, DB_SEC_E_PERMISSIONDENIED);
CLEANUP:
ReleaseColumnDesc(oldCD, oldlen);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Create a table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int RODataSource::Variation_3()
{
BOOL fResults = TEST_PASS;
DBID *pTableID = NULL;
if (!CHECK(m_pITableDefinition->CreateTable(NULL, NULL, m_cColumnDesc, m_rgColumnDesc,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_SEC_E_PERMISSIONDENIED))
{
fResults = TEST_FAIL;
m_pITableDefinition->DropTable(pTableID);
}
ReleaseDBID(pTableID);
return fResults;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Drop a table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int RODataSource::Variation_4()
{
BOOL fResults = TEST_PASS;
BOOL fExists;
if ( !CHECK(m_pITableDefinition->DropTable(&m_pTable->GetTableID()), DB_SEC_E_PERMISSIONDENIED)
|| !CHECK(m_pTable->DoesTableExist(&m_pTable->GetTableID(), &fExists), S_OK)
|| !fExists)
fResults = TEST_FAIL;
return fResults;
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL RODataSource::Terminate()
{
// {{ TCW_TERM_BASECLASS_CHECK2
SAFE_RELEASE(m_pITableDefinition);
m_pITableDefinition = m_pITableDefinition2;
m_pITableDefinition2 = NULL;
SetDBSession(m_pITableDefinition);
if (m_pTable)
{
m_hr = m_pTable->DropTable();
delete m_pTable;
m_pTable = NULL;
}
return(TCDropColumn::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);
TCITableDefinition *pObject = ((CInParam*)lpvThreadParam)->pObject;
pObject->MyThreadProc(((CInParam*)lpvThreadParam)->i);
CoUninitialize();
return 1;
} //ThreadProc
// {{ TCW_TC_PROTOTYPE(TCAddConstraint_Boundary)
//*-----------------------------------------------------------------------
//| Test Case: TCAddConstraint_Boundary - General and boundary/null test for ITableDefinitionWithConstraints::AddConstraint
//| Created: 7/29/99
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCAddConstraint_Boundary::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCITableDefinition::Init())
// }}
{
if (m_pITDWC == NULL || GetModInfo()->GetClassContext()==CLSCTX_LOCAL_SERVER)
{
odtLog << "ITableDefinitionWithConstraints is not supported.\n";
return TEST_SKIPPED;
}
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Check the session object (QI for interfaces)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_1()
{
return DefaultObjectTesting(m_pThisTestModule->m_pIUnknown2, SESSION_INTERFACE);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc pTableID is NULL => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_2()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(AddUniqueConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the check constraint
consCheck.SetConstraintText(L"TRUE != FALSE");
CHECK(AddConstraintAndCheck(m_pITDWC, NULL, consFK), E_INVALIDARG);
CHECK(AddConstraintAndCheck(m_pITDWC, NULL, consPK), E_INVALIDARG);
CHECK(AddConstraintAndCheck(m_pITDWC, NULL, consUnique), E_INVALIDARG);
CHECK(AddConstraintAndCheck(m_pITDWC, NULL, consCheck), E_INVALIDARG);
CLEANUP:
BaseTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc *pTableID is DB_NULLID => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_3()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
DBID TableID;
DuplicateDBID(DB_NULLID, &TableID);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(AddUniqueConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the check constraint
CHECK(consCheck.SetLTCheckConstraint(&BaseTable, rgBaseCol[0], 12), S_OK);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consFK), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consPK), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consUnique), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consCheck), DB_E_NOTABLE);
CLEANUP:
BaseTable.DropTable();
ReleaseDBID(&TableID, FALSE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Table name is NULL => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_4()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
DBID TableID;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(AddUniqueConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the check constraint
CHECK(consCheck.SetLTCheckConstraint(&BaseTable, rgBaseCol[0], 12), S_OK);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = NULL;
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consFK), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consPK), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consUnique), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consCheck), DB_E_NOTABLE);
CLEANUP:
BaseTable.DropTable();
ReleaseDBID(&TableID, FALSE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Table name is the empty string => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_5()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
DBID TableID;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(AddUniqueConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the check constraint
CHECK(consCheck.SetLTCheckConstraint(&BaseTable, rgBaseCol[0], 17), S_OK);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = wcsDuplicate(L"");
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consFK), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consPK), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consUnique), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consCheck), DB_E_NOTABLE);
CLEANUP:
BaseTable.DropTable();
ReleaseDBID(&TableID, FALSE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Table name has maximum length
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_6()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
DBID TableID;
// create a table with maximum length
BaseTable.MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = BuildValidName(m_cMaxTableName, BaseTable.GetTableName());
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0, 0, TableID.uName.pwszName), S_OK);
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
TESTC_(AddUniqueConstraint(&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol, m_SupportedMatchType), S_OK);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the check constraint
CHECK(consCheck.SetLTCheckConstraint(&BaseTable, rgBaseCol[0], 12), S_OK);
CHECK(AddConstraintAndCheck(m_pITDWC, &TableID, consFK), S_OK);
CHECK(AddConstraintAndCheck(m_pITDWC, &TableID, consPK), S_OK);
CHECK(AddConstraintAndCheck(m_pITDWC, &TableID, consUnique), S_OK);
CHECK(AddConstraintAndCheck(m_pITDWC, &TableID, consCheck), S_OK);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
ReleaseDBID(&TableID, FALSE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Table name exceeds maximum length => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_7()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
DBID TableID;
// create a table with maximum length
BaseTable.MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = BuildValidName(m_cMaxTableName+1, BaseTable.GetTableName());
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0, 0), S_OK);
TESTC_(AddUniqueConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the check constraint
CHECK(consCheck.SetLTCheckConstraint(&BaseTable, rgBaseCol[0], 12), S_OK);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consFK), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consPK), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consUnique), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consCheck), DB_E_NOTABLE);
CLEANUP:
BaseTable.DropTable();
ReleaseDBID(&TableID, FALSE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc Table name contains illegal characters
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_8()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
DBID TableID;
size_t m, n;
// create a table with maximum length
BaseTable.MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
m = min(m_cMaxTableName, n=5+wcslen(BaseTable.GetTableName()));
TableID.uName.pwszName = BuildInvalidName(m, BaseTable.GetTableName(), m_pwszInvalidTableChars);
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0, 0), S_OK);
TESTC_(AddUniqueConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the check constraint
CHECK(consCheck.SetLTCheckConstraint(&BaseTable, rgBaseCol[0], 12), S_OK);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consFK), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consPK), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consUnique), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consCheck), DB_E_NOTABLE);
CLEANUP:
BaseTable.DropTable();
ReleaseDBID(&TableID, FALSE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc Invalid DBKIND value for the base table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_9()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
DBID TableID;
// create a table with maximum length
BaseTable.MakeTableName(NULL);
memset(&TableID, 0, sizeof(DBID));
TableID.eKind = 0xce;
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0, 0), S_OK);
TESTC_(AddUniqueConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the check constraint
CHECK(consCheck.SetLTCheckConstraint(&BaseTable, rgBaseCol[0], 12), S_OK);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consFK), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consPK), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consUnique), DB_E_NOTABLE);
TESTC_(AddConstraintAndCheck(m_pITDWC, &TableID, consCheck), DB_E_NOTABLE);
CLEANUP:
BaseTable.DropTable();
ReleaseDBID(&TableID, FALSE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc NULL column list in a constraint, column size is not 0 => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_10()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1, 2, 3};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
DBCONSTRAINTDESC *pConsDesc;
DBID *p1 = NULL, *p2 = NULL;
// create a table with maximum length
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0, 0), S_OK);
TESTC_(AddUniqueConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
pConsDesc = consUnique;
p1 = pConsDesc->rgColumnList;
pConsDesc->rgColumnList = NULL;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consUnique), E_INVALIDARG);
pConsDesc->rgColumnList = p1;
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
pConsDesc = consPK;
p1 = pConsDesc->rgColumnList;
pConsDesc->rgColumnList = NULL;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consPK), E_INVALIDARG);
pConsDesc->rgColumnList = p1;
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
pConsDesc = consFK;
p1 = pConsDesc->rgColumnList;
pConsDesc->rgColumnList = NULL;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), E_INVALIDARG);
p2 = pConsDesc->rgForeignKeyColumnList;
pConsDesc->rgForeignKeyColumnList = NULL;
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), E_INVALIDARG);
pConsDesc->rgColumnList = p1;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), E_INVALIDARG);
pConsDesc->rgColumnList = p1;
pConsDesc->rgForeignKeyColumnList = p2;
CLEANUP:
BaseTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc NULL column name in a constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_11()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1, 2, 3};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
DBCONSTRAINTDESC *pConsDesc;
// create a table with maximum length
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0, 0), S_OK);
TESTC_(AddUniqueConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
pConsDesc = consFK;
ReleaseDBID(&pConsDesc->rgColumnList[1], FALSE);
pConsDesc->rgColumnList[1].eKind = DBKIND_NAME;
pConsDesc->rgColumnList[1].uName.pwszName = NULL;
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOCOLUMN);
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
pConsDesc = consFK;
ReleaseDBID(&pConsDesc->rgColumnList[1], FALSE);
pConsDesc->rgColumnList[1].eKind = DBKIND_NAME;
pConsDesc->rgColumnList[1].uName.pwszName = NULL;
ReleaseDBID(&pConsDesc->rgForeignKeyColumnList[2], FALSE);
pConsDesc->rgForeignKeyColumnList[1].eKind = DBKIND_NAME;
pConsDesc->rgForeignKeyColumnList[1].uName.pwszName = NULL;
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOCOLUMN);
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
pConsDesc = consFK;
ReleaseDBID(&pConsDesc->rgForeignKeyColumnList[1], FALSE);
pConsDesc->rgForeignKeyColumnList[1].eKind = DBKIND_NAME;
pConsDesc->rgForeignKeyColumnList[1].uName.pwszName = NULL;
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOCOLUMN);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
pConsDesc = consUnique;
ReleaseDBID(&pConsDesc->rgColumnList[1], FALSE);
pConsDesc->rgColumnList[1].eKind = DBKIND_NAME;
pConsDesc->rgColumnList[1].uName.pwszName = NULL;
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consUnique), DB_E_NOCOLUMN);
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
pConsDesc = consPK;
ReleaseDBID(&pConsDesc->rgColumnList[1], FALSE);
pConsDesc->rgColumnList[1].eKind = DBKIND_NAME;
pConsDesc->rgColumnList[1].uName.pwszName = NULL;
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consPK), DB_E_NOCOLUMN);
CLEANUP:
BaseTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc Empty string for a column name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_12()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1, 2, 3};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
DBCONSTRAINTDESC *pConsDesc;
// create a table with maximum length
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0, 0), S_OK);
TESTC_(AddUniqueConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
pConsDesc = consFK;
ReleaseDBID(&pConsDesc->rgColumnList[1], FALSE);
pConsDesc->rgColumnList[1].eKind = DBKIND_NAME;
pConsDesc->rgColumnList[1].uName.pwszName = wcsDuplicate(L"");
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOCOLUMN);
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
pConsDesc = consFK;
ReleaseDBID(&pConsDesc->rgColumnList[1], FALSE);
pConsDesc->rgColumnList[1].eKind = DBKIND_NAME;
pConsDesc->rgColumnList[1].uName.pwszName = wcsDuplicate(L"");
ReleaseDBID(&pConsDesc->rgForeignKeyColumnList[2], FALSE);
pConsDesc->rgForeignKeyColumnList[1].eKind = DBKIND_NAME;
pConsDesc->rgForeignKeyColumnList[1].uName.pwszName = wcsDuplicate(L"");
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOCOLUMN);
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
pConsDesc = consFK;
ReleaseDBID(&pConsDesc->rgForeignKeyColumnList[1], FALSE);
pConsDesc->rgForeignKeyColumnList[1].eKind = DBKIND_NAME;
pConsDesc->rgForeignKeyColumnList[1].uName.pwszName = wcsDuplicate(L"");
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOCOLUMN);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
pConsDesc = consUnique;
ReleaseDBID(&pConsDesc->rgColumnList[1], FALSE);
pConsDesc->rgColumnList[1].eKind = DBKIND_NAME;
pConsDesc->rgColumnList[1].uName.pwszName = wcsDuplicate(L"");
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consUnique), DB_E_NOCOLUMN);
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
pConsDesc = consPK;
ReleaseDBID(&pConsDesc->rgColumnList[1], FALSE);
pConsDesc->rgColumnList[1].eKind = DBKIND_NAME;
pConsDesc->rgColumnList[1].uName.pwszName = wcsDuplicate(L"");
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consPK), DB_E_NOCOLUMN);
CLEANUP:
BaseTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc Maximum length column name in a constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_13()
{
TBEGIN
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBORDINAL rgCol[] = {1};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
WCHAR *pwszName = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
BaseTable.SetColumnDesc(rgColumnDesc, cColumnDesc);
BaseTable.SetBuildColumnDesc(FALSE);
BaseTable.MakeTableName(NULL);
pwszName = wcsDuplicate(BaseTable.GetTableName());
if (rgColumnDesc[0].dbcid.uName.pwszName)
SAFE_FREE(rgColumnDesc[0].dbcid.uName.pwszName);
rgColumnDesc[0].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[0].dbcid.uName.pwszName = BuildValidName(m_cMaxColName, pwszName);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
TESTC_(AddUniqueConstraint(&ReferencedTable, NUMELEM(rgCol), rgCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&ReferencedTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgCol), rgCol), S_OK);
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgCol), rgCol), S_OK);
// set up the check constraint
CHECK(consCheck.SetLTCheckConstraint(&BaseTable, rgCol[0], 12), S_OK);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), S_OK);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consPK), S_OK);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consUnique), S_OK);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consCheck), S_OK);
CLEANUP:
SAFE_FREE(pwszName);
CHECK(BaseTable.DropTable(), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(14)
//*-----------------------------------------------------------------------
// @mfunc Column name exceeds maximum length
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_14()
{
TBEGIN
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBORDINAL rgCol[] = {1};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
WCHAR *pwszName = NULL;
WCHAR *pwszColName = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBCONSTRAINTDESC *pConsDesc;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
BaseTable.SetColumnDesc(rgColumnDesc, cColumnDesc);
BaseTable.SetBuildColumnDesc(FALSE);
BaseTable.MakeTableName(NULL);
pwszName = wcsDuplicate(BaseTable.GetTableName());
if (rgColumnDesc[0].dbcid.uName.pwszName)
SAFE_FREE(rgColumnDesc[0].dbcid.uName.pwszName);
rgColumnDesc[0].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[0].dbcid.uName.pwszName = BuildValidName(m_cMaxColName, pwszName);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
TESTC_(AddUniqueConstraint(&ReferencedTable, NUMELEM(rgCol), rgCol), S_OK);
pwszColName = BuildValidName(m_cMaxColName+1, pwszName);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&ReferencedTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
pConsDesc = consFK;
SAFE_FREE(pConsDesc->rgForeignKeyColumnList[0].uName.pwszName);
pConsDesc->rgForeignKeyColumnList[0].uName.pwszName = wcsDuplicate(pwszColName);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgCol), rgCol), S_OK);
pConsDesc = consUnique;
SAFE_FREE(pConsDesc->rgColumnList[0].uName.pwszName);
pConsDesc->rgColumnList[0].uName.pwszName = wcsDuplicate(pwszColName);
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgCol), rgCol), S_OK);
pConsDesc = consPK;
SAFE_FREE(pConsDesc->rgColumnList[0].uName.pwszName);
pConsDesc->rgColumnList[0].uName.pwszName = wcsDuplicate(pwszColName);
// set up the check constraint
CHECK(consCheck.SetIsNotNULLCheckConstraint(pwszColName), S_OK);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOCOLUMN);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consPK), DB_E_NOCOLUMN);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consUnique), DB_E_NOCOLUMN);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consCheck), E_FAIL);
CLEANUP:
SAFE_FREE(pwszColName);
SAFE_FREE(pwszName);
CHECK(BaseTable.DropTable(), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(15)
//*-----------------------------------------------------------------------
// @mfunc Invalid DBKIND for a column DBID of a constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_15()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1, 2, 3};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
DBCONSTRAINTDESC *pConsDesc;
// create a table with maximum length
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0, 0), S_OK);
TESTC_(AddUniqueConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
pConsDesc = consFK;
ReleaseDBID(&pConsDesc->rgColumnList[1], FALSE);
pConsDesc->rgColumnList[1].eKind = 0xfe;
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOCOLUMN);
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
pConsDesc = consFK;
ReleaseDBID(&pConsDesc->rgColumnList[1], FALSE);
pConsDesc->rgColumnList[1].eKind = 0xfe;
ReleaseDBID(&pConsDesc->rgForeignKeyColumnList[2], FALSE);
pConsDesc->rgForeignKeyColumnList[1].eKind = 0xfe;
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOCOLUMN);
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
pConsDesc = consFK;
ReleaseDBID(&pConsDesc->rgForeignKeyColumnList[1], FALSE);
pConsDesc->rgForeignKeyColumnList[1].eKind = 0xfe;
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOCOLUMN);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
pConsDesc = consUnique;
ReleaseDBID(&pConsDesc->rgColumnList[1], FALSE);
pConsDesc->rgColumnList[1].eKind = 0xee;
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consUnique), DB_E_NOCOLUMN);
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
pConsDesc = consPK;
ReleaseDBID(&pConsDesc->rgColumnList[1], FALSE);
pConsDesc->rgColumnList[1].eKind = 0xac;
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consPK), DB_E_NOCOLUMN);
CLEANUP:
BaseTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc Column ID is DB_NULLID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_16()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1, 2, 3};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
DBCONSTRAINTDESC *pConsDesc;
// create a table with maximum length
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0, 0), S_OK);
TESTC_(AddUniqueConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
pConsDesc = consFK;
ReleaseDBID(&pConsDesc->rgColumnList[1], FALSE);
DuplicateDBID(DB_NULLID, &pConsDesc->rgColumnList[1]);
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOCOLUMN);
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
pConsDesc = consFK;
ReleaseDBID(&pConsDesc->rgColumnList[1], FALSE);
DuplicateDBID(DB_NULLID, &pConsDesc->rgColumnList[1]);
ReleaseDBID(&pConsDesc->rgForeignKeyColumnList[2], FALSE);
DuplicateDBID(DB_NULLID, &pConsDesc->rgForeignKeyColumnList[1]);
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOCOLUMN);
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
pConsDesc = consFK;
ReleaseDBID(&pConsDesc->rgForeignKeyColumnList[1], FALSE);
DuplicateDBID(DB_NULLID, &pConsDesc->rgForeignKeyColumnList[1]);
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOCOLUMN);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
pConsDesc = consUnique;
ReleaseDBID(&pConsDesc->rgColumnList[1], FALSE);
memset(&pConsDesc->rgColumnList[1], 0, sizeof(DBID));
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consUnique), DB_E_NOCOLUMN);
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
pConsDesc = consPK;
ReleaseDBID(&pConsDesc->rgColumnList[1], FALSE);
memset(&pConsDesc->rgColumnList[1], 0, sizeof(DBID));
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consPK), DB_E_NOCOLUMN);
CLEANUP:
BaseTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(17)
//*-----------------------------------------------------------------------
// @mfunc NULL pReferencedTableID for a foreign key constraint (with and without cForeignKeyColumns being 0)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_17()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
CForeignKeyCons consFK;
// create the referenced table in this catalog
TESTC_PROVIDER(S_OK == ReferencedTable.CreateTable(0, 0));
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
// create the
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol,
m_SupportedMatchType), S_OK);
consFK.SetReferencedTableID(NULL);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_BADCONSTRAINTFORM);
CHECK(consFK.ReleaseForeignKeyColumnList(), S_OK);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_BADCONSTRAINTFORM);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(18)
//*-----------------------------------------------------------------------
// @mfunc DBNULL_ID *pReferencedTableID for a foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_18()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
CForeignKeyCons consFK;
// create the referenced table in this catalog
TESTC_PROVIDER(S_OK == ReferencedTable.CreateTable(0, 0));
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
// create the constraint
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol,
m_SupportedMatchType), S_OK);
consFK.SetReferencedTableID((DBID*)&DB_NULLID);
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOTABLE);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(19)
//*-----------------------------------------------------------------------
// @mfunc NULL referenced table name for a foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_19()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
CForeignKeyCons consFK;
DBID ReferencedTableID;
// create the referenced table in this catalog
TESTC_PROVIDER(S_OK == ReferencedTable.CreateTable(0, 0));
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
// create the
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol,
m_SupportedMatchType), S_OK);
ReferencedTableID.eKind = DBKIND_NAME;
ReferencedTableID.uName.pwszName = NULL;
consFK.SetReferencedTableID(&ReferencedTableID);
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOTABLE);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(20)
//*-----------------------------------------------------------------------
// @mfunc Emptry string referenced table name for a foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_20()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
CForeignKeyCons consFK;
DBID ReferencedTableID;
// create the referenced table in this catalog
TESTC_PROVIDER(S_OK == ReferencedTable.CreateTable(0, 0));
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
// create the constraint
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol,
m_SupportedMatchType), S_OK);
ReferencedTableID.eKind = DBKIND_NAME;
ReferencedTableID.uName.pwszName = L"";
consFK.SetReferencedTableID(&ReferencedTableID);
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOTABLE);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(21)
//*-----------------------------------------------------------------------
// @mfunc Maximum length referenced table name for a foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_21()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
CForeignKeyCons consFK;
WCHAR *pwszTableName = NULL;
// create the referenced table in this catalog
// create a table with maximum length
ReferencedTable.MakeTableName(NULL);
pwszTableName = BuildValidName(m_cMaxTableName, ReferencedTable.GetTableName());
TESTC_PROVIDER(S_OK == ReferencedTable.CreateTable(0, 0, pwszTableName));
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
// create the
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol,
m_SupportedMatchType), S_OK);
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), S_OK);
CLEANUP:
SAFE_FREE(pwszTableName);
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(22)
//*-----------------------------------------------------------------------
// @mfunc Referenced table name longer than allowed for a foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_22()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
CForeignKeyCons consFK;
WCHAR *pwszTableName = NULL;
DBCONSTRAINTDESC *pConsDesc = consFK;
// create the referenced table in this catalog
// create a table with maximum length
ReferencedTable.MakeTableName(NULL);
pwszTableName = BuildValidName(m_cMaxTableName, ReferencedTable.GetTableName());
TESTC_PROVIDER(S_OK == ReferencedTable.CreateTable(0, 0, pwszTableName));
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
// create the
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol,
m_SupportedMatchType), S_OK);
SAFE_FREE(pwszTableName);
ReleaseDBID(pConsDesc->pReferencedTableID, FALSE);
pConsDesc->pReferencedTableID->eKind = DBKIND_NAME;
pConsDesc->pReferencedTableID->uName.pwszName = BuildValidName(m_cMaxTableName + 1, ReferencedTable.GetTableName());
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOTABLE);
CLEANUP:
SAFE_FREE(pwszTableName);
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(23)
//*-----------------------------------------------------------------------
// @mfunc Illegal characters in the referenced table name for a foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_23()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
CForeignKeyCons consFK;
DBID ReferencedTableID;
size_t m, n;
// create the referenced table in this catalog
// create a table with maximum length
TESTC_PROVIDER(S_OK == ReferencedTable.CreateTable(0, 0));
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
// create the constraint
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol,
m_SupportedMatchType), S_OK);
m = min(m_cMaxTableName, n=5+wcslen(ReferencedTable.GetTableName()));
ReferencedTableID.uName.pwszName = BuildInvalidName(m, ReferencedTable.GetTableName(), m_pwszInvalidTableChars);
consFK.SetReferencedTableID(&ReferencedTableID);
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOTABLE);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
ReleaseDBID(&ReferencedTableID, FALSE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(24)
//*-----------------------------------------------------------------------
// @mfunc Bad constraint type
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_24()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CConsDesc cons((DBCONSTRAINTTYPE)0xfd);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), DB_E_BADCONSTRAINTTYPE);
CLEANUP:
BaseTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(25)
//*-----------------------------------------------------------------------
// @mfunc Empty list of columns for a unique, primay key or foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_25()
{
TBEGIN
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBORDINAL rgCol[] = {1};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
WCHAR *pwszConstraintText = NULL;
WCHAR *pwszColValue = NULL;
CCol col;
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0, 0), S_OK);
TESTC_(AddUniqueConstraint(&BaseTable, NUMELEM(rgCol), rgCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&ReferencedTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
consFK.ReleaseColumnList();
TEST2C_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), E_INVALIDARG, DB_E_BADCONSTRAINTFORM);
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&ReferencedTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
consFK.ReleaseForeignKeyColumnList();
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_BADCONSTRAINTFORM);
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&ReferencedTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
consFK.ReleaseForeignKeyColumnList();
consFK.ReleaseColumnList();
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_BADCONSTRAINTFORM);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgCol), rgCol), S_OK);
consUnique.ReleaseColumnList();
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consUnique), DB_E_BADCONSTRAINTFORM);
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgCol), rgCol), S_OK);
consPK.ReleaseColumnList();
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consPK), DB_E_BADCONSTRAINTFORM);
CLEANUP:
CHECK(BaseTable.DropTable(), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(26)
//*-----------------------------------------------------------------------
// @mfunc Non empty list of columns for a check constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_26()
{
TBEGIN
HRESULT hr;
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
CCheckCons consCheck;
DBCONSTRAINTDESC *pcons = consCheck;
WCHAR *pwszConstraintText = NULL;
WCHAR *pwszColValue = NULL;
CCol col;
DBID rgColList;
DBID rgForeignKeyColList;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
// set up the check constraint
CHECK(consCheck.SetLTCheckConstraint(&BaseTable, 1, 12), S_OK);
DuplicateDBID(*col.GetColID(), &rgColList);
DuplicateDBID(*col.GetColID(), &rgForeignKeyColList);
// not empty rgColumnList
pcons->cColumns = 1;
pcons->rgColumnList = &rgColList;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consCheck), DB_E_BADCONSTRAINTFORM);
// not empty rgForeignKeyColumnList
pcons->cColumns = 0;
pcons->rgColumnList = NULL;
pcons->cForeignKeyColumns = 1;
pcons->rgForeignKeyColumnList = &rgForeignKeyColList;
hr = AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consCheck);
// since the number of columns is different from the number of foreign key columns
// E_INVALIDARG can be returned as well
if (E_INVALIDARG != hr)
CHECK(hr, DB_E_BADCONSTRAINTFORM);
// not empty rgColumnList and rgForeignKeyColumnList
pcons->cColumns = 1;
pcons->rgColumnList = &rgColList;
pcons->cForeignKeyColumns = 1;
pcons->rgForeignKeyColumnList = &rgForeignKeyColList;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consCheck), DB_E_BADCONSTRAINTFORM);
CLEANUP:
pcons->cColumns = 0;
pcons->rgColumnList = NULL;
pcons->cForeignKeyColumns = 0;
pcons->rgForeignKeyColumnList = NULL;
ReleaseDBID(&rgColList, FALSE);
ReleaseDBID(&rgForeignKeyColList, FALSE);
SAFE_FREE(pwszConstraintText);
SAFE_FREE(pwszColValue);
BaseTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(27)
//*-----------------------------------------------------------------------
// @mfunc Not null pwszConstraintText in a unique, PK or FK constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_27()
{
TBEGIN
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
DBCONSTRAINTDESC *pcons;
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0, 0), S_OK);
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
TESTC_(AddUniqueConstraint(&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol, m_SupportedMatchType), S_OK);
pcons = consFK;
pcons->pwszConstraintText = L"fdfd";
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
pcons = consUnique;
pcons->pwszConstraintText = L"fdfd";
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
pcons = consPK;
pcons->pwszConstraintText = L"fdfd";
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_BADCONSTRAINTFORM);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consPK), DB_E_BADCONSTRAINTFORM);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consUnique), DB_E_BADCONSTRAINTFORM);
CLEANUP:
pcons = consFK;
pcons->pwszConstraintText = NULL;
pcons = consPK;
pcons->pwszConstraintText = NULL;
pcons = consUnique;
pcons->pwszConstraintText = NULL;
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(28)
//*-----------------------------------------------------------------------
// @mfunc NULL pConstraintDesc => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_28()
{
TBEGIN
CHECK(AddConstraintAndCheck(m_pITDWC, &m_pTable->GetTableID(), NULL), E_INVALIDARG);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(29)
//*-----------------------------------------------------------------------
// @mfunc 0 < cColumns and NULL == rgColumnList => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_29()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(AddUniqueConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
CHECK(consFK.ReleaseColumnList(), S_OK);
((DBCONSTRAINTDESC*)consFK)->cColumns = 3;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), E_INVALIDARG);
((DBCONSTRAINTDESC*)consFK)->cColumns = 0;
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
CHECK(consUnique.ReleaseColumnList(), S_OK);
((DBCONSTRAINTDESC*)consUnique)->cColumns = 3;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consUnique), E_INVALIDARG);
((DBCONSTRAINTDESC*)consUnique)->cColumns = 0;
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
CHECK(consPK.ReleaseColumnList(), S_OK);
((DBCONSTRAINTDESC*)consPK)->cColumns = 3;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consPK), E_INVALIDARG);
((DBCONSTRAINTDESC*)consPK)->cColumns = 0;
// set up the check constraint
consCheck.SetConstraintText(L"TRUE != FALSE");
((DBCONSTRAINTDESC*)consCheck)->cColumns = 3;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consCheck), E_INVALIDARG);
((DBCONSTRAINTDESC*)consCheck)->cColumns = 0;
CLEANUP:
BaseTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(30)
//*-----------------------------------------------------------------------
// @mfunc 0 < cForeignKeyColumns and NULL == rgForeignKeyColumnList => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_30()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(AddUniqueConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgBaseCol), rgBaseCol, m_SupportedMatchType), S_OK);
CHECK(consFK.ReleaseForeignKeyColumnList(), S_OK);
((DBCONSTRAINTDESC*)consFK)->cForeignKeyColumns = 3;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), E_INVALIDARG);
((DBCONSTRAINTDESC*)consFK)->cForeignKeyColumns = 0;
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
((DBCONSTRAINTDESC*)consUnique)->cForeignKeyColumns = 3;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consUnique), E_INVALIDARG);
((DBCONSTRAINTDESC*)consUnique)->cForeignKeyColumns = 0;
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
((DBCONSTRAINTDESC*)consPK)->cForeignKeyColumns = 3;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consPK), E_INVALIDARG);
((DBCONSTRAINTDESC*)consPK)->cForeignKeyColumns = 0;
// set up the check constraint
consCheck.SetConstraintText(L"TRUE != FALSE");
((DBCONSTRAINTDESC*)consCheck)->cForeignKeyColumns = 3;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consCheck), E_INVALIDARG);
((DBCONSTRAINTDESC*)consCheck)->cForeignKeyColumns = 0;
CLEANUP:
BaseTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(31)
//*-----------------------------------------------------------------------
// @mfunc Constraint is not foreign key and pReferencedTableID is not NULL
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_31()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
DBID ReferencedTableID;
WCHAR *pwszConstraintText = NULL;
WCHAR *pwszColValue = NULL;
CCol col;
ReferencedTableID.eKind = DBKIND_NAME;
ReferencedTableID.uName.pwszName = (LPWSTR)0x01234567;
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0, 0), S_OK);
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
((DBCONSTRAINTDESC*)consUnique)->pReferencedTableID = &ReferencedTableID;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consUnique), DB_E_BADCONSTRAINTFORM);
((DBCONSTRAINTDESC*)consUnique)->pReferencedTableID = NULL;
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
((DBCONSTRAINTDESC*)consPK)->pReferencedTableID = &ReferencedTableID;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consPK), DB_E_BADCONSTRAINTFORM);
((DBCONSTRAINTDESC*)consPK)->pReferencedTableID = NULL;
// set up the check constraint
TESTC_(BaseTable.GetColInfo(rgBaseCol[0], col), S_OK);
TESTC_(BaseTable.GetLiteralAndValue(col, &pwszColValue, rand(), col.GetColNum(), PRIMARY), S_OK);
SAFE_FREE(pwszConstraintText);
SAFE_ALLOC(pwszConstraintText, WCHAR, 1 + wcslen(col.GetColName()) + wcslen(pwszColValue) + 3);
wcscpy(pwszConstraintText, col.GetColName());
wcscat(pwszConstraintText, L" < ");
wcscat(pwszConstraintText, pwszColValue);
consCheck.SetConstraintText(pwszConstraintText);
((DBCONSTRAINTDESC*)consCheck)->pReferencedTableID = &ReferencedTableID;
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consCheck), DB_E_BADCONSTRAINTFORM);
((DBCONSTRAINTDESC*)consCheck)->pReferencedTableID = NULL;
CLEANUP:
SAFE_FREE(pwszConstraintText);
SAFE_FREE(pwszColValue);
BaseTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(32)
//*-----------------------------------------------------------------------
// @mfunc Non empty list of foreign keys for a constraint that is not foreign key
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_32()
{
TBEGIN
HRESULT hr;
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
const DBORDINAL cColumns = 2;
DBID rgColumnList[cColumns];
DBORDINAL rgBaseCol[cColumns] = {1, 2};
rgColumnList[0].eKind = DBKIND_NAME;
rgColumnList[0].uName.pwszName = (LPWSTR)0x01234567;
rgColumnList[1].eKind = 0xfe;
rgColumnList[1].uName.pwszName = (LPWSTR)0x01234567;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
// set up the unique constraint
TESTC_(consUnique.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
((DBCONSTRAINTDESC*)consUnique)->cForeignKeyColumns = cColumns;
((DBCONSTRAINTDESC*)consUnique)->rgForeignKeyColumnList = rgColumnList;
hr = AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consUnique);
CHECK(hr, DB_E_BADCONSTRAINTFORM);
((DBCONSTRAINTDESC*)consUnique)->cForeignKeyColumns = 0;
((DBCONSTRAINTDESC*)consUnique)->rgForeignKeyColumnList = NULL;
// set up the primary key constraint
TESTC_(consPK.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol), S_OK);
((DBCONSTRAINTDESC*)consPK)->cForeignKeyColumns = cColumns;
((DBCONSTRAINTDESC*)consPK)->rgForeignKeyColumnList = rgColumnList;
hr = AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consPK);
CHECK(hr, DB_E_BADCONSTRAINTFORM);
((DBCONSTRAINTDESC*)consPK)->cForeignKeyColumns = 0;
((DBCONSTRAINTDESC*)consPK)->rgForeignKeyColumnList = NULL;
// set up the check constraint
consCheck.SetConstraintText(L"TRUE != FALSE");
((DBCONSTRAINTDESC*)consCheck)->cForeignKeyColumns = cColumns;
((DBCONSTRAINTDESC*)consCheck)->rgForeignKeyColumnList = rgColumnList;
hr = AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consCheck);
if (E_INVALIDARG != hr)
CHECK(hr, DB_E_BADCONSTRAINTFORM);
((DBCONSTRAINTDESC*)consCheck)->cForeignKeyColumns = 0;
((DBCONSTRAINTDESC*)consCheck)->rgForeignKeyColumnList = NULL;
CLEANUP:
BaseTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(33)
//*-----------------------------------------------------------------------
// @mfunc Inexistent referenced table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_33()
{
TBEGIN
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable Table(m_pITDWC, (LPWSTR)gwszModuleName);
CForeignKeyCons cons;
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
// create a table
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
// select a column
TESTC_(cons.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgReferencedCol), rgReferencedCol, m_SupportedMatchType), S_OK);
// set referenced table to an inexistent table name
Table.MakeTableName(NULL);
cons.SetReferencedTableID(&Table.GetTableID());
// add the foreign key constraint
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), DB_E_NOTABLE);
CLEANUP:
BaseTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(34)
//*-----------------------------------------------------------------------
// @mfunc Add several constraints to the table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_34()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
CCheckCons consCheck;
DBORDINAL rgReferencedCol[] = {1};
DBORDINAL rgCols[] = {1};
CCol col;
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITableDefinition,
ReferencedTable.GetTableID().eKind? ReferencedTable.GetTableID().uName.pwszName: NULL);
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITableDefinition,
BaseTable.GetTableID().eKind? BaseTable.GetTableID().uName.pwszName: NULL);
// set a unique constraint on the second column
CHECK(consUnique.SetConstraint(&BaseTable, 1, rgCols), S_OK);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consUnique), S_OK);
// set a primary key on the first column of the table
CHECK(consPrimaryKey.SetConstraint(&BaseTable, 1, rgCols), S_OK);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consPrimaryKey), S_OK);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
TESTC_(BaseTable.GetColInfo(1, col), S_OK);
consForeignKey.AddForeignKeyColumn(col.GetColID());
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consForeignKey), S_OK);
TESTC_(consCheck.SetLTCheckConstraint(&BaseTable, 2, 3), S_OK);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consCheck), S_OK);
CLEANUP:
CHECK(BaseTable.DropTable(), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(35)
//*-----------------------------------------------------------------------
// @mfunc Inexistent table name => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_35()
{
TBEGIN
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBORDINAL rgCol[] = {1};
CForeignKeyCons consFK(NULL, m_SupportedMatchType);
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
CCol col;
DBID dbidInexistent;
dbidInexistent.eKind = DBKIND_NAME;
dbidInexistent.uName.pwszName = L"Inexistent";
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
TESTC_(AddUniqueConstraint(&ReferencedTable, NUMELEM(rgCol), rgCol), S_OK);
TESTC_(ReferencedTable.GetColInfo(rgCol[0], col), S_OK);
// since base table name has to be inexistent, use reference table name instead
consFK.SetReferencedTableID(&ReferencedTable.GetTableID());
consFK.AddColumn(col.GetColID());
consFK.AddForeignKeyColumn(col.GetColID());
// set up the unique constraint
consUnique.AddColumn(col.GetColID());
// set up the primary key constraint
consPK.AddColumn(col.GetColID());
// set up the check constraint
CHECK(consCheck.SetIsNotNULLCheckConstraint(col.GetColID()->uName.pwszName), S_OK);
CHECK(AddConstraintAndCheck(m_pITDWC, &dbidInexistent, consFK), DB_E_NOTABLE);
CHECK(AddConstraintAndCheck(m_pITDWC, &dbidInexistent, consPK), DB_E_NOTABLE);
CHECK(AddConstraintAndCheck(m_pITDWC, &dbidInexistent, consUnique), DB_E_NOTABLE);
CHECK(AddConstraintAndCheck(m_pITDWC, &dbidInexistent, consCheck), DB_E_NOTABLE);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(36)
//*-----------------------------------------------------------------------
// @mfunc Inexistent column name => DB_E_NOCOLUMN
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Boundary::Variation_36()
{
TBEGIN
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBORDINAL rgCol[] = {1};
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBID dbidInexistent;
dbidInexistent.eKind = DBKIND_NAME;
dbidInexistent.uName.pwszName = L"Inexistent";
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
BaseTable.SetColumnDesc(rgColumnDesc, cColumnDesc);
BaseTable.SetBuildColumnDesc(FALSE);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
TESTC_(AddUniqueConstraint(&ReferencedTable, NUMELEM(rgCol), rgCol), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(consFK.SetConstraint(&BaseTable, 0, NULL,
&ReferencedTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
consFK.AddForeignKeyColumn(&dbidInexistent);
// set up the unique constraint
consUnique.AddColumn(&dbidInexistent);
// set up the primary key constraint
consPK.AddColumn(&dbidInexistent);
// set up the check constraint
CHECK(consCheck.SetIsNotNULLCheckConstraint(dbidInexistent.uName.pwszName), S_OK);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consFK), DB_E_NOCOLUMN);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consPK), DB_E_NOCOLUMN);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consUnique), DB_E_NOCOLUMN);
CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), consCheck), DB_E_NOCOLUMN);
CLEANUP:
CHECK(BaseTable.DropTable(), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL TCAddConstraint_Boundary::Terminate()
{
// TO DO: Add your own code here
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCITableDefinition::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(TCAddConstraint_UNIQUE)
//*-----------------------------------------------------------------------
//| Test Case: TCAddConstraint_UNIQUE - Testcase for ITableDefinitionWithConstraints::AddConstraint used with DBCONSTRAINTTYPE_UNIQUE
//| Created: 7/29/99
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCAddConstraint_UNIQUE::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCITableDefinition::Init())
// }}
{
if (m_pITDWC == NULL)
{
odtLog << "ITableDefinitionWithConstraints is not supported.\n";
return TEST_SKIPPED;
}
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Create a table and try to apply the constraint on each column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_1()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL index;
CUniqueCons cons;
DBORDINAL cColCount = 0,
cTotalLength = 0,
start = 1,
cColsInTable = 0;
HRESULT hrExpected;
ULONG ulNumberOfTests = 0;
// create the base table
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// build the constraint
// try to set all the columns in the unique keyunique
// Step 1: Skip BLOBs and Variable length columns
// and set Unique constraint on fixed length columns.
// It should succeed.
cColsInTable = Table.CountColumnsOnTable();
while(start < cColsInTable) {
cons.ReleaseColumnList();
cTotalLength = 0;
hrExpected = S_OK;
for (index = start, cColCount = 0; index <= Table.CountColumnsOnTable() &&
cColCount < cMaxColsPerCons; index++)
{
CCol col;
DBORDINAL colSizeInBytes = 0; //how many bytes the column contributes into maximum size of constraint
TESTC_(Table.GetColInfo(index, col), S_OK);
// Note: col.GetColumnSize returns length for string data types and we need size in bytes
// so multiply ColumnSize by 2 for WSTR
if(col.GetIsFixedLength() )
colSizeInBytes = col.GetColumnSize() * (col.GetProviderType()==DBTYPE_WSTR ? 2:1);
else
colSizeInBytes = 0;
if (col.GetIsLong() ||
cTotalLength + colSizeInBytes > cMaxColLengthPerCons)
continue;
cTotalLength += colSizeInBytes;
cons.AddColumn(col.GetColID());
cColCount++;
}
if (cColCount)
{
ulNumberOfTests++;
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), hrExpected);
if (hrExpected == S_OK) {
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
}
}
start = index;
}
TESTC(ulNumberOfTests>0);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Set a unique constraint on each type of column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_2()
{
TBEGIN
DBORDINAL index;
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
HRESULT hrExpected = S_OK;
// create a new table with a NOT NULLABLE column
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
Table.BuildColumnDescs(&rgNewColumnDesc);
for (index=1; index <= Table.CountColumnsOnTable(); index++)
{
CCol col;
TESTC_(Table.GetColInfo(index, col), S_OK);
cons.ReleaseColumnList();
cons.AddColumn(col.GetColID());
// Note: col.GetColumnSize returns length for string data types and we need size in bytes
// so multiply ColumnSize by 2 for WSTR
if (col.GetIsLong() ||
(col.GetIsFixedLength() && (col.GetColumnSize() * (col.GetProviderType()==DBTYPE_WSTR ? 2:1) > cMaxColLengthPerCons)))
hrExpected = E_FAIL;
else
hrExpected = S_OK;
odtLog << col.GetProviderTypeName() << "\t -> Expected: " << (hrExpected==S_OK ? "S_OK" : "E_FAIL") << "\n";
CHECK(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), hrExpected);
if (hrExpected == S_OK) {
CHECK(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
}
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), hrExpected);
if (hrExpected == S_OK) {
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
}
CLEANUP:
ReleaseColumnDesc(rgNewColumnDesc, m_cColumnDesc, TRUE);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Create a unique constraint that uses several columns
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_3()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL index;
DBORDINAL indxCol;
CUniqueCons cons;
DBORDINAL cCols;
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
DBORDINAL cTotalLength = 0;
// create a new table with a NOT NULLABLE column
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
Table.BuildColumnDescs(&rgNewColumnDesc);
cCols = 2 + rand() % __min(20, (Table.CountColumnsOnTable()-1));
for (index=0, indxCol=1; index < cCols && indxCol <= Table.CountColumnsOnTable(); indxCol++)
{
CCol col;
DBORDINAL colSizeInBytes = 0; //how many bytes the column contributes into maximum size of constraint
//make sure we have at least 2 columns before randomizing the rest
if ( cons.cColumns() < 2 || rand() % 2)
{
TESTC_(Table.GetColInfo(indxCol, col), S_OK);
// Note: col.GetColumnSize returns length for string data types and we need size in bytes
// so multiply ColumnSize by 2 for WSTR
if(col.GetIsFixedLength() )
colSizeInBytes = col.GetColumnSize() * (col.GetProviderType()==DBTYPE_WSTR ? 2:1);
else
colSizeInBytes = 0;
if (col.GetIsLong() ||
cTotalLength + colSizeInBytes > cMaxColLengthPerCons)
continue;
// put this column in the list
cTotalLength += colSizeInBytes;
cons.AddColumn(col.GetColID());
index++;
}
}
odtLog << "Constraint has " << cons.cColumns() << " columns\n";
CHECK(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
TESTC_(cons.MakeConstraintName(), S_OK);
// try the same when creating a table
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
ReleaseColumnDesc(rgNewColumnDesc, m_cColumnDesc, TRUE);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Create several unique constraints on a table, no overlapping
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_4()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CUniqueCons cons2;
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
TESTC_PROVIDER(4 <= Table.CountColumnsOnTable());
// choose 2 columns and create a unique constraint on them
TESTC_(Table.GetColInfo(4, col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(Table.GetColInfo(2, col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// choose another 2 columns and create a unique constraint
TESTC_(Table.GetColInfo(3, col), S_OK);
cons2.AddColumn(col.GetColID());
TESTC_(Table.GetColInfo(1, col), S_OK);
cons2.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons2), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Create multiple, overlapping constraints on a table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_5()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CUniqueCons cons2;
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
TESTC_PROVIDER(3 <= Table.CountColumnsOnTable());
// choose 2 columns and create a unique constraint on them
TESTC_(Table.GetColInfo(3, col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(Table.GetColInfo(2, col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// choose another 2 columns and create a unique constraint
TESTC_(Table.GetColInfo(1, col), S_OK);
cons2.AddColumn(col.GetColID());
TESTC_(Table.GetColInfo(3, col), S_OK);
cons2.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons2), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Create a constraint, drop it and recreate it
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_6()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// choose 1 column and create a unique constraint on them
TESTC_(Table.GetColInfo(1, col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint and recreate it
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Create a constraint on a null column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_7()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
DBCOLUMNDESC *rgNewColumnDesc = NULL;
// create a new table with a NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
// by setting DBCOLUMNDESC, all nullable type column are created as nullable
Table.SetColumnDesc(rgNewColumnDesc, m_cColumnDesc);
Table.SetBuildColumnDesc(FALSE);
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// identify a nullable column
TESTC_PROVIDER(S_OK == Table.GetColInfo(IsCColNullable, col));
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc Create a contraint on a not nullable column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_8()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
// create a new table with a NOT NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
// create a new table with a NOT NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
SetProperty(&rgNewColumnDesc[0].rgPropertySets, &rgNewColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
Table.SetColumnDesc(rgNewColumnDesc, m_cColumnDesc);
Table.SetBuildColumnDesc(FALSE);
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// identify a nullable column
TESTC_PROVIDER(S_OK == Table.GetColInfo(IsCColNotNullable, col));
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// try the same when creating a table
TESTC_(cons.MakeConstraintName(), S_OK);
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc Create a constraint on a column that has a default value
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_9()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
DBCOLUMNDESC *rgNewColumnDesc = NULL;
VARIANT value;
DBORDINAL indexCol;
CList<WCHAR *,WCHAR *> NativeTypesList;
CList<DBTYPE,DBTYPE> ProviderTypesList;
DBID *pTableID = NULL;
Table.CreateTypeColInfo(NativeTypesList, ProviderTypesList);
// create a new table with a NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
// by setting DBCOLUMNDESC, all nullable type column are created as nullable
Table.SetColumnDesc(rgNewColumnDesc, m_cColumnDesc);
// create a default value on one of the columns
VariantInit(&value);
indexCol = 2;
if (rgNewColumnDesc[indexCol-1].pwszTypeName)
odtLog << "Default value on type " << rgNewColumnDesc[indexCol-1].pwszTypeName << "\n";
GetDefaultValue(&rgNewColumnDesc[indexCol-1], &value, &Table);
SetDefaultProperty(&rgNewColumnDesc[indexCol-1].rgPropertySets, &rgNewColumnDesc[indexCol-1].cPropertySets,
&value, DBPROPOPTIONS_REQUIRED); // might be not supported
VariantClear(&value);
Table.SetBuildColumnDesc(FALSE);
TESTC_PROVIDER(S_OK == Table.CreateTable(0, 0));
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// identify a nullable column
TESTC_(Table.GetColInfo(indexCol, col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// try the same when creating a table
TESTC_(cons.MakeConstraintName(), S_OK);
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc Create a constraint on a column defined as a primary key
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_10()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBORDINAL indexCol;
CList<WCHAR *,WCHAR *> NativeTypesList;
CList<DBTYPE,DBTYPE> ProviderTypesList;
DBID *pTableID = NULL;
Table.CreateTypeColInfo(NativeTypesList, ProviderTypesList);
// create a new table with a NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
// by setting DBCOLUMNDESC, all nullable type column are created as nullable
Table.SetColumnDesc(rgNewColumnDesc, m_cColumnDesc);
// create a default value on one of the columns
indexCol = 3;
if (rgNewColumnDesc[indexCol-1].pwszTypeName)
odtLog << "Default value on type " << rgNewColumnDesc[indexCol-1].pwszTypeName << "\n";
SetProperty(&rgNewColumnDesc[indexCol-1].rgPropertySets, &rgNewColumnDesc[indexCol-1].cPropertySets,
DBPROP_COL_PRIMARYKEY,
VT_BOOL, (LPVOID)VARIANT_TRUE,
DBPROPOPTIONS_REQUIRED);
Table.SetBuildColumnDesc(FALSE);
TESTC_PROVIDER(S_OK == Table.CreateTable(0, 0));
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// identify a nullable column
TESTC_(Table.GetColInfo(indexCol, col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// try the same when creating a table
cons.MakeConstraintName();
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc Create a constraint on a column defined as a foreign key
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_11()
{
TBEGIN
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col, col2;
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBORDINAL indexCol;
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CForeignKeyCons cons2(NULL, m_SupportedMatchType);
DBCONSTRAINTDESC *pConsDesc2 = (DBCONSTRAINTDESC*)cons2;
TESTC_(RefTable.CreateTable(0, 0), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
// select a column
TESTC(RefTable.CountColumnsOnTable() == BaseTable.CountColumnsOnTable())
indexCol = 1;
TESTC_(RefTable.GetColInfo(indexCol, col2), S_OK);
TESTC_(BaseTable.GetColInfo(indexCol, col), S_OK);
TESTC_(AddUniqueConstraint(&RefTable, 1, &indexCol), S_OK);
// build the foreign key constraint, use corresponding columns in tables
// set column on base table
cons2.AddColumn(col2.GetColID());
// set foreign column
cons2.AddForeignKeyColumn(col.GetColID());
// set reference table
cons2.SetReferencedTableID(&RefTable.GetTableID());
// add the foreign key constraint
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons2), S_OK);
// prepare and add the unique constraint on the column involved in a foreign key
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), S_OK);
CLEANUP:
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc Create a constraint on a column that is included in an index
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_12()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
// create a table and an index
TESTC_(Table.CreateTable(0, 1), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// select a column (the one used in index)
TESTC_(Table.GetColInfo(1, col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
TESTC_(cons.MakeConstraintName(), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc Use the name of an already existing constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_13()
{
TBEGIN
CTable Table(m_pITDWC, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CUniqueCons UniqueCons;
CPrimaryKeyCons PKCons;
CCheckCons CheckCons;
CForeignKeyCons FKCons;
DBORDINAL rgCol[] = {1};
HRESULT hr;
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
// create a new table with a NOT NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
// create a table
TESTC_(CreateTableWithNoNullableColumns(&Table, 0), S_OK);
TESTC_(ReferencedTable.CreateTable(0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
TESTC_(AddUniqueConstraint(&ReferencedTable, 1), S_OK);
// create a unique constraint
TESTC_(UniqueCons.SetConstraint(&Table, 1), S_OK);
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), UniqueCons), S_OK);
// create a check constraint
CheckCons.SetLTCheckConstraint(&Table, 1, 60);
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), CheckCons), S_OK);
// create a PK constraint
TESTC_(PKCons.SetConstraint(&Table, 1), S_OK);
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), PKCons), S_OK);
// create a FK constraint
TESTC_(FKCons.SetConstraint(&Table, NUMELEM(rgCol), rgCol,
&ReferencedTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), FKCons), S_OK);
// add the constraint again, this time on other column (if possible)
TESTC_(cons.SetConstraint(&Table, 2), S_OK);
odtLog << "Unique constraint duplicate unique constraint name\n";
cons.SetConstraintID(UniqueCons.GetConstraintID());
CHECK(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_DUPLICATECONSTRAINTID);
// try the same when creating a table
if (!CHECK(hr = CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_DUPLICATECONSTRAINTID) && SUCCEEDED(hr))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
odtLog << "Unique constraint duplicate check constraint name\n";
cons.SetConstraintID(CheckCons.GetConstraintID());
CHECK(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_DUPLICATECONSTRAINTID);
// try the same when creating a table
if (!CHECK(hr = CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_DUPLICATECONSTRAINTID) && SUCCEEDED(hr))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
odtLog << "Unique constraint duplicate primary key constraint name\n";
cons.SetConstraintID(PKCons.GetConstraintID());
CHECK(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_DUPLICATECONSTRAINTID);
// try the same when creating a table
if (!CHECK(hr = CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_DUPLICATECONSTRAINTID) && SUCCEEDED(hr))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
odtLog << "Unique constraint duplicate foreign key constraint name\n";
cons.SetConstraintID(FKCons.GetConstraintID());
CHECK(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_DUPLICATECONSTRAINTID);
// try the same when creating a table
if (!CHECK(hr = CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_DUPLICATECONSTRAINTID) && SUCCEEDED(hr))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
ReleaseColumnDesc(rgNewColumnDesc, m_cColumnDesc, TRUE);
CHECK(Table.DropTable(), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(14)
//*-----------------------------------------------------------------------
// @mfunc Constraint is created in a different catalog
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_14()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
DBCONSTRAINTDESC *pConsDesc = (DBCONSTRAINTDESC*)cons;
CCol col;
DBORDINAL indxCat = 0;
CCatalogs Catalogs(m_pIOpenRowset);
IDBProperties *pIDBProperties = NULL;
CPropSets PropSets;
WCHAR *pwszCurrentCatalog = NULL;
WCHAR *pwszQualTableName = NULL;
WCHAR *pwszCatalogName = NULL;
WCHAR *pwszSchemaName = NULL;
TESTC_PROVIDER(SettableProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, m_pIDBInitialize));
TESTC_PROVIDER(1 < Catalogs.cCatalogs());
// create a table and an index
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// select column
TESTC_(Table.GetColInfo(1, col), S_OK);
// set DBID of the table to its qualified form
TESTC(DBKIND_NAME == Table.GetTableID().eKind);
TESTC(GetCatalogSchemaNames(Table.GetTableName(), &pwszCatalogName, &pwszSchemaName));
//Construct a fully Qualified TableName...
TESTC_(m_pTable->GetQualifiedName(pwszCatalogName, pwszSchemaName, Table.GetTableName(), &pwszQualTableName),S_OK);
Table.SetTableName(pwszQualTableName);
// change the current catalog
TESTC(GetProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, m_pIDBInitialize,
&pwszCurrentCatalog));
TESTC(NULL != pwszCurrentCatalog);
TESTC(VerifyInterface(m_pIDBInitialize, IID_IDBProperties, DATASOURCE_INTERFACE, (IUnknown**)&pIDBProperties));
if (0 == wcscmp(pwszCurrentCatalog, Catalogs[0]))
indxCat++;
CHECK(PropSets.AddProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, VT_BSTR, (LPVOID)Catalogs[indxCat]), S_OK);
TESTC_PROVIDER(S_OK == pIDBProperties->SetProperties(PropSets, PropSets));
// alloc memory for column array
cons.AddColumn(col.GetColID());
// try to make column unique
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
if (CHECK(PropSets.SetProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, VT_BSTR, (LPVOID)pwszCurrentCatalog), S_OK))
CHECK(pIDBProperties->SetProperties(PropSets, PropSets), S_OK);
SAFE_FREE(pwszCatalogName);
SAFE_FREE(pwszSchemaName);
SAFE_FREE(pwszQualTableName);
SAFE_FREE(pwszCurrentCatalog);
SAFE_RELEASE(pIDBProperties);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(15)
//*-----------------------------------------------------------------------
// @mfunc create a unique constraint on a non empty table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_15()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
// create a table and an index
TESTC_(Table.CreateTable(10, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// select column
TESTC_(AddUniqueConstraint(&Table, 1), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc Create a unique constraints on a column that has doubled values
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_16()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
// create a table and an index
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// double one of the rows
TESTC_PROVIDER(S_OK == Table.Insert(5));
TESTC_PROVIDER(S_OK == Table.Insert(5));
// add the constraint
TESTC_(AddUniqueConstraint(&Table, 1), DB_E_SCHEMAVIOLATION);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(17)
//*-----------------------------------------------------------------------
// @mfunc Abort retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_17()
{
CAddUniqueConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
TRUE, // Abort
TRUE // Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(18)
//*-----------------------------------------------------------------------
// @mfunc Abort non retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_18()
{
CAddUniqueConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
TRUE, // Abort
FALSE // Non Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(19)
//*-----------------------------------------------------------------------
// @mfunc Commit retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_19()
{
CAddUniqueConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
FALSE, // Commit
TRUE // Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(20)
//*-----------------------------------------------------------------------
// @mfunc Commit non retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_UNIQUE::Variation_20()
{
CAddUniqueConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
FALSE, // Commit
TRUE // Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
int TCAddConstraint_UNIQUE::Variation_21() {
TBEGIN
CLimitTable Table;
TESTC_(Table.CheckUniqueKeyLimit(), S_OK);
CLEANUP:
TRETURN
}
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL TCAddConstraint_UNIQUE::Terminate()
{
// TO DO: Add your own code here
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCITableDefinition::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(TCAddConstraint_PRIMARYKEY)
//*-----------------------------------------------------------------------
//| Test Case: TCAddConstraint_PRIMARYKEY - Testcase for ITableDefinitionWithConstraints::AddConstraint used with DBCONSTRAINTTYPE_PRIMARYKEY
//| Created: 7/29/99
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCAddConstraint_PRIMARYKEY::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCITableDefinition::Init())
// }}
{
// TO DO: Add your own code here
if (m_pITDWC == NULL)
{
odtLog << "ITableDefinitionWithConstraints is not supported.\n";
return TEST_SKIPPED;
}
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Create a table and try to apply the constraint on each column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_1()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL index;
CPrimaryKeyCons cons;
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
HRESULT hrExpected = S_OK;
DBORDINAL cColCount = 0,
cTotalLength = 0,
start = 1,
cTotalColsInTable = 0;
ULONG ulNumberOfTests = 0;
// create a new table with a NOT NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
// create the base table
TESTC_(CreateTableWithNoNullableColumns(&Table, 0), S_OK);
// TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// build the constraint
cTotalColsInTable = Table.CountColumnsOnTable();
while(start < cTotalColsInTable) {
cTotalLength = 0;
hrExpected = S_OK;
cons.ReleaseColumnList();
for (index = start, cColCount = 0; index <= Table.CountColumnsOnTable() &&
cColCount < cMaxColsPerCons; index++, cColCount++)
{
CCol col;
DBORDINAL colSizeInBytes = 0; //how many bytes the column contributes into maximum size of constraint
TESTC_(Table.GetColInfo(index, col), S_OK);
// Note: col.GetColumnSize returns length for string data types and we need size in bytes
// so multiply ColumnSize by 2 for WSTR
if(col.GetIsFixedLength() )
colSizeInBytes = col.GetColumnSize() * (col.GetProviderType()==DBTYPE_WSTR ? 2:1);
else
colSizeInBytes = 0;
if (col.GetIsLong() ||
cTotalLength + colSizeInBytes > cMaxColLengthPerCons)
continue;
cTotalLength += colSizeInBytes;
cons.AddColumn(col.GetColID());
}
if (cColCount)
{
ulNumberOfTests++;
CHECK(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), hrExpected);
if (hrExpected == S_OK) {
CHECK(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
}
// try the same when creating a table
TESTC_(cons.MakeConstraintName(), S_OK);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), hrExpected);
if (hrExpected==S_OK)
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
}
start = index;
}
TESTC(ulNumberOfTests>0)
CLEANUP:
ReleaseColumnDesc(rgNewColumnDesc, m_cColumnDesc, TRUE);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Set a primary key constraint on each type of column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_2()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL index;
CPrimaryKeyCons cons;
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
HRESULT hrExpected = S_OK;
// create a new table with a NOT NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
// create a base table without nullable columns
TESTC_(CreateTableWithNoNullableColumns(&Table, 0), S_OK);
// build the constraint
for (index=1; index <= Table.CountColumnsOnTable(); index++)
{
CCol col;
TESTC_(Table.GetColInfo(index, col), S_OK);
TESTC_(cons.ReleaseColumnList(), S_OK);
cons.AddColumn(col.GetColID());
odtLog << col.GetProviderTypeName() << "\n";
// Depending on the type of column, set return value
// Note: col.GetColumnSize returns length for string data types and we need size in bytes
// so multiply ColumnSize by 2 for WSTR
if (col.GetIsLong() ||
(col.GetIsFixedLength() && (col.GetColumnSize() * (col.GetProviderType()==DBTYPE_WSTR ? 2:1) > cMaxColLengthPerCons)))
hrExpected = E_FAIL;
else
hrExpected = S_OK;
CHECK(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), hrExpected);
if (hrExpected == S_OK) {
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
}
// try the same when creating a table
TESTC_(cons.MakeConstraintName(), S_OK);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), hrExpected);
if (hrExpected == S_OK)
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
}
CLEANUP:
ReleaseColumnDesc(rgNewColumnDesc, m_cColumnDesc, TRUE);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Create a primary key constraint. Drop it. Create a primary key using the same name as before.
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_3()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CPrimaryKeyCons cons;
DBCONSTRAINTDESC *pConsDesc = (DBCONSTRAINTDESC*)cons;
CCol col;
// create a base table without nullable columns
TESTC_(CreateTableWithNoNullableColumns(&Table, 0), S_OK);
// build the constraint
// try to set all the columns as primary key
TESTC_(Table.GetColInfo(1, col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
ReleaseDBID(&pConsDesc->rgColumnList[0], FALSE);
TESTC_(Table.GetColInfo(2, col), S_OK);
DuplicateDBID(*col.GetColID(), &pConsDesc->rgColumnList[0]);
// create constraint with the same name as before, different column
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Create multiple-columned primary key
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_4()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CPrimaryKeyCons cons;
CCol col;
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
// create a new table with a NOT NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
// create a base table without nullable columns
TESTC_(CreateTableWithNoNullableColumns(&Table, 0), S_OK);
TESTC_(Table.GetColInfo(1, col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(Table.GetColInfo(2, col), S_OK);
cons.AddColumn(col.GetColID());
CHECK(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// try the same when creating a table
TESTC_(cons.MakeConstraintName(), S_OK);
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
ReleaseColumnDesc(rgNewColumnDesc, m_cColumnDesc, TRUE);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Create multiple primary key constraints using successive calls
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_5()
{
TBEGIN
HRESULT hr;
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
CPrimaryKeyCons cons;
CConsDescArray consArray;
CCol col;
// create a new table with a NOT NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
// create a base table without nullable columns
TESTC_(CreateTableWithNoNullableColumns(&Table, 0), S_OK);
// build the constraint
TESTC_(AddPrimaryKeyConstraint(&Table, 1), S_OK);
TESTC_(AddPrimaryKeyConstraint(&Table, 1), DB_E_DUPLICATECONSTRAINTID);
// try the same when creating a table
// add a first PK constraint
cons.AddColumn(&rgNewColumnDesc[0].dbcid);
cons.AddColumn(&rgNewColumnDesc[1].dbcid);
consArray.AddConsDesc(cons);
// add a second PK constraint
CHECK(cons.MakeConstraintName(), S_OK);
cons.ReleaseColumnList();
cons.AddColumn(&rgNewColumnDesc[2].dbcid);
consArray.AddConsDesc(cons);
if (!CHECK(hr = CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, consArray, consArray, IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_DUPLICATECONSTRAINTID) && SUCCEEDED(hr))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
ReleaseColumnDesc(rgNewColumnDesc, m_cColumnDesc, TRUE);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Successive calls, lists of columns overlap
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_6()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CPrimaryKeyCons cons;
CPrimaryKeyCons cons2;
CCol col;
// create a base table without nullable columns
TESTC_(CreateTableWithNoNullableColumns(&Table, 0), S_OK);
// build the constraint
TESTC_(Table.GetColInfo(1, col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
TESTC_(Table.GetColInfo(2, col), S_OK);
cons2.AddColumn(col.GetColID());
// try create second constraint
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons2), DB_E_DUPLICATECONSTRAINTID);
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons2), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Primary key constraint on a nullable column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_7()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCol col;
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
CPrimaryKeyCons cons;
// create a new table with a NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
SetProperty(&rgNewColumnDesc[0].rgPropertySets, &rgNewColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_TRUE,
DBPROPOPTIONS_REQUIRED);
Table.SetColumnDesc(rgNewColumnDesc, m_cColumnDesc);
Table.SetBuildColumnDesc(FALSE);
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// identify a nullable column
TESTC_PROVIDER(S_OK == Table.GetColInfo(IsCColNullable, col));
CHECK(AddPrimaryKeyConstraint(&Table, col.GetColNum()), E_FAIL);
// try the same when creating a table
cons.AddColumn(&rgNewColumnDesc[0].dbcid);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), E_FAIL);
//
//{
// CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
// ReleaseDBID(pTableID, TRUE);
//}
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc Primary key constraint on a not nullable column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_8()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
CPrimaryKeyCons cons;
// create a new table with a NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
SetProperty(&rgNewColumnDesc[0].rgPropertySets, &rgNewColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
Table.SetColumnDesc(rgNewColumnDesc, m_cColumnDesc);
Table.SetBuildColumnDesc(FALSE);
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// add a primary key on a not nullable column
CHECK(AddPrimaryKeyConstraint(&Table, 1), S_OK);
// try the same when creating a table
cons.AddColumn(&rgNewColumnDesc[0].dbcid);
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc Primary key constraint on a column with a default value
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_9()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBCOLUMNDESC *rgNewColumnDesc = NULL;
VARIANT value;
CList<WCHAR *,WCHAR *> NativeTypesList;
CList<DBTYPE,DBTYPE> ProviderTypesList;
DBID *pTableID = NULL;
CPrimaryKeyCons cons;
Table.CreateTypeColInfo(NativeTypesList, ProviderTypesList);
// create a new table with a NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
VariantInit(&value);
odtLog << "Default value on type " << rgNewColumnDesc[0].pwszTypeName << "\n";
GetDefaultValue(&rgNewColumnDesc[0], &value, &Table);
SetDefaultProperty(&rgNewColumnDesc[0].rgPropertySets, &rgNewColumnDesc[0].cPropertySets,
&value, DBPROPOPTIONS_REQUIRED); // might be not supported
VariantClear(&value);
SetProperty(&rgNewColumnDesc[0].rgPropertySets, &rgNewColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
Table.SetColumnDesc(rgNewColumnDesc, m_cColumnDesc);
Table.SetBuildColumnDesc(FALSE);
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// add a PK on a column with a default value
CHECK(AddPrimaryKeyConstraint(&Table, 1), S_OK);
// try the same when creating a table
cons.AddColumn(&rgNewColumnDesc[0].dbcid);
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc Primary key constraint on a column defined as unique
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_10()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
CPrimaryKeyCons cons;
TESTC_PROVIDER(SettableProperty(DBPROP_COL_UNIQUE, DBPROPSET_COLUMN, m_pIDBInitialize));
// create a new table with a NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
SetProperty(&rgNewColumnDesc[0].rgPropertySets, &rgNewColumnDesc[0].cPropertySets,
DBPROP_COL_UNIQUE,
VT_BOOL, (LPVOID)VARIANT_TRUE,
DBPROPOPTIONS_REQUIRED);
SetProperty(&rgNewColumnDesc[0].rgPropertySets, &rgNewColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_OPTIONAL);
Table.SetColumnDesc(rgNewColumnDesc, m_cColumnDesc);
Table.SetBuildColumnDesc(FALSE);
TEST2C_(Table.CreateTable(0, 0), S_OK, DB_S_ERRORSOCCURRED);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// add PK on a unique column
CHECK(AddPrimaryKeyConstraint(&Table, 1), S_OK);
// try the same when creating a table
CHECK(cons.MakeConstraintName(), S_OK);
cons.AddColumn(&rgNewColumnDesc[0].dbcid);
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc Primary key constraint on a column defined as primary key => DB_E_DUPLICATECONSTRAINTID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_11()
{
TBEGIN
HRESULT hr;
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
CPrimaryKeyCons cons;
TESTC_PROVIDER(SettableProperty(DBPROP_COL_PRIMARYKEY, DBPROPSET_COLUMN, m_pIDBInitialize));
// create a new table with a NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
SetProperty(&rgNewColumnDesc[0].rgPropertySets, &rgNewColumnDesc[0].cPropertySets,
DBPROP_COL_PRIMARYKEY,
VT_BOOL, (LPVOID)VARIANT_TRUE,
DBPROPOPTIONS_REQUIRED);
SetProperty(&rgNewColumnDesc[0].rgPropertySets, &rgNewColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_OPTIONAL);
Table.SetColumnDesc(rgNewColumnDesc, m_cColumnDesc);
Table.SetBuildColumnDesc(FALSE);
TEST2C_(Table.CreateTable(0, 0), S_OK, DB_S_ERRORSOCCURRED);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// since there already is a primary key on this table
// expect DB_E_DUPLICATECONSTRAINTID
CHECK(AddPrimaryKeyConstraint(&Table, 1), DB_E_DUPLICATECONSTRAINTID);
// try the same when creating a table
cons.AddColumn(&rgNewColumnDesc[0].dbcid);
if (!CHECK(hr = CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_DUPLICATECONSTRAINTID) && SUCCEEDED(hr))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc Primary key constraint on a column that already has a primary key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_12()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCol col;
CPrimaryKeyCons cons;
// create a base table without nullable columns
TESTC_(CreateTableWithNoNullableColumns(&Table, 0), S_OK);
// identify a nullable column
TESTC_(Table.GetColInfo(1, col), S_OK);
// alloc memory for column array
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// another constraint ID
CHECK(cons.MakeConstraintName(), S_OK);
CHECK(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_DUPLICATECONSTRAINTID);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc Primary key constraint on a column that is part of a foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_13()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL indexCol = 1;
DBID *pTableID = NULL;
DBCOLUMNDESC *rgNewColumnDesc = NULL;
CPrimaryKeyCons cons;
CForeignKeyCons consFK;
CConsDescArray consArray;
CCol col;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
// create a base table without nullable columns and a reference table
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0), S_OK);
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// select a column
TESTC(BaseTable.CountColumnsOnTable() == ReferencedTable.CountColumnsOnTable())
// prepare and add the unique constraint on the referenced table
TESTC_(AddUniqueConstraint(&ReferencedTable, indexCol), S_OK);
// build the foreign key constraint, use corresponding columns in tables
CHECK(AddForeignKeyConstraint(&BaseTable, 1, &indexCol,
&ReferencedTable, 1, &indexCol, m_SupportedMatchType), S_OK);
// add the PK constraint on the BaseTable
CHECK(AddPrimaryKeyConstraint(&BaseTable, indexCol), S_OK);
// try the same on a table -> create a PK and a FK, their column lists are not disjoint
// add a first PK constraint
TESTC_(ReferencedTable.GetColInfo(indexCol, col), S_OK);
consFK.AddColumn(col.GetColID());
consFK.AddForeignKeyColumn(&rgNewColumnDesc[indexCol-1].dbcid);
consFK.SetReferencedTableID(&ReferencedTable.GetTableID());
consArray.AddConsDesc(consFK);
// add a second PK constraint
cons.AddColumn(&rgNewColumnDesc[indexCol-1].dbcid);
consArray.AddConsDesc(cons);
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, consArray, consArray, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
ReleaseColumnDesc(rgNewColumnDesc, m_cColumnDesc, TRUE);
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(14)
//*-----------------------------------------------------------------------
// @mfunc Primary key constraint on a column that is part of an index
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_14()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL ulIndexCol = 1;
// create a base table without nullable columns
TESTC_(CreateTableWithNoNullableColumns(&Table, 0, ulIndexCol), S_OK);
// add a PK constraint on the index column
TESTC_(AddPrimaryKeyConstraint(&Table, ulIndexCol), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(15)
//*-----------------------------------------------------------------------
// @mfunc Primary key constraint on a column on a not empty table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_15()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
// create a base table without nullable columns
TESTC_(CreateTableWithNoNullableColumns(&Table, 10), S_OK);
// add PK constraint
TESTC_(AddPrimaryKeyConstraint(&Table, 1), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc Primary key constraint on a column that already has duplicates (for the whole key)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_16()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
// create a base table without nullable columns
TESTC_(CreateTableWithNoNullableColumns(&Table, 10), S_OK);
TESTC_(Table.Insert(7), S_OK);
// expect DB_E_SCHEMAVIOLATION because the table already contains duplicates
TESTC_(AddPrimaryKeyConstraint(&Table, 1), DB_E_SCHEMAVIOLATION);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(17)
//*-----------------------------------------------------------------------
// @mfunc Primary key constraint that has duplicates for a column in the key, but not for the whole key
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_17()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CPrimaryKeyCons cons;
CCol col;
VARIANT value;
DBCOLUMNDESC *rgNewColumnDesc = NULL;
HRESULT hr;
CList<WCHAR *,WCHAR *> NativeTypesList;
CList<DBTYPE,DBTYPE> ProviderTypesList;
Table.CreateTypeColInfo(NativeTypesList, ProviderTypesList);
// create a new table with a NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
SetProperty(&rgNewColumnDesc[0].rgPropertySets, &rgNewColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
VariantInit(&value);
GetDefaultValue(&rgNewColumnDesc[0], &value, &Table);
SetDefaultProperty(&rgNewColumnDesc[0].rgPropertySets, &rgNewColumnDesc[0].cPropertySets,
&value, DBPROPOPTIONS_REQUIRED); // might be not supported
VariantClear(&value);
Table.SetColumnDesc(rgNewColumnDesc+1, m_cColumnDesc-1);
Table.SetBuildColumnDesc(FALSE);
SetProperty(&rgNewColumnDesc[1].rgPropertySets, &rgNewColumnDesc[1].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
TEST2C_(hr = Table.CreateTable(10, 0), S_OK, DB_S_ERRORSOCCURRED);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
TEST2C_(hr = m_pITableDefinition->AddColumn(&Table.GetTableID(),
rgNewColumnDesc, NULL), S_OK, DB_E_ERRORSOCCURRED);
TESTC(S_OK == hr);
// identify a nullable column
TESTC_(Table.GetColInfo(1, col), S_OK);
// build the primary key
cons.AddColumn(&rgNewColumnDesc[0].dbcid);
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
Table.SetColumnDesc(NULL, 0);
ReleaseColumnDesc(rgNewColumnDesc, m_cColumnDesc);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(18)
//*-----------------------------------------------------------------------
// @mfunc Abort retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_18()
{
CAddPrimaryKeyConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
TRUE, // Abort
TRUE // Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(19)
//*-----------------------------------------------------------------------
// @mfunc Abort non retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_19()
{
CAddPrimaryKeyConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
TRUE, // Abort
FALSE // Non Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(20)
//*-----------------------------------------------------------------------
// @mfunc Commit retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_20()
{
CAddPrimaryKeyConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
FALSE, // Commit
TRUE // Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(21)
//*-----------------------------------------------------------------------
// @mfunc Commit non retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_21()
{
CAddPrimaryKeyConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
FALSE, // Commit
FALSE // Non Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(22)
//*-----------------------------------------------------------------------
// @mfunc Create PK in a different catalog
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_PRIMARYKEY::Variation_22()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CPrimaryKeyCons cons;
DBCONSTRAINTDESC *pConsDesc = (DBCONSTRAINTDESC*)cons;
CCol col;
DBORDINAL indxCat = 0;
CCatalogs Catalogs(m_pIOpenRowset);
IDBProperties *pIDBProperties = NULL;
CPropSets PropSets;
WCHAR *pwszCurrentCatalog = NULL;
WCHAR *pwszQualTableName = NULL;
WCHAR *pwszCatalogName = NULL;
WCHAR *pwszSchemaName = NULL;
TESTC_PROVIDER(SettableProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, m_pIDBInitialize));
TESTC_PROVIDER(1 < Catalogs.cCatalogs());
// create a table and an index
TESTC_(CreateTableWithNoNullableColumns(&Table, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// select column
TESTC_(Table.GetColInfo(1, col), S_OK);
// set DBID of the table to its qualified form
TESTC(DBKIND_NAME == Table.GetTableID().eKind);
TESTC(GetCatalogSchemaNames(Table.GetTableName(), &pwszCatalogName, &pwszSchemaName));
//Construct a fully Qualified TableName...
TESTC_(m_pTable->GetQualifiedName(pwszCatalogName, pwszSchemaName, Table.GetTableName(), &pwszQualTableName),S_OK);
Table.SetTableName(pwszQualTableName);
// change the current catalog
TESTC(GetProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, m_pIDBInitialize,
&pwszCurrentCatalog));
TESTC(NULL != pwszCurrentCatalog);
TESTC(VerifyInterface(m_pIDBInitialize, IID_IDBProperties, DATASOURCE_INTERFACE, (IUnknown**)&pIDBProperties));
if (0 == wcscmp(pwszCurrentCatalog, Catalogs[0]))
indxCat++;
CHECK(PropSets.AddProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, VT_BSTR, (LPVOID)Catalogs[indxCat]), S_OK);
TESTC_PROVIDER(S_OK == pIDBProperties->SetProperties(PropSets, PropSets));
// alloc memory for column array
cons.AddColumn(col.GetColID());
// try to make column unique
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
if (CHECK(PropSets.SetProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, VT_BSTR, (LPVOID)pwszCurrentCatalog), S_OK))
CHECK(pIDBProperties->SetProperties(PropSets, PropSets), S_OK);
SAFE_FREE(pwszCatalogName);
SAFE_FREE(pwszSchemaName);
SAFE_FREE(pwszQualTableName);
SAFE_FREE(pwszCurrentCatalog);
SAFE_RELEASE(pIDBProperties);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
int TCAddConstraint_PRIMARYKEY::Variation_23() {
TBEGIN
CLimitTable Table;
TESTC_(Table.CheckPrimaryKeyLimit(), S_OK);
CLEANUP:
TRETURN;
}
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL TCAddConstraint_PRIMARYKEY::Terminate()
{
// TO DO: Add your own code here
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCITableDefinition::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(TCAddConstraint_FOREIGNKEY)
//*-----------------------------------------------------------------------
//| Test Case: TCAddConstraint_FOREIGNKEY - Testcase for ITableDefinitionWithConstraints::AddConstraint used with DBCONSTRAINTTYPE_FOREIGNKEY
//| Created: 7/29/99
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCAddConstraint_FOREIGNKEY::Init()
{
m_pReferenceTable = NULL;
// {{ TCW_INIT_BASECLASS_CHECK
if(TCITableDefinition::Init())
// }}
{
if (m_pITDWC==NULL)
{
odtLog << "ITableDefinitionWithConstraints is not supported.\n";
return TEST_SKIPPED;
}
m_pReferenceTable = new CTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
TESTC_(m_pReferenceTable->CreateTable(0, 1), S_OK);
m_pReferenceTable->AddInfoFromColumnsSchemaRowset(m_pITDWC, m_pReferenceTable->GetTableName());
return TRUE;
}
CLEANUP:
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Simple foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_1()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCol col, col2;
DBORDINAL indexCol = 1;
CForeignKeyCons cons(NULL, m_SupportedMatchType);
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
TESTC_(Table.CreateTable(0, 0), S_OK);
// select columns from tables
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
Table.BuildColumnDescs(&rgNewColumnDesc);
TESTC(Table.CountColumnsOnTable() == m_pReferenceTable->CountColumnsOnTable())
TESTC_(Table.GetColInfo(indexCol, col), S_OK);
TESTC_(m_pReferenceTable->GetColInfo(indexCol, col2), S_OK);
// build the foreign key constraint, use corresponding columns in tables
cons.AddColumn(col2.GetColID());
cons.AddForeignKeyColumn(col.GetColID());
cons.SetReferencedTableID(&m_pReferenceTable->GetTableID());
// add the foreign key constraint
CHECK(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// try the same when creating a table
TESTC_(cons.MakeConstraintName(), S_OK);
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
ReleaseColumnDesc(rgNewColumnDesc, m_cColumnDesc, TRUE);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Foregin key is made of several columns
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_2()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgCol[] = {1, 2};
CForeignKeyCons cons(NULL, m_SupportedMatchType);
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
CCol col;
DBORDINAL index;
// create a new table with a NOT NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(RefTable.CreateTable(0, 0), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
// select a column
TESTC(BaseTable.CountColumnsOnTable() == RefTable.CountColumnsOnTable())
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&RefTable, NUMELEM(rgCol), rgCol), S_OK);
// add the foreign key constraint
CHECK(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&RefTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
// try the same when creating a table
for (index=0; index < NUMELEM(rgCol); index++)
{
TESTC_(RefTable.GetColInfo(rgCol[index], col), S_OK);
cons.AddColumn(col.GetColID());
cons.AddForeignKeyColumn(&rgNewColumnDesc[rgCol[index]-1].dbcid);
}
cons.SetReferencedTableID(&RefTable.GetTableID());
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
ReleaseColumnDesc(rgNewColumnDesc, m_cColumnDesc, TRUE);
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Multiple foreign key constraints on a table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_3()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgCol[] = {1, 2};
DBORDINAL rgCol2[] = {3, 4};
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
CForeignKeyCons cons(NULL, m_SupportedMatchType);
CConsDescArray consArray;
CCol col;
// create a new table with a NOT NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(RefTable.CreateTable(0, 0), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
// select a column
TESTC(BaseTable.CountColumnsOnTable() == RefTable.CountColumnsOnTable())
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&RefTable, NUMELEM(rgCol), rgCol), S_OK);
TESTC_(AddUniqueConstraint(&RefTable, NUMELEM(rgCol2), rgCol2), S_OK);
// add the foreign key constraint
TESTC_(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&RefTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
// set a second foreign constraint
CHECK(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgCol2), rgCol2,
&RefTable, NUMELEM(rgCol2), rgCol2, m_SupportedMatchType), S_OK);
// try to create a table with 2 disjoint FK constraint
TESTC_(RefTable.GetColInfo(rgCol[0], col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(RefTable.GetColInfo(rgCol[1], col), S_OK);
cons.AddColumn(col.GetColID());
cons.AddForeignKeyColumn(&rgNewColumnDesc[rgCol[0]-1].dbcid);
cons.AddForeignKeyColumn(&rgNewColumnDesc[rgCol[1]-1].dbcid);
cons.SetReferencedTableID(&RefTable.GetTableID());
consArray.AddConsDesc(cons);
TESTC_(cons.MakeConstraintName(), S_OK);
CHECK(cons.ReleaseColumnList(), S_OK);
CHECK(cons.ReleaseForeignKeyColumnList(), S_OK);
TESTC_(RefTable.GetColInfo(rgCol2[0], col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(RefTable.GetColInfo(rgCol2[1], col), S_OK);
cons.AddColumn(col.GetColID());
cons.AddForeignKeyColumn(&rgNewColumnDesc[rgCol2[0]-1].dbcid);
cons.AddForeignKeyColumn(&rgNewColumnDesc[rgCol2[1]-1].dbcid);
consArray.AddConsDesc(cons);
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, consArray, consArray, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
ReleaseColumnDesc(rgNewColumnDesc, m_cColumnDesc, TRUE);
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Multiple overlapping foreign key constraints
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_4()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgCol[] = {1, 2};
DBORDINAL rgCol2[] = {3, 2};
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
CForeignKeyCons cons(NULL, m_SupportedMatchType);
CConsDescArray consArray;
CCol col;
// create a new table with a NOT NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(RefTable.CreateTable(0, 0), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
// select a column
TESTC(BaseTable.CountColumnsOnTable() == RefTable.CountColumnsOnTable())
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&RefTable, NUMELEM(rgCol), rgCol), S_OK);
TESTC_(AddUniqueConstraint(&RefTable, NUMELEM(rgCol2), rgCol2), S_OK);
// add the foreign key constraint
TESTC_(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&RefTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
// set a second foreign constraint
TESTC_(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgCol2), rgCol2,
&RefTable, NUMELEM(rgCol2), rgCol2, m_SupportedMatchType), S_OK);
// try to create a table with 2 overlapping FK constraint
TESTC_(RefTable.GetColInfo(rgCol[0], col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(RefTable.GetColInfo(rgCol[1], col), S_OK);
cons.AddColumn(col.GetColID());
cons.AddForeignKeyColumn(&rgNewColumnDesc[rgCol[0]-1].dbcid);
cons.AddForeignKeyColumn(&rgNewColumnDesc[rgCol[1]-1].dbcid);
cons.SetReferencedTableID(&RefTable.GetTableID());
consArray.AddConsDesc(cons);
TESTC_(cons.MakeConstraintName(), S_OK);
CHECK(cons.ReleaseColumnList(), S_OK);
CHECK(cons.ReleaseForeignKeyColumnList(), S_OK);
TESTC_(RefTable.GetColInfo(rgCol2[0], col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(RefTable.GetColInfo(rgCol2[1], col), S_OK);
cons.AddColumn(col.GetColID());
cons.AddForeignKeyColumn(&rgNewColumnDesc[rgCol2[0]-1].dbcid);
cons.AddForeignKeyColumn(&rgNewColumnDesc[rgCol2[1]-1].dbcid);
consArray.AddConsDesc(cons);
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, consArray, consArray, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
ReleaseColumnDesc(rgNewColumnDesc, m_cColumnDesc, TRUE);
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Create a foreign key on each column of the table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_5()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCol col;
CForeignKeyCons cons(NULL, m_SupportedMatchType);
DBORDINAL indexCol;
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
// create a new table with a NOT NULLABLE column
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
BaseTable.BuildColumnDescs(&rgNewColumnDesc);
TESTC_(RefTable.CreateTable(0, 0), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
// select a column
TESTC(BaseTable.CountColumnsOnTable() == RefTable.CountColumnsOnTable())
// set referenced table
cons.SetReferencedTableID(&RefTable.GetTableID());
// make room for columns id
for (indexCol = 1; indexCol <= BaseTable.CountColumnsOnTable(); indexCol++)
{
if (!CHECK(BaseTable.GetColInfo(indexCol, col), S_OK))
continue;
odtLog << col.GetProviderTypeName() << "\n";
// make the referenced columns unique
if (S_OK != AddUniqueConstraint(&RefTable, indexCol))
continue;
// build the foreign key constraint, use corresponding columns in tables
// set column on base table
cons.ReleaseForeignKeyColumnList();
cons.AddForeignKeyColumn(col.GetColID());
// set foreign column
if (!CHECK(RefTable.GetColInfo(indexCol, col), S_OK))
continue;
cons.ReleaseColumnList();
cons.AddColumn(col.GetColID());
// add the foreign key constraint
if (CHECK(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), S_OK))
{
// drop the constraint
CHECK(DropConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), S_OK);
}
// try the same when creating a table
TESTC_(cons.MakeConstraintName(), S_OK);
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
}
CLEANUP:
ReleaseColumnDesc(rgNewColumnDesc, m_cColumnDesc, TRUE);
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Create a foreign key on all columns
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_6()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCol col;
CForeignKeyCons cons(NULL, m_SupportedMatchType);
DBORDINAL indexCol;
CUniqueCons consUnique;
ULONG_PTR uMaxColsInIndex = 0,
uAdded = 0,
uMaxIndexSize = 0,
uCurIndexSize = 0,
uColSizeInBytes = 0;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(RefTable.CreateTable(0, 0), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
// select a column
TESTC(BaseTable.CountColumnsOnTable() == RefTable.CountColumnsOnTable())
// set referenced table
cons.SetReferencedTableID(&RefTable.GetTableID());
if (SupportedProperty(DBPROP_MAXINDEXSIZE, DBPROPSET_DATASOURCEINFO, GetModInfo()->GetThisTestModule()->m_pIUnknown, DATASOURCE_INTERFACE))
TESTC(GetProperty(DBPROP_MAXINDEXSIZE, DBPROPSET_DATASOURCEINFO, GetModInfo()->GetThisTestModule()->m_pIUnknown, &uMaxIndexSize));
for (indexCol = 1; indexCol <= BaseTable.CountColumnsOnTable(); indexCol++)
{
// set column on base table
TESTC_(BaseTable.GetColInfo(indexCol, col), S_OK);
// Note: col.GetColumnSize returns length for string data types and we need size in bytes
// so multiply ColumnSize by 2 for WSTR
if(col.GetIsFixedLength() )
uColSizeInBytes = col.GetColumnSize() * (col.GetProviderType()==DBTYPE_WSTR ? 2:1);
else
uColSizeInBytes = 0;
if (uMaxIndexSize && (uMaxIndexSize - uCurIndexSize) < uColSizeInBytes)
continue;
cons.AddForeignKeyColumn(col.GetColID());
// set foreign column
TESTC_(RefTable.GetColInfo(indexCol, col), S_OK);
cons.AddColumn(col.GetColID());
consUnique.AddColumn(col.GetColID());
uAdded++;
uCurIndexSize += uColSizeInBytes;
if (uMaxColsInIndex && uAdded == uMaxColsInIndex)
break;
}
// make the referenced columns unique
TESTC_(AddConstraintAndCheck(m_pITDWC, &RefTable.GetTableID(), consUnique), S_OK);
// add the foreign key constraint
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), S_OK);
CLEANUP:
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Create foreign key and try to drop the reference table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_7()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CForeignKeyCons cons(NULL, m_SupportedMatchType);
CCol col;
DBORDINAL rgCol[] = {1};
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(RefTable.CreateTable(0, 0), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
// select a column
TESTC(BaseTable.CountColumnsOnTable() == RefTable.CountColumnsOnTable())
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&RefTable, NUMELEM(rgCol), rgCol), S_OK);
// add the foreign key constraint
TESTC_(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&RefTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
// try to drop the table or a column in the FK constraint
TESTC_PROVIDER(S_OK == RefTable.GetColInfo(rgCol[0], col));
CHECK(DropTableAndCheck(&RefTable.GetTableID()), DB_E_DROPRESTRICTED);
CHECK(DropColumnAndCheck(&RefTable.GetTableID(), col.GetColID()), DB_E_DROPRESTRICTED);
CLEANUP:
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc On a nullable column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_8()
{
TBEGIN
DBORDINAL rgCol[] = {1};
DBCOLUMNDESC *rgNewColumnDesc = NULL;
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID *pTableID = NULL;
CForeignKeyCons cons;
CCol col;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
SetProperty(&rgNewColumnDesc[rgCol[0]-1].rgPropertySets, &rgNewColumnDesc[rgCol[0]-1].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_TRUE,
DBPROPOPTIONS_REQUIRED);
BaseTable.SetColumnDesc(rgNewColumnDesc, m_cColumnDesc);
BaseTable.SetBuildColumnDesc(FALSE);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(RefTable.CreateTable(0, 0), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&RefTable, NUMELEM(rgCol), rgCol), S_OK);
// add the FK constraint on the NULLABLE column
CHECK(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&RefTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
// try the same when creating a table
cons.SetReferencedTableID(&RefTable.GetTableID());
cons.AddForeignKeyColumn(&rgNewColumnDesc[rgCol[0]-1].dbcid);
TESTC_(RefTable.GetColInfo(rgCol[0], col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(cons.MakeConstraintName(), S_OK);
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc On a not nullable column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_9()
{
TBEGIN
DBORDINAL rgCol[] = {1};
DBCOLUMNDESC *rgNewColumnDesc = NULL;
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID *pTableID = NULL;
CForeignKeyCons cons;
CCol col;
// create a new table with a NOT NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
SetProperty(&rgNewColumnDesc[rgCol[0]-1].rgPropertySets, &rgNewColumnDesc[rgCol[0]-1].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
BaseTable.SetColumnDesc(rgNewColumnDesc, m_cColumnDesc);
BaseTable.SetBuildColumnDesc(FALSE);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(RefTable.CreateTable(0, 0), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&RefTable, NUMELEM(rgCol), rgCol), S_OK);
// add the FK constraint on the not NULLABLE column
CHECK(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&RefTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
// try the same when creating a table
cons.SetReferencedTableID(&RefTable.GetTableID());
cons.AddForeignKeyColumn(&rgNewColumnDesc[rgCol[0]-1].dbcid);
TESTC_(RefTable.GetColInfo(rgCol[0], col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(cons.MakeConstraintName(), S_OK);
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc On a column having a default value
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_10()
{
TBEGIN
VARIANT value;
DBORDINAL rgCol[] = {1};
DBCOLUMNDESC *rgNewColumnDesc = NULL;
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CList<WCHAR *,WCHAR *> NativeTypesList;
CList<DBTYPE,DBTYPE> ProviderTypesList;
DBID *pTableID = NULL;
CForeignKeyCons cons;
CCol col;
BaseTable.CreateTypeColInfo(NativeTypesList, ProviderTypesList);
// create a new table with a NOT NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
VariantInit(&value);
GetDefaultValue(&rgNewColumnDesc[rgCol[0]-1], &value, &BaseTable);
SetDefaultProperty(&rgNewColumnDesc[rgCol[0]-1].rgPropertySets, &rgNewColumnDesc[rgCol[0]-1].cPropertySets,
&value, DBPROPOPTIONS_REQUIRED); // might be not supported
VariantClear(&value);
BaseTable.SetColumnDesc(rgNewColumnDesc, m_cColumnDesc);
BaseTable.SetBuildColumnDesc(FALSE);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(RefTable.CreateTable(0, 0), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&RefTable, NUMELEM(rgCol), rgCol), S_OK);
// add the FK constraint
CHECK(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&RefTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
// try the same when creating a table
cons.SetReferencedTableID(&RefTable.GetTableID());
cons.AddForeignKeyColumn(&rgNewColumnDesc[rgCol[0]-1].dbcid);
TESTC_(RefTable.GetColInfo(rgCol[0], col), S_OK);
cons.AddColumn(col.GetColID());
TESTC_(cons.MakeConstraintName(), S_OK);
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, 1, cons, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc On a column defined as unique
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_11()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgCol[] = {1};
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
CForeignKeyCons consFK;
CUniqueCons cons;
CCol col, col2;
CConsDescArray consArray;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
BaseTable.BuildColumnDescs(&rgNewColumnDesc);
TESTC_(RefTable.CreateTable(0, 0), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
// select a column
TESTC(BaseTable.CountColumnsOnTable() == RefTable.CountColumnsOnTable())
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&RefTable, NUMELEM(rgCol), rgCol), S_OK);
// make the base column unique
TESTC_(AddUniqueConstraint(&BaseTable, NUMELEM(rgCol), rgCol), S_OK);
// add the FK constraint
TESTC_(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&RefTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
// try to create a table with a unique and a FK cons
TESTC_(RefTable.GetColInfo(rgCol[0], col), S_OK);
TESTC_(BaseTable.GetColInfo(rgCol[0], col2), S_OK);
cons.AddColumn(col2.GetColID());
consArray.AddConsDesc(cons);
consFK.SetReferencedTableID(&RefTable.GetTableID());
consFK.AddForeignKeyColumn(col2.GetColID());
consFK.AddColumn(col.GetColID());
consArray.AddConsDesc(consFK);
TESTC_(cons.MakeConstraintName(), S_OK);
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, consArray, consArray, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
ReleaseColumnDesc(rgNewColumnDesc, m_cColumnDesc, TRUE);
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc On a primary key column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_12()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgCol[] = {1};
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBID *pTableID = NULL;
CForeignKeyCons consFK;
CPrimaryKeyCons cons;
CCol col, col2;
CConsDescArray consArray;
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0), S_OK);
BaseTable.BuildColumnDescs(&rgNewColumnDesc);
TESTC_(RefTable.CreateTable(0, 0), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&RefTable, rgCol[0], (DBDEFERRABILITY)0), S_OK);
// make the base column unique
TESTC_(AddPrimaryKeyConstraint(&BaseTable, rgCol[0], (DBDEFERRABILITY)0), S_OK);
// add FK constraint
CHECK(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&RefTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
// try to create a table with a unique and a FK cons
TESTC_(RefTable.GetColInfo(rgCol[0], col), S_OK);
TESTC_(BaseTable.GetColInfo(rgCol[0], col2), S_OK);
cons.AddColumn(col2.GetColID());
consArray.AddConsDesc(cons);
consFK.SetReferencedTableID(&RefTable.GetTableID());
consFK.AddForeignKeyColumn(col2.GetColID());
consFK.AddColumn(col.GetColID());
consArray.AddConsDesc(consFK);
TESTC_(cons.MakeConstraintName(), S_OK);
if (CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
m_cColumnDesc, rgNewColumnDesc, consArray, consArray, IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK))
{
CHECK(DropTableAndCheck(pTableID, m_pITDWC), S_OK);
ReleaseDBID(pTableID, TRUE);
}
CLEANUP:
ReleaseColumnDesc(rgNewColumnDesc, m_cColumnDesc, TRUE);
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc On a column that is part of the index
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_13()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgCol[] = {1};
TESTC_(BaseTable.CreateTable(0, 1), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(RefTable.CreateTable(0, 1), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&RefTable, 1, (DBDEFERRABILITY)0), S_OK);
TESTC_(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&RefTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
CLEANUP:
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(14)
//*-----------------------------------------------------------------------
// @mfunc On a table that is in another catalog
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_14()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
CCatalogs Catalogs(m_pIOpenRowset);
WCHAR *pwszCurrentCatalog = NULL;
WCHAR *pwszCatalogName = NULL;
WCHAR *pwszSchemaName = NULL;
WCHAR *pwszQualTableName = NULL;
TESTC_PROVIDER(SettableProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, m_pIDBInitialize));
TESTC_PROVIDER(1 < Catalogs.cCatalogs());
// store the name of the current catalog
TESTC(Catalogs.GetCurrentCatalog(&pwszCurrentCatalog));
// change the current catalog
TESTC_(Catalogs.ChangeCurrentCatalog(), S_OK);
// create the referenced table in this catalog
TESTC_PROVIDER(S_OK == ReferencedTable.CreateTable(0, 0));
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
TESTC(GetCatalogSchemaNames(ReferencedTable.GetTableName(), &pwszCatalogName, &pwszSchemaName));
//Construct a fully Qualified TableName...
TESTC_(BaseTable.GetQualifiedName(pwszCatalogName, pwszSchemaName, ReferencedTable.GetTableName(), &pwszQualTableName),S_OK);
ReferencedTable.SetTableName(pwszQualTableName);
// switch back the current catalog
TESTC_(Catalogs.SetCurrentCatalog(pwszCurrentCatalog), S_OK);
// create the base table
BaseTable.SetTableName(NULL);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
// create the
CHECK(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol,
m_SupportedMatchType), S_OK);
CLEANUP:
if (pwszCurrentCatalog)
// restore the name of the current catalog
COMPARE(Catalogs.SetCurrentCatalog(pwszCurrentCatalog), S_OK);
SAFE_FREE(pwszCurrentCatalog);
SAFE_FREE(pwszCatalogName);
SAFE_FREE(pwszSchemaName);
SAFE_FREE(pwszQualTableName);
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(15)
//*-----------------------------------------------------------------------
// @mfunc Use different combination for update/delete rules, as well as match type
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_15()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgCol[] = {1};
DBUPDELRULE rgUPDLValues[] = {DBUPDELRULE_NOACTION, DBUPDELRULE_CASCADE,
DBUPDELRULE_SETNULL, DBUPDELRULE_SETDEFAULT};
WCHAR *rgUPDLValuesText[] = {L"DBUPDELRULE_NOACTION", L"DBUPDELRULE_CASCADE",
L"DBUPDELRULE_SETNULL", L"DBUPDELRULE_SETDEFAULT"};
DBORDINAL indexDelete;
DBORDINAL indexUpdate;
DBMATCHTYPE rgMatchType[] = {DBMATCHTYPE_NONE, DBMATCHTYPE_FULL, DBMATCHTYPE_PARTIAL};
WCHAR *rgMatchTypeText[] = {L"DBMATCHTYPE_NONE", L"DBMATCHTYPE_FULL", L"DBMATCHTYPE_PARTIAL"};
DBORDINAL indexMatchType;
DBORDINAL cSuccess = 0;
HRESULT hr;
TESTC_(BaseTable.CreateTable(0, 1), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(RefTable.CreateTable(0, 0), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&RefTable, 1, (DBDEFERRABILITY)0), S_OK);
for (indexDelete = 0; indexDelete < NUMELEM(rgUPDLValues); indexDelete++)
{
// all delete rules
odtLog << "\t" << rgUPDLValuesText[indexDelete] << "\n";
for (indexUpdate = 0; indexUpdate < NUMELEM(rgUPDLValues); indexUpdate++)
{
// all update rules
odtLog << "\t\t" << rgUPDLValuesText[indexUpdate] << "\n";
for (indexMatchType = 0; indexMatchType < NUMELEM(rgMatchType); indexMatchType++)
{
CForeignKeyCons cons;
// all match type rules
odtLog << "\t\t\t" << rgMatchTypeText[indexMatchType];
cons.SetConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&RefTable, NUMELEM(rgCol), rgCol,
rgMatchType[indexMatchType],
rgUPDLValues[indexUpdate],
rgUPDLValues[indexDelete],
(DBDEFERRABILITY)0);
hr = AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons);
if (S_OK == hr)
{
odtLog << "\n";
cSuccess++;
CHECK(DropConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(),
cons.GetConstraintID()), S_OK);
}
else if (DB_E_BADUPDATEDELETERULE != hr && DB_E_BADMATCHTYPE!= hr)
{
CHECK(hr, S_OK);
}
else
odtLog << "\tunsupported " << ((DB_E_BADUPDATEDELETERULE == hr) ? "rule" : "match type") << "\n";
}
}
}
TESTC(0 < cSuccess);
CLEANUP:
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc Referenced table name and base table names have maximum length
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_16()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgCol[] = {1};
WCHAR *pwszTableName = NULL;
BaseTable.MakeTableName(NULL);
pwszTableName = BuildValidName(m_cMaxTableName, BaseTable.GetTableName());
TESTC_(BaseTable.CreateTable(0, 0, pwszTableName), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(RefTable.CreateTable(0, 0), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&RefTable, 1, (DBDEFERRABILITY)0), S_OK);
TESTC_(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&RefTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
CLEANUP:
SAFE_FREE(pwszTableName);
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(17)
//*-----------------------------------------------------------------------
// @mfunc Columns in the foreign key (base table and reference table) have different names
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_17()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBCOLUMNDESC *rgNewColumnDesc = NULL;
DBORDINAL rgCol[] = {1};
// the name of the column should be different
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgNewColumnDesc);
ReleaseDBID(&rgNewColumnDesc[0].dbcid, FALSE);
rgNewColumnDesc[0].dbcid.eKind = DBKIND_NAME;
rgNewColumnDesc[0].dbcid.uName.pwszName = wcsDuplicate(L"AnotherColumn");
BaseTable.SetColumnDesc(rgNewColumnDesc, m_cColumnDesc);
BaseTable.SetBuildColumnDesc(FALSE);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(RefTable.CreateTable(0, 0), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&RefTable, 1, (DBDEFERRABILITY)0), S_OK);
TESTC_(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&RefTable, NUMELEM(rgCol), rgCol, m_SupportedMatchType), S_OK);
CLEANUP:
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(18)
//*-----------------------------------------------------------------------
// @mfunc Different size in column lists (base table and referenced)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_18()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable RefTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgCol[] = {1};
DBORDINAL rgCol2[] = {1, 2};
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(RefTable.CreateTable(0, 0), S_OK);
RefTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, RefTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&RefTable, 1, (DBDEFERRABILITY)0), S_OK);
TESTC_(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&RefTable, NUMELEM(rgCol2), rgCol2, m_SupportedMatchType), E_INVALIDARG);
TESTC_(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgCol), rgCol,
&RefTable, NUMELEM(rgCol2), rgCol2, m_SupportedMatchType), E_INVALIDARG);
CLEANUP:
BaseTable.DropTable();
RefTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(19)
//*-----------------------------------------------------------------------
// @mfunc Column types in base table and reference table are different
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_19()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {3};
CCol col;
HRESULT hr;
CForeignKeyCons cons(NULL, m_SupportedMatchType);
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// find 2 columns of different types (DBTYPE_I4 and DBTYPE_R4)
TESTC_PROVIDER(S_OK == ReferencedTable.GetColInfo(col, DBTYPE_I4));
rgReferencedCol[0] = col.GetColNum();
TESTC_PROVIDER(S_OK == BaseTable.GetColInfo(col, DBTYPE_R4));
rgBaseCol[0] = col.GetColNum();
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
CHECK(ReferencedTable.GetColInfo(rgReferencedCol[0], col), S_OK);
cons.AddColumn(col.GetColID());
CHECK(BaseTable.GetColInfo(rgBaseCol[0], col), S_OK);
cons.AddForeignKeyColumn(col.GetColID());
cons.SetReferencedTableID(&ReferencedTable.GetTableID());
CHECK(hr = AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons, TRUE), DB_E_BADCONSTRAINTFORM);
if (S_OK == hr)
{
// challenge the constraint
TESTC_(ReferencedTable.Insert(12), S_OK);
TESTC_(BaseTable.Insert(12), S_OK);
}
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(20)
//*-----------------------------------------------------------------------
// @mfunc Invalid value for the update rule
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_20()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
CHECK(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol,
m_SupportedMatchType, 0xFF), DB_E_BADUPDATEDELETERULE);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(21)
//*-----------------------------------------------------------------------
// @mfunc Invalid value for the delete rule
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_21()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
CHECK(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol,
m_SupportedMatchType, DBUPDELRULE_NOACTION, 0xFF), DB_E_BADUPDATEDELETERULE);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(22)
//*-----------------------------------------------------------------------
// @mfunc Invalid value for the MatchType
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_22()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
CHECK(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol,
0xFF), DB_E_BADMATCHTYPE);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(23)
//*-----------------------------------------------------------------------
// @mfunc Inexistent column names in the referenced table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_23()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
CForeignKeyCons cons;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
TESTC_(cons.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol, m_SupportedMatchType), S_OK);
// release the referenced column and set inexistent name
SAFE_FREE(((DBCONSTRAINTDESC*)cons)->rgColumnList[0].uName.pwszName);
((DBCONSTRAINTDESC*)cons)->rgColumnList[0].uName.pwszName = wcsDuplicate(L"NuExista");
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), DB_E_NOCOLUMN);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(24)
//*-----------------------------------------------------------------------
// @mfunc Inexistent column name in the base table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_24()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
CForeignKeyCons cons;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
TESTC_(cons.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol, m_SupportedMatchType), S_OK);
// release the referenced column and set inexistent name
SAFE_FREE(((DBCONSTRAINTDESC*)cons)->rgForeignKeyColumnList[0].uName.pwszName);
((DBCONSTRAINTDESC*)cons)->rgForeignKeyColumnList[0].uName.pwszName = wcsDuplicate(L"NuExista");
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), DB_E_NOCOLUMN);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(25)
//*-----------------------------------------------------------------------
// @mfunc Inexistent base table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_25()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
CForeignKeyCons cons;
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// since base table name has to be inexistent, use reference table name instead
TESTC_(cons.SetConstraint(&ReferencedTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol, m_SupportedMatchType), S_OK);
TESTC_(BaseTable.MakeTableName(NULL), S_OK);
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), DB_E_NOTABLE);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(26)
//*-----------------------------------------------------------------------
// @mfunc Inexistent reference table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_26()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
CForeignKeyCons cons;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
// since base table name has to be inexistent, use reference table name instead
TESTC_(cons.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&BaseTable, NUMELEM(rgReferencedCol), rgReferencedCol, m_SupportedMatchType), S_OK);
// fill-in an inexistent table name
TESTC_(ReferencedTable.MakeTableName(NULL), S_OK);
ReleaseDBID(((DBCONSTRAINTDESC*)cons)->pReferencedTableID, FALSE);
TESTC_(DuplicateDBID(ReferencedTable.GetTableID(), ((DBCONSTRAINTDESC*)cons)->pReferencedTableID), S_OK);
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), DB_E_NOTABLE);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(27)
//*-----------------------------------------------------------------------
// @mfunc NULL pConstraintID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_27()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
CForeignKeyCons cons;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
TESTC_(cons.SetConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol, m_SupportedMatchType), S_OK);
// release pConstraintID
ReleaseDBID(((DBCONSTRAINTDESC*)cons)->pConstraintID, TRUE);
((DBCONSTRAINTDESC*)cons)->pConstraintID = NULL;
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), S_OK);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(28)
//*-----------------------------------------------------------------------
// @mfunc Referenced col list is not a unique / pk constraint => failure
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_28()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCol col, col2;
DBORDINAL indexCol = 1;
CForeignKeyCons cons(NULL, m_SupportedMatchType);
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
// select columns from tables
TESTC(BaseTable.CountColumnsOnTable() == ReferencedTable.CountColumnsOnTable())
TESTC_(BaseTable.GetColInfo(indexCol, col), S_OK);
TESTC_(ReferencedTable.GetColInfo(indexCol, col2), S_OK);
// build the foreign key constraint, use corresponding columns in tables
cons.AddColumn(col2.GetColID());
cons.AddForeignKeyColumn(col.GetColID());
cons.SetReferencedTableID(&ReferencedTable.GetTableID());
// add the foreign key constraint
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), E_FAIL);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(29)
//*-----------------------------------------------------------------------
// @mfunc Create a foreign key and then insert a NULL value for one of the fk columns
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_29()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBORDINAL rgCols[] = {1, 2, 3};
IRowsetChange *pIRowsetChange = NULL;
DBMATCHTYPE rgMatchType[] = {DBMATCHTYPE_NONE, DBMATCHTYPE_FULL, DBMATCHTYPE_PARTIAL};
WCHAR *rgMatchTypeText[] = {L"DBMATCHTYPE_NONE", L"DBMATCHTYPE_FULL", L"DBMATCHTYPE_PARTIAL"};
DBORDINAL indexMatchType;
DBORDINAL cSuccess = 0;
HRESULT hr;
const DBORDINAL cProp = 1;
DBPROP rgProp[cProp];
const DBORDINAL cPropSets = 1;
DBPROPSET rgPropSets[cPropSets];
rgPropSets[0].guidPropertySet = DBPROPSET_ROWSET;
rgPropSets[0].cProperties = 1;
rgPropSets[0].rgProperties = rgProp;
memset(rgProp, 0, sizeof(DBPROP));
rgProp[0].dwPropertyID = DBPROP_UPDATABILITY;
rgProp[0].vValue.vt = VT_I4;
V_I4(&rgProp[0].vValue) = DBPROPVAL_UP_INSERT;
CList<WCHAR *,WCHAR *> NativeTypesList;
CList<DBTYPE,DBTYPE> ProviderTypesList;
DBCOLUMNDESC *rgColumnDesc = NULL;
BaseTable.CreateTypeColInfo(NativeTypesList, ProviderTypesList);
TESTC_PROVIDER(2 < m_cColumnDesc);
// create a new table with a NOT NULLABLE column
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_TRUE,
DBPROPOPTIONS_REQUIRED);
SetProperty(&rgColumnDesc[1].rgPropertySets, &rgColumnDesc[1].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_TRUE,
DBPROPOPTIONS_REQUIRED);
SetProperty(&rgColumnDesc[2].rgPropertySets, &rgColumnDesc[2].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_TRUE,
DBPROPOPTIONS_REQUIRED);
BaseTable.SetColumnDesc(rgColumnDesc, m_cColumnDesc);
BaseTable.SetBuildColumnDesc(FALSE);
TESTC_PROVIDER(S_OK == BaseTable.CreateTable(0, 0));
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(CreateTableWithNoNullableColumns(&ReferencedTable, 5, 0), S_OK);
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, NUMELEM(rgCols), rgCols, (DBDEFERRABILITY)0), S_OK);
for (indexMatchType = 0; indexMatchType < NUMELEM(rgMatchType); indexMatchType++)
{
CForeignKeyCons cons;
// all match type rules
odtLog << "\t\t\t" << rgMatchTypeText[indexMatchType];
cons.SetConstraint(&BaseTable, NUMELEM(rgCols), rgCols,
&ReferencedTable, NUMELEM(rgCols), rgCols,
rgMatchType[indexMatchType],
DBUPDELRULE_NOACTION,
DBUPDELRULE_NOACTION,
(DBDEFERRABILITY)0);
hr = AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons);
if (S_OK == hr)
{
odtLog << "\n";
cSuccess++;
{
// open a rowset on the base table
TESTC_(g_pIOpenRowset->OpenRowset(NULL, &BaseTable.GetTableID(), NULL,
IID_IRowsetChange, cPropSets, rgPropSets, (IUnknown**)&pIRowsetChange), S_OK);
// try to insert a NULL in the second column
// this should succeed if the match type is partial and the rest
// of the key matches a rows in the referenced table
CHECK(Insert(3, pIRowsetChange, 1, rgCols + 1, &BaseTable),
(DBMATCHTYPE_FULL != rgMatchType[indexMatchType])? S_OK: DB_E_INTEGRITYVIOLATION);
CHECK(Insert(3, pIRowsetChange, 3, rgCols, &BaseTable), S_OK);
//(DBMATCHTYPE_FULL == rgMatchType[indexMatchType])? S_OK: DB_E_INTEGRITYVIOLATION);
CHECK(Insert(32, pIRowsetChange, 1, rgCols + 1, &BaseTable),
(DBMATCHTYPE_NONE == rgMatchType[indexMatchType])? S_OK: DB_E_INTEGRITYVIOLATION);
SAFE_RELEASE(pIRowsetChange);
}
CHECK(DropConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(),
cons.GetConstraintID()), S_OK);
}
else if (DB_E_BADMATCHTYPE!= hr)
{
CHECK(hr, S_OK);
}
else
odtLog << "\tunsupported " << ((DB_E_BADUPDATEDELETERULE == hr) ? "rule" : "match type") << "\n";
}
TESTC(0 < cSuccess);
CLEANUP:
SAFE_RELEASE(pIRowsetChange);
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(30)
//*-----------------------------------------------------------------------
// @mfunc The referenced table and the base table are the same
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_30()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCol col, col2;
DBORDINAL indexCol = 1;
HRESULT hr;
CForeignKeyCons cons(NULL, m_SupportedMatchType);
DBCOLUMNDESC *rgColumnDesc;
DuplicateColumnDesc(m_rgColumnDesc, 1, &rgColumnDesc);
ReleaseDBID(&rgColumnDesc[0].dbcid, FALSE);
rgColumnDesc[0].dbcid.eKind = DBKIND_NAME;
rgColumnDesc[0].dbcid.uName.pwszName = wcsDuplicate(L"NewColumn");
ReleaseAllColumnPropSets(rgColumnDesc, 1);
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
TESTC_(AddUniqueConstraint(&Table, indexCol), S_OK);
TESTC_(AddColumnAndCheck(&Table.GetTableID(), rgColumnDesc, NULL, m_pITDWC), S_OK);
// select columns from tables
TESTC_(Table.GetColInfo(indexCol, col), S_OK);
// build the foreign key constraint, use corresponding columns in tables
cons.AddColumn(col.GetColID());
cons.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
cons.SetReferencedTableID(&Table.GetTableID());
// add the foreign key constraint
hr = AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons);
TEST2C_(hr, S_OK, DB_E_BADMATCHTYPE);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, 1);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(31)
//*-----------------------------------------------------------------------
// @mfunc The base and referenced tables are temporary tables
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_31()
{
TBEGIN
CCol col;
DBORDINAL indexCol = 1;
CForeignKeyCons cons(NULL, m_SupportedMatchType);
CUniqueCons UniqueCons;
DBID *pBaseTableID = NULL;
DBID *pReferencedTableID = NULL;
DBPROPSET rgPropSets[1];
DBPROP rgProp[1];
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
TESTC_PROVIDER(SettableProperty(DBPROP_TBL_TEMPTABLE, DBPROPSET_TABLE));
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// temp table, TableID generated by provider
FILL_PROP_SET(rgPropSets[0], NUMELEM(rgProp), rgProp, DBPROPSET_TABLE);
FILL_PROP(rgProp[0], DBPROP_TBL_TEMPTABLE, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
TESTC_(CreateAndCheckTable(m_pITDWC, NULL, NULL, cColumnDesc, rgColumnDesc,
IID_IRowset, NUMELEM(rgPropSets), rgPropSets, &pReferencedTableID, NULL), S_OK);
UniqueCons.AddColumn(&rgColumnDesc[0].dbcid);
TESTC_(AddConstraintAndCheck(m_pITDWC, pReferencedTableID, UniqueCons), S_OK);
TESTC_(CreateAndCheckTable(m_pITDWC, NULL, NULL, cColumnDesc, rgColumnDesc,
IID_IRowset, NUMELEM(rgPropSets), rgPropSets, &pBaseTableID, NULL), S_OK);
// select columns from tables
// build the foreign key constraint, use corresponding columns in tables
cons.AddColumn(&rgColumnDesc[0].dbcid);
cons.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
cons.SetReferencedTableID(pReferencedTableID);
// add the foreign key constraint
TESTC_(AddConstraintAndCheck(m_pITDWC, pBaseTableID, cons), S_OK);
CLEANUP:
DropTableAndCheck(pBaseTableID);
DropTableAndCheck(pReferencedTableID);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pReferencedTableID, TRUE);
ReleaseDBID(pBaseTableID, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(32)
//*-----------------------------------------------------------------------
// @mfunc Base table is a temporary table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_32()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCol col;
DBORDINAL indexCol = 1;
CForeignKeyCons cons(NULL, m_SupportedMatchType);
DBID *pBaseTableID = NULL;
DBPROPSET rgPropSets[1];
DBPROP rgProp[1];
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
TESTC_PROVIDER(SettableProperty(DBPROP_TBL_TEMPTABLE, DBPROPSET_TABLE));
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
// temp table, TableID generated by provider
FILL_PROP_SET(rgPropSets[0], NUMELEM(rgProp), rgProp, DBPROPSET_TABLE);
FILL_PROP(rgProp[0], DBPROP_TBL_TEMPTABLE, VT_BOOL, V_BOOL, VARIANT_TRUE, DBPROPOPTIONS_REQUIRED);
TESTC_(CreateAndCheckTable(m_pITDWC, NULL, NULL, cColumnDesc, rgColumnDesc,
IID_IRowset, NUMELEM(rgPropSets), rgPropSets, &pBaseTableID, NULL), S_OK);
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
TESTC_(AddUniqueConstraint(&ReferencedTable, indexCol), S_OK);
// select columns from tables
TESTC(ReferencedTable.CountColumnsOnTable() == cColumnDesc)
TESTC_(ReferencedTable.GetColInfo(indexCol, col), S_OK);
// build the foreign key constraint, use corresponding columns in tables
cons.AddColumn(col.GetColID());
cons.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
cons.SetReferencedTableID(&ReferencedTable.GetTableID());
// add the foreign key constraint
TESTC_(AddConstraintAndCheck(m_pITDWC, pBaseTableID, cons), S_OK);
CLEANUP:
DropTableAndCheck(pBaseTableID);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pBaseTableID, TRUE);
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(33)
//*-----------------------------------------------------------------------
// @mfunc Abort retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_33()
{
CAddFKConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
TRUE, // Abort
TRUE // Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(34)
//*-----------------------------------------------------------------------
// @mfunc Abort non retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_34()
{
CAddFKConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
TRUE, // Abort
FALSE // Non Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(35)
//*-----------------------------------------------------------------------
// @mfunc Commit retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_35()
{
CAddFKConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
FALSE, // Commit
TRUE // Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(36)
//*-----------------------------------------------------------------------
// @mfunc Commit non retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_36()
{
CAddFKConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
FALSE, // Commit
FALSE // Non Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(37)
//*-----------------------------------------------------------------------
// @mfunc The base table is already populated and the referenced one is empty => DB_E_SCHEMAVIOLATION
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_FOREIGNKEY::Variation_37()
{
TBEGIN
CTable BaseTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCol col, col2;
DBORDINAL indexCol = 1;
CForeignKeyCons cons(NULL, m_SupportedMatchType);
TESTC_(BaseTable.CreateTable(5, 0), S_OK);
// select columns from tables
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC(BaseTable.CountColumnsOnTable() == m_pReferenceTable->CountColumnsOnTable())
TESTC_(BaseTable.GetColInfo(indexCol, col), S_OK);
TESTC_(m_pReferenceTable->GetColInfo(indexCol, col2), S_OK);
// build the foreign key constraint, use corresponding columns in tables
cons.AddColumn(col2.GetColID());
cons.AddForeignKeyColumn(col.GetColID());
cons.SetReferencedTableID(&m_pReferenceTable->GetTableID());
// add the foreign key constraint
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), DB_E_SCHEMAVIOLATION);
CLEANUP:
BaseTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
int TCAddConstraint_FOREIGNKEY::Variation_38() {
TBEGIN
CLimitTable Table;
TESTC_(Table.CheckForeignKeyLimit(), S_OK);
CLEANUP:
TRETURN
}
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL TCAddConstraint_FOREIGNKEY::Terminate()
{
if (m_pReferenceTable)
m_pReferenceTable->DropTable();
delete m_pReferenceTable;
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCITableDefinition::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(TCAddConstraint_CHECK)
//*-----------------------------------------------------------------------
//| Test Case: TCAddConstraint_CHECK - Testcase for ITableDefinitionWithConstraints::AddConstraint used with DBCONSTRAINTTYPE_UNIQUE
//| Created: 7/29/99
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCAddConstraint_CHECK::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCITableDefinition::Init())
// }}
{
if (m_pITDWC == NULL)
{
odtLog << "ITableDefinitionWithConstraints is not supported.\n";
return TEST_SKIPPED;
}
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Add simple check constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_1()
{
TBEGIN
HRESULT hr;
IRowsetChange *pIRowsetChange = NULL;
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons;
DBORDINAL rgNULLCols[] = {1};
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITableDefinition,
Table.GetTableID().eKind? Table.GetTableID().uName.pwszName: NULL);
// get the first column of the table
cons.SetIsNotNULLCheckConstraint(&Table, rgNULLCols[0]);
// add the constraint and check its addition
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
TEST2C_(hr = m_pIOpenRowset->OpenRowset(NULL, &Table.GetTableID(), NULL,
IID_IRowsetChange, 0, NULL, (IUnknown**)&pIRowsetChange), S_OK, E_NOINTERFACE);
TESTC_PROVIDER(S_OK == hr);
// try to insert a null value in a not null column
TESTC_(hr = Insert(0, pIRowsetChange, NUMELEM(rgNULLCols), rgNULLCols), DB_E_INTEGRITYVIOLATION);
TESTC_(Table.GetColInfo(rgNULLCols[0], col), S_OK);
TEST2C_(hr = DropColumnAndCheck(&Table.GetTableID(), col.GetColID()), S_OK, DB_E_DROPRESTRICTED);
CLEANUP:
SAFE_RELEASE(pIRowsetChange);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Add 2 check constraints on the same column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_2()
{
TBEGIN
CCheckCons cons;
DBORDINAL indexCol = 1;
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// get the first column of the table
TESTC_(cons.SetIsNotNULLCheckConstraint(&Table, indexCol), S_OK);
// add the constraint and check its addition
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// change the name of the constraint helper object
CHECK(cons.MakeConstraintName(), S_OK);
// create the text of the constraint
TESTC_(cons.SetLTCheckConstraint(&Table, indexCol, 2), S_OK);
// add the constraint and check its addition
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Add check constraint for each column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_3()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons;
CCol col;
DBORDINAL indexCol;
HRESULT hrExpected = S_OK;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
for (indexCol = 0; indexCol < Table.CountColumnsOnTable(); indexCol++)
{
// get the first column of the table
TESTC_(Table.GetColInfo(indexCol+1, col), S_OK);
// change the name of the constraint helper object
cons.SetConstraintName(col.GetColName());
CHECK(cons.MakeConstraintName(), S_OK);
// create the text of the constraint
if (S_OK != cons.SetLTCheckConstraint(&Table, indexCol+1, 2))
CHECK(cons.SetIsNotNULLCheckConstraint(&Table, indexCol+1), S_OK);
// Check Constraints on BLOBs should fail
if (col.GetIsLong())
hrExpected = E_FAIL;
else
hrExpected = S_OK;
odtLog << col.GetColName() << "\t -> " << (hrExpected==S_OK ? "S_OK" : "E_FAIL") << "\n";
// add the constraint and check its addition
CHECK(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), hrExpected);
}
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Check constraint is always TRUE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_4()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons(L"TRUE");
CWString wszText;
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// add the constraint and check its addition
TESTC_(Table.GetColInfo(1, col), S_OK);
wszText = col.GetColName();
wszText + L" IS NULL OR ";
wszText + col.GetColName();
wszText + L" IS NOT NULL";
cons.SetConstraintText((LPWSTR)(LPCWSTR)wszText);
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Check constraint is always false
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_5()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons(L"FALSE");
CWString wszText;
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// add the constraint and check its addition
TESTC_(Table.GetColInfo(1, col), S_OK);
wszText = col.GetColName();
wszText + L" IS NULL AND ";
wszText + col.GetColName();
wszText + L" IS NOT NULL";
cons.SetConstraintText((LPWSTR)(LPCWSTR)wszText);
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Long text for the check constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_6()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons;
const DBORDINAL cTextLen = 1001;
WCHAR wszText[cTextLen];
CCol col;
CWString wszText1;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
TESTC_(Table.GetColInfo(1, col), S_OK);
wszText1 = col.GetColName();
wszText1 + L" IS NULL";
swprintf(wszText, L"%1000s", (LPCWSTR)wszText1);
cons.SetConstraintText(wszText);
// add the constraint and check its addition
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Check constraint is made of white characters
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_7()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons(L" \t");
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// add the constraint and check its addition
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), E_FAIL);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc Maximum length for the table name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_8()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons;
WCHAR *pwszTableName = NULL;
// set a long table name
m_pTable->MakeTableName(NULL);
pwszTableName = BuildValidName(m_cMaxTableName, m_pTable->GetTableName());
TESTC_(Table.CreateTable(0, 0, pwszTableName), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// create the text of the constraint
CHECK(cons.SetLTCheckConstraint(&Table, 1, 5), S_OK);
// add the constraint and check its addition
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
SAFE_FREE(pwszTableName);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc Create the constraint, drop it, readd it with different text
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_9()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons;
// create a table with an index
TESTC_(Table.CreateTable(0, 1), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// create the text of the constraint
CHECK(cons.SetLTCheckConstraint(&Table, 1, 5), S_OK);
// add the constraint and check its addition
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// set a different text
CHECK(cons.SetIsNotNULLCheckConstraint(&Table, 2), S_OK);
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc Use inexistent column names in the check constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_10()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons(L"InexistentCol < 10");
CCol col;
// create a table with an index
TESTC_(Table.CreateTable(0, 1), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// add the constraint and check its addition
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_NOCOLUMN);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc Use qualified table column with different table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_11()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable Table2(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons;
CCol col;
WCHAR *pwszColValue = NULL;
CWString wszText;
HRESULT hr = S_OK;
DBCOLUMNDESC *rgColumnDesc = NULL;
// create a table with an index
TESTC_(Table.CreateTable(0, 1), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
Table.BuildColumnDescs(&rgColumnDesc);
//Second table should have the same columns' names
Table2.SetColumnDesc(rgColumnDesc, Table.CountColumnsOnTable());
Table2.SetBuildColumnDesc(FALSE);
TESTC_(Table2.CreateTable(0, 1), S_OK);
Table2.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table2.GetTableName());
// get the first column of the table
TESTC_(Table2.GetColInfo(1 , col), S_OK);
// create the text of the constraint
TESTC_(Table.GetLiteralAndValue(col, &pwszColValue, rand(), col.GetColNum(), PRIMARY), S_OK);
wszText = Table2.GetTableName();
wszText + L".";
wszText + col.GetColName();
wszText + L" < ";
wszText + pwszColValue;
cons.SetConstraintText((LPWSTR)(LPCWSTR)wszText);
// add the constraint and check its addition
//Note: according to the spec provider can return E_FAIL or DB_E_NOCOLUMN when
// column referenced by pwszConstraintText does not exist
// DB_E_BADCONSTRAINTFORM can not be retunred in this case
//TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_BADCONSTRAINTFORM);
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_NOCOLUMN);
CLEANUP:
SAFE_FREE(pwszColValue);
Table.DropTable();
Table2.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc Set a check condition on an index column
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_12()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons;
DBORDINAL indexCol = 1;
// create a table with an index
TESTC_(Table.CreateTable(0, indexCol), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
CHECK(cons.SetLTCheckConstraint(&Table, indexCol, 7), S_OK);
// add the constraint and check its addition
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc pwszConstraintText is NULL
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_13()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
cons.SetConstraintText(NULL);
// add the constraint and check its addition
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_BADCONSTRAINTFORM);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(14)
//*-----------------------------------------------------------------------
// @mfunc pwszConstraintText is an empty string
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_14()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons(L"");
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// add the constraint and check its addition
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), E_FAIL);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(15)
//*-----------------------------------------------------------------------
// @mfunc Abort retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_15()
{
CAddCheckConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
TRUE, // Abort
TRUE // Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc Abort non retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_16()
{
CAddCheckConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
TRUE, // Abort
FALSE // Non Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(17)
//*-----------------------------------------------------------------------
// @mfunc Commit retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_17()
{
CAddCheckConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
FALSE, // Commit
TRUE // Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(18)
//*-----------------------------------------------------------------------
// @mfunc Commit non retaining
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_18()
{
CAddCheckConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
FALSE, // Commit
FALSE // Non Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(19)
//*-----------------------------------------------------------------------
// @mfunc Table is populated with rows that break the constraint to be added => DB_E_SCHEMAVIOLATION
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_CHECK::Variation_19()
{
TBEGIN
HRESULT hr;
IRowsetChange *pIRowsetChange = NULL;
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons;
CCol col;
DBORDINAL rgNULLCols[1];
WCHAR *pwszConstraintText = NULL;
WCHAR wszText[] = L" IS NOT NULL";
TESTC_(Table.CreateTable(5, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITableDefinition,
Table.GetTableID().eKind? Table.GetTableID().uName.pwszName: NULL);
// get the first column of the table
TESTC_(Table.GetColInfo(1 , col), S_OK);
SAFE_ALLOC(pwszConstraintText, WCHAR, 1 + wcslen(col.GetColName()) + wcslen(wszText));
wcscpy(pwszConstraintText, col.GetColName());
wcscat(pwszConstraintText, wszText);
cons.SetConstraintText(pwszConstraintText);
// add a row with a NULL first column
TEST2C_(hr = m_pIOpenRowset->OpenRowset(NULL, &Table.GetTableID(), NULL,
IID_IRowsetChange, 0, NULL, (IUnknown**)&pIRowsetChange), S_OK, E_NOINTERFACE);
TESTC_PROVIDER(S_OK == hr);
// try to insert a null value in a not null column
rgNULLCols[0] = col.GetColNum();
TESTC_(hr = Insert(0, pIRowsetChange, NUMELEM(rgNULLCols), rgNULLCols), S_OK);
// try to add the constraint
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_SCHEMAVIOLATION);
CLEANUP:
SAFE_RELEASE(pIRowsetChange);
SAFE_FREE(pwszConstraintText);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
int TCAddConstraint_CHECK::Variation_20() {
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons;
DBCONSTRAINTDESC *pConsDesc = (DBCONSTRAINTDESC*)cons;
CCol col;
DBORDINAL indxCat = 0;
CCatalogs Catalogs(m_pIOpenRowset);
IDBProperties *pIDBProperties = NULL;
CPropSets PropSets;
WCHAR *pwszCurrentCatalog = NULL;
WCHAR *pwszQualTableName = NULL;
WCHAR *pwszCatalogName = NULL;
WCHAR *pwszSchemaName = NULL;
TESTC_PROVIDER(SettableProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, m_pIDBInitialize));
TESTC_PROVIDER(1 < Catalogs.cCatalogs());
// create a table and an index
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// select column
TESTC_(Table.GetColInfo(1, col), S_OK);
// set DBID of the table to its qualified form
TESTC(DBKIND_NAME == Table.GetTableID().eKind);
TESTC(GetCatalogSchemaNames(Table.GetTableName(), &pwszCatalogName, &pwszSchemaName));
//Construct a fully Qualified TableName...
TESTC_(m_pTable->GetQualifiedName(pwszCatalogName, pwszSchemaName, Table.GetTableName(), &pwszQualTableName),S_OK);
Table.SetTableName(pwszQualTableName);
// change the current catalog
TESTC(GetProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, m_pIDBInitialize,
&pwszCurrentCatalog));
TESTC(NULL != pwszCurrentCatalog);
TESTC(VerifyInterface(m_pIDBInitialize, IID_IDBProperties, DATASOURCE_INTERFACE, (IUnknown**)&pIDBProperties));
if (0 == wcscmp(pwszCurrentCatalog, Catalogs[0]))
indxCat++;
CHECK(PropSets.AddProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, VT_BSTR, (LPVOID)Catalogs[indxCat]), S_OK);
TESTC_PROVIDER(S_OK == pIDBProperties->SetProperties(PropSets, PropSets));
// alloc memory for column array
cons.SetIsNotNULLCheckConstraint(&Table, col.GetColNum());
// try to make column unique
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
if (CHECK(PropSets.SetProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, VT_BSTR, (LPVOID)pwszCurrentCatalog), S_OK))
CHECK(pIDBProperties->SetProperties(PropSets, PropSets), S_OK);
SAFE_FREE(pwszCatalogName);
SAFE_FREE(pwszSchemaName);
SAFE_FREE(pwszQualTableName);
SAFE_FREE(pwszCurrentCatalog);
SAFE_RELEASE(pIDBProperties);
Table.DropTable();
TRETURN
}
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL TCAddConstraint_CHECK::Terminate()
{
// TO DO: Add your own code here
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCITableDefinition::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(TCAddConstraint_Deferrability)
//*-----------------------------------------------------------------------
//| Test Case: TCAddConstraint_Deferrability - Testcase for ITableDefinitionWithConstraints::AddConstraint used with deferrability setting
//| Created: 7/29/99
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCAddConstraint_Deferrability::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCITableDefinition::Init())
// }}
{
if (m_pITDWC == NULL)
{
odtLog << "ITableDefinitionWithConstraints is not supported.\n";
return TEST_SKIPPED;
}
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Immediate unique constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Deferrability::Variation_1()
{
TBEGIN
CTable Table(m_pITDWC, (LPWSTR)gwszModuleName);
// create a table
TESTC_(Table.CreateTable(3, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// create an immediate unique constraint
TESTC_(AddUniqueConstraint(&Table, 1, (DBDEFERRABILITY)0), S_OK);
// check that adding row with seed 2 again will fail
TESTC_(Table.Insert(2), DB_E_INTEGRITYVIOLATION);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Defferable unique constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Deferrability::Variation_2()
{
TBEGIN
HRESULT hr;
CTable Table(m_pITDWC, (LPWSTR)gwszModuleName);
// create a table
TESTC_(Table.CreateTable(3, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// create a deferrable unique constraint
TEST2C_(hr = AddUniqueConstraint(&Table, 1, DBDEFERRABILITY_DEFERRABLE), S_OK, DB_E_BADDEFERRABILITY);
// check that adding row with seed 2 again will fail
if (S_OK == hr)
{
TESTC_(Table.Insert(2), DB_E_INTEGRITYVIOLATION);
}
else
odtLog << "Deferrable unique constraints are not supported\n";
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Deffered unique constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Deferrability::Variation_3()
{
TBEGIN
HRESULT hr;
CTable Table(m_pITDWC, (LPWSTR)gwszModuleName);
// create a table
TESTC_(Table.CreateTable(3, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// create an deferred unique constraint
TEST2C_(hr = AddUniqueConstraint(&Table, 1,
DBDEFERRABILITY_DEFERRABLE | DBDEFERRABILITY_DEFERRED), S_OK, DB_E_BADDEFERRABILITY);
// check that adding row with seed 2 again will fail
if (S_OK == hr)
{
TESTC_(Table.Insert(2), DB_E_INTEGRITYVIOLATION);
}
else
odtLog << "Deferred unique constraints are not supported\n";
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Bad deferrability value unique constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Deferrability::Variation_4()
{
TBEGIN
CTable Table(m_pITDWC, (LPWSTR)gwszModuleName);
// create a table
TESTC_(Table.CreateTable(0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// create a unique constraint
TESTC_(AddUniqueConstraint(&Table, 1,
~(DBDEFERRABILITY_DEFERRABLE | DBDEFERRABILITY_DEFERRED)), DB_E_BADDEFERRABILITY);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Immediate primary key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Deferrability::Variation_5()
{
TBEGIN
CTable Table(m_pITDWC, (LPWSTR)gwszModuleName);
// create a table
TESTC_(CreateTableWithNoNullableColumns(&Table, 3), S_OK);
// create an immediate unique constraint
TESTC_(AddPrimaryKeyConstraint(&Table, 1, (DBDEFERRABILITY)0), S_OK);
// check that adding row with seed 2 again will fail
TESTC_(Table.Insert(2), DB_E_INTEGRITYVIOLATION);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Deferrable primary key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Deferrability::Variation_6()
{
TBEGIN
HRESULT hr;
CTable Table(m_pITDWC, (LPWSTR)gwszModuleName);
// create a table
TESTC_(CreateTableWithNoNullableColumns(&Table, 3), S_OK);
// create a deferrable unique constraint
TEST2C_(hr = AddPrimaryKeyConstraint(&Table, 1, DBDEFERRABILITY_DEFERRABLE), S_OK, DB_E_BADDEFERRABILITY);
// check that adding row with seed 2 again will fail
if (S_OK == hr)
{
TESTC_(Table.Insert(2), DB_E_INTEGRITYVIOLATION);
}
else
odtLog << "Deferrable primary key constraints are not supported\n";
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Deferred primary key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Deferrability::Variation_7()
{
TBEGIN
HRESULT hr;
CTable Table(m_pITDWC, (LPWSTR)gwszModuleName);
// create a table
TESTC_(CreateTableWithNoNullableColumns(&Table, 3), S_OK);
// create an deferred primary key constraint
TEST2C_(hr = AddPrimaryKeyConstraint(&Table, 1,
DBDEFERRABILITY_DEFERRABLE | DBDEFERRABILITY_DEFERRED), S_OK, DB_E_BADDEFERRABILITY);
// check that adding row with seed 2 again will fail
if (S_OK == hr)
{
TESTC_(Table.Insert(2), DB_E_INTEGRITYVIOLATION);
}
else
odtLog << "Deferred primary key constraints are not supported\n";
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc Bad deferrability value primary key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Deferrability::Variation_8()
{
TBEGIN
CTable Table(m_pITDWC, (LPWSTR)gwszModuleName);
// create a table
TESTC_(CreateTableWithNoNullableColumns(&Table, 0), S_OK);
// create a primary key constraint
TESTC_(AddPrimaryKeyConstraint(&Table, 1,
~(DBDEFERRABILITY_DEFERRABLE | DBDEFERRABILITY_DEFERRED)), DB_E_BADDEFERRABILITY);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc Immediate foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Deferrability::Variation_9()
{
TBEGIN
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
// create a table
TESTC_(BaseTable.CreateTable(0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// create a unique constraint in the refereced table
TESTC_PROVIDER(S_OK == AddUniqueConstraint(&ReferencedTable, 1));
// create an immediate foreign key constraint
TESTC_(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol,
m_SupportedMatchType, DBUPDELRULE_NOACTION, DBUPDELRULE_NOACTION,
(DBDEFERRABILITY)0), S_OK);
// check that adding row with seed 2 again will fail
TESTC_(BaseTable.Insert(10), DB_E_INTEGRITYVIOLATION);
// check adding row in the referenced table is ok
TESTC_(ReferencedTable.Insert(10), S_OK);
TESTC_(BaseTable.Insert(10), S_OK);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc Deferrable foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Deferrability::Variation_10()
{
TBEGIN
HRESULT hr;
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
// create a table
TESTC_(BaseTable.CreateTable(0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// create a unique constraint in the refereced table
TESTC_PROVIDER(S_OK == AddUniqueConstraint(&ReferencedTable, 1));
// create a deferrable foreign key constraint
TEST2C_(hr = AddForeignKeyConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol,
m_SupportedMatchType, DBUPDELRULE_NOACTION, DBUPDELRULE_NOACTION,
DBDEFERRABILITY_DEFERRABLE), S_OK, DB_E_BADDEFERRABILITY);
if (S_OK == hr)
{
// check that adding row with seed 2 again will fail
TESTC_(BaseTable.Insert(2), DB_E_INTEGRITYVIOLATION);
// check adding row in the referenced table is ok
TESTC_(ReferencedTable.Insert(2), S_OK);
TESTC_(BaseTable.Insert(2), S_OK);
}
else
odtLog << "Deferrable foreign key not supported\n";
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc Deferred foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Deferrability::Variation_11()
{
TBEGIN
HRESULT hr;
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
// create a table
TESTC_(BaseTable.CreateTable(0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// create a unique constraint in the refereced table
TESTC_PROVIDER(S_OK == AddUniqueConstraint(&ReferencedTable, 1));
// create a deferrable foreign key constraint
TEST2C_(hr = AddForeignKeyConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol,
m_SupportedMatchType, DBUPDELRULE_NOACTION, DBUPDELRULE_NOACTION,
DBDEFERRABILITY_DEFERRABLE | DBDEFERRABILITY_DEFERRED),
S_OK, DB_E_BADDEFERRABILITY);
if (S_OK == hr)
{
// check that adding row with seed 2 again will fail
TESTC_(BaseTable.Insert(2), S_OK);
// check adding row in the referenced table is ok
TESTC_(ReferencedTable.Insert(2), S_OK);
TESTC_(BaseTable.Insert(2), S_OK);
}
else
odtLog << "Deferred foreign key not supported\n";
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc Bad deferrability value foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Deferrability::Variation_12()
{
TBEGIN
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBORDINAL rgBaseCol[] = {1};
DBORDINAL rgReferencedCol[] = {1};
// create a table
TESTC_(BaseTable.CreateTable(0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// create a unique constraint in the refereced table
TESTC_PROVIDER(S_OK == AddUniqueConstraint(&ReferencedTable, 1));
// create an immediate foreign key constraint
TESTC_(AddForeignKeyConstraint(&BaseTable, NUMELEM(rgBaseCol), rgBaseCol,
&ReferencedTable, NUMELEM(rgReferencedCol), rgReferencedCol,
m_SupportedMatchType, DBUPDELRULE_NOACTION, DBUPDELRULE_NOACTION,
~(DBDEFERRABILITY_DEFERRABLE | DBDEFERRABILITY_DEFERRED)), DB_E_BADDEFERRABILITY);
// check adding row in the referenced table is ok
TESTC_(ReferencedTable.Insert(2), S_OK);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc Immediate check constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Deferrability::Variation_13()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons;
CCol col;
WCHAR *pwszConstraintText = NULL;
WCHAR wszText[] = L" IS NULL";
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// get the first column of the table
TESTC_(Table.GetColInfo(1 , col), S_OK);
SAFE_ALLOC(pwszConstraintText, WCHAR, 1 + wcslen(col.GetColName()) + wcslen(wszText));
wcscpy(pwszConstraintText, col.GetColName());
wcscat(pwszConstraintText, wszText);
cons.SetConstraintText(pwszConstraintText);
cons.SetDeferrability((DBDEFERRABILITY)0);
// add the constraint and check its addition
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// add a row that does not have NULL in the checked column
TESTC_PROVIDER(2 < Table.CountColumnsOnTable());
TESTC_(Table.Insert(3), DB_E_INTEGRITYVIOLATION);
CLEANUP:
SAFE_FREE(pwszConstraintText);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(14)
//*-----------------------------------------------------------------------
// @mfunc Deferrable check constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Deferrability::Variation_14()
{
TBEGIN
HRESULT hr;
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons;
CCol col;
WCHAR *pwszConstraintText = NULL;
WCHAR wszText[] = L" IS NULL";
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// get the first column of the table
TESTC_(Table.GetColInfo(1 , col), S_OK);
SAFE_ALLOC(pwszConstraintText, WCHAR, 1 + wcslen(col.GetColName()) + wcslen(wszText));
wcscpy(pwszConstraintText, col.GetColName());
wcscat(pwszConstraintText, wszText);
cons.SetConstraintText(pwszConstraintText);
cons.SetDeferrability(DBDEFERRABILITY_DEFERRABLE);
// add the constraint and check its addition
TEST2C_(hr = AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK, DB_E_BADDEFERRABILITY);
if (S_OK == hr)
{
// add a row that does not have NULL in the checked column
TESTC_PROVIDER(2 < Table.CountColumnsOnTable());
TESTC_(Table.Insert(3), DB_E_INTEGRITYVIOLATION);
}
else
odtLog << "Deferrable check constraints are not supported\n";
CLEANUP:
SAFE_FREE(pwszConstraintText);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(15)
//*-----------------------------------------------------------------------
// @mfunc Deferred check constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Deferrability::Variation_15()
{
TBEGIN
HRESULT hr;
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons;
CCol col;
WCHAR *pwszConstraintText = NULL;
WCHAR wszText[] = L" IS NULL";
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// get the first column of the table
TESTC_(Table.GetColInfo(1 , col), S_OK);
SAFE_ALLOC(pwszConstraintText, WCHAR, 1 + wcslen(col.GetColName()) + wcslen(wszText));
wcscpy(pwszConstraintText, col.GetColName());
wcscat(pwszConstraintText, wszText);
cons.SetConstraintText(pwszConstraintText);
cons.SetDeferrability(DBDEFERRABILITY_DEFERRABLE | DBDEFERRABILITY_DEFERRED);
// add the constraint and check its addition
TEST2C_(hr = AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK, DB_E_BADDEFERRABILITY);
if (S_OK == hr)
{
// add a row that does not have NULL in the checked column
TESTC_(Table.Insert(3), S_OK);
}
else
odtLog << "Deferred check constraints are not supported\n";
CLEANUP:
SAFE_FREE(pwszConstraintText);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc Bad deferrability value check constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Deferrability::Variation_16()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons;
CCol col;
WCHAR *pwszConstraintText = NULL;
WCHAR wszText[] = L" IS NULL";
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// get the first column of the table
TESTC_(Table.GetColInfo(1 , col), S_OK);
SAFE_ALLOC(pwszConstraintText, WCHAR, 1 + wcslen(col.GetColName()) + wcslen(wszText));
wcscpy(pwszConstraintText, col.GetColName());
wcscat(pwszConstraintText, wszText);
cons.SetConstraintText(pwszConstraintText);
cons.SetDeferrability(~(DBDEFERRABILITY_DEFERRABLE | DBDEFERRABILITY_DEFERRED));
// add the constraint and check its addition
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_BADDEFERRABILITY);
CLEANUP:
SAFE_FREE(pwszConstraintText);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL TCAddConstraint_Deferrability::Terminate()
{
// TO DO: Add your own code here
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCITableDefinition::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(TCCreateTableWithConstraints_NoConstraint)
//*-----------------------------------------------------------------------
//| Test Case: TCCreateTableWithConstraints_NoConstraint - Testcase for ITableDefinitionWithConstraints::AddConstraint used with deferrability setting
//| Created: 7/29/99
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCCreateTableWithConstraints_NoConstraint::Init()
{
ITableDefinitionWithConstraints *pITableDefinitionWithConstraints = NULL;
if(TCCreateTable::Init())
{
// check for ITableDefinition
if (!(m_hr=VerifyInterface(m_pIOpenRowset, IID_ITableDefinitionWithConstraints, SESSION_INTERFACE, (IUnknown**)&pITableDefinitionWithConstraints)))
{
odtLog << "ITableDefinitionWithConstraints is not supported\n";
return TEST_SKIPPED;
}
SAFE_RELEASE(pITableDefinitionWithConstraints);
return TRUE;
}
return FALSE;
}
//---------------------------------------------------------------------
//
// @member Create the table using ITableDefinition::CreateTable and
// check its creation
//---------------------------------------------------------------------
HRESULT TCCreateTableWithConstraints_NoConstraint::CreateAndCheckTable(
ITableDefinition *pITableDefinition, // [in] pointer to the ITableDefinition interface to be used
IUnknown *pUnkOuter, // [in] pointer to controlling unknown
DBID *pTableID, // [in] pointer to the input table ID
DBORDINAL cColumnDescs, // [in] the number of columns to be created
DBCOLUMNDESC *rgColumnDescs, // [in/out] array of columns to be created
REFIID riid, // [in] rowset interface to be returned
ULONG cPropertySets, // [in] number of roset property sets asked
DBPROPSET *rgPropertySets, // [in/out] array of rowset property sets
DBID **ppTableID, // [out] returned table ID
IUnknown **ppRowset // [out] pointer to outer interface
)
{
HRESULT hr = E_FAIL;
ITableDefinitionWithConstraints *pITDWC = NULL;
TESTC(NULL != pITableDefinition);
TESTC(VerifyInterface(pITableDefinition, IID_ITableDefinitionWithConstraints,
SESSION_INTERFACE, (IUnknown**)&pITDWC));
hr = CreateAndCheckTableWithConstraints(pITDWC, pUnkOuter, pTableID,
cColumnDescs, rgColumnDescs, 0, NULL,
riid, cPropertySets, rgPropertySets,
ppTableID, ppRowset);
CLEANUP:
SAFE_RELEASE(pITDWC);
return hr;
} //TCCreateTableWithConstraints_NoConstraint::CreateAndCheckTable
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL TCCreateTableWithConstraints_NoConstraint::Terminate()
{
return(TCCreateTable::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(TCCreateTableWithConstraints)
//*-----------------------------------------------------------------------
//| Test Case: TCCreateTableWithConstraints - Testcase for ITableDefinitionWithConstraints::CreateTableWithConstraints when constraints are set
//| Created: 7/29/99
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCCreateTableWithConstraints::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCITableDefinition::Init())
// }}
{
if (m_pITDWC == NULL)
{
odtLog << "ITableDefinitionWithConstraints is not supported.\n";
return TEST_SKIPPED;
}
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Create a table and multiple constraint of various types
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_1()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CConsDescArray ConsDescArray;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&rgColumnDesc[0].dbcid);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
// add all constraint to the array
ConsDescArray.AddConsDesc(consUnique);
ConsDescArray.AddConsDesc(consForeignKey);
ConsDescArray.AddConsDesc(consPrimaryKey);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
ConsDescArray, ConsDescArray,
IID_IRowset, 0, NULL, NULL, NULL), S_OK);
CLEANUP:
CHECK(DropTableAndCheck(&TableID), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Table with a unique constraint (on a single column)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_2()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CUniqueCons consUnique;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[0].dbcid);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consUnique,
IID_IRowset, 0, NULL, NULL, NULL), S_OK);
CLEANUP:
CHECK(DropTableAndCheck(&TableID), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Table with a unique constraint (on multiple columns)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_3()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CUniqueCons consUnique;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[0].dbcid);
consUnique.AddColumn(&rgColumnDesc[3].dbcid);
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consUnique,
IID_IRowset, 0, NULL, NULL, NULL), S_OK);
CLEANUP:
CHECK(DropTableAndCheck(&TableID), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Table with a primary key constraint (on a single column)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_4()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CPrimaryKeyCons consPK;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// set a primary key constraint on the second column
consPK.AddColumn(&rgColumnDesc[0].dbcid);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consPK,
IID_IRowset, 0, NULL, NULL, NULL), S_OK);
CLEANUP:
CHECK(DropTableAndCheck(&TableID), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Table with a primary key constraint (on multiple columns)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_5()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CPrimaryKeyCons consPK;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// set a primary key constraint on the second column
consPK.AddColumn(&rgColumnDesc[1].dbcid);
consPK.AddColumn(&rgColumnDesc[3].dbcid);
consPK.AddColumn(&rgColumnDesc[2].dbcid);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consPK,
IID_IRowset, 0, NULL, NULL, NULL), S_OK);
CLEANUP:
CHECK(DropTableAndCheck(&TableID), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Table with a foreign key constraint (single column)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_6()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBORDINAL indexCol = 2;
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CForeignKeyCons consFK(NULL, m_SupportedMatchType);
CCol col;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, indexCol, (DBDEFERRABILITY)0), S_OK);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(indexCol, col), S_OK);
consFK.AddColumn(col.GetColID());
consFK.AddForeignKeyColumn(&rgColumnDesc[indexCol-1].dbcid);
consFK.SetReferencedTableID(&ReferencedTable.GetTableID());
TESTC_(consFK.MakeConstraintName(), S_OK);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consFK,
IID_IRowset, 0, NULL, NULL, NULL), S_OK);
CLEANUP:
CHECK(DropTableAndCheck(&TableID), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Table with foreign key constraint defined on multiple keys
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_7()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBORDINAL rgColumns[] = {2, 1};
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CForeignKeyCons consFK(NULL, m_SupportedMatchType);
CCol col;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, NUMELEM(rgColumns), rgColumns, (DBDEFERRABILITY)0), S_OK);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(rgColumns[0], col), S_OK);
consFK.AddColumn(col.GetColID());
TESTC_(ReferencedTable.GetColInfo(rgColumns[1], col), S_OK);
consFK.AddColumn(col.GetColID());
consFK.AddForeignKeyColumn(&rgColumnDesc[rgColumns[0]-1].dbcid);
consFK.AddForeignKeyColumn(&rgColumnDesc[rgColumns[1]-1].dbcid);
consFK.SetReferencedTableID(&ReferencedTable.GetTableID());
TESTC_(consFK.MakeConstraintName(), S_OK);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consFK,
IID_IRowset, 0, NULL, NULL, NULL), S_OK);
CLEANUP:
CHECK(DropTableAndCheck(&TableID), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc Table with a simple check constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_8()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CCheckCons cons;
WCHAR *pwszConstraintText = NULL;
WCHAR wszText[] = L" IS NOT NULL";
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// build constraint text
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[0].dbcid.eKind);
SAFE_ALLOC(pwszConstraintText, WCHAR, 1 + wcslen(rgColumnDesc[0].dbcid.uName.pwszName) + wcslen(wszText));
wcscpy(pwszConstraintText, rgColumnDesc[0].dbcid.uName.pwszName);
wcscat(pwszConstraintText, wszText);
cons.SetConstraintText(pwszConstraintText);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, cons,
IID_IRowset, 0, NULL, NULL, NULL), S_OK);
CLEANUP:
SAFE_FREE(pwszConstraintText);
CHECK(DropTableAndCheck(&TableID), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc Table with multiple unique constraints defined
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_9()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CConsDescArray ConsDescArray;
CUniqueCons consUnique;
CUniqueCons consUnique1;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
consUnique.MakeConstraintName();
// set second unique constraints on the firstcolumn
consUnique1.AddColumn(&rgColumnDesc[0].dbcid);
consUnique1.MakeConstraintName();
// add all constraint to the array
ConsDescArray.AddConsDesc(consUnique);
ConsDescArray.AddConsDesc(consUnique1);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
ConsDescArray, ConsDescArray,
IID_IRowset, 0, NULL, NULL, NULL), S_OK);
CLEANUP:
CHECK(DropTableAndCheck(&TableID), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc Table with unique constraint and foreign key
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_10()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CConsDescArray ConsDescArray;
CUniqueCons consUnique;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
consUnique.MakeConstraintName();
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
consForeignKey.MakeConstraintName();
// add all constraint to the array
ConsDescArray.AddConsDesc(consForeignKey);
ConsDescArray.AddConsDesc(consUnique);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
ConsDescArray, ConsDescArray,
IID_IRowset, 0, NULL, NULL, NULL), S_OK);
CLEANUP:
CHECK(DropTableAndCheck(&TableID), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc Table with primary key and check constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_11()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CConsDescArray ConsDescArray;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
WCHAR *pwszConstraintText = NULL;
WCHAR wszText[] = L" IS NOT NULL";
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
SetProperty(&rgColumnDesc[1].rgPropertySets, &rgColumnDesc[1].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// set a primary key constraint on the first column
consPK.AddColumn(&rgColumnDesc[0].dbcid);
// build constraint text
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[1].dbcid.eKind);
SAFE_ALLOC(pwszConstraintText, WCHAR, 1 + wcslen(rgColumnDesc[1].dbcid.uName.pwszName) + wcslen(wszText));
wcscpy(pwszConstraintText, rgColumnDesc[1].dbcid.uName.pwszName);
wcscat(pwszConstraintText, wszText);
consCheck.SetConstraintText(pwszConstraintText);
// add all constraint to the array
ConsDescArray.AddConsDesc(consPK);
ConsDescArray.AddConsDesc(consCheck);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
ConsDescArray, ConsDescArray,
IID_IRowset, 0, NULL, NULL, NULL), S_OK);
CLEANUP:
SAFE_FREE(pwszConstraintText);
CHECK(DropTableAndCheck(&TableID), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc Deferrable, immediate constraints
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_12()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
CCheckCons consCheck;
WCHAR *pwszConstraintText = NULL;
WCHAR wszText[] = L" IS NULL";
DBORDINAL rgReferencedCol[] = {1};
CCol col;
HRESULT hr;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
consUnique.SetDeferrability(DBDEFERRABILITY_DEFERRABLE);
// try to create a table with a deferrable unique constraint
hr = CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consUnique, IID_IRowset, 0, NULL, NULL, NULL);
if (S_OK == hr)
{
// drop the table
CHECK(DropTableAndCheck(&TableID, m_pITableDefinition), S_OK);
}
else
{
CHECK(hr, DB_E_BADDEFERRABILITY);
}
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&rgColumnDesc[0].dbcid);
consPrimaryKey.SetDeferrability(DBDEFERRABILITY_DEFERRABLE);
// try to create a table with a deferrable primary key constraint
hr = CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consPrimaryKey, IID_IRowset, 0, NULL, NULL, NULL);
if (S_OK == hr)
{
// drop the table
CHECK(DropTableAndCheck(&TableID, m_pITableDefinition), S_OK);
}
else
{
CHECK(hr, DB_E_BADDEFERRABILITY);
}
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
consForeignKey.SetDeferrability(DBDEFERRABILITY_DEFERRABLE);
// try to create a table with a deferrable foreign key constraint
hr = CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consForeignKey, IID_IRowset, 0, NULL, NULL, NULL);
if (S_OK == hr)
{
// drop the table
CHECK(DropTableAndCheck(&TableID, m_pITableDefinition), S_OK);
}
else
{
CHECK(hr, DB_E_BADDEFERRABILITY);
}
// build constraint text
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[4].dbcid.eKind);
SAFE_ALLOC(pwszConstraintText, WCHAR, 1 + wcslen(rgColumnDesc[4].dbcid.uName.pwszName) + wcslen(wszText));
wcscpy(pwszConstraintText, rgColumnDesc[4].dbcid.uName.pwszName);
wcscat(pwszConstraintText, wszText);
consCheck.SetConstraintText(pwszConstraintText);
consCheck.SetDeferrability(DBDEFERRABILITY_DEFERRABLE);
// try to create a table with a deferrable check constraint
hr = CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consCheck, IID_IRowset, 0, NULL, NULL, NULL);
if (S_OK == hr)
{
// drop the table
CHECK(DropTableAndCheck(&TableID, m_pITableDefinition), S_OK);
}
else
{
CHECK(hr, DB_E_BADDEFERRABILITY);
}
CLEANUP:
SAFE_FREE(pwszConstraintText);
DropTableAndCheck(&TableID);
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc Deferred constraints
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_13()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
CCheckCons consCheck;
WCHAR *pwszConstraintText = NULL;
WCHAR wszText[] = L" IS NULL";
DBORDINAL rgReferencedCol[] = {1};
CCol col;
HRESULT hr;
CTable Table(m_pITableDefinition, (LPWSTR)gwszModuleName);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
consUnique.SetDeferrability(DBDEFERRABILITY_DEFERRABLE | DBDEFERRABILITY_DEFERRED);
// try to create a table with a deferrable unique constraint
hr = CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consUnique, IID_IRowset, 0, NULL, NULL, NULL);
if (S_OK == hr)
{
// try to insert a duplicate value in the second column and check it is possible
Table.SetTableID(TableID);
if (CHECK(Table.GetTableColumnInfo(&TableID), S_OK))
{
CHECK(Table.Insert(1), S_OK);
CHECK(Table.Insert(1), S_OK);
}
// drop the table
CHECK(DropTableAndCheck(&TableID, m_pITableDefinition), S_OK);
}
else
{
CHECK(hr, DB_E_BADDEFERRABILITY);
}
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&rgColumnDesc[0].dbcid);
consPrimaryKey.SetDeferrability(DBDEFERRABILITY_DEFERRABLE | DBDEFERRABILITY_DEFERRED);
// try to create a table with a deferrable primary key constraint
hr = CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consPrimaryKey, IID_IRowset, 0, NULL, NULL, NULL);
if (S_OK == hr)
{
// try to insert a duplicate value in the primary key column and check it is possible
Table.SetTableID(TableID);
if (CHECK(Table.GetTableColumnInfo(&TableID), S_OK))
{
CHECK(Table.Insert(1), S_OK);
CHECK(Table.Insert(1), S_OK);
}
// drop the table
CHECK(DropTableAndCheck(&TableID, m_pITableDefinition), S_OK);
}
else
{
CHECK(hr, DB_E_BADDEFERRABILITY);
}
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
consForeignKey.SetDeferrability(DBDEFERRABILITY_DEFERRABLE | DBDEFERRABILITY_DEFERRED);
// try to create a table with a deferrable foreign key constraint
hr = CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consForeignKey, IID_IRowset, 0, NULL, NULL, NULL);
if (S_OK == hr)
{
// try to insert a row base table (referenced table is empty)
Table.SetTableID(TableID);
if (CHECK(Table.GetTableColumnInfo(&TableID), S_OK))
{
CHECK(Table.Insert(7), S_OK);
CHECK(Table.Insert(5), S_OK);
}
// drop the table
CHECK(DropTableAndCheck(&TableID, m_pITableDefinition), S_OK);
}
else
{
CHECK(hr, DB_E_BADDEFERRABILITY);
}
// build constraint text
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[4].dbcid.eKind);
SAFE_ALLOC(pwszConstraintText, WCHAR, 1 + wcslen(rgColumnDesc[4].dbcid.uName.pwszName) + wcslen(wszText));
wcscpy(pwszConstraintText, rgColumnDesc[4].dbcid.uName.pwszName);
wcscat(pwszConstraintText, wszText);
consCheck.SetConstraintText(pwszConstraintText);
consCheck.SetDeferrability(DBDEFERRABILITY_DEFERRABLE | DBDEFERRABILITY_DEFERRED);
// try to create a table with a deferrable check constraint
hr = CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consCheck, IID_IRowset, 0, NULL, NULL, NULL);
if (S_OK == hr)
{
// try to insert a not null value in the checked column
Table.SetTableID(TableID);
if (CHECK(Table.GetTableColumnInfo(&TableID), S_OK))
{
CHECK(Table.Insert(1), S_OK);
CHECK(Table.Insert(10), S_OK);
}
// drop the table
CHECK(DropTableAndCheck(&TableID, m_pITableDefinition), S_OK);
}
else
{
CHECK(hr, DB_E_BADDEFERRABILITY);
}
CLEANUP:
SAFE_FREE(pwszConstraintText);
DropTableAndCheck(&TableID);
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(14)
//*-----------------------------------------------------------------------
// @mfunc Abort retain
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_14()
{
CCreateTableWithConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
TRUE, // Abort
TRUE // Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(15)
//*-----------------------------------------------------------------------
// @mfunc Abort non retain
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_15()
{
CCreateTableWithConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
TRUE, // Abort
FALSE // Non Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc Commit retain
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_16()
{
CCreateTableWithConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
FALSE, // Commit
TRUE // Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(17)
//*-----------------------------------------------------------------------
// @mfunc Commit non retain
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints::Variation_17()
{
CCreateTableWithConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
FALSE, // Commit
FALSE // Non Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL TCCreateTableWithConstraints::Terminate()
{
// TO DO: Add your own code here
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCITableDefinition::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(TCCreateTableWithConstraints_Boundary)
//*-----------------------------------------------------------------------
//| Test Case: TCCreateTableWithConstraints_Boundary - Boundary and NULL testcase for ITableDefinitionWithConstraints::CreateTableWithConstraints
//| Created: 9/3/99
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCCreateTableWithConstraints_Boundary::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCITableDefinition::Init())
// }}
{
if (m_pITDWC == NULL)
{
odtLog << "ITableDefinitionWithConstraints is not supported.\n";
return TEST_SKIPPED;
}
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc 0 < cConstraintDescs and NULL == rgConstraintDescs => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_1()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
3, NULL,
IID_IRowset, 0, NULL, NULL, NULL), E_INVALIDARG);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc 0 == cConstraintDescs and NULL != rgConstraintDescs => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_2()
{
TBEGIN
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CUniqueCons cons;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
cons.AddColumn(&rgColumnDesc[0].dbcid);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
0, cons,
IID_IRowset, 0, NULL, NULL, NULL), S_OK);
CLEANUP:
CHECK(this->DropTableAndCheck(&TableID), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc pTableID is NULL ppTableID is not NULL => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_3()
{
TBEGIN
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CConsDescArray ConsDescArray;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&rgColumnDesc[0].dbcid);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
// add all constraint to the array
ConsDescArray.AddConsDesc(consUnique);
ConsDescArray.AddConsDesc(consForeignKey);
ConsDescArray.AddConsDesc(consPrimaryKey);
TESTC_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
ConsDescArray, ConsDescArray,
IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK);
CLEANUP:
CHECK(DropTableAndCheck(pTableID), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Bad DBKIND of a constraint ID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_4()
{
TBEGIN
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CConsDescArray ConsDescArray;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&rgColumnDesc[0].dbcid);
ReleaseDBID(((DBCONSTRAINTDESC*)consPrimaryKey)->pConstraintID, FALSE);
((DBCONSTRAINTDESC*)consPrimaryKey)->pConstraintID->eKind = 0xb2;
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
// add all constraint to the array
ConsDescArray.AddConsDesc(consUnique);
ConsDescArray.AddConsDesc(consForeignKey);
ConsDescArray.AddConsDesc(consPrimaryKey);
TESTC_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
ConsDescArray, ConsDescArray,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_BADCONSTRAINTID);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc NULL pConstraintID in a constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_5()
{
TBEGIN
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CConsDescArray ConsDescArray;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&rgColumnDesc[0].dbcid);
ReleaseDBID(((DBCONSTRAINTDESC*)consPrimaryKey)->pConstraintID, TRUE);
((DBCONSTRAINTDESC*)consPrimaryKey)->pConstraintID = NULL;
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
// add all constraint to the array
ConsDescArray.AddConsDesc(consUnique);
ConsDescArray.AddConsDesc(consForeignKey);
ConsDescArray.AddConsDesc(consPrimaryKey);
TESTC_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
ConsDescArray, ConsDescArray,
IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK);
CLEANUP:
CHECK(DropTableAndCheck(pTableID), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc NULL column list in a constraint, column size is not 0 => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_6()
{
// this tests rgColumnList for PK, FK and unique constraints
// as well as rgForeignKeyColumnList for FK
TBEGIN
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CConsDescArray ConsDescArray;
CUniqueCons consUnique;
CUniqueCons cons;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DBCONSTRAINTDESC *pConsDesc;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
cons.AddColumn(&rgColumnDesc[0].dbcid);
pConsDesc = consUnique;
pConsDesc->cColumns = 2;
pConsDesc->rgColumnList = NULL;
ConsDescArray.AddConsDesc(cons);
ConsDescArray.AddConsDesc(consUnique);
TESTC_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
ConsDescArray, ConsDescArray,
IID_IRowset, 0, NULL,
&pTableID, NULL), E_INVALIDARG);
// set a primary key on the first column of the table
pConsDesc = consPrimaryKey;
pConsDesc->cColumns = 5;
pConsDesc->rgColumnList = NULL;
TESTC_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consPrimaryKey,
IID_IRowset, 0, NULL,
&pTableID, NULL), E_INVALIDARG);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
pConsDesc = consForeignKey;
pConsDesc->cColumns = 1;
pConsDesc->rgColumnList = NULL;
TESTC_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL,
&pTableID, NULL), E_INVALIDARG);
// the same check for foreign key column list
consForeignKey.ReleaseForeignKeyColumnList();
pConsDesc->cForeignKeyColumns = 1;
pConsDesc->cColumns = 0;
consForeignKey.AddColumn(&rgColumnDesc[0].dbcid);
TESTC_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL,
&pTableID, NULL), E_INVALIDARG);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Empty list of columns for a unique, primay key or foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_7()
{
// this tests rgColumnList for PK, FK and unique constraints
// as well as rgForeignKeyColumnList for FK
TBEGIN
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CConsDescArray ConsDescArray;
CUniqueCons consUnique;
CUniqueCons cons;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
cons.AddColumn(&rgColumnDesc[0].dbcid);
ConsDescArray.AddConsDesc(cons);
ConsDescArray.AddConsDesc(consUnique);
TESTC_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
ConsDescArray, ConsDescArray,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_BADCONSTRAINTFORM);
// set a primary key on the first column of the table
TESTC_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consPrimaryKey,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_BADCONSTRAINTFORM);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
TEST2C_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL,
&pTableID, NULL), E_INVALIDARG, DB_E_BADCONSTRAINTFORM);
// the same check for foreign key column list
consForeignKey.ReleaseForeignKeyColumnList();
consForeignKey.AddColumn(&rgColumnDesc[0].dbcid);
TESTC_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_BADCONSTRAINTFORM);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc Non empty list of columns for a check constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_8()
{
// this tests the case when rgColumnList or rgForeignKeyColumnList
// are not empty in a check constraint
TBEGIN
CCheckCons consCheck;
DBCONSTRAINTDESC *pcons = consCheck;
WCHAR *pwszConstraintText = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBID *pTableID = NULL;
WCHAR wszText[] = L" IS NOT NULL";
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[0].dbcid.eKind
&& rgColumnDesc[0].dbcid.uName.pwszName);
// set up the check constraint
// create the text of the constraint
SAFE_FREE(pwszConstraintText);
SAFE_ALLOC(pwszConstraintText, WCHAR, 1 + wcslen(rgColumnDesc[0].dbcid.uName.pwszName) + wcslen(wszText));
wcscpy(pwszConstraintText, rgColumnDesc[0].dbcid.uName.pwszName);
wcscat(pwszConstraintText, wszText);
consCheck.SetConstraintText(pwszConstraintText);
// not empty rgColumnList
pcons->cColumns = 1;
pcons->rgColumnList = &rgColumnDesc[0].dbcid;
TESTC_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consCheck,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_BADCONSTRAINTFORM);
// not empty rgForeignKeyColumnList
pcons->cColumns = 0;
pcons->rgColumnList = NULL;
pcons->cForeignKeyColumns = 1;
pcons->rgForeignKeyColumnList = &rgColumnDesc[0].dbcid;
TEST2C_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consCheck,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_BADCONSTRAINTFORM, E_INVALIDARG);
// not empty rgColumnList and rgForeignKeyColumnList
pcons->cColumns = 1;
pcons->rgColumnList = &rgColumnDesc[0].dbcid;
pcons->cForeignKeyColumns = 1;
pcons->rgForeignKeyColumnList = &rgColumnDesc[0].dbcid;
TESTC_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consCheck,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_BADCONSTRAINTFORM);
CLEANUP:
pcons->cColumns = 0;
pcons->rgColumnList = NULL;
pcons->cForeignKeyColumns = 0;
pcons->rgForeignKeyColumnList = NULL;
SAFE_FREE(pwszConstraintText);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc Non empty list of foreign keys for a constraint that is not foreign key
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_9()
{
TBEGIN
CForeignKeyCons consFK;
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
const DBORDINAL cColumns = 2;
DBID rgColumnList[cColumns];
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBID *pTableID = NULL;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[0].dbcid.eKind
&& rgColumnDesc[0].dbcid.uName.pwszName);
rgColumnList[0].eKind = DBKIND_NAME;
rgColumnList[0].uName.pwszName = (LPWSTR)0x01234567;
rgColumnList[1].eKind = 0xfe;
rgColumnList[1].uName.pwszName = (LPWSTR)0x01234567;
// set up the unique constraint
consUnique.AddColumn(&rgColumnDesc[0].dbcid);
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
((DBCONSTRAINTDESC*)consUnique)->cForeignKeyColumns = cColumns;
((DBCONSTRAINTDESC*)consUnique)->rgForeignKeyColumnList = rgColumnList;
CHECK(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consUnique,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_BADCONSTRAINTFORM);
((DBCONSTRAINTDESC*)consUnique)->cForeignKeyColumns = 0;
((DBCONSTRAINTDESC*)consUnique)->rgForeignKeyColumnList = NULL;
// set up the primary key constraint
consPK.AddColumn(&rgColumnDesc[0].dbcid);
consPK.AddColumn(&rgColumnDesc[1].dbcid);
((DBCONSTRAINTDESC*)consPK)->cForeignKeyColumns = cColumns;
((DBCONSTRAINTDESC*)consPK)->rgForeignKeyColumnList = rgColumnList;
CHECK(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consPK,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_BADCONSTRAINTFORM);
((DBCONSTRAINTDESC*)consPK)->cForeignKeyColumns = 0;
((DBCONSTRAINTDESC*)consPK)->rgForeignKeyColumnList = NULL;
// set up the check constraint
consCheck.SetConstraintText(L"TRUE != FALSE");
((DBCONSTRAINTDESC*)consCheck)->cForeignKeyColumns = cColumns;
((DBCONSTRAINTDESC*)consCheck)->rgForeignKeyColumnList = rgColumnList;
TEST2C_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consCheck,
IID_IRowset, 0, NULL,
&pTableID, NULL), E_INVALIDARG, DB_E_BADCONSTRAINTFORM);
CLEANUP:
((DBCONSTRAINTDESC*)consCheck)->cForeignKeyColumns = 0;
((DBCONSTRAINTDESC*)consCheck)->rgForeignKeyColumnList = NULL;
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc 0 < cForeignKeyColumns and NULL == rgForeignKeyColumnList => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_10()
{
// this tests rgColumnList for PK, FK and unique constraints
// as well as rgForeignKeyColumnList for FK
TBEGIN
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CUniqueCons cons;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a simple foreign key constraint
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.AddColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
consForeignKey.ReleaseForeignKeyColumnList();
((DBCONSTRAINTDESC*)consForeignKey)->cForeignKeyColumns = 1;
consForeignKey.AddColumn(&rgColumnDesc[0].dbcid);
TESTC_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL,
&pTableID, NULL), E_INVALIDARG);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc Constraint is not foreign key and pReferencedTableID is not NULL
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_11()
{
TBEGIN
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CUniqueCons consUnique;
CPrimaryKeyCons consPK;
CCheckCons consCheck;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBID *pTableID = NULL;
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[0].dbcid.eKind
&& rgColumnDesc[0].dbcid.uName.pwszName);
// set up the unique constraint
consUnique.AddColumn(&rgColumnDesc[0].dbcid);
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
DBID* pTempDBID = NULL;
DuplicateDBID(ReferencedTable.GetTableIDRef(), pTempDBID);
((DBCONSTRAINTDESC*)consUnique)->pReferencedTableID = pTempDBID;
CHECK(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consUnique,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_BADCONSTRAINTFORM);
((DBCONSTRAINTDESC*)consUnique)->pReferencedTableID = NULL;
// set up the primary key constraint
consPK.AddColumn(&rgColumnDesc[0].dbcid);
consPK.AddColumn(&rgColumnDesc[1].dbcid);
DuplicateDBID(ReferencedTable.GetTableIDRef(), pTempDBID);
((DBCONSTRAINTDESC*)consPK)->pReferencedTableID = pTempDBID;
CHECK(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consPK,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_BADCONSTRAINTFORM);
((DBCONSTRAINTDESC*)consPK)->pReferencedTableID = NULL;
// set up the check constraint
consCheck.SetConstraintText(L"TRUE != FALSE");
DuplicateDBID(ReferencedTable.GetTableIDRef(), pTempDBID);
((DBCONSTRAINTDESC*)consCheck)->pReferencedTableID = pTempDBID;
CHECK(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consCheck,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_BADCONSTRAINTFORM);
((DBCONSTRAINTDESC*)consCheck)->pReferencedTableID = NULL;
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc NULL pReferencedTableID for a foreign key constraint (with and without cForeignKeyColumns being 0)
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_12()
{
TBEGIN
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBID *pTableID = NULL;
CCol col;
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[0].dbcid.eKind
&& rgColumnDesc[0].dbcid.uName.pwszName);
// set up the check constraint
consForeignKey.SetReferencedTableID(NULL);
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
CHECK(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_BADCONSTRAINTFORM);
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
CHECK(consForeignKey.MakeConstraintName(), S_OK);
CHECK(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_BADCONSTRAINTFORM);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc NULL referenced table name for a foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_13()
{
TBEGIN
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBID *pTableID = NULL;
CCol col;
DBID ReferencedTableID;
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[0].dbcid.eKind
&& rgColumnDesc[0].dbcid.uName.pwszName);
// set up the check constraint
ReferencedTableID.eKind = DBKIND_NAME;
ReferencedTableID.uName.pwszName = NULL;
consForeignKey.SetReferencedTableID(&ReferencedTableID);
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
CHECK(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_NOTABLE);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(14)
//*-----------------------------------------------------------------------
// @mfunc DB_NULLID *pReferencedTableID for a foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_14()
{
TBEGIN
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBID *pTableID = NULL;
CCol col;
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[0].dbcid.eKind
&& rgColumnDesc[0].dbcid.uName.pwszName);
// set up the check constraint
consForeignKey.SetReferencedTableID((DBID*)&DB_NULLID);
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
CHECK(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_NOTABLE);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(15)
//*-----------------------------------------------------------------------
// @mfunc Empty string referenced table name for a foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_15()
{
TBEGIN
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBID *pTableID = NULL;
CCol col;
DBID ReferencedTableID;
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[0].dbcid.eKind
&& rgColumnDesc[0].dbcid.uName.pwszName);
// set up the check constraint
ReferencedTableID.eKind = DBKIND_NAME;
ReferencedTableID.uName.pwszName = L"";
consForeignKey.SetReferencedTableID(&ReferencedTableID);
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
CHECK(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_NOTABLE);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc Maximum length referenced table name for a foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_16()
{
TBEGIN
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBID *pTableID = NULL;
CCol col;
WCHAR *pwszTableName = NULL;
CUniqueCons cons;
// create support for foreign key constraint
ReferencedTable.MakeTableName(NULL);
pwszTableName = BuildValidName(m_cMaxTableName, ReferencedTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0, 0, pwszTableName), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
CHECK(AddUniqueConstraint(&ReferencedTable, 1), S_OK);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[0].dbcid.eKind
&& rgColumnDesc[0].dbcid.uName.pwszName);
// set up the check constraint
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
CHECK(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL,
&pTableID, NULL), S_OK);
CLEANUP:
CHECK(DropTableAndCheck(pTableID), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
SAFE_FREE(pwszTableName);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(17)
//*-----------------------------------------------------------------------
// @mfunc Referenced table name longer than allowed for a foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_17()
{
TBEGIN
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBID *pTableID = NULL;
CCol col;
DBID ReferencedTableID;
// create support for foreign key constraint
ReferencedTable.MakeTableName(NULL);
ReferencedTableID.eKind = DBKIND_NAME;
ReferencedTableID.uName.pwszName = BuildValidName(m_cMaxTableName+1, ReferencedTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[0].dbcid.eKind
&& rgColumnDesc[0].dbcid.uName.pwszName);
// set up the check constraint
consForeignKey.SetReferencedTableID(&ReferencedTableID);
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
TESTC_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_NOTABLE);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
ReleaseDBID(&ReferencedTableID, FALSE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(18)
//*-----------------------------------------------------------------------
// @mfunc Illegal characters in the referenced table name for a foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_18()
{
TBEGIN
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBID *pTableID = NULL;
CCol col;
DBID ReferencedTableID;
size_t m, n;
// create support for foreign key constraint
ReferencedTable.MakeTableName(NULL);
ReferencedTableID.eKind = DBKIND_NAME;
m = min(m_cMaxTableName, n=5+wcslen(ReferencedTable.GetTableName()));
ReferencedTableID.uName.pwszName = BuildInvalidName(m, ReferencedTable.GetTableName(), m_pwszInvalidTableChars);
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[0].dbcid.eKind
&& rgColumnDesc[0].dbcid.uName.pwszName);
// set up the check constraint
consForeignKey.SetReferencedTableID(&ReferencedTableID);
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
TESTC_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_NOTABLE);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
ReleaseDBID(&ReferencedTableID, FALSE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(19)
//*-----------------------------------------------------------------------
// @mfunc Bad constraint type
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_19()
{
TBEGIN
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBID *pTableID = NULL;
DBCONSTRAINTDESC ConsDesc;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// set up the check constraint
memset(&ConsDesc, 0, sizeof(DBCONSTRAINTDESC));
ConsDesc.ConstraintType = 0x4b;
TESTC_(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, &ConsDesc,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_BADCONSTRAINTTYPE);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(20)
//*-----------------------------------------------------------------------
// @mfunc Inexistent referenced table
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_20()
{
TBEGIN
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
DBID *pTableID = NULL;
// create support for foreign key constraint
ReferencedTable.MakeTableName(NULL);
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[0].dbcid.eKind
&& rgColumnDesc[0].dbcid.uName.pwszName);
// set up the check constraint
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
consForeignKey.AddColumn(&rgColumnDesc[0].dbcid);
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
CHECK(CreateAndCheckTableWithConstraints(
m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL,
&pTableID, NULL), DB_E_NOTABLE);
CLEANUP:
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
ReleaseDBID(pTableID, TRUE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(21)
//*-----------------------------------------------------------------------
// @mfunc Empty string for a column name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_21()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DBID colid;
colid.eKind = DBKIND_NAME;
colid.uName.pwszName = L"";
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&colid);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consUnique,
IID_IRowset, 0, NULL, NULL, NULL), DB_E_NOCOLUMN);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&colid);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consPrimaryKey,
IID_IRowset, 0, NULL, NULL, NULL), DB_E_NOCOLUMN);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&colid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL, NULL, NULL), DB_E_NOCOLUMN);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(22)
//*-----------------------------------------------------------------------
// @mfunc Maximum length column name in a constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_22()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
WCHAR *pwszColName = NULL;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
// build the column name
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[0].dbcid.eKind);
pwszColName = rgColumnDesc[0].dbcid.uName.pwszName;
rgColumnDesc[0].dbcid.uName.pwszName = BuildValidName(m_cMaxColName, pwszColName);
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[0].dbcid);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consUnique,
IID_IRowset, 0, NULL, &pTableID, NULL), S_OK);
CHECK(DropTableAndCheck(pTableID), S_OK);
ReleaseDBID(pTableID, TRUE);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&rgColumnDesc[0].dbcid);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consPrimaryKey,
IID_IRowset, 0, NULL, &pTableID, NULL), S_OK);
CHECK(DropTableAndCheck(pTableID), S_OK);
ReleaseDBID(pTableID, TRUE);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL, &pTableID, NULL), S_OK);
CHECK(DropTableAndCheck(pTableID), S_OK);
ReleaseDBID(pTableID, TRUE);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
SAFE_FREE(pwszColName);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(23)
//*-----------------------------------------------------------------------
// @mfunc Invalid DBKIND for a column DBID of a constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_23()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DBID dbcid;
dbcid.eKind = 0x3c;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
((DBCONSTRAINTDESC*)consUnique)->cColumns = 1;
((DBCONSTRAINTDESC*)consUnique)->rgColumnList = &dbcid;
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consUnique,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
// set a primary key on the first column of the table
((DBCONSTRAINTDESC*)consPrimaryKey)->cColumns = 1;
((DBCONSTRAINTDESC*)consPrimaryKey)->rgColumnList = &dbcid;
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consPrimaryKey,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
((DBCONSTRAINTDESC*)consForeignKey)->cForeignKeyColumns = 1;
((DBCONSTRAINTDESC*)consForeignKey)->rgForeignKeyColumnList = &dbcid;
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
CLEANUP:
((DBCONSTRAINTDESC*)consUnique)->cColumns = 0;
((DBCONSTRAINTDESC*)consUnique)->rgColumnList = NULL;
((DBCONSTRAINTDESC*)consPrimaryKey)->cColumns = 0;
((DBCONSTRAINTDESC*)consPrimaryKey)->rgColumnList = NULL;
((DBCONSTRAINTDESC*)consForeignKey)->cForeignKeyColumns = 0;
((DBCONSTRAINTDESC*)consForeignKey)->rgForeignKeyColumnList = NULL;
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(24)
//*-----------------------------------------------------------------------
// @mfunc Column ID is DB_NULLID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_24()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
WCHAR *pwszColName = NULL;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
// build the column name
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[0].dbcid.eKind);
pwszColName = rgColumnDesc[0].dbcid.uName.pwszName;
rgColumnDesc[0].dbcid.uName.pwszName = BuildValidName(m_cMaxColName, pwszColName);
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on column DB_NULLID
consUnique.AddColumn((DBID*)&DB_NULLID);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consUnique,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
// set a primary key on DB_NULLID
consPrimaryKey.AddColumn((DBID*)&DB_NULLID);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consPrimaryKey,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn((DBID*)&DB_NULLID);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
SAFE_FREE(pwszColName);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(25)
//*-----------------------------------------------------------------------
// @mfunc Inexistent column => DB_E_NOCOLUMN
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_25()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc-1;
TESTC_PROVIDER(1 < m_cColumnDesc);
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[cColumnDesc].dbcid);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consUnique,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&rgColumnDesc[cColumnDesc].dbcid);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consPrimaryKey,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[cColumnDesc].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
cColumnDesc = m_cColumnDesc;
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(26)
//*-----------------------------------------------------------------------
// @mfunc NULL column name => DB_E_NOCOLUMN
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_26()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DBID dbcid;
dbcid.eKind = DBKIND_NAME;
dbcid.uName.pwszName = NULL;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&dbcid);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consUnique,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&dbcid);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consPrimaryKey,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(27)
//*-----------------------------------------------------------------------
// @mfunc Column name exceeds maximum length name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_27()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DBID dbcid;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[0].dbcid.eKind);
dbcid.eKind = DBKIND_NAME;
dbcid.uName.pwszName = BuildValidName(m_cMaxColName+1, rgColumnDesc[0].dbcid.uName.pwszName);
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&dbcid);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consUnique,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&dbcid);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consPrimaryKey,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(28)
//*-----------------------------------------------------------------------
// @mfunc Invalid column name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_28()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID *pTableID = NULL;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DBID dbcid;
size_t m, n;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
TESTC_PROVIDER(DBKIND_NAME == rgColumnDesc[0].dbcid.eKind);
m = min(m_cMaxColName, n=5+wcslen(rgColumnDesc[0].dbcid.uName.pwszName));
dbcid.eKind = DBKIND_NAME;
dbcid.uName.pwszName = BuildInvalidName(m, rgColumnDesc[0].dbcid.uName.pwszName, m_pwszInvalidColChars);
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&dbcid);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consUnique,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&dbcid);
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consPrimaryKey,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
CHECK(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, NULL,
cColumnDesc, rgColumnDesc,
1, consForeignKey,
IID_IRowset, 0, NULL, &pTableID, NULL), DB_E_NOCOLUMN);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(29)
//*-----------------------------------------------------------------------
// @mfunc Existent table name => DB_E_DUPLICATETABLEID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_29()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CConsDescArray ConsDescArray;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&rgColumnDesc[0].dbcid);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
// add all constraint to the array
ConsDescArray.AddConsDesc(consUnique);
ConsDescArray.AddConsDesc(consForeignKey);
ConsDescArray.AddConsDesc(consPrimaryKey);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
ConsDescArray, ConsDescArray,
IID_IRowset, 0, NULL, NULL, NULL), S_OK);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
ConsDescArray, ConsDescArray,
IID_IRowset, 0, NULL, NULL, NULL), DB_E_DUPLICATETABLEID);
CLEANUP:
CHECK(DropTableAndCheck(&TableID), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(30)
//*-----------------------------------------------------------------------
// @mfunc Same constraint name in 2 constraints => DB_E_DUPLICATECONSTRAINTID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_30()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CConsDescArray ConsDescArray;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&rgColumnDesc[0].dbcid);
consPrimaryKey.SetConstraintName(consUnique.GetConstraintID()->uName.pwszName);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
// add all constraint to the array
ConsDescArray.AddConsDesc(consUnique);
ConsDescArray.AddConsDesc(consForeignKey);
ConsDescArray.AddConsDesc(consPrimaryKey);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
ConsDescArray, ConsDescArray,
IID_IRowset, 0, NULL, NULL, NULL), DB_E_DUPLICATECONSTRAINTID);
CLEANUP:
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(31)
//*-----------------------------------------------------------------------
// @mfunc NULL pConstraintID in 2 constraints => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_31()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CConsDescArray ConsDescArray;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
ReleaseDBID(((DBCONSTRAINTDESC*)consUnique)->pConstraintID, TRUE);
((DBCONSTRAINTDESC*)consUnique)->pConstraintID = NULL;
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&rgColumnDesc[0].dbcid);
ReleaseDBID(((DBCONSTRAINTDESC*)consPrimaryKey)->pConstraintID);
((DBCONSTRAINTDESC*)consPrimaryKey)->pConstraintID = NULL;
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
// add all constraint to the array
ConsDescArray.AddConsDesc(consUnique);
ConsDescArray.AddConsDesc(consForeignKey);
ConsDescArray.AddConsDesc(consPrimaryKey);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
ConsDescArray, ConsDescArray,
IID_IRowset, 0, NULL, NULL, NULL), S_OK);
CLEANUP:
CHECK(DropTableAndCheck(&TableID), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(32)
//*-----------------------------------------------------------------------
// @mfunc Try to create table with constraints, but table already exists => DB_E_DUPLICATEDTABLEID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Boundary::Variation_32()
{
TBEGIN
HRESULT hr;
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CConsDescArray ConsDescArray;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&rgColumnDesc[0].dbcid);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
// add all constraint to the array
ConsDescArray.AddConsDesc(consUnique);
ConsDescArray.AddConsDesc(consForeignKey);
ConsDescArray.AddConsDesc(consPrimaryKey);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
ConsDescArray, ConsDescArray,
IID_IRowset, 0, NULL, NULL, NULL), S_OK);
TESTC_(hr = CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
ConsDescArray, ConsDescArray,
IID_IRowset, 0, NULL, NULL, NULL), DB_E_DUPLICATETABLEID);
CLEANUP:
CHECK(DropTableAndCheck(&TableID), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL TCCreateTableWithConstraints_Boundary::Terminate()
{
// TO DO: Add your own code here
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCITableDefinition::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(TCDropConstraint)
//*-----------------------------------------------------------------------
//| Test Case: TCDropConstraint - Testcase for ITableDefinitionWithConstraints::DropConstraint
//| Created: 8/9/99
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCDropConstraint::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCITableDefinition::Init())
// }}
{
if (m_pITDWC == NULL)
{
odtLog << "ITableDefinitionWithConstraints is not supported.\n";
return TEST_SKIPPED;
}
return TRUE;
}
return FALSE;
}
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc pTableID is NULL => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_1()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// choose 1 column and create a unique constraint on them
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
TESTC_(DropConstraintAndCheck(m_pITDWC, NULL, cons), E_INVALIDARG);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc pTableID.uName.pwszName is NULL => DB_E_BADTABLEID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_2()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
DBCONSTRAINTDESC *pConsDesc = (DBCONSTRAINTDESC*)cons;
CCol col;
DBID TableID;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// alloc memory for column array
pConsDesc->cColumns = 1;
SAFE_ALLOC(pConsDesc->rgColumnList, DBID, pConsDesc->cColumns);
memset(pConsDesc->rgColumnList, 0, sizeof(pConsDesc->rgColumnList));
// choose 1 column and create a unique constraint on them
TESTC_(Table.GetColInfo(1, col), S_OK);
DuplicateDBID(*col.GetColID(), pConsDesc->rgColumnList);
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = NULL;
TEST2C_(DropConstraintAndCheck(m_pITDWC, &TableID, pConsDesc->pConstraintID), DB_E_BADTABLEID, DB_E_NOTABLE);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Table name is empty => DB_E_BADTABLEID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_3()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
DBCONSTRAINTDESC *pConsDesc = (DBCONSTRAINTDESC*)cons;
CCol col;
DBID TableID;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// alloc memory for column array
pConsDesc->cColumns = 1;
SAFE_ALLOC(pConsDesc->rgColumnList, DBID, pConsDesc->cColumns);
memset(pConsDesc->rgColumnList, 0, sizeof(pConsDesc->rgColumnList));
// choose 1 column and create a unique constraint on them
TESTC_(Table.GetColInfo(1, col), S_OK);
DuplicateDBID(*col.GetColID(), pConsDesc->rgColumnList);
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = L"";
TEST2C_(DropConstraintAndCheck(m_pITDWC, &TableID, pConsDesc->pConstraintID),
DB_E_BADTABLEID, DB_E_NOTABLE);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Table name is not the one on which the column was created
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_4()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable Table2(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
DBCONSTRAINTDESC *pConsDesc = (DBCONSTRAINTDESC*)cons;
CCol col;
HRESULT hr;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
TESTC_(Table2.CreateTable(0, 0), S_OK);
Table2.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table2.GetTableName());
// alloc memory for column array
pConsDesc->cColumns = 1;
SAFE_ALLOC(pConsDesc->rgColumnList, DBID, pConsDesc->cColumns);
memset(pConsDesc->rgColumnList, 0, sizeof(pConsDesc->rgColumnList));
// choose 1 column and create a unique constraint on them
TESTC_(Table.GetColInfo(1, col), S_OK);
DuplicateDBID(*col.GetColID(), pConsDesc->rgColumnList);
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
TEST2C_(hr = DropConstraintAndCheck(m_pITDWC, &Table2.GetTableID(),
pConsDesc->pConstraintID), S_OK, E_FAIL);
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), pConsDesc->pConstraintID),
(S_OK == hr)? DB_E_BADTABLEID: S_OK);
CLEANUP:
Table.DropTable();
Table2.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc Inexistent table name => DB_E_NOTABLE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_5()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CTable Table2(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
DBCONSTRAINTDESC *pConsDesc = (DBCONSTRAINTDESC*)cons;
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// alloc memory for column array
pConsDesc->cColumns = 1;
SAFE_ALLOC(pConsDesc->rgColumnList, DBID, pConsDesc->cColumns);
memset(pConsDesc->rgColumnList, 0, sizeof(pConsDesc->rgColumnList));
// choose 1 column and create a unique constraint on them
TESTC_(Table.GetColInfo(1, col), S_OK);
DuplicateDBID(*col.GetColID(), pConsDesc->rgColumnList);
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
TESTC_(Table2.MakeTableName(NULL), S_OK);
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table2.GetTableID(), pConsDesc->pConstraintID), DB_E_NOTABLE);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(6)
//*-----------------------------------------------------------------------
// @mfunc Maximum table name => S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_6()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
WCHAR *pwszTableName = NULL;
// create the base table with maximum name length
Table.MakeTableName(NULL);
pwszTableName = BuildValidName(m_cMaxTableName, Table.GetTableName());
TESTC_(Table.CreateTable(0, 0, pwszTableName), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// choose 1 column and create a unique constraint on them
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(),
cons.GetConstraintID()), S_OK);
CLEANUP:
Table.DropTable();
SAFE_FREE(pwszTableName);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(7)
//*-----------------------------------------------------------------------
// @mfunc Invalid characters in table's name => DB_E_BADTABLEID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_7()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
size_t m, n;
DBID TableID;
// create the base table
TESTC_(Table.CreateTable(0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// choose 1 column and create a unique constraint on them
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// set an invalid table name
m = min(m_cMaxColName, n=5+wcslen(Table.GetTableName()));
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = BuildInvalidName(m, Table.GetTableName(), m_pwszInvalidColChars);
// drop the constraint
TEST2C_(DropConstraintAndCheck(m_pITDWC, &TableID, cons.GetConstraintID()), DB_E_BADTABLEID, DB_E_NOTABLE);
CLEANUP:
Table.DropTable();
ReleaseDBID(&TableID, FALSE);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(8)
//*-----------------------------------------------------------------------
// @mfunc pConstraintID is NUL => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_8()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// choose 1 column and create a unique constraint on them
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint and recreate it
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), NULL), E_INVALIDARG);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(9)
//*-----------------------------------------------------------------------
// @mfunc *pConstraintID is DB_NULLID => DB_E_NOCONSTRAINT
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_9()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// choose 1 column and create a unique constraint on them
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
cons.SetConstraintID((DBID*)&DB_NULLID);
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_NOCONSTRAINT);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(10)
//*-----------------------------------------------------------------------
// @mfunc Invalid DBKIND in the constraint name => DB_E_NOCONSTRAINT
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_10()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// choose 1 column and create a unique constraint on them
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
ReleaseDBID(((DBCONSTRAINTDESC*)cons)->pConstraintID, FALSE);
((DBCONSTRAINTDESC*)cons)->pConstraintID->eKind = 0xa0;
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_NOCONSTRAINT);
CLEANUP:
((DBCONSTRAINTDESC*)cons)->pConstraintID->eKind = DBKIND_NAME;
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(11)
//*-----------------------------------------------------------------------
// @mfunc NULL constraint name => DB_E_NOCONSTRAINT
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_11()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// choose 1 column and create a unique constraint on them
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
cons.SetConstraintName(NULL);
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_NOCONSTRAINT);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(12)
//*-----------------------------------------------------------------------
// @mfunc Constraint name is empty string => DB_E_NOCONSTRAINT
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_12()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// choose 1 column and create a unique constraint on them
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
cons.SetConstraintName(L"");
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_NOCONSTRAINT);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(13)
//*-----------------------------------------------------------------------
// @mfunc Inexistent constraint name => DB_E_NOCONSTRAINT
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_13()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// choose 1 column and create a unique constraint on them
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
cons.MakeConstraintName();
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_NOCONSTRAINT);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(14)
//*-----------------------------------------------------------------------
// @mfunc Drop a constraint twice
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_14()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// choose a column and create a unique constraint on it
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), DB_E_NOCONSTRAINT);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(15)
//*-----------------------------------------------------------------------
// @mfunc Drop a unique constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_15()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// choose a column and create a unique constraint on it
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(16)
//*-----------------------------------------------------------------------
// @mfunc Drop a primary key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_16()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CPrimaryKeyCons cons;
CCol col;
TESTC_(CreateTableWithNoNullableColumns(&Table, 0), S_OK);
// choose a column and create a primary key constraint on it
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(17)
//*-----------------------------------------------------------------------
// @mfunc Drop a foreign key constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_17()
{
TBEGIN
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CForeignKeyCons cons(NULL, m_SupportedMatchType);
CCol col;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
TESTC_(AddUniqueConstraint(&ReferencedTable, 1), S_OK);
// choose 1 column and create a unique constraint on them
TESTC_(BaseTable.GetColInfo(1, col), S_OK);
cons.AddForeignKeyColumn(col.GetColID());
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
cons.AddColumn(col.GetColID());
cons.SetReferencedTableID(&ReferencedTable.GetTableID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), S_OK);
// drop the constraint
TESTC_(DropConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), S_OK);
CLEANUP:
CHECK(BaseTable.DropTable(), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(18)
//*-----------------------------------------------------------------------
// @mfunc Drop a check constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_18()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons;
CCol col;
WCHAR *pwszConstraintText = NULL;
WCHAR wszText[] = L" IS NOT NULL";
TESTC_(CreateTableWithNoNullableColumns(&Table, 0), S_OK);
// choose a column and create a primary key constraint on it
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
// build constraint text
TESTC_PROVIDER(DBKIND_NAME == col.GetColID()->eKind);
SAFE_ALLOC(pwszConstraintText, WCHAR, 1 + wcslen(col.GetColID()->uName.pwszName) + wcslen(wszText));
wcscpy(pwszConstraintText, col.GetColID()->uName.pwszName);
wcscat(pwszConstraintText, wszText);
cons.SetConstraintText(pwszConstraintText);
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
TESTC_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
CLEANUP:
Table.DropTable();
SAFE_FREE(pwszConstraintText);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(19)
//*-----------------------------------------------------------------------
// @mfunc Create several constraints, drop a single constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_19()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBID TableID;
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CConsDescArray ConsDescArray;
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
DBORDINAL rgReferencedCol[] = {1};
CCol col;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
m_pTable->MakeTableName(NULL);
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = m_pTable->GetTableName();
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&rgColumnDesc[0].dbcid);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
// add all constraint to the array
ConsDescArray.AddConsDesc(consUnique);
ConsDescArray.AddConsDesc(consForeignKey);
ConsDescArray.AddConsDesc(consPrimaryKey);
TESTC_(CreateAndCheckTableWithConstraints(m_pITDWC, NULL, &TableID, cColumnDesc, rgColumnDesc,
ConsDescArray, ConsDescArray,
IID_IRowset, 0, NULL, NULL, NULL), S_OK);
CHECK(DropConstraintAndCheck(m_pITDWC, &TableID, consForeignKey), S_OK);
CHECK(DropConstraintAndCheck(m_pITDWC, &TableID, consUnique), S_OK);
CHECK(DropConstraintAndCheck(m_pITDWC, &TableID, consPrimaryKey), S_OK);
CLEANUP:
CHECK(DropTableAndCheck(&TableID), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(20)
//*-----------------------------------------------------------------------
// @mfunc Drop a unique constraint in the referenced table, after the foreign key constraint was added
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_20()
{
TBEGIN
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CForeignKeyCons cons(NULL, m_SupportedMatchType);
CUniqueCons consUnique;
CUniqueCons consUnique1;
CCol col;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
consUnique.SetConstraint(&ReferencedTable, 1);
TESTC_(AddConstraintAndCheck(m_pITDWC, &ReferencedTable.GetTableID(), consUnique), S_OK);
consUnique1.SetConstraint(&ReferencedTable, 2);
TESTC_(AddConstraintAndCheck(m_pITDWC, &ReferencedTable.GetTableID(), consUnique1), S_OK);
// choose 1 column and create a unique constraint on them
TESTC_(BaseTable.GetColInfo(1, col), S_OK);
cons.AddForeignKeyColumn(col.GetColID());
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
cons.AddColumn(col.GetColID());
cons.SetReferencedTableID(&ReferencedTable.GetTableID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), S_OK);
// drop the unique constraints on the referenced table
CHECK(DropConstraintAndCheck(m_pITDWC, &ReferencedTable.GetTableID(), consUnique),
DB_E_DROPRESTRICTED);
CHECK(DropConstraintAndCheck(m_pITDWC, &ReferencedTable.GetTableID(), consUnique1),
S_OK);
// drop the foreign key constraint on the base table
CHECK(DropConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), S_OK);
// drop the unique constraint on the referenced table
CHECK(DropConstraintAndCheck(m_pITDWC, &ReferencedTable.GetTableID(), consUnique),
S_OK);
CLEANUP:
CHECK(BaseTable.DropTable(), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(21)
//*-----------------------------------------------------------------------
// @mfunc Try to drop a unique constraint while a rowset is opened on the table => DB_E_TABLEINUSE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_21()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
IRowsetChange *pIRowsetChange = NULL;
HRESULT hr;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// choose a column and create a unique constraint on it
TESTC_(Table.GetColInfo(3, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// open a rowset on the table
CHECK(Table.Insert(7), S_OK);
CHECK(Table.Insert(7), DB_E_INTEGRITYVIOLATION);
TESTC_(hr = m_pIOpenRowset->OpenRowset(NULL, &Table.GetTableID(), NULL,
IID_IRowsetChange, 0, NULL, (IUnknown**)&pIRowsetChange), S_OK);
// drop the constraint
TEST2C_(hr = DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons),
S_OK, DB_E_TABLEINUSE);
if (S_OK == hr)
{
odtLog << "Constraint was dropped\n";
CHECK(Table.Insert(7), S_OK);
}
else
CHECK(Table.Insert(7), DB_E_INTEGRITYVIOLATION);
CLEANUP:
SAFE_RELEASE(pIRowsetChange);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(22)
//*-----------------------------------------------------------------------
// @mfunc *pTableID is DB_NULLID => DB_E_BADTABLEID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_22()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// choose 1 column and create a unique constraint on them
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
TEST2C_(DropConstraintAndCheck(m_pITDWC, (DBID*)&DB_NULLID, cons), DB_E_BADTABLEID, DB_E_NOTABLE);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(23)
//*-----------------------------------------------------------------------
// @mfunc Invalid DBKIND in pTableID => DB_E_BADTABLEID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_23()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
DBID TableID;
TESTC_(Table.CreateTable(0, 0), S_OK);
Table.AddInfoFromColumnsSchemaRowset(m_pITDWC, Table.GetTableName());
// choose 1 column and create a unique constraint on them
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
// drop the constraint
TableID.eKind = 0x44;
TEST2C_(DropConstraintAndCheck(m_pITDWC, &TableID, cons), DB_E_BADTABLEID, DB_E_NOTABLE);
CLEANUP:
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(24)
//*-----------------------------------------------------------------------
// @mfunc Try to drop a check constraint while a rowset is opened on the table => DB_E_TABLEINUSE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_24()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CCheckCons cons;
CCol col;
WCHAR *pwszConstraintText = NULL;
WCHAR wszText[] = L" IS NOT NULL";
IRowsetChange *pIRowsetChange = NULL;
TESTC_(CreateTableWithNoNullableColumns(&Table, 0), S_OK);
// choose a column and create a primary key constraint on it
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
// build constraint text
TESTC_PROVIDER(DBKIND_NAME == col.GetColID()->eKind);
SAFE_ALLOC(pwszConstraintText, WCHAR, 1 + wcslen(col.GetColID()->uName.pwszName) + wcslen(wszText));
wcscpy(pwszConstraintText, col.GetColID()->uName.pwszName);
wcscat(pwszConstraintText, wszText);
cons.SetConstraintText(pwszConstraintText);
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
TESTC_(m_pIOpenRowset->OpenRowset(NULL, &Table.GetTableID(), NULL,
IID_IRowsetChange, 0, NULL, (IUnknown**)&pIRowsetChange), S_OK);
// drop the constraint
TEST2C_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK, DB_E_TABLEINUSE);
CLEANUP:
SAFE_RELEASE(pIRowsetChange);
Table.DropTable();
SAFE_FREE(pwszConstraintText);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(25)
//*-----------------------------------------------------------------------
// @mfunc Try to drop a pk constraint while a rowset is opened on the table => DB_E_TABLEINUSE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_25()
{
TBEGIN
CTable Table(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
CPrimaryKeyCons cons;
CCol col;
IRowsetChange *pIRowsetChange = NULL;
TESTC_(CreateTableWithNoNullableColumns(&Table, 0), S_OK);
// choose a column and create a primary key constraint on it
TESTC_(Table.GetColInfo(1, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK);
TESTC_(m_pIOpenRowset->OpenRowset(NULL, &Table.GetTableID(), NULL,
IID_IRowsetChange, 0, NULL, (IUnknown**)&pIRowsetChange), S_OK);
// drop the constraint
TEST2C_(DropConstraintAndCheck(m_pITDWC, &Table.GetTableID(), cons), S_OK, DB_E_TABLEINUSE);
CLEANUP:
SAFE_RELEASE(pIRowsetChange);
Table.DropTable();
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(26)
//*-----------------------------------------------------------------------
// @mfunc Try to drop a fk constraint while a rowset is opened on the table => DB_E_TABLEINUSE
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_26()
{
TBEGIN
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CForeignKeyCons cons(NULL, m_SupportedMatchType);
CCol col;
IRowsetChange *pIRowsetChange = NULL;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
TESTC_(AddUniqueConstraint(&ReferencedTable, 1), S_OK);
// choose 1 column and create a unique constraint on them
TESTC_(BaseTable.GetColInfo(1, col), S_OK);
cons.AddForeignKeyColumn(col.GetColID());
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
cons.AddColumn(col.GetColID());
cons.SetReferencedTableID(&ReferencedTable.GetTableID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), S_OK);
TESTC_(m_pIOpenRowset->OpenRowset(NULL, &BaseTable.GetTableID(), NULL,
IID_IRowsetChange, 0, NULL, (IUnknown**)&pIRowsetChange), S_OK);
// drop the constraint
TEST2C_(DropConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), S_OK, DB_E_TABLEINUSE);
CLEANUP:
SAFE_RELEASE(pIRowsetChange);
CHECK(BaseTable.DropTable(), S_OK);
CHECK(ReferencedTable.DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(27)
//*-----------------------------------------------------------------------
// @mfunc Both pTableID and pConstraintID are NULL => E_INVALIDARG
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_27()
{
TBEGIN
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
CUniqueCons cons;
CCol col;
IRowsetChange *pIRowsetChange = NULL;
TESTC_(BaseTable.CreateTable(0, 0), S_OK);
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
// choose 1 column and create a unique constraint on them
TESTC_(BaseTable.GetColInfo(1, col), S_OK);
// Add constraint
cons.AddColumn(col.GetColID());
TESTC_(AddConstraintAndCheck(m_pITDWC, &BaseTable.GetTableID(), cons), S_OK);
TESTC_(m_pIOpenRowset->OpenRowset(NULL, &BaseTable.GetTableID(), NULL,
IID_IRowsetChange, 0, NULL, (IUnknown**)&pIRowsetChange), S_OK);
// drop the constraint
TESTC_(DropConstraintAndCheck(m_pITDWC, NULL, NULL), E_INVALIDARG);
CLEANUP:
SAFE_RELEASE(pIRowsetChange);
CHECK(BaseTable.DropTable(), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(28)
//*-----------------------------------------------------------------------
// @mfunc Abort retain
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_28()
{
CDropConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
TRUE, // Abort
TRUE // Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(29)
//*-----------------------------------------------------------------------
// @mfunc Abort non retain
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_29()
{
CDropConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
TRUE, // Abort
FALSE // Non Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(30)
//*-----------------------------------------------------------------------
// @mfunc Commit retain
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_30()
{
CDropConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
FALSE, // Commit
TRUE // Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(31)
//*-----------------------------------------------------------------------
// @mfunc Commit non retain
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint::Variation_31()
{
CDropConsTxnAdapter TxnAdapter(this);
CTransactionLocal TxnLocal;
return TxnLocal.DoTransactionTest(m_pITDWC, &TxnAdapter,
TRUE, // DDL
FALSE, // Commit
FALSE // Non Retaining
);
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL TCDropConstraint::Terminate()
{
// TO DO: Add your own code here
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCITableDefinition::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(TCAddConstraint_Multithreading)
//*-----------------------------------------------------------------------
//| Test Case: TCAddConstraint_Multithreading - Testcase for ITableDefinitionWithConstraints::AddConstraint used in multithreaded calls
//| Created: 9/14/99
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCAddConstraint_Multithreading::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCITableDefinition::Init())
// }}
{
if (m_pITDWC == NULL)
{
odtLog << "ITableDefinitionWithConstraints is not supported.\n";
return TEST_SKIPPED;
}
return TRUE;
}
return FALSE;
}
//---------------------------------------------------------------------
//
// @cmember Thread funtion for TCAddConstraint_Multithreading
//---------------------------------------------------------------------
unsigned TCAddConstraint_Multithreading::MyThreadProc(ULONG i)
{
HRESULT hr;
if (i>= nThreads)
return 0;
Sleep(0); // switch the context
hr = m_pITDWC->AddConstraint(m_prgTableID[i], &m_rgConstraintDesc[i]);
Sleep(0); // switch the context
m_rgResult[i] = hr;
return 1;
} //TCAddConstraint_Multithreading::MyThreadProc
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Each thread creates a different constraint
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Multithreading::Variation_1()
{
TBEGIN
DBORDINAL cThreads = nThreads;
CConsDesc *pConsDesc = NULL;
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
ULONG i;
DBORDINAL rgCol[] = {1};
HRESULT rgValidHRes[] = { S_OK,
E_FAIL,
E_INVALIDARG,
DB_E_DUPLICATECONSTRAINTID,
DB_E_BADCONSTRAINTID,
DB_E_BADCONSTRAINTTYPE,
DB_E_BADUPDATEDELETERULE,
DB_E_BADMATCHTYPE,
DB_E_BADDEFERRABILITY,
DB_E_BADCONSTRAINTFORM,
DB_E_NOCOLUMN,
DB_E_NOTABLE,
DB_E_TABLEINUSE,
DB_SEC_E_PERMISSIONDENIED,
XACT_E_XTIONEXISTS,
DB_E_SCHEMAVIOLATION
};
ULONG cValidHRes = NUMELEM(rgValidHRes);
CConstraints Constraints(m_pITDWC);
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0), S_OK);
TESTC_(ReferencedTable.CreateTable(0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
TESTC_(AddUniqueConstraint(&ReferencedTable, 1), S_OK);
SAFE_ALLOC(m_prgTableID, DBID*, nThreads);
SAFE_ALLOC(m_rgConstraintDesc, DBCONSTRAINTDESC, nThreads);
memset(m_rgConstraintDesc, 0, nThreads * sizeof(DBCONSTRAINTDESC));
for (i=0; i< nThreads; i++)
{
m_rgResult[i] = -1;
m_prgTableID[i] = &BaseTable.GetTableIDRef();
if (0 == i)
{
pConsDesc = new CPrimaryKeyCons(m_rgConstraintDesc+i);
TESTC_(((CPrimaryKeyCons*)pConsDesc)->SetConstraint(&BaseTable, 1), S_OK);
}
else if (i%2)
{
pConsDesc = new CUniqueCons(m_rgConstraintDesc+i);
TESTC_(((CUniqueCons*)pConsDesc)->SetConstraint(&BaseTable, 1), S_OK);
}
else
{
pConsDesc = new CForeignKeyCons(m_rgConstraintDesc+i);
TESTC_(((CForeignKeyCons*)pConsDesc)->SetConstraint(&BaseTable, 1, rgCol, &ReferencedTable, 1, rgCol, m_SupportedMatchType), S_OK);
}
pConsDesc->MakeConstraintName();
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
}
// start the threads
for (i=0; i<nThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(nThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< nThreads; i++)
CloseHandle(hrgThread[i]);
for (i=0; i<nThreads; i++)
{
if (!CHECK(m_rgResult[i], S_OK))
{
if ( m_rgConstraintDesc[i].pConstraintID
&& DBKIND_NAME == m_rgConstraintDesc[i].pConstraintID->eKind
&& m_rgConstraintDesc[i].pConstraintID->uName.pwszName)
odtLog << "Constraint " << m_rgConstraintDesc[i].pConstraintID->uName.pwszName << " failed to be added\n";
else
odtLog << "Constraint no " << i << " failed to be added\n";
COMPARE(CheckResult(m_rgResult[i], cValidHRes, rgValidHRes), TRUE);
}
else
{
// get all the constraints associated with the table
if ( m_prgTableID[i]
&& DBKIND_NAME == m_prgTableID[i]->eKind
&& CHECK(Constraints.GetConstraints(NULL, NULL, m_prgTableID[i]->uName.pwszName, NULL, NULL, NULL), S_OK))
{
CHECK(Constraints.CheckIncludedConstraints(1, &m_rgConstraintDesc[i]), S_OK);
}
}
}
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
SAFE_FREE(m_prgTableID);
CHECK(FreeConstraintDesc(&cThreads, &m_rgConstraintDesc, TRUE), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Some of the threads try to create the same constraint name
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Multithreading::Variation_2()
{
TBEGIN
DBORDINAL cThreads = nThreads;
CConsDesc *pConsDesc = NULL;
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
ULONG i;
const ULONG cSameName = 5;
DBORDINAL cDuplicates = 0;
DBORDINAL rgCol[] = {1};
HRESULT rgValidHRes[] = { S_OK,
E_FAIL,
E_INVALIDARG,
DB_E_DUPLICATECONSTRAINTID,
DB_E_BADCONSTRAINTID,
DB_E_BADCONSTRAINTTYPE,
DB_E_BADUPDATEDELETERULE,
DB_E_BADMATCHTYPE,
DB_E_BADDEFERRABILITY,
DB_E_BADCONSTRAINTFORM,
DB_E_NOCOLUMN,
DB_E_NOTABLE,
DB_E_TABLEINUSE,
DB_SEC_E_PERMISSIONDENIED,
XACT_E_XTIONEXISTS,
DB_E_SCHEMAVIOLATION
};
ULONG cValidHRes = NUMELEM(rgValidHRes);
CConstraints Constraints(m_pITDWC);
TESTC_PROVIDER(cSameName <= nThreads);
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0), S_OK);
TESTC_(ReferencedTable.CreateTable(0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
TESTC_(AddUniqueConstraint(&ReferencedTable, 1), S_OK);
SAFE_ALLOC(m_prgTableID, DBID*, nThreads);
SAFE_ALLOC(m_rgConstraintDesc, DBCONSTRAINTDESC, nThreads);
memset(m_rgConstraintDesc, 0, nThreads * sizeof(DBCONSTRAINTDESC));
for (i=0; i< nThreads; i++)
{
m_rgResult[i] = -1;
m_prgTableID[i] = &BaseTable.GetTableIDRef();
if (0 == i)
{
pConsDesc = new CPrimaryKeyCons(m_rgConstraintDesc+i);
TESTC_(((CPrimaryKeyCons*)pConsDesc)->SetConstraint(&BaseTable, 1), S_OK);
}
else if (i%2)
{
pConsDesc = new CUniqueCons(m_rgConstraintDesc+i);
TESTC_(((CUniqueCons*)pConsDesc)->SetConstraint(&BaseTable, 1), S_OK);
}
else
{
pConsDesc = new CForeignKeyCons(m_rgConstraintDesc+i);
TESTC_(((CForeignKeyCons*)pConsDesc)->SetConstraint(&BaseTable, 1, rgCol, &ReferencedTable, 1, rgCol, m_SupportedMatchType), S_OK);
}
if (0 == i || i >= cSameName)
pConsDesc->MakeConstraintName();
else
// several constraints have the same name
pConsDesc->SetConstraintID(m_rgConstraintDesc[0].pConstraintID);
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
}
// start threads
for (i=0; i<nThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(nThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< nThreads; i++)
CloseHandle(hrgThread[i]);
for (i=0; i<nThreads; i++)
{
if (S_OK != m_rgResult[i])
{
COMPARE(CompareDBID(*m_rgConstraintDesc[0].pConstraintID,
*m_rgConstraintDesc[i].pConstraintID), TRUE);
if (CHECK(m_rgResult[i], DB_E_DUPLICATECONSTRAINTID))
cDuplicates++;
if ( m_rgConstraintDesc[i].pConstraintID
&& DBKIND_NAME == m_rgConstraintDesc[i].pConstraintID->eKind
&& m_rgConstraintDesc[i].pConstraintID->uName.pwszName)
odtLog << "Constraint " << m_rgConstraintDesc[i].pConstraintID->uName.pwszName << " failed to be added\n";
else
odtLog << "Constraint no " << i << " failed to be added\n";
}
else
{
// get all the constraints associated with the table
if ( m_prgTableID[i]
&& DBKIND_NAME == m_prgTableID[i]->eKind
&& CHECK(Constraints.GetConstraints(NULL, NULL, m_prgTableID[i]->uName.pwszName, NULL, NULL, NULL), S_OK))
{
CHECK(Constraints.CheckIncludedConstraints(1, &m_rgConstraintDesc[i]), S_OK);
}
}
}
// exactly cSameName - 1 ops should have failed
TESTC(cSameName - 1 == cDuplicates);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
SAFE_FREE(m_prgTableID);
CHECK(FreeConstraintDesc(&cThreads, &m_rgConstraintDesc, TRUE), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(3)
//*-----------------------------------------------------------------------
// @mfunc Unique constraints with disjoint columns
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Multithreading::Variation_3()
{
TBEGIN
ULONG cThreads = nThreads;
CConsDesc *pConsDesc = NULL;
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
ULONG i;
DBORDINAL iCol;
DBORDINAL cConsDescs = 0;
HRESULT rgValidHRes[] = { S_OK,
E_FAIL,
E_INVALIDARG,
DB_E_DUPLICATECONSTRAINTID,
DB_E_BADCONSTRAINTID,
DB_E_BADCONSTRAINTTYPE,
DB_E_BADUPDATEDELETERULE,
DB_E_BADMATCHTYPE,
DB_E_BADDEFERRABILITY,
DB_E_BADCONSTRAINTFORM,
DB_E_NOCOLUMN,
DB_E_NOTABLE,
DB_E_TABLEINUSE,
DB_SEC_E_PERMISSIONDENIED,
XACT_E_XTIONEXISTS,
DB_E_SCHEMAVIOLATION
};
ULONG cValidHRes = NUMELEM(rgValidHRes);
CConstraints Constraints(m_pITDWC);
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0), S_OK);
TESTC_PROVIDER(nThreads <= BaseTable.CountColumnsOnTable());
BaseTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, BaseTable.GetTableName());
SAFE_ALLOC(m_prgTableID, DBID*, nThreads);
SAFE_ALLOC(m_rgConstraintDesc, DBCONSTRAINTDESC, nThreads);
memset(m_rgConstraintDesc, 0, nThreads * sizeof(DBCONSTRAINTDESC));
for (cThreads=0, iCol=1; iCol <= BaseTable.CountColumnsOnTable() && cThreads < nThreads; iCol++)
{
CCol col;
TESTC_(BaseTable.GetColInfo(iCol, col), S_OK);
// Generally, setting unique constraints on BLOBs fail
// Note: col.GetColumnSize returns length for string data types and we need size in bytes
// so multiply ColumnSize by 2 for WSTR
if (col.GetIsLong() ||
(col.GetIsFixedLength() && (col.GetColumnSize() * (col.GetProviderType()==DBTYPE_WSTR ? 2:1) > cMaxColLengthPerCons)))
continue;
m_rgResult[cThreads] = -1;
m_prgTableID[cThreads] = &BaseTable.GetTableIDRef();
pConsDesc = new CUniqueCons(m_rgConstraintDesc+cThreads);
TESTC_(((CUniqueCons*)pConsDesc)->SetConstraint(&BaseTable, iCol), S_OK);
pConsDesc->MakeConstraintName();
rgThreadParam[cThreads].pObject = this;
rgThreadParam[cThreads].i = cThreads;
cThreads++;
}
cConsDescs = cThreads;
// start threads
for (i=0; i<cThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(cThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< cThreads; i++)
CloseHandle(hrgThread[i]);
for (i=0; i< cThreads; i++)
{
if (CHECK(m_rgResult[i], S_OK))
{
// get all the constraints associated with the table
if ( m_prgTableID[i]
&& DBKIND_NAME == m_prgTableID[i]->eKind
&& CHECK(Constraints.GetConstraints(NULL, NULL, m_prgTableID[i]->uName.pwszName, NULL, NULL, NULL), S_OK))
{
CHECK(Constraints.CheckIncludedConstraints(1, &m_rgConstraintDesc[i]), S_OK);
}
}
}
CLEANUP:
BaseTable.DropTable();
SAFE_FREE(m_prgTableID);
CHECK(FreeConstraintDesc(&cConsDescs, &m_rgConstraintDesc, TRUE), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(4)
//*-----------------------------------------------------------------------
// @mfunc Unique constraints with overlapping columns
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Multithreading::Variation_4()
{
TBEGIN
DBORDINAL cThreads = nThreads;
CConsDesc *pConsDesc = NULL;
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
ULONG i;
HRESULT rgValidHRes[] = { S_OK,
E_FAIL,
E_INVALIDARG,
DB_E_DUPLICATECONSTRAINTID,
DB_E_BADCONSTRAINTID,
DB_E_BADCONSTRAINTTYPE,
DB_E_BADUPDATEDELETERULE,
DB_E_BADMATCHTYPE,
DB_E_BADDEFERRABILITY,
DB_E_BADCONSTRAINTFORM,
DB_E_NOCOLUMN,
DB_E_NOTABLE,
DB_E_TABLEINUSE,
DB_SEC_E_PERMISSIONDENIED,
XACT_E_XTIONEXISTS,
DB_E_SCHEMAVIOLATION
};
ULONG cValidHRes = NUMELEM(rgValidHRes);
CConstraints Constraints(m_pITDWC);
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0), S_OK);
TESTC_PROVIDER(nThreads <= BaseTable.CountColumnsOnTable());
SAFE_ALLOC(m_prgTableID, DBID*, nThreads);
SAFE_ALLOC(m_rgConstraintDesc, DBCONSTRAINTDESC, nThreads);
memset(m_rgConstraintDesc, 0, nThreads * sizeof(DBCONSTRAINTDESC));
for (i=0; i< nThreads; i++)
{
m_rgResult[i] = -1;
m_prgTableID[i] = &BaseTable.GetTableIDRef();
pConsDesc = new CUniqueCons(m_rgConstraintDesc+i);
TESTC_(((CUniqueCons*)pConsDesc)->SetConstraint(&BaseTable, 1), S_OK);
pConsDesc->MakeConstraintName();
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
}
// start threads
for (i=0; i<nThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(nThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< nThreads; i++)
CloseHandle(hrgThread[i]);
for (i=0; i<nThreads; i++)
{
if (CHECK(m_rgResult[i], S_OK))
{
// get all the constraints associated with the table
if ( m_prgTableID[i]
&& DBKIND_NAME == m_prgTableID[i]->eKind
&& CHECK(Constraints.GetConstraints(NULL, NULL, m_prgTableID[i]->uName.pwszName, NULL, NULL, NULL), S_OK))
{
CHECK(Constraints.CheckIncludedConstraints(1, &m_rgConstraintDesc[i]), S_OK);
}
}
}
CLEANUP:
BaseTable.DropTable();
SAFE_FREE(m_prgTableID);
CHECK(FreeConstraintDesc(&cThreads, &m_rgConstraintDesc, TRUE), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(5)
//*-----------------------------------------------------------------------
// @mfunc All constraint IDs are generated by the provider
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCAddConstraint_Multithreading::Variation_5()
{
TBEGIN
DBORDINAL cThreads = nThreads;
CConsDesc *pConsDesc = NULL;
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
ULONG i;
DBORDINAL rgCol[] = {1};
HRESULT rgValidHRes[] = { S_OK,
E_FAIL,
E_INVALIDARG,
DB_E_DUPLICATECONSTRAINTID,
DB_E_BADCONSTRAINTID,
DB_E_BADCONSTRAINTTYPE,
DB_E_BADUPDATEDELETERULE,
DB_E_BADMATCHTYPE,
DB_E_BADDEFERRABILITY,
DB_E_BADCONSTRAINTFORM,
DB_E_NOCOLUMN,
DB_E_NOTABLE,
DB_E_TABLEINUSE,
DB_SEC_E_PERMISSIONDENIED,
XACT_E_XTIONEXISTS,
DB_E_SCHEMAVIOLATION
};
ULONG cValidHRes = NUMELEM(rgValidHRes);
CConstraints Constraints(m_pITDWC);
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0), S_OK);
TESTC_(ReferencedTable.CreateTable(0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
TESTC_(AddUniqueConstraint(&ReferencedTable, 1), S_OK);
SAFE_ALLOC(m_prgTableID, DBID*, nThreads);
SAFE_ALLOC(m_rgConstraintDesc, DBCONSTRAINTDESC, nThreads);
memset(m_rgConstraintDesc, 0, nThreads * sizeof(DBCONSTRAINTDESC));
for (i=0; i< nThreads; i++)
{
m_rgResult[i] = -1;
m_prgTableID[i] = &BaseTable.GetTableIDRef();
if (0 == i)
{
pConsDesc = new CPrimaryKeyCons(m_rgConstraintDesc+i);
TESTC_(((CPrimaryKeyCons*)pConsDesc)->SetConstraint(&BaseTable, 1), S_OK);
}
else if (i%2)
{
pConsDesc = new CUniqueCons(m_rgConstraintDesc+i);
TESTC_(((CUniqueCons*)pConsDesc)->SetConstraint(&BaseTable, 1), S_OK);
}
else
{
pConsDesc = new CForeignKeyCons(m_rgConstraintDesc+i);
TESTC_(((CForeignKeyCons*)pConsDesc)->SetConstraint(&BaseTable, 1, rgCol, &ReferencedTable, 1, rgCol, m_SupportedMatchType), S_OK);
}
pConsDesc->SetConstraintID(NULL);
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
}
// start the threads
for (i=0; i<nThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(nThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< nThreads; i++)
CloseHandle(hrgThread[i]);
for (i=0; i<nThreads; i++)
{
if (CHECK(m_rgResult[i], S_OK))
{
// get all the constraints associated with the table
if ( m_prgTableID[i]
&& DBKIND_NAME == m_prgTableID[i]->eKind
&& CHECK(Constraints.GetConstraints(NULL, NULL, m_prgTableID[i]->uName.pwszName, NULL, NULL, NULL), S_OK)
&& m_rgConstraintDesc[i].pConstraintID
)
{
CHECK(Constraints.CheckIncludedConstraints(1, &m_rgConstraintDesc[i]), S_OK);
}
}
}
COMPARE(Constraints.GetConstrNo(), nThreads);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
SAFE_FREE(m_prgTableID);
CHECK(FreeConstraintDesc(&cThreads, &m_rgConstraintDesc, TRUE), S_OK);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL TCAddConstraint_Multithreading::Terminate()
{
// TO DO: Add your own code here
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCITableDefinition::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(TCDropConstraint_Multithreading)
//*-----------------------------------------------------------------------
//| Test Case: TCDropConstraint_Multithreading - Multithreading test case for ITableDefinitionWithConstraints::DropConstraints
//| Created: 9/16/99
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCDropConstraint_Multithreading::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCITableDefinition::Init())
// }}
{
if (m_pITDWC == NULL)
{
odtLog << "ITableDefinitionWithConstraints is not supported.\n";
return TEST_SKIPPED;
}
return TRUE;
}
return FALSE;
}
//---------------------------------------------------------------------
//
// @cmember Thread funtion for TCDropConstraint_Multithreading
//---------------------------------------------------------------------
unsigned TCDropConstraint_Multithreading::MyThreadProc(ULONG i)
{
HRESULT hr;
if (i>= nThreads)
return 0;
Sleep(0); // switch the context
hr = m_pITDWC->DropConstraint(m_prgTableID[i], m_prgConstraintID[i]);
Sleep(0); // switch the context
m_rgResult[i] = hr;
return 1;
} //TCDropConstraint_Multithreading::MyThreadProc
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Each thread drops a different constraint => all S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint_Multithreading::Variation_1()
{
TBEGIN
DBORDINAL cThreads = nThreads;
CConsDesc *pConsDesc = NULL;
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
ULONG i;
DBCONSTRAINTDESC *rgConstraintDesc = NULL;
DBORDINAL rgCol[] = {1};
HRESULT rgValidHRes[] = { S_OK,
E_FAIL,
E_INVALIDARG,
DB_E_NOCONSTRAINT,
DB_E_BADTABLEID,
DB_E_DROPRESTRICTED,
DB_E_NOTABLE,
DB_E_TABLEINUSE,
DB_SEC_E_PERMISSIONDENIED,
XACT_E_XTIONEXISTS,
DB_E_SCHEMAVIOLATION
};
ULONG cValidHRes = NUMELEM(rgValidHRes);
CConstraints Constraints(m_pITDWC);
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0), S_OK);
TESTC_(ReferencedTable.CreateTable(0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
TESTC_(AddUniqueConstraint(&ReferencedTable, 1), S_OK);
SAFE_ALLOC(m_prgTableID, DBID*, nThreads);
SAFE_ALLOC(rgConstraintDesc, DBCONSTRAINTDESC, nThreads);
SAFE_ALLOC(m_prgConstraintID, DBID*, nThreads);
memset(rgConstraintDesc, 0, nThreads * sizeof(DBCONSTRAINTDESC));
for (i=0; i< nThreads; i++)
{
m_rgResult[i] = -1;
m_prgTableID[i] = &BaseTable.GetTableIDRef();
// create a constraint
if (0 == i)
{
pConsDesc = new CPrimaryKeyCons(rgConstraintDesc+i);
TESTC_(((CPrimaryKeyCons*)pConsDesc)->SetConstraint(&BaseTable, 1), S_OK);
}
else if (i%2)
{
pConsDesc = new CUniqueCons(rgConstraintDesc+i);
TESTC_(((CUniqueCons*)pConsDesc)->SetConstraint(&BaseTable, 1), S_OK);
}
else
{
pConsDesc = new CForeignKeyCons(rgConstraintDesc+i);
TESTC_(((CForeignKeyCons*)pConsDesc)->SetConstraint(&BaseTable, 1, rgCol, &ReferencedTable, 1, rgCol, m_SupportedMatchType), S_OK);
}
pConsDesc->MakeConstraintName();
TESTC_(m_pITDWC->AddConstraint(m_prgTableID[i], &rgConstraintDesc[i]), S_OK);
m_prgConstraintID[i] = rgConstraintDesc[i].pConstraintID;
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
}
// start the threads
for (i=0; i<nThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(nThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< nThreads; i++)
CloseHandle(hrgThread[i]);
for (i=0; i<nThreads; i++)
{
if (!CHECK(m_rgResult[i], S_OK))
{
if ( rgConstraintDesc[i].pConstraintID
&& DBKIND_NAME == rgConstraintDesc[i].pConstraintID->eKind
&& rgConstraintDesc[i].pConstraintID->uName.pwszName)
odtLog << "Constraint " << rgConstraintDesc[i].pConstraintID->uName.pwszName << " failed to be added\n";
else
odtLog << "Constraint no " << i << " failed to be dropped\n";
COMPARE(CheckResult(m_rgResult[i], cValidHRes, rgValidHRes), TRUE);
}
else
{
// get all the constraints associated with the table
if ( m_prgTableID[i]
&& DBKIND_NAME == m_prgTableID[i]->eKind
&& CHECK(Constraints.GetConstraints(NULL, NULL, m_prgTableID[i]->uName.pwszName, NULL, NULL, NULL), S_OK))
{
COMPARE(NULL == Constraints[m_prgConstraintID[i]], TRUE);
}
}
}
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
SAFE_FREE(m_prgTableID);
CHECK(FreeConstraintDesc(&cThreads, &rgConstraintDesc, TRUE), S_OK);
SAFE_FREE(m_prgConstraintID);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Some threads try to drop the same constraint => S_OK and DB_E_NOCONSTRAINT
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCDropConstraint_Multithreading::Variation_2()
{
TBEGIN
DBORDINAL cThreads = nThreads;
CConsDesc *pConsDesc = NULL;
CTable ReferencedTable(m_pITDWC, (LPWSTR)gwszModuleName);
CTable BaseTable(m_pITDWC, (LPWSTR)gwszModuleName);
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
ULONG i;
DBCONSTRAINTDESC *rgConstraintDesc = NULL;
DBORDINAL rgCol[] = {1};
HRESULT rgValidHRes[] = { S_OK,
E_FAIL,
E_INVALIDARG,
DB_E_NOCONSTRAINT,
DB_E_BADTABLEID,
DB_E_DROPRESTRICTED,
DB_E_NOTABLE,
DB_E_TABLEINUSE,
DB_SEC_E_PERMISSIONDENIED,
XACT_E_XTIONEXISTS,
DB_E_SCHEMAVIOLATION
};
ULONG cValidHRes = NUMELEM(rgValidHRes);
CConstraints Constraints(m_pITDWC);
DBORDINAL ulFailed = 0;
const DBORDINAL cSameName = 5;
TESTC_PROVIDER(cSameName <= nThreads);
TESTC_(CreateTableWithNoNullableColumns(&BaseTable, 0), S_OK);
TESTC_(ReferencedTable.CreateTable(0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
TESTC_(AddUniqueConstraint(&ReferencedTable, 1), S_OK);
SAFE_ALLOC(m_prgTableID, DBID*, nThreads);
SAFE_ALLOC(rgConstraintDesc, DBCONSTRAINTDESC, nThreads);
SAFE_ALLOC(m_prgConstraintID, DBID*, nThreads);
memset(rgConstraintDesc, 0, nThreads * sizeof(DBCONSTRAINTDESC));
for (i=0; i< nThreads; i++)
{
m_rgResult[i] = -1;
m_prgTableID[i] = &BaseTable.GetTableIDRef();
// create a constraint
if (0 == i)
{
pConsDesc = new CPrimaryKeyCons(rgConstraintDesc+i);
TESTC_(((CPrimaryKeyCons*)pConsDesc)->SetConstraint(&BaseTable, 1), S_OK);
}
else if (i%2)
{
pConsDesc = new CUniqueCons(rgConstraintDesc+i);
TESTC_(((CUniqueCons*)pConsDesc)->SetConstraint(&BaseTable, 1), S_OK);
}
else
{
pConsDesc = new CForeignKeyCons(rgConstraintDesc+i);
TESTC_(((CForeignKeyCons*)pConsDesc)->SetConstraint(&BaseTable, 1, rgCol, &ReferencedTable, 1, rgCol, m_SupportedMatchType), S_OK);
}
pConsDesc->MakeConstraintName();
TESTC_(m_pITDWC->AddConstraint(m_prgTableID[i], &rgConstraintDesc[i]), S_OK);
if (i < cSameName)
m_prgConstraintID[i] = rgConstraintDesc[0].pConstraintID;
else
m_prgConstraintID[i] = rgConstraintDesc[i].pConstraintID;
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
}
// start the threads
for (i=0; i<nThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(nThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< nThreads; i++)
CloseHandle(hrgThread[i]);
for (i=0; i<nThreads; i++)
{
if (S_OK != m_rgResult[i])
{
CHECK(m_rgResult[i], DB_E_NOCONSTRAINT);
ulFailed++;
if ( rgConstraintDesc[i].pConstraintID
&& DBKIND_NAME == rgConstraintDesc[i].pConstraintID->eKind
&& rgConstraintDesc[i].pConstraintID->uName.pwszName)
odtLog << "Constraint " << rgConstraintDesc[i].pConstraintID->uName.pwszName << " failed to be added\n";
else
odtLog << "Constraint no " << i << " failed to be dropped\n";
COMPARE(CheckResult(m_rgResult[i], cValidHRes, rgValidHRes), TRUE);
}
else
{
// get all the constraints associated with the table
if ( m_prgTableID[i]
&& DBKIND_NAME == m_prgTableID[i]->eKind
&& CHECK(Constraints.GetConstraints(NULL, NULL, m_prgTableID[i]->uName.pwszName, NULL, NULL, NULL), S_OK))
{
COMPARE(NULL == Constraints[m_prgConstraintID[i]], TRUE);
}
}
}
TESTC(cSameName - 1 == ulFailed);
CLEANUP:
BaseTable.DropTable();
ReferencedTable.DropTable();
SAFE_FREE(m_prgTableID);
CHECK(FreeConstraintDesc(&cThreads, &rgConstraintDesc, TRUE), S_OK);
SAFE_FREE(m_prgConstraintID);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL TCDropConstraint_Multithreading::Terminate()
{
// TO DO: Add your own code here
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCITableDefinition::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
// {{ TCW_TC_PROTOTYPE(TCCreateTableWithConstraints_Multithreading)
//*-----------------------------------------------------------------------
//| Test Case: TCCreateTableWithConstraints_Multithreading - Multithreading test case for ITableDefinitionWithConstraints::CreateTableWithConstraints
//| Created: 9/17/99
//*-----------------------------------------------------------------------
//*-----------------------------------------------------------------------
// @mfunc TestCase Initialization Routine
//
// @rdesc TRUE or FALSE
//
BOOL TCCreateTableWithConstraints_Multithreading::Init()
{
// {{ TCW_INIT_BASECLASS_CHECK
if(TCITableDefinition::Init())
// }}
{
if (m_pITDWC == NULL)
{
odtLog << "ITableDefinitionWithConstraints is not supported.\n";
return TEST_SKIPPED;
}
return TRUE;
}
return FALSE;
}
//---------------------------------------------------------------------
//
// @cmember Thread funtion for TCCreateTableWithConstraints_Multithreading
//---------------------------------------------------------------------
unsigned TCCreateTableWithConstraints_Multithreading::MyThreadProc(ULONG i)
{
HRESULT hr;
if (i>= nThreads)
return 0;
Sleep(0); // switch the context
hr = m_pITDWC->CreateTableWithConstraints(
m_rgThreadParams[i].m_pUnkOuter,
m_rgThreadParams[i].m_pTableID,
m_rgThreadParams[i].m_cColumnDescs,
m_rgThreadParams[i].m_rgColumnDescs,
m_rgThreadParams[i].m_cConstraintDescs,
m_rgThreadParams[i].m_rgConstraintDescs,
*m_rgThreadParams[i].m_piid,
m_rgThreadParams[i].m_cPropertySets,
m_rgThreadParams[i].m_rgPropertySets,
m_rgThreadParams[i].m_ppTableID,
m_rgThreadParams[i].m_ppRowset
);
Sleep(0); // switch the context
m_rgThreadParams[i].m_hr = hr;
return 1;
} //TCCreateTableWithConstraints_Multithreading::MyThreadProc
// {{ TCW_VAR_PROTOTYPE(1)
//*-----------------------------------------------------------------------
// @mfunc Each thread builds different table => all S_OK
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Multithreading::Variation_1()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CConsDescArray ConsDescArray[nThreads];
ULONG i;
CCol col;
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
CConstraints Constraints(m_pITDWC);
m_rgThreadParams = NULL;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, 1, (DBDEFERRABILITY)0), S_OK);
m_rgThreadParams = new CCTWCThreadParam[nThreads];
for (i=0; i< nThreads; i++)
{
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
m_rgThreadParams[i].m_hr = E_FAIL;
m_rgThreadParams[i].m_op = CREATETABLE_CONSTRAINTS;
m_rgThreadParams[i].m_pUnkOuter = NULL;
m_rgThreadParams[i].m_pTableID = NULL;
m_rgThreadParams[i].m_cColumnDescs = cColumnDesc;
m_rgThreadParams[i].m_rgColumnDescs = rgColumnDesc;
// create the array of constraints
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&rgColumnDesc[0].dbcid);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
// add all constraint to the array
ConsDescArray[i].AddConsDesc(consUnique);
ConsDescArray[i].AddConsDesc(consForeignKey);
ConsDescArray[i].AddConsDesc(consPrimaryKey);
m_rgThreadParams[i].m_cConstraintDescs = ConsDescArray[i];
m_rgThreadParams[i].m_rgConstraintDescs = ConsDescArray[i];
m_rgThreadParams[i].m_piid = NULL;
m_rgThreadParams[i].m_cPropertySets = 0;
m_rgThreadParams[i].m_rgPropertySets= NULL;
SAFE_ALLOC(m_rgThreadParams[i].m_ppTableID, DBID*, 1);
//*m_rgThreadParams[i].m_ppTableID = NULL;
m_rgThreadParams[i].m_ppRowset = NULL;
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
}
// start the threads
for (i=0; i<nThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(nThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< nThreads; i++)
CloseHandle(hrgThread[i]);
for (i=0; i<nThreads; i++)
{
DBID *pTableID = NULL;
if (m_rgThreadParams[i].m_ppTableID)
pTableID = (*m_rgThreadParams[i].m_ppTableID);
else if (m_rgThreadParams[i].m_pTableID)
pTableID = m_rgThreadParams[i].m_pTableID;
if (CHECK(m_rgThreadParams[i].m_hr, S_OK))
{
COMPARE(NULL != pTableID, TRUE);
// get all the constraints associated with the table
if ( pTableID
&& DBKIND_NAME == pTableID->eKind
&& CHECK(Constraints.GetConstraints(NULL, NULL, pTableID->uName.pwszName, NULL, NULL, NULL), S_OK))
{
CHECK(Constraints.CheckIncludedConstraints(m_rgThreadParams[i].m_cConstraintDescs, m_rgThreadParams[i].m_rgConstraintDescs), S_OK);
}
// drop the newly created table
CHECK(m_pITableDefinition->DropTable(pTableID), S_OK);
}
}
CLEANUP:
delete [] m_rgThreadParams;
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_VAR_PROTOTYPE(2)
//*-----------------------------------------------------------------------
// @mfunc Some threads build the same table => S_OK and DB_E_DUPLICATETABLEID
//
// @rdesc TEST_PASS or TEST_FAIL
//
int TCCreateTableWithConstraints_Multithreading::Variation_2()
{
TBEGIN
CTable ReferencedTable(m_pThisTestModule->m_pIUnknown2, (LPWSTR)gwszModuleName);
DBCOLUMNDESC *rgColumnDesc = NULL;
DBORDINAL cColumnDesc = 0;
CConsDescArray ConsDescArray[nThreads];
ULONG i;
CCol col;
unsigned rgIDThread[nThreads];
HANDLE hrgThread[nThreads];
CInParam rgThreadParam[nThreads];
CConstraints Constraints(m_pITDWC);
WCHAR *pwszBaseName = NULL;
WCHAR number[3];
DBORDINAL cSameName = 5;
DBORDINAL cDuplicates = 0;
TESTC_PROVIDER(cSameName <= nThreads);
m_rgThreadParams = NULL;
DuplicateColumnDesc(m_rgColumnDesc, m_cColumnDesc, &rgColumnDesc);
cColumnDesc = m_cColumnDesc;
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(rgColumnDesc, cColumnDesc);
SetProperty(&rgColumnDesc[0].rgPropertySets, &rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
// create support for foreign key constraint
TESTC_(ReferencedTable.CreateTable(0, 0), S_OK);
ReferencedTable.AddInfoFromColumnsSchemaRowset(m_pITDWC, ReferencedTable.GetTableName());
// make the referenced columns unique
TESTC_(AddUniqueConstraint(&ReferencedTable, 1, (DBDEFERRABILITY)0), S_OK);
m_pTable->MakeTableName(NULL);
pwszBaseName = m_pTable->GetTableName();
m_rgThreadParams = new CCTWCThreadParam[nThreads];
for (i=0; i< nThreads; i++)
{
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_SupportedMatchType);
m_rgThreadParams[i].m_hr = E_FAIL;
m_rgThreadParams[i].m_op = CREATETABLE_CONSTRAINTS;
m_rgThreadParams[i].m_pUnkOuter = NULL;
SAFE_ALLOC(m_rgThreadParams[i].m_pTableID, DBID, 1);
m_rgThreadParams[i].m_pTableID->eKind = DBKIND_NAME;
SAFE_ALLOC(m_rgThreadParams[i].m_pTableID->uName.pwszName, WCHAR,
(3+wcslen(pwszBaseName)));
wcscpy(m_rgThreadParams[i].m_pTableID->uName.pwszName, pwszBaseName);
swprintf(number, L"%02d", (i < cSameName)? 0: i);
wcscat(m_rgThreadParams[i].m_pTableID->uName.pwszName, number);
m_rgThreadParams[i].m_cColumnDescs = cColumnDesc;
m_rgThreadParams[i].m_rgColumnDescs = rgColumnDesc;
// create the array of constraints
// set a unique constraint on the second column
consUnique.AddColumn(&rgColumnDesc[1].dbcid);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&rgColumnDesc[0].dbcid);
// set a simple foreign key constraint
TESTC_(ReferencedTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&ReferencedTable.GetTableID());
// add all constraint to the array
ConsDescArray[i].AddConsDesc(consUnique);
ConsDescArray[i].AddConsDesc(consForeignKey);
ConsDescArray[i].AddConsDesc(consPrimaryKey);
m_rgThreadParams[i].m_cConstraintDescs = ConsDescArray[i];
m_rgThreadParams[i].m_rgConstraintDescs = ConsDescArray[i];
m_rgThreadParams[i].m_piid = NULL;
m_rgThreadParams[i].m_cPropertySets = 0;
m_rgThreadParams[i].m_rgPropertySets= NULL;
m_rgThreadParams[i].m_ppTableID = NULL;
m_rgThreadParams[i].m_ppRowset = NULL;
rgThreadParam[i].pObject = this;
rgThreadParam[i].i = i;
}
// start the threads
for (i=0; i<nThreads; i++)
{
hrgThread[i] = (HANDLE)_beginthreadex(NULL, 0, ThreadProc,
(void*)&rgThreadParam[i],
0,
&rgIDThread[i]); // input param
TESTC(0 != hrgThread[i]);
}
WaitForMultipleObjects(nThreads, (CONST HANDLE*)hrgThread, TRUE, 1000);
Sleep(1000);
for (i=0; i< nThreads; i++)
CloseHandle(hrgThread[i]);
for (i=0; i<nThreads; i++)
{
DBID *pTableID = NULL;
if (m_rgThreadParams[i].m_ppTableID)
pTableID = (*m_rgThreadParams[i].m_ppTableID);
else if (m_rgThreadParams[i].m_pTableID)
pTableID = m_rgThreadParams[i].m_pTableID;
if (S_OK == m_rgThreadParams[i].m_hr)
{
COMPARE(NULL != pTableID, TRUE);
// get all the constraints associated with the table
if ( pTableID
&& DBKIND_NAME == pTableID->eKind
&& CHECK(Constraints.GetConstraints(NULL, NULL, pTableID->uName.pwszName, NULL, NULL, NULL), S_OK))
{
CHECK(Constraints.CheckIncludedConstraints(m_rgThreadParams[i].m_cConstraintDescs, m_rgThreadParams[i].m_rgConstraintDescs), S_OK);
}
// drop the newly created table
CHECK(m_pITableDefinition->DropTable(pTableID), S_OK);
}
else
{
if (CHECK(m_rgThreadParams[i].m_hr, DB_E_DUPLICATETABLEID))
cDuplicates++;
}
}
TESTC(cDuplicates + 1 == cSameName);
CLEANUP:
delete [] m_rgThreadParams;
CHECK(ReferencedTable.DropTable(), S_OK);
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
TRETURN
}
// }} TCW_VAR_PROTOTYPE_END
// {{ TCW_TERMINATE_METHOD
//*-----------------------------------------------------------------------
// @mfunc TestCase Termination Routine
//
// @rdesc TEST_PASS or TEST_FAIL
//
BOOL TCCreateTableWithConstraints_Multithreading::Terminate()
{
// TO DO: Add your own code here
// {{ TCW_TERM_BASECLASS_CHECK2
return(TCITableDefinition::Terminate());
} // }}
// }} TCW_TERMINATE_METHOD_END
// }} TCW_TC_PROTOTYPE_END
///////////////////////////////////////////////////////////////////////////
//
// CAddConstraintTxnAdapter class
//
///////////////////////////////////////////////////////////////////////////
BOOL CAddConstraintTxnAdapter::BeforeTransaction()
{
TBEGIN
// create a table and populate it
TESTC_(pTCITableDefinition()->CreateTableWithNoNullableColumns(&m_Table, 0, 0), S_OK);
m_Table.AddInfoFromColumnsSchemaRowset(g_pIOpenRowset, m_Table.GetTableName());
// get the list of the constraints on the table
m_pConstraints = new CConstraints(g_pIOpenRowset);
TESTC_(m_pConstraints->GetConstraints(NULL, NULL, m_Table.GetTableName(), NULL, NULL, NULL), S_OK);
CLEANUP:
TRETURN
} //CAddConstraintTxnAdapter::BeforeTransaction
///////////////////////////////////////////////////////////////////////////
//
// CAddUniqueConsTxnAdapter class
//
///////////////////////////////////////////////////////////////////////////
BOOL CAddUniqueConsTxnAdapter::BeforeTransaction()
{
TBEGIN
CCol col;
TESTC(CAddConstraintTxnAdapter::BeforeTransaction());
// select column
TESTC_(m_Table.GetColInfo(1, col), S_OK);
// add the constraint
m_pCons = new CUniqueCons();
((CUniqueCons*)m_pCons)->AddColumn(col.GetColID());
CLEANUP:
TRETURN
} //CAddUniqueConsTxnAdapter::BeforeTransaction
HRESULT CAddUniqueConsTxnAdapter::InsideTransactionScope()
{
HRESULT hr = E_FAIL;
CCol col;
CHECK(CAddConstraintTxnAdapter::InsideTransactionScope(), S_OK);
// create a table
TESTC_(pTCITableDefinition()->CreateTableWithNoNullableColumns(&m_TransactedTable, 0, 0), S_OK);
m_TransactedTable.AddInfoFromColumnsSchemaRowset(g_pIOpenRowset, m_TransactedTable.GetTableName());
// get the list of the constraints on the table
m_pTxnConstraints = new CConstraints(g_pIOpenRowset);
TESTC_(m_pTxnConstraints->GetConstraints(NULL, NULL, m_TransactedTable.GetTableName(), NULL, NULL, NULL), S_OK);
// select column
TESTC_(m_TransactedTable.GetColInfo(1, col), S_OK);
// add the constraint
m_pTransactedTableCons= new CUniqueCons();
((CUniqueCons*)m_pTransactedTableCons)->AddColumn(col.GetColID());
hr = m_pTCITableDefinition->AddConstraintAndCheck(
m_pTCITableDefinition->pITDWC(),
&m_TransactedTable.GetTableID(),
*m_pTransactedTableCons);
CLEANUP:
return hr;
} //CAddUniqueConsTxnAdapter::InsideTransactionScope
HRESULT CAddUniqueConsTxnAdapter::InsideTransactionOnDDLLock()
{
HRESULT hr = E_FAIL;
CCol col;
CHECK(CAddConstraintTxnAdapter::InsideTransactionOnDDLLock(), S_OK);
// create a table and populate it
TESTC_(pTCITableDefinition()->CreateTableWithNoNullableColumns(&m_TransactedTable, 0, 0), S_OK);
m_TransactedTable.AddInfoFromColumnsSchemaRowset(g_pIOpenRowset, m_TransactedTable.GetTableName());
// select column
TESTC_(m_TransactedTable.GetColInfo(1, col), S_OK);
// add the constraint
m_pTransactedTableCons = new CUniqueCons();
((CUniqueCons*)m_pTransactedTableCons)->AddColumn(col.GetColID());
// get the list of the constraints on the table
m_pTxnConstraints = new CConstraints(g_pIOpenRowset);
TESTC_(m_pTxnConstraints->GetConstraints(NULL, NULL, m_TransactedTable.GetTableName(), NULL, NULL, NULL), S_OK);
hr = m_pTCITableDefinition->pITDWC()->AddConstraint(
&m_TransactedTable.GetTableID(),
*m_pTransactedTableCons);
CLEANUP:
return hr;
} //CAddUniqueConsTxnAdapter::InsideTransactionOnDDLLock
BOOL CAddUniqueConsTxnAdapter::CheckCompletion()
{
TBEGIN
ASSERT(m_pCons);
TESTC(CAddConstraintTxnAdapter::CheckCompletion());
// check unique constraint here
TESTC_(m_Table.Insert(5), S_OK);
TESTC_(m_Table.Insert(5), DB_E_INTEGRITYVIOLATION);
ASSERT(m_pTransactedTableCons);
TESTC_(m_TransactedTable.Insert(5), S_OK);
TESTC_(m_TransactedTable.Insert(5), DB_E_INTEGRITYVIOLATION);
CLEANUP:
TRETURN
} //CAddUniqueConsTxnAdapter::CheckCompletion
BOOL CAddUniqueConsTxnAdapter::CheckRollBack()
{
TBEGIN
ASSERT(m_pCons);
TESTC(CAddConstraintTxnAdapter::CheckRollBack());
// check unique constraint here
TESTC_(m_Table.Insert(5), S_OK);
TESTC_(m_Table.Insert(5), S_OK);
CLEANUP:
TRETURN
} //CAddUniqueConsTxnAdapter::CheckRollBack
///////////////////////////////////////////////////////////////////////////
//
// CAddPrimaryKeyConsTxnAdapter class
//
///////////////////////////////////////////////////////////////////////////
BOOL CAddPrimaryKeyConsTxnAdapter::BeforeTransaction()
{
TBEGIN
CCol col;
TESTC(CAddConstraintTxnAdapter::BeforeTransaction());
// select column
TESTC_(m_Table.GetColInfo(1, col), S_OK);
// add the constraint
m_pCons = new CPrimaryKeyCons();
((CPrimaryKeyCons*)m_pCons)->AddColumn(col.GetColID());
CLEANUP:
TRETURN
} //CAddPrimaryKeyConsTxnAdapter::BeforeTransaction
//////////////////////////////////////////////////////////////////
//
// CAddFKConsTxnAdapter class
//
//////////////////////////////////////////////////////////////////
BOOL CAddFKConsTxnAdapter::BeforeTransaction()
{
TBEGIN
CCol col;
CUniqueCons uniqueCons;
// create a reference table and populate it
TESTC_(m_ReferencedTable.CreateTable(4, 0), S_OK);
m_ReferencedTable.AddInfoFromColumnsSchemaRowset(g_pIOpenRowset, m_ReferencedTable.GetTableName());
// add unique constraint on the first column
TESTC_(m_ReferencedTable.GetColInfo(1, col), S_OK);
uniqueCons.AddColumn(col.GetColID());
CHECK(m_pTCITableDefinition->AddConstraintAndCheck(
m_pTCITableDefinition->pITDWC(),
&m_ReferencedTable.GetTableID(), uniqueCons), S_OK);
// create a table and populate it
TESTC_(m_Table.CreateTable(4, 0), S_OK);
m_Table.AddInfoFromColumnsSchemaRowset(g_pIOpenRowset, m_Table.GetTableName());
// get the list of the constraints on the table
m_pConstraints = new CConstraints(g_pIOpenRowset);
TESTC_(m_pConstraints->GetConstraints(NULL, NULL, m_Table.GetTableName(), NULL, NULL, NULL), S_OK);
// prepare the constraint
m_pCons = new CForeignKeyCons();
// select column to be foreign key
TESTC_(m_Table.GetColInfo(1, col), S_OK);
((CForeignKeyCons*)m_pCons)->AddForeignKeyColumn(col.GetColID());
TESTC_(m_ReferencedTable.GetColInfo(1, col), S_OK);
((CForeignKeyCons*)m_pCons)->AddColumn(col.GetColID());
((CForeignKeyCons*)m_pCons)->SetReferencedTableID(&m_ReferencedTable.GetTableID());
CLEANUP:
TRETURN
} //CAddFKConsTxnAdapter::BeforeTransaction
HRESULT CAddFKConsTxnAdapter::InsideTransactionScope()
{
HRESULT hr = E_FAIL;
CCol col;
CHECK(CAddConstraintTxnAdapter::InsideTransactionScope(), S_OK);
// create a table and populate it
TESTC_(pTCITableDefinition()->CreateTableWithNoNullableColumns(&m_TransactedTable, 0, 0), S_OK);
m_TransactedTable.AddInfoFromColumnsSchemaRowset(g_pIOpenRowset, m_TransactedTable.GetTableName());
// get the list of the constraints on the table
m_pTxnConstraints = new CConstraints(g_pIOpenRowset);
TESTC_(m_pTxnConstraints->GetConstraints(NULL, NULL, m_TransactedTable.GetTableName(), NULL, NULL, NULL), S_OK);
// prepare the constraint
m_pTransactedTableCons = new CForeignKeyCons();
// select column
TESTC_(m_TransactedTable.GetColInfo(1, col), S_OK);
((CForeignKeyCons*)m_pTransactedTableCons)->AddForeignKeyColumn(col.GetColID());
TESTC_(m_ReferencedTable.GetColInfo(1, col), S_OK);
((CForeignKeyCons*)m_pTransactedTableCons)->AddColumn(col.GetColID());
((CForeignKeyCons*)m_pTransactedTableCons)->SetReferencedTableID(&m_ReferencedTable.GetTableID());
hr = m_pTCITableDefinition->AddConstraintAndCheck(
m_pTCITableDefinition->pITDWC(),
&m_TransactedTable.GetTableID(),
*m_pTransactedTableCons);
CLEANUP:
return hr;
} //CAddFKConsTxnAdapter::InsideTransactionScope
HRESULT CAddFKConsTxnAdapter::InsideTransactionOnDDLLock()
{
HRESULT hr = E_FAIL;
CCol col;
CHECK(CAddConstraintTxnAdapter::InsideTransactionOnDDLLock(), S_OK);
// create a table and populate it
TESTC_(pTCITableDefinition()->CreateTableWithNoNullableColumns(&m_TransactedTable, 0, 0), S_OK);
m_TransactedTable.AddInfoFromColumnsSchemaRowset(g_pIOpenRowset, m_TransactedTable.GetTableName());
// select column
TESTC_(m_TransactedTable.GetColInfo(1, col), S_OK);
// get the list of the constraints on the table
m_pTxnConstraints = new CConstraints(g_pIOpenRowset);
TESTC_(m_pTxnConstraints->GetConstraints(NULL, NULL, m_TransactedTable.GetTableName(), NULL, NULL, NULL), S_OK);
// prepare the constraint
m_pTransactedTableCons = new CForeignKeyCons();
((CForeignKeyCons*)m_pTransactedTableCons)->AddColumn(col.GetColID());
TESTC_(m_ReferencedTable.GetColInfo(1, col), S_OK);
((CForeignKeyCons*)m_pTransactedTableCons)->AddForeignKeyColumn(col.GetColID());
((CForeignKeyCons*)m_pTransactedTableCons)->SetReferencedTableID(&m_ReferencedTable.GetTableID());
hr = m_pTCITableDefinition->pITDWC()->AddConstraint(
&m_TransactedTable.GetTableID(),
*m_pTransactedTableCons);
CLEANUP:
return hr;
} //CAddFKConsTxnAdapter::InsideTransactionOnDDLLock
BOOL CAddFKConsTxnAdapter::CheckCompletion()
{
TBEGIN
ASSERT(m_pCons);
TESTC(CAddConstraintTxnAdapter::CheckCompletion());
// check foreign key constraint here
TESTC_(m_Table.Insert(2), S_OK);
// there isn't a row with seed 15 in the referenced table
TESTC_(m_Table.Insert(15), DB_E_INTEGRITYVIOLATION);
CLEANUP:
TRETURN
} //CAddFKConsTxnAdapter::CheckCompletion
BOOL CAddFKConsTxnAdapter::CheckRollBack()
{
TBEGIN
ASSERT(m_pCons);
TESTC(CAddConstraintTxnAdapter::CheckRollBack());
// check foreign key constraint here
TESTC_(m_Table.Insert(2), S_OK);
TESTC_(m_Table.Insert(15), S_OK);
CLEANUP:
TRETURN
} //CAddFKConsTxnAdapter::CheckRollBack
//////////////////////////////////////////////////////////////////
//
// CAddCheckConsTxnAdapter class
//
//////////////////////////////////////////////////////////////////
BOOL CAddCheckConsTxnAdapter::BeforeTransaction()
{
TBEGIN
CCol col;
// create a table and populate it
TESTC_(m_Table.CreateTable(0, 0), S_OK);
m_Table.AddInfoFromColumnsSchemaRowset(g_pIOpenRowset, m_Table.GetTableName());
// get the list of the constraints on the table
m_pConstraints = new CConstraints(g_pIOpenRowset);
TESTC_(m_pConstraints->GetConstraints(NULL, NULL, m_Table.GetTableName(), NULL, NULL, NULL), S_OK);
// select column to be foreign key
TESTC_(m_Table.GetColInfo(1, col), S_OK);
// prepare the constraint
m_pCons = new CCheckCons();
// every 3rd row has a negative value
CHECK(((CCheckCons*)m_pCons)->SetLTCheckConstraint(&m_Table, col.GetColNum(), 6), S_OK);
CLEANUP:
TRETURN
} //CAddCheckConsTxnAdapter::BeforeTransaction
HRESULT CAddCheckConsTxnAdapter::InsideTransactionScope()
{
TBEGIN
CCol col;
HRESULT hr = E_FAIL;
CHECK(CAddConstraintTxnAdapter::InsideTransactionScope(), S_OK);
// create a table and populate it
TESTC_(m_TransactedTable.CreateTable(0, 0), S_OK);
m_Table.AddInfoFromColumnsSchemaRowset(g_pIOpenRowset, m_TransactedTable.GetTableName());
// get the list of the constraints on the table
m_pTxnConstraints = new CConstraints(g_pIOpenRowset);
TESTC_(m_pTxnConstraints->GetConstraints(NULL, NULL, m_TransactedTable.GetTableName(), NULL, NULL, NULL), S_OK);
// select column to be foreign key
TESTC_(m_TransactedTable.GetColInfo(1, col), S_OK);
// prepare the constraint
m_pTransactedTableCons = new CCheckCons();
// every 3rd row has a negative value
CHECK(((CCheckCons*)m_pTransactedTableCons)->SetLTCheckConstraint(&m_TransactedTable, col.GetColNum(), 6), S_OK);
hr = m_pTCITableDefinition->AddConstraintAndCheck(
m_pTCITableDefinition->pITDWC(),
&m_TransactedTable.GetTableID(), *m_pTransactedTableCons);
CLEANUP:
return hr;
} //CAddCheckConsTxnAdapter::InsideTransactionScope
HRESULT CAddCheckConsTxnAdapter::InsideTransactionOnDDLLock()
{
TBEGIN
CCol col;
HRESULT hr = E_FAIL;
CHECK(CAddConstraintTxnAdapter::InsideTransactionOnDDLLock(), S_OK);
// create a table and populate it
TESTC_(m_TransactedTable.CreateTable(0, 0), S_OK);
m_TransactedTable.AddInfoFromColumnsSchemaRowset(g_pIOpenRowset, m_TransactedTable.GetTableName());
// get the list of the constraints on the table
m_pTxnConstraints = new CConstraints(g_pIOpenRowset);
TESTC_(m_pTxnConstraints->GetConstraints(NULL, NULL, m_TransactedTable.GetTableName(), NULL, NULL, NULL), S_OK);
// select column to be foreign key
TESTC_(m_TransactedTable.GetColInfo(1, col), S_OK);
// prepare the constraint
m_pTransactedTableCons = new CCheckCons();
// every 3rd row has a negative value
CHECK(((CCheckCons*)m_pTransactedTableCons)->SetLTCheckConstraint(&m_TransactedTable, col.GetColNum(), 6), S_OK);
hr = m_pTCITableDefinition->pITDWC()->AddConstraint(
&m_TransactedTable.GetTableID(), *m_pTransactedTableCons);
CLEANUP:
return hr;
} //CAddCheckConsTxnAdapter::InsideTransactionOnDDLLock
BOOL CAddCheckConsTxnAdapter::CheckCompletion()
{
TBEGIN
ASSERT(m_pCons);
TESTC(CAddConstraintTxnAdapter::CheckCompletion());
// check foreign key constraint here
TESTC_(m_Table.Insert(4), S_OK);
TESTC_(m_Table.Insert(8), DB_E_INTEGRITYVIOLATION);
TESTC_(m_TransactedTable.Insert(4), S_OK);
TESTC_(m_TransactedTable.Insert(8), DB_E_INTEGRITYVIOLATION);
CLEANUP:
TRETURN
} //CAddCheckConsTxnAdapter::CheckCompletion
BOOL CAddCheckConsTxnAdapter::CheckRollBack()
{
TBEGIN
ASSERT(m_pCons);
TESTC(CAddConstraintTxnAdapter::CheckRollBack());
// check constraint here
TESTC_(m_Table.Insert(4), S_OK);
TESTC_(m_Table.Insert(8), S_OK);
CLEANUP:
TRETURN
} //CAddCheckConsTxnAdapter::CheckRollBack
////////////////////////////////////////////////////////
//
// class CCreateTableWithConsTxnAdapter
//
////////////////////////////////////////////////////////
BOOL CCreateTableWithConsTxnAdapter::BeforeTransaction()
{
TBEGIN
CUniqueCons consUnique;
CPrimaryKeyCons consPrimaryKey;
CForeignKeyCons consForeignKey(NULL, m_pTCITableDefinition->SupportedMatchType());
DBORDINAL rgReferencedCol[] = {1};
CCol col;
CList <WCHAR*, WCHAR*> ListNativeTemp;
CList <DBTYPE, DBTYPE> ListDataTypes;
CList <CCol, CCol&> ColList;
// create table name
m_Table.MakeTableName(NULL);
// get the provider types list
// all types appear in CreateColList, so I don't have to use CreateTypeColInfo
m_Table.CreateTypeColInfo(ListNativeTemp, ListDataTypes, ALLTYPES);
m_Table.DuplicateColList(ColList);
// in m_rgColumnDesc I would rather load just the types prepared for table creation
m_Table.CreateColInfo(ListNativeTemp, ListDataTypes, ALLTYPES);
// build the column description array
m_Table.BuildColumnDescs(&m_rgColumnDesc);
m_cColumnDesc = m_Table.CountColumnsOnTable();
m_Table.SetBuildColumnDesc(FALSE);
// release the properties on all column and make the first column not nullable
ReleaseAllColumnPropSets(m_rgColumnDesc, m_cColumnDesc);
m_pTCITableDefinition->SetProperty(&m_rgColumnDesc[0].rgPropertySets, &m_rgColumnDesc[0].cPropertySets,
DBPROP_COL_NULLABLE,
VT_BOOL, (LPVOID)VARIANT_FALSE,
DBPROPOPTIONS_REQUIRED);
// create support for foreign key constraint
TESTC_(m_RefTable.CreateTable(0, 0), S_OK);
m_RefTable.AddInfoFromColumnsSchemaRowset(m_pTCITableDefinition->pITDWC(), m_RefTable.GetTableName());
// make the referenced columns unique
TESTC_(m_pTCITableDefinition->AddUniqueConstraint(&m_RefTable, rgReferencedCol[0], (DBDEFERRABILITY)0), S_OK);
// set a unique constraint on the second column
consUnique.AddColumn(&m_rgColumnDesc[1].dbcid);
// set a primary key on the first column of the table
consPrimaryKey.AddColumn(&m_rgColumnDesc[0].dbcid);
// set a simple foreign key constraint
TESTC_(m_RefTable.GetColInfo(1, col), S_OK);
consForeignKey.AddColumn(col.GetColID());
consForeignKey.AddForeignKeyColumn(&m_rgColumnDesc[0].dbcid);
consForeignKey.SetReferencedTableID(&m_RefTable.GetTableID());
// add all constraint to the array
m_ConsDescArray.AddConsDesc(consUnique);
m_ConsDescArray.AddConsDesc(consForeignKey);
m_ConsDescArray.AddConsDesc(consPrimaryKey);
// get the list of the constraints on the table
m_pConstraints = new CConstraints(g_pIOpenRowset);
TESTC_(m_pConstraints->GetConstraints(NULL, NULL, m_Table.GetTableName(), NULL, NULL, NULL), S_OK);
CLEANUP:
TRETURN
} //CCreateTableWithConsTxnAdapter::BeforeTransaction
///////////////////////////////////////////////////////////
//
// class CDropConsTxnAdapter
//
///////////////////////////////////////////////////////////
BOOL CDropConsTxnAdapter::BeforeTransaction()
{
TBEGIN
CCol col;
TESTC_(pTCITableDefinition()->CreateTableWithNoNullableColumns(&m_Table, 0, 0), S_OK);
m_Table.AddInfoFromColumnsSchemaRowset(m_pTCITableDefinition->pITDWC(), m_Table.GetTableName());
TESTC_(pTCITableDefinition()->CreateTableWithNoNullableColumns(&m_RefTable, 0, 0), S_OK);
m_RefTable.AddInfoFromColumnsSchemaRowset(m_pTCITableDefinition->pITDWC(), m_RefTable.GetTableName());
TESTC_(m_pTCITableDefinition->AddUniqueConstraint(&m_RefTable, 1), S_OK);
// choose 1 column and create a unique constraint on them
TESTC_(m_Table.GetColInfo(1, col), S_OK);
m_pFKCons = new CForeignKeyCons(NULL, m_pTCITableDefinition->SupportedMatchType());
m_pFKCons->AddForeignKeyColumn(col.GetColID());
TESTC_(m_RefTable.GetColInfo(1, col), S_OK);
m_pFKCons->AddColumn(col.GetColID());
m_pFKCons->SetReferencedTableID(&m_RefTable.GetTableID());
CHECK(m_pTCITableDefinition->AddConstraintAndCheck(m_pTCITableDefinition->pITDWC(), &m_Table.GetTableID(), *m_pFKCons), S_OK);
// Add constraint
m_pPKCons = new CPrimaryKeyCons();
m_pPKCons->AddColumn(col.GetColID());
CHECK(m_pTCITableDefinition->AddConstraintAndCheck(m_pTCITableDefinition->pITDWC(), &m_Table.GetTableID(), *m_pPKCons), S_OK);
// Add constraint
m_pUniqueCons = new CUniqueCons();
m_pUniqueCons->AddColumn(col.GetColID());
CHECK(m_pTCITableDefinition->AddConstraintAndCheck(m_pTCITableDefinition->pITDWC(), &m_Table.GetTableID(), *m_pUniqueCons), S_OK);
// Add constraint
m_pCheckCons = new CCheckCons();
m_pCheckCons->SetLTCheckConstraint(&m_Table, col.GetColNum(), 5);
CHECK(m_pTCITableDefinition->AddConstraintAndCheck(m_pTCITableDefinition->pITDWC(), &m_Table.GetTableID(), *m_pCheckCons), S_OK);
// get the list of the constraints on the table
m_pConstraints = new CConstraints(g_pIOpenRowset);
CHECK(m_pConstraints->GetConstraints(NULL, NULL, m_Table.GetTableName(), NULL, NULL, NULL), S_OK);
CLEANUP:
TRETURN
} //CDropConsTxnAdapter::BeforeTransaction
HRESULT CTransactionLocal::StartTransaction(
IUnknown *pISessionUnknown,
// arguments for ITransactionLocal::StartTransaction
ISOLEVEL isoLevel,
ULONG isoFlags,
ITransactionOptions *pOtherOptions
)
{
HRESULT hr = E_FAIL;
CPropSets PropSets;
DBPROP *pSupportedTxnDDL;
m_lSupportedTxnDDL = DBPROPVAL_TC_NONE;
if (!pISessionUnknown)
return E_INVALIDARG;
m_Session = pISessionUnknown;
TESTC_(m_Session.GetDataSource(m_DataSource), S_OK);
// get DBPROP_SUPPORTEDTXNDDL
TESTC_(m_DataSource.GetProperties(&PropSets), S_OK);
pSupportedTxnDDL = PropSets.FindProperty(DBPROP_SUPPORTEDTXNDDL, DBPROPSET_DATASOURCEINFO);
TESTC(!pSupportedTxnDDL || (VT_I4 == pSupportedTxnDDL->vValue.vt));
if (pSupportedTxnDDL)
m_lSupportedTxnDDL = V_I4(&pSupportedTxnDDL->vValue);
else if ((ITransactionLocal*)m_Session)
m_lSupportedTxnDDL = DBPROPVAL_TC_ALL;
// check the relation between the property and the interface
TESTC( (NULL != (ITransactionLocal*)m_Session)
|| (!pSupportedTxnDDL || (DBPROPVAL_TC_NONE == m_lSupportedTxnDDL)));
// if the interface is not supported just return
if (NULL == (ITransactionLocal*)m_Session)
return S_OK;
hr = ((ITransactionLocal*)m_Session)->StartTransaction(isoLevel, isoFlags, pOtherOptions, NULL);
if (hr==S_OK)
// Set the flag that we're inside transaction
CConsDesc::s_fInsideTransaction = TRUE;
CLEANUP:
return hr;
} //CTransactionLocal::StartTransaction
BOOL CTransactionLocal::DoTransactionTest(
IUnknown *pISessionUnknown,
CTransactionAdapter *pTAdapter,
// arguments for ITransactionLocal::Abort / Commit
BOOL fDDL, // whether or not this is a DDL call
BOOL fAbortCommit, // whether to abort or commit
BOOL fRetaining // if it's retaining or not
)
{
TBEGIN
HRESULT hr;
ULONG cIsoLevel, i;
ISOLEVEL rgIsoLevel[] = {ISOLATIONLEVEL_BROWSE, ISOLATIONLEVEL_CURSORSTABILITY,
ISOLATIONLEVEL_ISOLATED, ISOLATIONLEVEL_CHAOS};
cIsoLevel = NUMELEM(rgIsoLevel);
TESTC(NULL != pISessionUnknown);
TESTC(NULL != pTAdapter);
m_pTAdapter = pTAdapter;
// do work / testing that precedes transaction
COMPARE(m_pTAdapter->BeforeTransaction(), TRUE);
// start the transaction
for (i=0; i<cIsoLevel; i++)
{
if (S_OK == (hr = StartTransaction(pISessionUnknown, rgIsoLevel[i], 0, NULL)))
break;
}
if (cIsoLevel < i)
return E_FAIL;
// TESTC_(m_pTAdapter->pTCITableDefinition()->StartTransaction(), S_OK);
// TESTC_(StartTransaction(pISessionUnknown, isoLevel, isoFlags, pOtherOptions), S_OK);
// check that we have a local transaction; return if not
TESTC_PROVIDER(NULL != (ITransactionLocal*)m_Session);
if (!fDDL)
{ TESTC_(m_pTAdapter->InsideTransactionScope(), S_OK);}
else
{
switch (m_lSupportedTxnDDL)
{
case DBPROPVAL_TC_DML:
//check for XACT_E_XTIONEXISTS
CHECK(hr = m_pTAdapter->InsideTransactionScope(), XACT_E_XTIONEXISTS);
break;
case DBPROPVAL_TC_DDL_IGNORE:
// the statement is not transacted
case DBPROPVAL_TC_ALL:
case DBPROPVAL_TC_DDL_COMMIT:
CHECK(hr = m_pTAdapter->InsideTransactionScope(), S_OK);
break;
case DBPROPVAL_TC_DDL_LOCK:
CHECK(hr = m_pTAdapter->InsideTransactionOnDDLLock(), S_OK);
break;
default:
TESTC(FALSE);
}
}
// end transaction
if (!fDDL || (DBPROPVAL_TC_DDL_COMMIT != m_lSupportedTxnDDL))
{
if (fAbortCommit)
{
CHECK(Abort(NULL, fRetaining, FALSE), S_OK);
}
else
{
CHECK(Commit(fRetaining, 0, 0), S_OK);
}
}
// check the result of the operation
if (
// DDL and aborted but prop is DDL ignore or DDL commit
( fDDL
&& ( (DBPROPVAL_TC_DDL_COMMIT == m_lSupportedTxnDDL)
|| (DBPROPVAL_TC_DDL_IGNORE == m_lSupportedTxnDDL))
//&& fAbortCommit // this is not necessary
)
// DDL and committed but prop is DML
|| ( fDDL
&& (DBPROPVAL_TC_DML == m_lSupportedTxnDDL)
//&& !fAbortCommit // this is not necessary
)
// operation is not a DDL and txn is committed
|| !fAbortCommit)
COMPARE(m_pTAdapter->CheckCompletion(), TRUE);
else
COMPARE(m_pTAdapter->CheckRollBack(), TRUE);
// end this transaction
CHECK(Commit(FALSE, 0, 0), fRetaining? S_OK: XACT_E_NOTRANSACTION);
CHECK(Abort(NULL, FALSE, FALSE), XACT_E_NOTRANSACTION);
CLEANUP:
CConsDesc::s_fInsideTransaction = FALSE;
TRETURN
} //CTransactionLocal::DoTransactionTest