15306 lines
433 KiB
C++
15306 lines
433 KiB
C++
//-----------------------------------------------------------------------
|
|
// Microsoft OLE DB
|
|
//
|
|
// Copyright (C) 1997-2000 Microsoft Corporation
|
|
//
|
|
// @doc
|
|
//
|
|
// @module QUIKTEST.CPP | This test module performs minimum testing
|
|
// of an OLE DB provider by calling each method in the API.
|
|
//
|
|
|
|
#include "MODStandard.hpp" //Standard headers to be precompiled in MODStandard.cpp
|
|
#include "QuikTest.h"
|
|
#include "ExtraLib.h"
|
|
#include "msdasc.h" //IID_IDataInitialize
|
|
#include "msdadc.h" //IID_IRowPosition
|
|
#include <direct.h> //Needed for _getcwd (current working directory)
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Module Values
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// {{ TCW_MODULE_GLOBALS
|
|
DECLARE_MODULE_CLSID = { 0xca9539f1, 0xd59f, 0x11ce, { 0xa9, 0xda, 0x00, 0xaa, 0x00, 0x3e, 0x77, 0x8a }};
|
|
DECLARE_MODULE_NAME("Quiktest");
|
|
DECLARE_MODULE_OWNER("Microsoft");
|
|
DECLARE_MODULE_DESCRIP("OLE DB Quik Test");
|
|
DECLARE_MODULE_VERSION(810940912);
|
|
// TCW_WizardVersion(2)
|
|
// TCW_Automation(False)
|
|
// }} TCW_MODULE_GLOBALS_END
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// @func Module level initialization routine
|
|
//
|
|
// @rdesc Success or Failure
|
|
// @flag TRUE | Successful initialization
|
|
// @flag FALSE | Initialization problems
|
|
BOOL ModuleInit(CThisTestModule * pThisTestModule)
|
|
{
|
|
return CreateModInfo(pThisTestModule);
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// @func Module level termination routine
|
|
//
|
|
// @rdesc Success or Failure
|
|
// @flag TRUE | Successful initialization
|
|
// @flag FALSE | Initialization problems
|
|
BOOL ModuleTerminate(CThisTestModule * pThisTestModule)
|
|
{
|
|
return ReleaseModInfo(pThisTestModule);
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//Prints the error messages when run as a stand-alone executable.
|
|
//
|
|
HRESULT OutputText(const WCHAR* pwszFmt, ...)
|
|
{
|
|
va_list marker;
|
|
|
|
va_start(marker, pwszFmt);
|
|
vwprintf(pwszFmt, marker);
|
|
va_end(marker);
|
|
|
|
return S_OK;
|
|
} //OutputText
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// CBaseError Implementation
|
|
//
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
//This class has the IError interface. Below is the implementation of the
|
|
//methods of the IError interface and methods specific to the CBaseError
|
|
//class. This class will be used as the error object when quiktest is
|
|
//run as a stand-alone executable.
|
|
|
|
//Constructor for CBaseError.
|
|
CBaseError::CBaseError()
|
|
{
|
|
//Errors
|
|
m_cModErrors = 0;
|
|
m_cCaseErrors = 0;
|
|
m_cVarErrors = 0;
|
|
|
|
//Warnings
|
|
m_cModWarnings = 0;
|
|
m_cCaseWarnings = 0;
|
|
m_cVarWarnings = 0;
|
|
|
|
m_ErrorLevel = HR_STRICT;
|
|
m_ExpectedHr = NULL;
|
|
m_ActualHr = NULL;
|
|
|
|
m_cRef = 0;
|
|
}
|
|
|
|
//Destructor (virtual) for CBaseError.
|
|
CBaseError::~CBaseError()
|
|
{
|
|
}
|
|
|
|
//QI for a supported interface.
|
|
STDMETHODIMP CBaseError::QueryInterface(REFIID riid, void **ppvObject)
|
|
{
|
|
if(ppvObject == NULL)
|
|
return E_INVALIDARG;
|
|
*ppvObject = NULL;
|
|
|
|
if(riid == IID_IUnknown)
|
|
*ppvObject = (IUnknown*)this;
|
|
else if(riid == IID_IError)
|
|
*ppvObject = (IError*)this;
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
((IUnknown*)*ppvObject)->AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
//Add reference count.
|
|
STDMETHODIMP_(DWORD) CBaseError::AddRef(void)
|
|
{
|
|
return InterlockedIncrement((LONG*)&m_cRef);
|
|
}
|
|
|
|
//Decrement the reference count. If it goes down to zero delete
|
|
//this object.
|
|
STDMETHODIMP_(DWORD) CBaseError::Release(void)
|
|
{
|
|
InterlockedDecrement((LONG*)&m_cRef);
|
|
if(m_cRef == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
return m_cRef;
|
|
}
|
|
|
|
STDMETHODIMP CBaseError::ResetModErrors(void)
|
|
{
|
|
m_cModErrors = 0;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CBaseError::ResetModWarnings(void)
|
|
{
|
|
m_cModWarnings = 0;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CBaseError::ResetCaseErrors(void)
|
|
{
|
|
m_cCaseErrors = 0;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CBaseError::ResetCaseWarnings(void)
|
|
{
|
|
m_cCaseWarnings = 0;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CBaseError::ResetVarErrors(void)
|
|
{
|
|
m_cVarErrors = 0;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CBaseError::ResetVarWarnings(void)
|
|
{
|
|
m_cVarWarnings = 0;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CBaseError::GetVarErrors(LONG *pdw)
|
|
{
|
|
*pdw = m_cVarErrors;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CBaseError::GetVarWarnings(LONG *pdw)
|
|
{
|
|
*pdw = m_cVarWarnings;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CBaseError::GetCaseErrors(LONG *pdw)
|
|
{
|
|
*pdw = m_cCaseErrors;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CBaseError::GetCaseWarnings(LONG *pdw)
|
|
{
|
|
*pdw = m_cCaseWarnings;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CBaseError::GetModErrors(LONG *pdw)
|
|
{
|
|
*pdw = m_cModErrors;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CBaseError::GetModWarnings(LONG *pdw)
|
|
{
|
|
*pdw = m_cModWarnings;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CBaseError::GetActualHr(LONG *pHR)
|
|
{
|
|
*pHR = m_ActualHr;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CBaseError::SetErrorLevel(ERRORLEVEL eLevel)
|
|
{
|
|
m_ErrorLevel = eLevel;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CBaseError::GetErrorLevel(ERRORLEVEL *pLevel)
|
|
{
|
|
*pLevel = m_ErrorLevel;
|
|
return S_OK;
|
|
}
|
|
|
|
//Print the expected HRESULT.
|
|
STDMETHODIMP CBaseError::LogExpectedHr(LONG hrExpected)
|
|
{
|
|
//Try to find the Error
|
|
WCHAR* pwszError = GetErrorName(hrExpected);
|
|
if(pwszError)
|
|
return OutputText(L"\t\t%s %s\n", wszExpectedHR, pwszError);
|
|
else
|
|
return OutputText(L"\t\t%s 0x%08x\n", wszExpectedHR, hrExpected);
|
|
}
|
|
|
|
//Print the received HRESULT, file name, and line number.
|
|
STDMETHODIMP CBaseError::LogReceivedHr(LONG hrExpected, BSTR bstrFile, LONG udwLine)
|
|
{
|
|
//Try to find the Error
|
|
WCHAR* pwszError = GetErrorName(hrExpected);
|
|
if(pwszError)
|
|
OutputText(L"\t\t%s %s\n", wszReceivedHR, pwszError);
|
|
else
|
|
OutputText(L"\t\t%s 0x%08x\n", wszReceivedHR, hrExpected);
|
|
|
|
//Print File and Line Number...
|
|
return OutputText(L"\t\t%s %s %s %d\n\n", wszFile, bstrFile, wszLine, udwLine);
|
|
}
|
|
|
|
//Compare the actual HR with the expected HR and increment error or
|
|
//warning count accordingly. Print appropriate message.
|
|
STDMETHODIMP CBaseError::Validate(
|
|
|
|
LONG ActualHr,
|
|
BSTR bstrFile,
|
|
LONG udwLine,
|
|
LONG ExpectedHr,
|
|
VARIANT_BOOL *pfResult)
|
|
{
|
|
//Record the HRESULT received by the function in question
|
|
m_ActualHr = ActualHr;
|
|
|
|
//Now we decide what to do about it
|
|
switch (m_ErrorLevel)
|
|
{
|
|
case HR_OPTIONAL: //We don't care what the received result is
|
|
*pfResult = TRUE;
|
|
return S_OK;
|
|
|
|
case HR_WARNING: //Expected must match received.
|
|
case HR_STRICT: //NOTE: we differentiate between warning
|
|
//and strict in Increment and Logxxxxx.
|
|
if(ActualHr != ExpectedHr)
|
|
{
|
|
//Display the Header
|
|
if(HR_WARNING == m_ErrorLevel)
|
|
{
|
|
Transmit((WCHAR*)wszWarningTitle);
|
|
}
|
|
else
|
|
{
|
|
Transmit((WCHAR*)wszErrorTitle);
|
|
}
|
|
|
|
//Log what we expected
|
|
Increment();
|
|
LogExpectedHr(ExpectedHr);
|
|
}
|
|
else
|
|
{
|
|
*pfResult = TRUE;
|
|
return S_OK;
|
|
}
|
|
break;
|
|
|
|
case HR_SUCCEED: //Received result must be success code
|
|
if(!SUCCEEDED(ActualHr))
|
|
{
|
|
//Log what we expected
|
|
OutputText(L"\t\t%s\n", wszExpectedSuccess);
|
|
}
|
|
else
|
|
{
|
|
*pfResult = TRUE;
|
|
return S_OK;
|
|
}
|
|
break;
|
|
|
|
case HR_FAIL: //Received result must be failure code
|
|
if(!FAILED(ActualHr))
|
|
{
|
|
//Log what we expected
|
|
Transmit("Expected a Failing HRESULT\n");
|
|
}
|
|
else
|
|
{
|
|
*pfResult = TRUE;
|
|
return S_OK;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
//If we got this far, the HRESULT received didn't match
|
|
//what was expected, so log what was received and where
|
|
LogReceivedHr(ActualHr, bstrFile, udwLine);
|
|
*pfResult = FALSE;
|
|
return S_OK;
|
|
}
|
|
|
|
//If objects compared were not equal, increment the error or warning
|
|
//count. Print appropriate message.
|
|
STDMETHODIMP CBaseError::Compare(
|
|
|
|
VARIANT_BOOL fEqual,
|
|
BSTR bstrFile,
|
|
LONG udwLine,
|
|
VARIANT_BOOL * pfResult)
|
|
{
|
|
//If the objects where not equal, increment error and print message
|
|
if(!fEqual)
|
|
{
|
|
Increment();
|
|
OutputText(L"\t\t%s\n", wszCompareFailed);
|
|
OutputText(L"\t\t%s %s %s %d\n\n", wszFile, bstrFile, wszLine, udwLine);
|
|
}
|
|
|
|
*pfResult = fEqual;
|
|
return S_OK;
|
|
}
|
|
|
|
//Increment the error or warning counters.
|
|
STDMETHODIMP CBaseError::Increment(void)
|
|
{
|
|
if(HR_WARNING == m_ErrorLevel)
|
|
{
|
|
//Increment all warning counters, from variation level on up
|
|
m_cVarWarnings++;
|
|
m_cCaseWarnings++;
|
|
m_cModWarnings++;
|
|
}
|
|
else
|
|
{
|
|
//Increment all error counters, from variation level on up
|
|
m_cVarErrors++;
|
|
m_cCaseErrors++;
|
|
m_cModErrors++;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//Print text which is passed in as a CHAR*
|
|
HRESULT CBaseError::Transmit(CHAR* pszString)
|
|
{
|
|
WCHAR* pwszString = NULL;
|
|
pwszString = ConvertToWCHAR(pszString);
|
|
OutputText(L"\t\t");
|
|
OutputText(pwszString);
|
|
SAFE_FREE(pwszString);
|
|
return S_OK;
|
|
};
|
|
|
|
//Print text which is passed in as a BSTR.
|
|
HRESULT CBaseError::Transmit(BSTR bstrString)
|
|
{
|
|
OutputText(L"\t\t");
|
|
return OutputText(bstrString);
|
|
};
|
|
|
|
STDMETHODIMP CBaseError::Initialize(void)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// CQuickTest Class
|
|
//
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
// @class A base class used to do common work for all interface testcases,
|
|
// such as verifying the interface is supported, and storage and cleanup of
|
|
// interface pointers. It is assumed that any interfaces/objects obtained
|
|
// by the user outside member functions are released by the user before
|
|
// the next attempt to obtain new objects/interfaces via the member
|
|
// functions.
|
|
|
|
class CQuickTest : public CSessionObject
|
|
{
|
|
protected:
|
|
|
|
//VARIABLES
|
|
|
|
//@cmember DBPROP_SQLSUPPORT
|
|
ULONG_PTR m_ulSQLSup;
|
|
|
|
//@cmember Maximum number of open rows (DBPROP_MAXOPENROWS)
|
|
ULONG_PTR m_ulMaxOpenRows;
|
|
|
|
//@cmember Can Fetch bachwards (DBPROP_CANFETCHBACKWARDS)
|
|
BOOL m_fFetchBackwards;
|
|
|
|
//@cmember File name for persisted file
|
|
WCHAR m_wszFile[2*PATH_SIZE];
|
|
|
|
//@cmember Number of property Info sets.
|
|
ULONG m_cPropInfoSets;
|
|
|
|
//@cmember Array of property Info Sets.
|
|
DBPROPINFOSET* m_rgPropInfoSets;
|
|
|
|
//@cmember Number of property ID sets.
|
|
ULONG m_cPropIDSets;
|
|
|
|
//@cmember Array of property ID Sets.
|
|
DBPROPIDSET* m_rgPropIDSets;
|
|
|
|
//@cmember URL to a rowset (the rowset dumped into the INI file).
|
|
WCHAR* m_pwszRowsetURL;
|
|
|
|
//@cmember Pointer to a CRowset object.
|
|
CRowset* m_pCRowset;
|
|
|
|
//INTERFACES
|
|
|
|
//@cmember Pointer to IpersistFile interface
|
|
IPersistFile* m_pIPersistFile;
|
|
|
|
//@cmember Pointer to IDBProperties interface
|
|
IDBProperties* m_pIDBProperties;
|
|
|
|
//@cmember Pointer to IRowset interface
|
|
IRowset* m_pIRowset;
|
|
|
|
//@cmember Pointer to ICommand interface
|
|
ICommand* m_pICommand;
|
|
|
|
//@cmember Pointer to IBindResource (Binder) interface
|
|
IBindResource* m_pIBindResource;
|
|
|
|
//@cmember Pointer to IRow interface
|
|
IRow* m_pIRow;
|
|
|
|
private:
|
|
|
|
//List of Provider types
|
|
DBTYPE* m_rgProviderTypes;
|
|
|
|
//Count of List of Provider types
|
|
ULONG m_cProviderTypes;
|
|
|
|
//@cmember Path to current working directory
|
|
CHAR m_szPath[PATH_SIZE];
|
|
|
|
protected:
|
|
|
|
//@cmember Constructor - Takes the derived TestCase name as parameter
|
|
CQuickTest(LPWSTR wszTestCaseName); //[IN] Testcase Name
|
|
|
|
//@cmember Destructor
|
|
virtual ~CQuickTest();
|
|
|
|
//@cmember Saves object to file in current working directory
|
|
HRESULT PersistToFile();
|
|
|
|
//@cmember Adds another DBPROPINFO or DBPROPINFOSET to the dynamic
|
|
// array m_rgPropInfoSets.
|
|
HRESULT SetPropInfo(
|
|
DBPROPID propID, //[IN] Property ID
|
|
const GUID& guidPropSet, //[IN] Property Set
|
|
VARTYPE varType //[IN] Variant type
|
|
);
|
|
|
|
//@cmember Adds another DBPROPID or DBPROPIDSET to the dynamic
|
|
// array m_rgPropIDSets.
|
|
HRESULT SetPropID(
|
|
DBPROPID propID, //[IN] Property ID
|
|
const GUID& guidPropSet //[IN] Property Set
|
|
);
|
|
|
|
//@cmember Initializes m_rgPropIDSets and m_rgPropInfoSets with some
|
|
// selected properties.
|
|
void InitPropIDStructs();
|
|
|
|
//@cmember Set the flags of the given property info.
|
|
BOOL SetFlags(
|
|
DBPROPID propID, //[IN] Property ID
|
|
const GUID& guidPropSet, //[IN] Property Set
|
|
DBPROPFLAGS dwFlags //[IN] Prop Flags
|
|
);
|
|
|
|
//@cmember Call GetPropertyInfo and sets the Flag of the properties
|
|
// in m_rgPropInfoSets. This can be used later to check if
|
|
// the property is supported.
|
|
void InitSupInfo();
|
|
|
|
//@cmember Check if the I2 value is positive. Used for checking
|
|
// value of DBPROP_INIT_PROMPT.
|
|
BOOL checkPositive_I2(VARIANT* pv);
|
|
|
|
//@cmember Wrapper for IRowset::GetNextRows.
|
|
HRESULT GetNextRows(
|
|
IRowset* pIRowset, //[IN] Pointer to rowset
|
|
HCHAPTER* hChapter, //[IN] Handle to chapter
|
|
DBROWOFFSET lRowsOffset, //[IN] Offset to row
|
|
DBROWCOUNT cRows, //[IN] Number of rows to fetch
|
|
DBCOUNTITEM* pcRowsObtained, //[OUT] Number of rows fetched
|
|
HROW** prghRows //[OUT] Handle to fetched rows.
|
|
);
|
|
|
|
//@cmember Wrapper for IRowset::ReleaseRows.
|
|
HRESULT ReleaseRows(
|
|
IRowset** ppIRowset, //[IN] Pointer to rowset
|
|
DBCOUNTITEM* pcRows, //[IN] Num of rows to release
|
|
HROW** prghRows //[IN] HROW of rows to release
|
|
);
|
|
|
|
//@cmember Wrapper for IRowset::RestartPosition.
|
|
HRESULT RestartPosition(IRowset* pIRowset) ;
|
|
|
|
//@cmember Release the HACCESSOR and free the bindings. Release
|
|
// IAccessor if pbReleaseIAcc is TRUE.
|
|
HRESULT FreeAccessorAndBindings(
|
|
IAccessor** ppIAccessor, //[IN] Pointer to IAccessor
|
|
HACCESSOR* phAccessor, //[IN] Handle to accessor
|
|
DBCOUNTITEM* pcBindings, //[IN] Number of bindings
|
|
DBBINDING** prgBindings, //[IN] Binding Structs.
|
|
BOOL pbReleaseIAcc=TRUE //[IN] Release IAccessor?
|
|
);
|
|
|
|
//@cmember Append a property and its value to the Init String.
|
|
HRESULT AppendToInitString(
|
|
WCHAR** ppwszInitString,
|
|
DBPROPID dwPropertyID,
|
|
GUID guidPropertySet,
|
|
VARIANT* pVariant
|
|
);
|
|
|
|
//@cmember Generate a rowset (call OpenRowset) on the given table.
|
|
HRESULT CreateOpenRowset(
|
|
CTable* pTable, //[IN] Table on which to open the rowset.
|
|
const IID& riid, //[IN] IID of requested interface on rowset.
|
|
IUnknown** ppRowset, //[OUT] Pointer to rowset interface.
|
|
IUnknown* pUnkOuter = NULL //[IN] For aggregation.
|
|
);
|
|
|
|
//@cmember Verify the bindings obtained by GetBindings is same as
|
|
// that used for creating the accessor.
|
|
BOOL VerifyBindings(
|
|
IAccessor* pIAccessor, //[IN] Pointer to IAccessor.
|
|
HACCESSOR hAccessor, //[IN] handle to accessor
|
|
DBCOUNTITEM cBindings, //[IN] Number of binding structs
|
|
DBBINDING* rgBindings, //[IN] Binding structures
|
|
DBACCESSORFLAGS dwCreateAccessorFlags //[IN] Value of Accessor flags used to create accessor
|
|
);
|
|
|
|
//@cmember Fetch the specified rows, get their data and compare.
|
|
BOOL GetDataAndCompare(
|
|
DBROWOFFSET cSkipRows, //[IN] num of rows to skip.
|
|
DBROWCOUNT cGetRows, //[IN] num of rows to fetch.
|
|
DBCOUNTITEM numFirstRowInSet, //[IN] num of the first row in the set of rows to be fetched.
|
|
DBORDINAL cColumns, //[IN] num of columns.
|
|
DB_LORDINAL* rgColumnsOrd, //[IN] list of column ordinals.
|
|
IRowset* pIRowset, //[IN] Pointer to IRowset.
|
|
HACCESSOR hAccessor, //[IN] handle to accessor
|
|
DBCOUNTITEM cBindings, //[IN] Number of bindings
|
|
DBBINDING* rgBindings, //[IN] Binding structs
|
|
DBLENGTH cbRowSize, //[IN] row size
|
|
CTable* pTable = NULL //[IN] pointer to base table
|
|
);
|
|
|
|
//@cmember Get the bookmark for the given row.
|
|
BOOL GetBookmark(
|
|
DBCOUNTITEM ulRow, //[IN] row number for which to get bookmark (1 based)
|
|
DBLENGTH cbRowSize, //[IN] row size
|
|
HACCESSOR hAccessor, //[IN] handle to accessor
|
|
DBCOUNTITEM cBindings, //[IN] number of bindings
|
|
DBBINDING* rgBindings, //[IN] binding structs
|
|
IUnknown* pIUnkRowset, //[IN] pointer to the rowset
|
|
DBBKMARK *pcbBookmark, //[OUT] size of bookmark
|
|
BYTE **ppBookmark //[OUT] value of bookmark
|
|
);
|
|
|
|
//@cmember Check if the two DBCOLUMNDESC are equal.
|
|
BOOL CompareColumnDesc(
|
|
DBCOLUMNDESC* pCD1, //[IN] column description
|
|
DBCOLUMNDESC* pCD2 //[IN] column description
|
|
);
|
|
|
|
//@cmember Get the supported DBTYPEs from CTable's CCol structs.
|
|
void GetProviderTypes(CTable* pTable);
|
|
|
|
//@cmember Check if a given Type exists in CTable's CCol structs.
|
|
BOOL IsSupportedType(DBTYPE dwType);
|
|
|
|
//@cmember Check if the given index exists in the given table.
|
|
TESTRESULT DoesIndexExist(
|
|
IDBSchemaRowset* pIDSR, //[IN] pointer to interface
|
|
DBID* pTableID, //[IN] table ID
|
|
DBID* pIndexID, //[IN] Index ID
|
|
BOOL* pfExists //[OUT] does index exist
|
|
);
|
|
|
|
//@cmember Get the available optional columns through IColumnsRowset.
|
|
HRESULT GetAvailableColumns(
|
|
IUnknown* pUnk, //[IN] Pointer to the object.
|
|
DBORDINAL* pcOptCols, //[OUT] Number of optional columns.
|
|
DBID** prgOptCols //[OUT] DBIDs of optional columns.
|
|
);
|
|
|
|
//@cmember Check the list of optional metadata columns returned by
|
|
// IColumnsRowset::GetAvailableColumns.
|
|
BOOL CheckOptColumns(
|
|
const DBORDINAL cOptCols, //[IN] num of optional columns
|
|
const DBID* rgOptCols //[IN] array of optional columns
|
|
);
|
|
|
|
//@cmember Check the columns rowset returned by IColumnsRowset::
|
|
// GetColumnsRowset.
|
|
BOOL CheckColumnsRowset(
|
|
IUnknown* pIUnk, //[IN] pointer to the columns rowset
|
|
const DBORDINAL cOptCols, //[IN] num of optional columns
|
|
const BOOL bOrgRowsetHasBookmark //[IN] does the original rowset have bookmark column
|
|
);
|
|
|
|
//@cmember Create an instance of the Root Binder, requesting
|
|
// IBindResource. Then QI for IDBBinderProperties and
|
|
// set the initialization properties.
|
|
BOOL CreateRootBinder();
|
|
|
|
//@cmember Test IDBProperties::Getproperties method.
|
|
TESTRESULT testGetProperties();
|
|
|
|
//@cmember Test IDBProperties::Getproperties method with (0,NULL).
|
|
TESTRESULT testGetAllProperties(IDBProperties* pIDBProp);
|
|
|
|
//@cmember Test IDBProperties::GetPropertyInfo method.
|
|
TESTRESULT testGetPropInfo();
|
|
|
|
//@cmember Test IDBProperties::GetPropertyInfo method with (0,NULL).
|
|
TESTRESULT testGetAllPropInfo(IDBProperties* pIDBProp);
|
|
|
|
//@cmember Test IDBProperties::SetProperties method (set to a valid
|
|
// value).
|
|
TESTRESULT testSetProperties1();
|
|
|
|
//@cmember Test IDBProperties::SetProperties method (set to VT_EMPTY)
|
|
TESTRESULT testSetProperties2();
|
|
|
|
//@cmember Test GetProperties and GetPropertyInfo while DSO is
|
|
// uninitialized.
|
|
TESTRESULT testGetPropBeforeInit();
|
|
|
|
//@cmember Test IDBInfo::GetKeywords method.
|
|
TESTRESULT testGetKeywords();
|
|
|
|
//@cmember Test IDBInfo::GetLiteralInfo method.
|
|
TESTRESULT testGetLiteralInfo();
|
|
|
|
//@cmember Test ISourcesRowset interface.
|
|
TESTRESULT testISrcRowset();
|
|
|
|
//@cmember Test IDataInitialize::CreateDBInstance method.
|
|
TESTRESULT testIDataIzCreateDBIns();
|
|
|
|
//@cmember Test IDataInitialize::GetDataSource method.
|
|
TESTRESULT testIDataIzGetDS();
|
|
|
|
//@cmember Test IGetDataSource::GetDataSource method.
|
|
TESTRESULT testGetDataSource();
|
|
|
|
//@cmember Test IOpenRowset::OpenRowset method.
|
|
TESTRESULT testOpenRowset();
|
|
|
|
//@cmember Test ISessionProperties::GetProperties method.
|
|
TESTRESULT testSessGetProp();
|
|
|
|
//@cmember Test ISessionProperties::SetProperties method.
|
|
TESTRESULT testSessSetProp();
|
|
|
|
//@cmember Test IDBCreateCommand interface.
|
|
TESTRESULT testCreateCommand();
|
|
|
|
//@cmember Test IDBSchemaRowset::GetSchemas method.
|
|
TESTRESULT testGetSchemas();
|
|
|
|
//@cmember Test the COLUMNS rowset obtained by calling
|
|
// IDBSchemaRowset::GetRowset.
|
|
TESTRESULT testColumnsSchemaRowset();
|
|
|
|
//@cmember Test the TABLES rowset obtained by calling
|
|
// IDBSchemaRowset::GetRowset.
|
|
TESTRESULT testTablesSchemaRowset();
|
|
|
|
//@cmember Test the PROVIDER_TYPES rowset obtained by calling
|
|
// IDBSchemaRowset::GetRowset.
|
|
TESTRESULT testProvTypesSchemaRowset();
|
|
|
|
//@cmember Test ITableDefinition::AddColumn method.
|
|
TESTRESULT testAddColumn();
|
|
|
|
//@cmember Test ITableDefinition::CreateTable method.
|
|
TESTRESULT testCreateTable();
|
|
|
|
//@cmember Test ITableDefinition::DropColumn method.
|
|
TESTRESULT testDropColumn();
|
|
|
|
//@cmember Test ITableDefinition::DropTable method.
|
|
TESTRESULT testDropTable();
|
|
|
|
//@cmember Test IIndexDefinition methods.
|
|
TESTRESULT testIIndexDef();
|
|
|
|
//@cmember Test IAlterIndex::AlterIndex method.
|
|
TESTRESULT testAlterIndex();
|
|
|
|
//@cmember Test IAlterTable::AlterColumn method.
|
|
TESTRESULT testAlterColumn();
|
|
|
|
//@cmember Test IAlterTable::AlterTable method.
|
|
TESTRESULT testAlterTable();
|
|
|
|
//@cmember Test ITableDefinitionWithConstraints::AddConstraint & DropConstraint methods.
|
|
TESTRESULT testAddAndDropConstraint();
|
|
|
|
//@cmember Test ITableDefinitionWithConstraints::CreateTableWithConstraints method.
|
|
TESTRESULT testCreateTableWithConstraints();
|
|
|
|
//@cmember Test aggregation of Session.
|
|
TESTRESULT testAggregateSession(IDBCreateSession* pIDBCreateSession);
|
|
|
|
//@cmember Test IConvertType method.
|
|
TESTRESULT testIConvertType();
|
|
|
|
//@cmember Test IColumnsInfo::GetColumnInfo method.
|
|
TESTRESULT testGetColumnInfo(IUnknown* pIUnknown);
|
|
|
|
//@cmember Test IColumnsInfo::MapColumnIDs method.
|
|
TESTRESULT testMapColumnIDs(IUnknown* pIUnknown);
|
|
|
|
//@cmember Test the IAccessor interface methods.
|
|
TESTRESULT testIAccessor();
|
|
|
|
//@cmember Test the IRowsetInfo::GetProperties method
|
|
// or the ICommandProperties::GetProperties method.
|
|
TESTRESULT testRowsetGetProp(IUnknown* pIUnknown);
|
|
|
|
//@cmember Test the IRowsetInfo::GetReferencedRowset method
|
|
TESTRESULT testIRowsetInfoGetRefRowset();
|
|
|
|
//@cmember Test the IRowsetInfo::GetSpecification method on a
|
|
// rowset generated from Session.
|
|
TESTRESULT testIRowsetInfoGetSpec();
|
|
|
|
//@cmember Test the IRowsetInfo::GetSpecification method on a
|
|
// rowset generated from Command.
|
|
TESTRESULT testIRowsetInfoGetSpecCmd();
|
|
|
|
//@cmember Test the IRowset (No props set)
|
|
TESTRESULT testIRowset2();
|
|
|
|
//@cmember Test the IRowset (Scroll_Back and CANHOLDROWS set)
|
|
TESTRESULT testIRowset3();
|
|
|
|
//@cmember Test the IRowsetLocate::Compare
|
|
TESTRESULT testIRowsetLocateCompare();
|
|
|
|
//@cmember Test the IRowsetLocate::GetRowsAt
|
|
TESTRESULT testIRowsetLocateGetRowsAt();
|
|
|
|
//@cmember Test the IRowsetLocate::GetRowsByBookmark
|
|
TESTRESULT testIRowsetLocateGetRowsByBkm();
|
|
|
|
//@cmember Test the IRowsetLocate::Hash
|
|
TESTRESULT testIRowsetLocateHash();
|
|
|
|
//@cmember Test the IRowsetFind::FindNextRow
|
|
TESTRESULT testFindNextRow();
|
|
|
|
//@cmember Test the IRowsetScroll::GetApproximatePosition
|
|
TESTRESULT testGetApproxPos();
|
|
|
|
//@cmember Test the IRowsetScroll::GetRowsAtRatio
|
|
TESTRESULT testGetRowsAtRatio();
|
|
|
|
//@cmember Test the IRowPosition methods.
|
|
TESTRESULT testIRowPosition();
|
|
|
|
//@cmember Test aggregation of Rowset.
|
|
TESTRESULT testAggregateRowset();
|
|
|
|
//@cmember Test the IRowsetIdentity methods.
|
|
TESTRESULT testIRowsetIdentity();
|
|
|
|
//@cmember Test the IRowset methods (various properties set)
|
|
TESTRESULT testIRowset();
|
|
|
|
//@cmember Test the IRowsetChange::SetData method.
|
|
TESTRESULT testIRowsetChangeSet();
|
|
|
|
//@cmember Test the IRowsetChange::DeleteRows method.
|
|
TESTRESULT testIRowsetChangeDelete();
|
|
|
|
//@cmember Test the IRowsetChange::Insert method.
|
|
TESTRESULT testIRowsetChangeInsert();
|
|
|
|
//@cmember Test the IRowsetUpdate interface.
|
|
TESTRESULT testIRowsetUpdate();
|
|
|
|
//@cmember Test the IRowsetResynch methods.
|
|
TESTRESULT testIRowsetResynch();
|
|
|
|
//@cmember Test the IRowsetRefresh methods.
|
|
TESTRESULT testIRowsetRefresh();
|
|
|
|
//@cmember Test the IAccessor (Command interface) methods.
|
|
TESTRESULT testCmdIAccessor();
|
|
|
|
//@cmember Test the ICommandProperties::SetProperties method.
|
|
TESTRESULT testSetCmdProp();
|
|
|
|
//@cmember Test the ICommandText interface.
|
|
TESTRESULT testICmdText();
|
|
|
|
//@cmember Test the ICommand::GetDBSession method.
|
|
TESTRESULT testICmdGetDBSession();
|
|
|
|
//@cmember Test the ICommand::Execute method (set, exe, set, exe,
|
|
// set, exe).
|
|
TESTRESULT testICmdExec1();
|
|
|
|
//@cmember Test the ICommand::Execute method (set, prepare, exe,
|
|
// exe, exe).
|
|
TESTRESULT testICmdExec2();
|
|
|
|
//@cmember Test the ICommandPrepare::Prepare method.
|
|
TESTRESULT testCmdPrep();
|
|
|
|
//@cmember Test the ICommandPrepare::UnPrepare method.
|
|
TESTRESULT testCmdUnprep();
|
|
|
|
//@cmember Make the parameter bindings to be used in testICmdWParam.
|
|
BOOL MakeParamBindings(
|
|
CTable* pTable,
|
|
DBORDINAL cColumnsOnTable,
|
|
DBORDINAL* pcParamColMap,
|
|
LONG_PTR* rgParamColMap,
|
|
DB_UPARAMS* pcDbParamBindInfo,
|
|
DBPARAMBINDINFO* rgDbParamBindInfo,
|
|
DB_UPARAMS* rgParamOrdinals,
|
|
DBCOLUMNINFO* rgTableInfo);
|
|
|
|
//@cmember Test GetParameterInfo for ICommandWithParameters.
|
|
TESTRESULT testGetParamInfo(
|
|
ICommandWithParameters* pICWP,
|
|
CTable* pTable,
|
|
DB_UPARAMS cDbParamBindInfo,
|
|
DBPARAMBINDINFO* rgDbParamBindInfo,
|
|
LONG_PTR* rgParamColMap);
|
|
|
|
//@cmember Test the ICommandWithParameters methods.
|
|
TESTRESULT testICmdWParam();
|
|
|
|
//@cmember Test the IMultipleResults.
|
|
TESTRESULT testIMultipleResults();
|
|
|
|
//@cmember Test the Error interfaces.
|
|
TESTRESULT testIError();
|
|
|
|
//@cmember Test transaction commit (fRetaining=FALSE).
|
|
TESTRESULT testTransactionCommit();
|
|
|
|
//@cmember Test transaction abort (fRetaining=FALSE).
|
|
TESTRESULT testTransactionAbort();
|
|
|
|
//@cmember Test the Storage Object (ISequentialStream).
|
|
TESTRESULT testStorageObj();
|
|
|
|
//@cmember Test the IRow methods.
|
|
BOOL testIRow(IRow* pIRow, DBCOUNTITEM ulRowNum=0);
|
|
|
|
//@cmember Test the IColumnsInfo methods on a Row object. If
|
|
// bTestResColInfo is TRUE, then it also tests the
|
|
// method GetRestrictedColumnInfo.
|
|
BOOL testColInfo2(
|
|
CRowObject* pCRowObj,
|
|
BOOL bTestResColInfo = FALSE);
|
|
|
|
//@cmember Test the IRowChange method SetColumns on a Row object.
|
|
BOOL testIRowChange(CRowObject* pCRowObj);
|
|
|
|
//@cmember Test the IRowSchemaChange methods on a Row object.
|
|
BOOL testIRowSchemaChange(CRowObject* pCRowObj);
|
|
|
|
};
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// CQuickTest Implementation
|
|
//
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
//----------------------------------------------------------------------
|
|
// @mfunc Connection base class constructor, must take testcase name
|
|
// as parameter.
|
|
//
|
|
CQuickTest::CQuickTest(LPWSTR wszName) //Takes TestCase name as parameter
|
|
: CSessionObject(wszName)
|
|
{
|
|
//Empty file so we know it hasn't been set yet
|
|
m_wszFile[0] = L'\0' ;
|
|
m_szPath[0] = '\0';
|
|
m_cProviderTypes = 0;
|
|
m_rgProviderTypes = NULL;
|
|
m_pwszRowsetURL = NULL;
|
|
m_pCRowset = NULL;
|
|
|
|
m_ulSQLSup = 0;
|
|
m_ulMaxOpenRows = 0;
|
|
m_fFetchBackwards = FALSE;
|
|
|
|
m_cPropSets = 0;
|
|
m_cPropInfoSets = 0;
|
|
m_cPropIDSets = 0;
|
|
m_rgPropSets = NULL;
|
|
m_rgPropInfoSets = NULL;
|
|
m_rgPropIDSets = NULL;
|
|
m_pIPersistFile = NULL;
|
|
m_pIDBProperties = NULL;
|
|
m_pIRowset = NULL;
|
|
m_pICommand = NULL;
|
|
m_pIBindResource = NULL;
|
|
m_pIRow = NULL;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Destructor for CQuickTest class.
|
|
//
|
|
CQuickTest::~CQuickTest()
|
|
{
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
FreeProperties(&m_cPropInfoSets, &m_rgPropInfoSets);
|
|
FreeProperties(&m_cPropIDSets, &m_rgPropIDSets);
|
|
|
|
SAFE_FREE(m_rgProviderTypes);
|
|
SAFE_FREE(m_pwszRowsetURL);
|
|
|
|
//Release here if we haven't before
|
|
SAFE_RELEASE(m_pIPersistFile);
|
|
SAFE_RELEASE(m_pIDBProperties);
|
|
SAFE_RELEASE(m_pIRowset);
|
|
SAFE_RELEASE(m_pICommand);
|
|
SAFE_RELEASE(m_pIBindResource);
|
|
SAFE_RELEASE(m_pIRow);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc Find the current working directory and use it to set
|
|
// the path and file name for persisting files. Then attempt to
|
|
// save to that file. An instance of CLocaleInfo is created temporarily,
|
|
// only to use its member function 'MakeUnicodeIntlString'.
|
|
//
|
|
HRESULT CQuickTest::PersistToFile()
|
|
{
|
|
WCHAR wszSaveFile[2*PATH_SIZE];
|
|
HRESULT hr = E_FAIL;
|
|
CLocaleInfo* pCLI=NULL;
|
|
|
|
m_szPath[0] = '\0';
|
|
|
|
//If file is set, we've saved already, so just return NO_ERROR.
|
|
if (m_wszFile[0] != L'\0')
|
|
return NO_ERROR;
|
|
|
|
//Get current working directory to be used for creating files
|
|
if(!_getcwd(m_szPath,PATH_SIZE))
|
|
{
|
|
odtLog << wszErrorFindingCurrentPath;
|
|
return ResultFromScode(E_FAIL);
|
|
}
|
|
|
|
//Build whole file path and name
|
|
MultiByteToWideChar(CP_ACP,0,(LPCSTR)m_szPath,-1,m_wszFile,PATH_SIZE);
|
|
|
|
//For International strings.
|
|
BOOL fIntl = FindIntlSetting();
|
|
|
|
if(!fIntl)
|
|
wcscat(m_wszFile,L"\\QuikTest long file name.tst");
|
|
else
|
|
{
|
|
pCLI = new CLocaleInfo(GetUserDefaultLCID());
|
|
if(pCLI==NULL) goto CLEANUP;
|
|
pCLI->MakeUnicodeIntlString(wszSaveFile, 16);
|
|
wcscat(m_wszFile, L"\\");
|
|
wcscat(m_wszFile, wszSaveFile);
|
|
wcscat(m_wszFile, L".tst");
|
|
}
|
|
|
|
//Save to the specified file.
|
|
hr = m_pIPersistFile->Save((LPOLESTR)m_wszFile,TRUE);
|
|
if(hr != S_OK)
|
|
m_wszFile[0] = L'\0';
|
|
|
|
CLEANUP:
|
|
SAFE_DELETE(pCLI)
|
|
return hr;
|
|
} //PersistToFile
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
//@mfunc Append another DBPROPINFO and/or DBPROPINFOSET to m_rgPropInfoSets
|
|
//and increment the counter m_cPropInfoSets. The variant is left empty
|
|
//and dwFlags is initalized to NOT_SUPPORTED.
|
|
//
|
|
HRESULT CQuickTest::SetPropInfo(
|
|
DBPROPID propID, //[IN] Property ID
|
|
const GUID& guidPropSet, //[IN] Property Set
|
|
VARTYPE varType //[IN] Variant type
|
|
)
|
|
{
|
|
ASSERT(propID);
|
|
|
|
ULONG cPropertyInfos = 0;
|
|
DBPROPINFO* rgPropertyInfos = NULL;
|
|
|
|
ULONG cPropInfoSets = m_cPropInfoSets;
|
|
DBPROPINFOSET* rgPropInfoSets = m_rgPropInfoSets;
|
|
|
|
//Find the propertyInfo Set in which to insert the new DBPROPINFO.
|
|
ULONG iPropInfoSet = ULONG_MAX;
|
|
for(ULONG i=0; i<cPropInfoSets; i++)
|
|
if(guidPropSet == rgPropInfoSets[i].guidPropertySet)
|
|
iPropInfoSet = i;
|
|
|
|
//If propertyInfo Set is not found, create one.
|
|
if(iPropInfoSet == ULONG_MAX)
|
|
{
|
|
iPropInfoSet = cPropInfoSets;
|
|
SAFE_REALLOC(rgPropInfoSets, DBPROPINFOSET, cPropInfoSets+1);
|
|
rgPropInfoSets[iPropInfoSet].cPropertyInfos = 0;
|
|
rgPropInfoSets[iPropInfoSet].rgPropertyInfos = NULL;
|
|
rgPropInfoSets[iPropInfoSet].guidPropertySet = guidPropSet;
|
|
cPropInfoSets++;
|
|
}
|
|
|
|
//Fill values into DBPROPINFOSET.
|
|
cPropertyInfos = rgPropInfoSets[iPropInfoSet].cPropertyInfos;
|
|
rgPropertyInfos = rgPropInfoSets[iPropInfoSet].rgPropertyInfos;
|
|
|
|
SAFE_REALLOC(rgPropertyInfos, DBPROPINFO, cPropertyInfos+1);
|
|
|
|
//Fill values into DBPROPINFO.
|
|
rgPropertyInfos[cPropertyInfos].pwszDescription = L"\0";
|
|
rgPropertyInfos[cPropertyInfos].dwPropertyID = propID;
|
|
rgPropertyInfos[cPropertyInfos].vtType = varType;
|
|
VariantInit(&(rgPropertyInfos[cPropertyInfos].vValues));
|
|
rgPropertyInfos[cPropertyInfos].dwFlags = DBPROPFLAGS_NOTSUPPORTED;
|
|
|
|
cPropertyInfos++;
|
|
|
|
CLEANUP:
|
|
rgPropInfoSets[iPropInfoSet].cPropertyInfos = cPropertyInfos;
|
|
rgPropInfoSets[iPropInfoSet].rgPropertyInfos = rgPropertyInfos;
|
|
m_cPropInfoSets = cPropInfoSets;
|
|
m_rgPropInfoSets = rgPropInfoSets;
|
|
return S_OK;
|
|
} //SetPropInfo
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Append another DBPROPID and/or DBPROPIDSET to m_rgPropIDSets
|
|
//and increment the counter m_cPropIDSets.
|
|
//
|
|
HRESULT CQuickTest::SetPropID(
|
|
DBPROPID propID, //[IN] Property ID
|
|
const GUID& guidPropSet //[IN] Property Set
|
|
)
|
|
{
|
|
ASSERT(propID);
|
|
|
|
ULONG cPropertyIDs = 0;
|
|
DBPROPID* rgPropertyIDs = NULL;
|
|
|
|
ULONG cPropIDSets = m_cPropIDSets;
|
|
DBPROPIDSET* rgPropIDSets = m_rgPropIDSets;
|
|
|
|
//Find the propertyID Set in which to insert the new DBPROPID.
|
|
ULONG iPropIDSet = ULONG_MAX;
|
|
for(ULONG i=0; i<cPropIDSets; i++)
|
|
if(guidPropSet == rgPropIDSets[i].guidPropertySet)
|
|
iPropIDSet = i;
|
|
|
|
//If propertyID Set is not found, create one.
|
|
if(iPropIDSet == ULONG_MAX)
|
|
{
|
|
iPropIDSet = cPropIDSets;
|
|
SAFE_REALLOC(rgPropIDSets, DBPROPIDSET, cPropIDSets+1);
|
|
rgPropIDSets[iPropIDSet].cPropertyIDs = 0;
|
|
rgPropIDSets[iPropIDSet].rgPropertyIDs = NULL;
|
|
rgPropIDSets[iPropIDSet].guidPropertySet = guidPropSet;
|
|
cPropIDSets++;
|
|
}
|
|
|
|
//Fill values into DBPROPIDSET.
|
|
cPropertyIDs = rgPropIDSets[iPropIDSet].cPropertyIDs;
|
|
rgPropertyIDs = rgPropIDSets[iPropIDSet].rgPropertyIDs;
|
|
|
|
SAFE_REALLOC(rgPropertyIDs, DBPROPID, cPropertyIDs+1);
|
|
|
|
//Fill in DBPROPID.
|
|
rgPropertyIDs[cPropertyIDs] = propID;
|
|
|
|
cPropertyIDs++;
|
|
|
|
CLEANUP:
|
|
rgPropIDSets[iPropIDSet].cPropertyIDs = cPropertyIDs;
|
|
rgPropIDSets[iPropIDSet].rgPropertyIDs = rgPropertyIDs;
|
|
m_cPropIDSets = cPropIDSets;
|
|
m_rgPropIDSets = rgPropIDSets;
|
|
return S_OK;
|
|
} //SetPropID
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
//@mfunc Initialize m_rgPropIDSets and m_rgPropInfoSets with some chosen
|
|
//properties. For this it uses the function calls to SetPropID and
|
|
//SetPropInfo. Properties may be added or removed from m_rgPropIDSets
|
|
//and m_rgPropInfoSets by adding or removing calls to SetPropID and
|
|
//SetPropInfo below.
|
|
//
|
|
void CQuickTest::InitPropIDStructs()
|
|
{
|
|
m_cPropInfoSets = 0;
|
|
m_cPropIDSets = 0;
|
|
m_rgPropInfoSets = NULL;
|
|
m_rgPropIDSets = NULL;
|
|
|
|
//DBPROPSET_DATASOURCEINFO
|
|
|
|
SetPropInfo(DBPROP_ACTIVESESSIONS, DBPROPSET_DATASOURCEINFO, VT_I4);
|
|
SetPropID(DBPROP_ACTIVESESSIONS, DBPROPSET_DATASOURCEINFO);
|
|
|
|
SetPropInfo(DBPROP_CATALOGLOCATION, DBPROPSET_DATASOURCEINFO, VT_I4);
|
|
SetPropID(DBPROP_CATALOGLOCATION, DBPROPSET_DATASOURCEINFO);
|
|
|
|
SetPropInfo(DBPROP_COLUMNDEFINITION, DBPROPSET_DATASOURCEINFO, VT_I4);
|
|
SetPropID(DBPROP_COLUMNDEFINITION, DBPROPSET_DATASOURCEINFO);
|
|
|
|
SetPropInfo(DBPROP_DATASOURCENAME, DBPROPSET_DATASOURCEINFO, VT_BSTR);
|
|
SetPropID(DBPROP_DATASOURCENAME, DBPROPSET_DATASOURCEINFO);
|
|
|
|
SetPropInfo(DBPROP_DATASOURCEREADONLY, DBPROPSET_DATASOURCEINFO, VT_BOOL);
|
|
SetPropID(DBPROP_DATASOURCEREADONLY, DBPROPSET_DATASOURCEINFO);
|
|
|
|
SetPropInfo(DBPROP_DBMSNAME, DBPROPSET_DATASOURCEINFO, VT_BSTR);
|
|
SetPropID(DBPROP_DBMSNAME, DBPROPSET_DATASOURCEINFO);
|
|
|
|
SetPropInfo(DBPROP_DBMSVER, DBPROPSET_DATASOURCEINFO, VT_BSTR);
|
|
SetPropID(DBPROP_DBMSVER, DBPROPSET_DATASOURCEINFO);
|
|
|
|
SetPropInfo(DBPROP_IDENTIFIERCASE, DBPROPSET_DATASOURCEINFO, VT_I4);
|
|
SetPropID(DBPROP_IDENTIFIERCASE, DBPROPSET_DATASOURCEINFO);
|
|
|
|
SetPropInfo(DBPROP_MAXROWSIZE, DBPROPSET_DATASOURCEINFO, VT_I4);
|
|
SetPropID(DBPROP_MAXROWSIZE, DBPROPSET_DATASOURCEINFO);
|
|
|
|
SetPropInfo(DBPROP_MAXTABLESINSELECT, DBPROPSET_DATASOURCEINFO, VT_I4);
|
|
SetPropID(DBPROP_MAXTABLESINSELECT, DBPROPSET_DATASOURCEINFO);
|
|
|
|
SetPropInfo(DBPROP_PROVIDERNAME, DBPROPSET_DATASOURCEINFO, VT_BSTR);
|
|
SetPropID(DBPROP_PROVIDERNAME, DBPROPSET_DATASOURCEINFO);
|
|
|
|
SetPropInfo(DBPROP_QUOTEDIDENTIFIERCASE, DBPROPSET_DATASOURCEINFO, VT_I4);
|
|
SetPropID(DBPROP_QUOTEDIDENTIFIERCASE, DBPROPSET_DATASOURCEINFO);
|
|
|
|
SetPropInfo(DBPROP_ROWSETCONVERSIONSONCOMMAND, DBPROPSET_DATASOURCEINFO, VT_BOOL);
|
|
SetPropID(DBPROP_ROWSETCONVERSIONSONCOMMAND, DBPROPSET_DATASOURCEINFO);
|
|
|
|
SetPropInfo(DBPROP_SQLSUPPORT, DBPROPSET_DATASOURCEINFO, VT_I4);
|
|
SetPropID(DBPROP_SQLSUPPORT, DBPROPSET_DATASOURCEINFO);
|
|
|
|
SetPropInfo(DBPROP_USERNAME, DBPROPSET_DATASOURCEINFO, VT_BSTR);
|
|
SetPropID(DBPROP_USERNAME, DBPROPSET_DATASOURCEINFO);
|
|
|
|
//DBPROPSET_DBINIT
|
|
|
|
SetPropInfo(DBPROP_AUTH_PASSWORD, DBPROPSET_DBINIT, VT_BSTR);
|
|
SetPropID(DBPROP_AUTH_PASSWORD, DBPROPSET_DBINIT);
|
|
|
|
SetPropInfo(DBPROP_AUTH_USERID, DBPROPSET_DBINIT, VT_BSTR);
|
|
SetPropID(DBPROP_AUTH_USERID, DBPROPSET_DBINIT);
|
|
|
|
SetPropInfo(DBPROP_INIT_DATASOURCE, DBPROPSET_DBINIT, VT_BSTR);
|
|
SetPropID(DBPROP_INIT_DATASOURCE, DBPROPSET_DBINIT);
|
|
|
|
SetPropInfo(DBPROP_INIT_LCID, DBPROPSET_DBINIT, VT_I4);
|
|
SetPropID(DBPROP_INIT_LCID, DBPROPSET_DBINIT);
|
|
|
|
SetPropInfo(DBPROP_INIT_LOCATION, DBPROPSET_DBINIT, VT_BSTR);
|
|
SetPropID(DBPROP_INIT_LOCATION, DBPROPSET_DBINIT);
|
|
|
|
SetPropInfo(DBPROP_INIT_MODE, DBPROPSET_DBINIT, VT_I4);
|
|
SetPropID(DBPROP_INIT_MODE, DBPROPSET_DBINIT);
|
|
|
|
SetPropInfo(DBPROP_INIT_PROMPT, DBPROPSET_DBINIT, VT_I2);
|
|
SetPropID(DBPROP_INIT_PROMPT, DBPROPSET_DBINIT);
|
|
|
|
SetPropInfo(DBPROP_INIT_PROVIDERSTRING, DBPROPSET_DBINIT, VT_BSTR);
|
|
SetPropID(DBPROP_INIT_PROVIDERSTRING, DBPROPSET_DBINIT);
|
|
|
|
SetPropInfo(DBPROP_INIT_TIMEOUT, DBPROPSET_DBINIT, VT_I4);
|
|
SetPropID(DBPROP_INIT_TIMEOUT, DBPROPSET_DBINIT);
|
|
|
|
//DBPROPSET_ROWSET
|
|
|
|
SetPropInfo(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, VT_BOOL);
|
|
|
|
return;
|
|
} //InitPropIDStructs
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Set the flag of the given property in m_rgPropInfoSets to the
|
|
//given value. If the property was not found in m_rgPropInfoSets, then
|
|
//return FALSE. If the property was found and the flag was set, return
|
|
//TRUE.
|
|
//
|
|
BOOL CQuickTest::SetFlags(
|
|
DBPROPID propID, //[IN] Property ID
|
|
const GUID& guidPropSet, //[IN] Property Set
|
|
DBPROPFLAGS dwFlags //[IN] Prop Flags
|
|
)
|
|
{
|
|
ULONG iSet = 0;
|
|
ULONG iInfo = 0;
|
|
|
|
for(iSet=0; iSet<m_cPropInfoSets; iSet++)
|
|
{
|
|
if(m_rgPropInfoSets[iSet].guidPropertySet == guidPropSet)
|
|
{
|
|
for(iInfo=0; iInfo<m_rgPropInfoSets[iSet].cPropertyInfos; iInfo++)
|
|
{
|
|
if(m_rgPropInfoSets[iSet].rgPropertyInfos[iInfo].dwPropertyID ==
|
|
propID)
|
|
{
|
|
m_rgPropInfoSets[iSet].rgPropertyInfos[iInfo].dwFlags =
|
|
dwFlags;
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
} //SetFlags
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Call GetPropertyInfo and then initalize the property flags in
|
|
//m_rgPropInfoSets to that of those obtained through the GetPropertyInfo
|
|
//call. This can be used later to verify if the property is supported.
|
|
//The function SetFlags is called to locate the property in
|
|
//m_rgPropInfoSets and set the flag. All the properties in this function
|
|
//have been added to m_rgPropInfoSets in the function InitPropIDStructs.
|
|
//
|
|
void CQuickTest::InitSupInfo()
|
|
{
|
|
ULONG iSet=0, iInfo=0;
|
|
ULONG cPropInfoSets = 0;
|
|
DBPROPINFO* pInfo = NULL;
|
|
DBPROPINFOSET* pSet = NULL;
|
|
DBPROPINFOSET* rgPropInfoSets = NULL;
|
|
|
|
if(m_pIDBProperties==NULL)
|
|
goto CLEANUP;
|
|
if(!CHECK(m_pIDBProperties->GetPropertyInfo(0,NULL,&cPropInfoSets,
|
|
&rgPropInfoSets,NULL), S_OK))
|
|
goto CLEANUP;
|
|
|
|
//At least CANHOLDROWS has to be supported.
|
|
TESTC(cPropInfoSets !=0)
|
|
TESTC(rgPropInfoSets !=NULL)
|
|
|
|
for(iSet=0; iSet<cPropInfoSets; iSet++)
|
|
{
|
|
pSet = &(rgPropInfoSets[iSet]) ;
|
|
|
|
for(iInfo=0; iInfo<pSet->cPropertyInfos; iInfo++)
|
|
{
|
|
if(pSet->guidPropertySet==DBPROPSET_DATASOURCEINFO)
|
|
{
|
|
pInfo = &(pSet->rgPropertyInfos[iInfo]) ;
|
|
|
|
switch(pInfo->dwPropertyID)
|
|
{
|
|
case DBPROP_ACTIVESESSIONS:
|
|
COMPARE(SetFlags(DBPROP_ACTIVESESSIONS,
|
|
DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_CATALOGLOCATION:
|
|
COMPARE(SetFlags(DBPROP_CATALOGLOCATION,
|
|
DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_COLUMNDEFINITION:
|
|
COMPARE(SetFlags(DBPROP_COLUMNDEFINITION,
|
|
DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_DATASOURCENAME:
|
|
COMPARE(SetFlags(DBPROP_DATASOURCENAME,
|
|
DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_DATASOURCEREADONLY:
|
|
COMPARE(SetFlags(DBPROP_DATASOURCEREADONLY,
|
|
DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_DBMSNAME:
|
|
COMPARE(SetFlags(DBPROP_DBMSNAME,
|
|
DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_DBMSVER:
|
|
COMPARE(SetFlags(DBPROP_DBMSVER,
|
|
DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_IDENTIFIERCASE:
|
|
COMPARE(SetFlags(DBPROP_IDENTIFIERCASE,
|
|
DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_MAXROWSIZE:
|
|
COMPARE(SetFlags(DBPROP_MAXROWSIZE,
|
|
DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_MAXTABLESINSELECT:
|
|
COMPARE(SetFlags(DBPROP_MAXTABLESINSELECT,
|
|
DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_PROVIDERNAME:
|
|
COMPARE(SetFlags(DBPROP_PROVIDERNAME,
|
|
DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_QUOTEDIDENTIFIERCASE:
|
|
COMPARE(SetFlags(DBPROP_QUOTEDIDENTIFIERCASE,
|
|
DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_ROWSETCONVERSIONSONCOMMAND:
|
|
COMPARE(SetFlags(DBPROP_ROWSETCONVERSIONSONCOMMAND,
|
|
DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_SQLSUPPORT:
|
|
COMPARE(SetFlags(DBPROP_SQLSUPPORT,
|
|
DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_USERNAME:
|
|
COMPARE(SetFlags(DBPROP_USERNAME,
|
|
DBPROPSET_DATASOURCEINFO, pInfo->dwFlags),TRUE);
|
|
break;
|
|
default:
|
|
break;
|
|
}//switch
|
|
}
|
|
else if(pSet->guidPropertySet==DBPROPSET_DBINIT)
|
|
{
|
|
pInfo = &(pSet->rgPropertyInfos[iInfo]) ;
|
|
|
|
switch(pInfo->dwPropertyID)
|
|
{
|
|
case DBPROP_AUTH_PASSWORD:
|
|
COMPARE(SetFlags(DBPROP_AUTH_PASSWORD,
|
|
DBPROPSET_DBINIT, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_AUTH_USERID:
|
|
COMPARE(SetFlags(DBPROP_AUTH_USERID,
|
|
DBPROPSET_DBINIT, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_INIT_DATASOURCE:
|
|
COMPARE(SetFlags(DBPROP_INIT_DATASOURCE,
|
|
DBPROPSET_DBINIT, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_INIT_LCID:
|
|
COMPARE(SetFlags(DBPROP_INIT_LCID,
|
|
DBPROPSET_DBINIT, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_INIT_LOCATION:
|
|
COMPARE(SetFlags(DBPROP_INIT_LOCATION,
|
|
DBPROPSET_DBINIT, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_INIT_MODE:
|
|
COMPARE(SetFlags(DBPROP_INIT_MODE,
|
|
DBPROPSET_DBINIT, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_INIT_PROMPT:
|
|
COMPARE(SetFlags(DBPROP_INIT_PROMPT,
|
|
DBPROPSET_DBINIT, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_INIT_PROVIDERSTRING:
|
|
COMPARE(SetFlags(DBPROP_INIT_PROVIDERSTRING,
|
|
DBPROPSET_DBINIT, pInfo->dwFlags),TRUE);
|
|
break;
|
|
case DBPROP_INIT_TIMEOUT:
|
|
COMPARE(SetFlags(DBPROP_INIT_TIMEOUT,
|
|
DBPROPSET_DBINIT, pInfo->dwFlags),TRUE);
|
|
break;
|
|
default:
|
|
break;
|
|
}//switch
|
|
}
|
|
else if(pSet->guidPropertySet==DBPROPSET_ROWSET)
|
|
{
|
|
pInfo = &(pSet->rgPropertyInfos[iInfo]) ;
|
|
|
|
switch(pInfo->dwPropertyID)
|
|
{
|
|
case DBPROP_CANHOLDROWS:
|
|
COMPARE(SetFlags(DBPROP_CANHOLDROWS,
|
|
DBPROPSET_ROWSET, pInfo->dwFlags),TRUE);
|
|
break;
|
|
default:
|
|
break;
|
|
}//switch
|
|
}
|
|
}
|
|
}
|
|
|
|
CLEANUP:
|
|
FreeProperties(&cPropInfoSets, &rgPropInfoSets);
|
|
return;
|
|
} //InitSupInfo
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Verify that the VT_I2 variant has a non-negative value.
|
|
//
|
|
BOOL CQuickTest::checkPositive_I2(VARIANT* pv)
|
|
{
|
|
if((V_VT(pv) == VT_I2) && (V_I2(pv) >= 0))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
} //checkPositive_I2
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Wrapper for IRowset::GetNextRows.
|
|
//
|
|
HRESULT CQuickTest::GetNextRows(
|
|
IRowset* pIRowset, //[IN] Pointer to rowset
|
|
HCHAPTER* hChapter, //[IN] Handle to chapter
|
|
DBROWOFFSET lRowsOffset, //[IN] Offset to row
|
|
DBROWCOUNT cRows, //[IN] Number of rows to fetch
|
|
DBCOUNTITEM* pcRowsObtained, //[OUT] Number of rows fetched
|
|
HROW** prghRows //[OUT] Handle to fetched rows.
|
|
)
|
|
{
|
|
DBCOUNTITEM cRowsObtained = NO_ROWS;
|
|
DBCOUNTITEM i=0;
|
|
HROW* rghRowsInput = NULL;
|
|
HRESULT hr = S_OK;
|
|
HRESULT hrRet = E_FAIL;
|
|
|
|
TESTC(prghRows != NULL)
|
|
TESTC(pcRowsObtained != NULL)
|
|
TESTC(pIRowset != NULL)
|
|
|
|
//Record if we passed in consumer allocated array...
|
|
rghRowsInput = *prghRows;
|
|
|
|
//Fetch the rows.
|
|
hr = pIRowset->GetNextRows(NULL, lRowsOffset, cRows, &cRowsObtained, prghRows);
|
|
|
|
//Verify correct values are returned
|
|
if(hr == S_OK)
|
|
{
|
|
TESTC(cRowsObtained == (DBCOUNTITEM) ABS(cRows));
|
|
|
|
//Verify row array
|
|
for(i=0; i<cRowsObtained; i++)
|
|
{
|
|
TESTC(*prghRows != NULL);
|
|
TESTC((*prghRows)[i]!=DB_NULL_HROW)
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TESTC(cRowsObtained <= (DBCOUNTITEM) ABS(cRows));
|
|
if(cRowsObtained>0)
|
|
{
|
|
TESTC(*prghRows != NULL)
|
|
TESTC(**prghRows != DB_NULL_HROW)
|
|
}
|
|
}
|
|
|
|
//Verify output array, depending upon whether it is consumer or
|
|
//provider allocated...
|
|
if(rghRowsInput)
|
|
{
|
|
//This is a user allocated static array.
|
|
//This had better not be nulled out by the provider, if non-null
|
|
//on input.
|
|
TESTC(*prghRows == rghRowsInput);
|
|
}
|
|
else
|
|
{
|
|
TESTC(cRowsObtained ? *prghRows != NULL : *prghRows == NULL);
|
|
}
|
|
|
|
hrRet = hr;
|
|
|
|
CLEANUP:
|
|
if(pcRowsObtained)
|
|
*pcRowsObtained = cRowsObtained;
|
|
return hrRet;
|
|
} //GetNextRows
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Wrapper for IRowset::ReleaseRows.
|
|
//
|
|
HRESULT CQuickTest::ReleaseRows(
|
|
IRowset** ppIRowset, //[IN] Pointer to rowset
|
|
DBCOUNTITEM* pcRows, //[IN] Num of rows to release
|
|
HROW** prghRows //[IN] HROW of rows to release
|
|
)
|
|
{
|
|
HRESULT hr=S_OK;
|
|
|
|
if(ppIRowset==NULL || pcRows==NULL || prghRows==NULL)
|
|
return E_FAIL;
|
|
|
|
if(*ppIRowset && *prghRows)
|
|
hr = (*ppIRowset)->ReleaseRows(*pcRows, *prghRows, NULL, NULL,
|
|
NULL);
|
|
*pcRows = 0;
|
|
PROVIDER_FREE(*prghRows); //*prghRows = NULL
|
|
|
|
return hr;
|
|
} //ReleaseRows
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Wrapper for IRowset::RestartPosition.
|
|
//
|
|
HRESULT CQuickTest::RestartPosition(IRowset* pIRowset)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
TESTC(pIRowset != NULL)
|
|
hr = pIRowset->RestartPosition(NULL);
|
|
|
|
//Mask the hr.
|
|
if(hr==DB_S_COMMANDREEXECUTED)
|
|
{
|
|
hr = S_OK;
|
|
odtLog<<L"INFO: Got DB_S_COMMANDREEXECUTED for IRowset::RestartPosition.\n";
|
|
}
|
|
|
|
CLEANUP:
|
|
return hr;
|
|
} //RestartPosition
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Release the hAccessor and free the bindings. If bReleaseIAcc is
|
|
//TRUE(this is the default), then release IAccessor.
|
|
//
|
|
HRESULT CQuickTest::FreeAccessorAndBindings(
|
|
IAccessor** ppIAccessor, //[IN] Pointer to IAccessor
|
|
HACCESSOR* phAccessor, //[IN] Handle to accessor
|
|
DBCOUNTITEM* pcBindings, //[IN] Number of bindings
|
|
DBBINDING** prgBindings, //[IN] Binding Structs.
|
|
BOOL bReleaseIAcc //[IN] Release IAccessor ?
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if(!ppIAccessor || !phAccessor || !pcBindings || !prgBindings)
|
|
return E_FAIL;
|
|
|
|
if(*ppIAccessor && *phAccessor)
|
|
hr = (*ppIAccessor)->ReleaseAccessor(*phAccessor, NULL);
|
|
*phAccessor = DB_NULL_HACCESSOR;
|
|
hr = FreeAccessorBindings(*pcBindings, *prgBindings);
|
|
*pcBindings = 0;
|
|
*prgBindings = NULL;
|
|
if(bReleaseIAcc)
|
|
SAFE_RELEASE(*ppIAccessor);
|
|
return hr;
|
|
} //FreeAccessorAndBindings
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Appends a property and its value to the Init String. Returns a
|
|
//NULL if an error occurs.
|
|
//
|
|
HRESULT CQuickTest::AppendToInitString(WCHAR** ppwszInitString, DBPROPID dwPropertyID, GUID guidPropertySet, VARIANT* pVariant)
|
|
{
|
|
TBEGIN
|
|
ASSERT(ppwszInitString);
|
|
WCHAR wszBuffer[MAX_QUERY_LEN+100];
|
|
wszBuffer[0] = L'\0';
|
|
WCHAR* pwszNewString = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
//Now get the Keyword and Value
|
|
WCHAR* pwszKeyword = GetPropDesc(dwPropertyID, guidPropertySet, m_pIDBInitialize);
|
|
TESTC_(hr = VariantToString(pVariant, wszBuffer, MAX_QUERY_LEN+100, FALSE),S_OK);
|
|
|
|
//Don't neccessaryly need a value, "keyword=;", but we
|
|
//do need a keyword. This should map to a non-NULL property description
|
|
TESTC(pwszKeyword != NULL);
|
|
|
|
//Add this to the String
|
|
pwszNewString = CreateString(L"%s%s =", *ppwszInitString ? L";" : L"", pwszKeyword);
|
|
hr = AppendString(ppwszInitString, pwszNewString);
|
|
SAFE_FREE(pwszNewString);
|
|
|
|
//We might need to quote the items if there is an embedded semi
|
|
if(wcschr(wszBuffer, L';'))
|
|
pwszNewString = CreateString(L"\"%s\"", wszBuffer);
|
|
else
|
|
pwszNewString = CreateString(L"%s", wszBuffer);
|
|
hr = AppendString(ppwszInitString, pwszNewString);
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(pwszKeyword);
|
|
SAFE_FREE(pwszNewString);
|
|
return hr;
|
|
} //AppendToInitString
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Call OpenRowset and verify the returned IRowset. This method
|
|
//implicity uses m_cPropSets/m_rgPropSets. So if you want particular
|
|
//properties set, just simply set them before calling this method.
|
|
//
|
|
HRESULT CQuickTest::CreateOpenRowset(
|
|
CTable* pTable, //[IN] Table on which to open the rowset.
|
|
const IID& riid, //[IN] IID of requested interface on rowset.
|
|
IUnknown** ppRowset, //[OUT] Pointer to rowset interface.
|
|
IUnknown* pUnkOuter //[IN] For aggregation.
|
|
)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
DBID* pTableID = NULL;
|
|
|
|
TESTC(pTable != NULL)
|
|
TESTC(m_pIOpenRowset != NULL)
|
|
|
|
pTableID = &(pTable->GetTableIDRef()) ;
|
|
//Call OpenRowset
|
|
hr = m_pIOpenRowset->OpenRowset(pUnkOuter,pTableID,NULL,
|
|
riid,m_cPropSets,m_rgPropSets,ppRowset);
|
|
|
|
if(hr==S_OK || hr==DB_S_ERRORSOCCURRED)
|
|
{
|
|
//Verify Usable Rowset
|
|
if(ppRowset && riid!=IID_NULL)
|
|
{
|
|
TESTC(*ppRowset!=NULL)
|
|
}
|
|
|
|
//Verify no errors
|
|
if(hr==S_OK)
|
|
{
|
|
TESTC(VerifyPropSetStatus(m_cPropSets, m_rgPropSets,
|
|
DBPROPSTATUS_OK))
|
|
}
|
|
|
|
if(riid==IID_NULL)
|
|
{
|
|
//Verify no rowset returned
|
|
if(ppRowset)
|
|
TESTC(*ppRowset==NULL)
|
|
}
|
|
}
|
|
else //OpenRowset failed.
|
|
{
|
|
//Verify no rowset returned
|
|
if(ppRowset)
|
|
TESTC(*ppRowset==NULL)
|
|
}
|
|
|
|
CLEANUP:
|
|
return hr;
|
|
} //CreateOpenRowset
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// @mfunc This a test for IAccessor::GetBindings method. It checks if
|
|
// GetBindings returns the same bindings array as the ones used to create
|
|
// the accessor.
|
|
//
|
|
BOOL CQuickTest::VerifyBindings(
|
|
IAccessor* pIAccessor, //[IN] Pointer to IAccessor.
|
|
HACCESSOR hAccessor, //[IN] handle to accessor
|
|
DBCOUNTITEM cBindings, //[IN] Number of binding structs
|
|
DBBINDING* rgBindings, //[IN] Binding structures
|
|
DBACCESSORFLAGS dwCreateAccessorFlags //[IN] Value of Accessor flags used to create accessor
|
|
)
|
|
{
|
|
BOOL bSuccess = FALSE;
|
|
DBCOUNTITEM cGetBindings = 0;
|
|
DBCOUNTITEM ulIndex=0;
|
|
DBBINDING* pGetBind = NULL;
|
|
DBBINDING* pBind = NULL;
|
|
DBBINDING* rgGetBindings = NULL;
|
|
DBACCESSORFLAGS dwGetAccessorFlags = 0;
|
|
|
|
TESTC(pIAccessor != NULL)
|
|
|
|
//Obtained the bindings.
|
|
TESTC_(pIAccessor->GetBindings(hAccessor, &dwGetAccessorFlags,
|
|
&cGetBindings, &rgGetBindings),S_OK)
|
|
|
|
//Verify the Accessor Flags and number of bindings.
|
|
COMPARE(dwGetAccessorFlags , dwCreateAccessorFlags);
|
|
COMPARE(cGetBindings , cBindings);
|
|
|
|
//Verify the binding stuctures.
|
|
if (cGetBindings == 0)
|
|
{
|
|
//This is a null accessor, binding array should be null
|
|
TESTC(rgGetBindings == NULL)
|
|
}
|
|
else
|
|
{
|
|
TESTC(cGetBindings != 0)
|
|
TESTC(rgGetBindings != NULL)
|
|
|
|
for(ulIndex=0; ulIndex<cGetBindings; ulIndex++)
|
|
{
|
|
pGetBind = &(rgGetBindings[ulIndex]);
|
|
pBind = &(rgBindings[ulIndex]);
|
|
|
|
COMPARE(pGetBind->dwPart , pBind->dwPart);
|
|
COMPARE(pGetBind->iOrdinal , pBind->iOrdinal);
|
|
COMPARE(pGetBind->wType , pBind->wType);
|
|
COMPARE(pGetBind->eParamIO , pBind->eParamIO);
|
|
COMPARE(pGetBind->pTypeInfo , pBind->pTypeInfo);
|
|
|
|
//Precision and scale only apply for numeric and decimal
|
|
//types and then only if VALUE is bound.
|
|
if ((pBind->wType == DBTYPE_NUMERIC ||
|
|
pBind->wType == DBTYPE_DECIMAL ||
|
|
pBind->wType == DBTYPE_DBTIMESTAMP) &&
|
|
(pBind->dwPart & DBPART_VALUE))
|
|
{
|
|
COMPARE(pGetBind->bPrecision ,
|
|
pBind->bPrecision);
|
|
COMPARE(pGetBind->bScale , pBind->bScale);
|
|
}
|
|
|
|
//These only apply if value is bound
|
|
if (pBind->dwPart & DBPART_VALUE)
|
|
{
|
|
COMPARE(pGetBind->obValue , pBind->obValue);
|
|
COMPARE(pGetBind->cbMaxLen , pBind->cbMaxLen);
|
|
}
|
|
|
|
//These only apply if type is DBTYPE_UNKNOWN
|
|
if ((pBind->wType == DBTYPE_IUNKNOWN) &&
|
|
(pGetBind->pObject != NULL))
|
|
{
|
|
COMPARE(pGetBind->pObject->dwFlags ,
|
|
pBind->pObject->dwFlags) ;
|
|
COMPARE(pGetBind->pObject->iid ,
|
|
pBind->pObject->iid);
|
|
}
|
|
|
|
//These only apply if length is bound
|
|
if (pBind->dwPart & DBPART_LENGTH)
|
|
COMPARE(pGetBind->obLength , pBind->obLength);
|
|
|
|
//These only apply if status is bound
|
|
if (pBind->dwPart & DBPART_STATUS)
|
|
COMPARE(pGetBind->obStatus , pBind->obStatus);
|
|
}//For Loop
|
|
}
|
|
|
|
//If we get here, we must have passed
|
|
bSuccess = TRUE;
|
|
|
|
CLEANUP:
|
|
FreeAccessorBindings(cGetBindings, rgGetBindings);
|
|
return bSuccess;
|
|
} //VerifyBindings
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
//@mfunc Get the specified rows. Obtain their data and verify it using the
|
|
//function CompareData. Then release all the obtained rows. It is left to
|
|
//the caller of this function to make sure that the rows asked for exist
|
|
//and check (and set) the values of properties DBPROP_CANHOLDROWS and
|
|
//DBPROP_MAXOPENROWS if required. This function does not call
|
|
//RestartPosition.
|
|
//
|
|
BOOL CQuickTest::GetDataAndCompare(
|
|
DBROWOFFSET cSkipRows, //[IN] num of rows to skip.
|
|
DBROWCOUNT cGetRows, //[IN] num of rows to fetch.
|
|
DBCOUNTITEM numFirstRowInSet, //[IN] num of the first row in the set of rows to be fetched.
|
|
DBORDINAL cColumns, //[IN] num of columns.
|
|
DB_LORDINAL* rgColumnsOrd, //[IN] list of column ordinals.
|
|
IRowset* pIRowset, //[IN] Pointer to IRowset.
|
|
HACCESSOR hAccessor, //[IN] handle to accessor
|
|
DBCOUNTITEM cBindings, //[IN] Number of bindings
|
|
DBBINDING* rgBindings, //[IN] Binding structs
|
|
DBLENGTH cbRowSize, //[IN] row size
|
|
CTable* pTable //[IN] pointer to base table
|
|
)
|
|
{
|
|
BOOL bSuccess = FALSE;
|
|
DBCOUNTITEM ulIndex = 0;
|
|
DBCOUNTITEM rowNum = 0; //Row number of row to be compared.
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HRESULT hr = S_OK;
|
|
BYTE* pData = NULL;
|
|
HROW* rghRows = NULL;
|
|
|
|
TESTC(pIRowset != NULL)
|
|
|
|
if(pTable == NULL)
|
|
pTable = m_pTable;
|
|
|
|
TESTC(pTable != NULL)
|
|
|
|
//Use IRowset to retrieve data
|
|
TESTC_(GetNextRows(pIRowset, NULL, cSkipRows, cGetRows,
|
|
&cRowsObtained, (HROW **)&rghRows), S_OK)
|
|
|
|
TESTC(cRowsObtained == (DBCOUNTITEM) ABS(cGetRows));
|
|
|
|
//Allocate a new data buffer.
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
|
|
for(ulIndex=0; ulIndex<cRowsObtained; ulIndex++)
|
|
{
|
|
//Initialize pData and call GetData for a row.
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
if(!CHECK(hr = pIRowset->GetData(rghRows[ulIndex], hAccessor,
|
|
pData),S_OK))
|
|
continue;
|
|
|
|
//adjust the rowNum according to the fetch direction.
|
|
if(cGetRows >= 0)
|
|
rowNum = numFirstRowInSet+ulIndex;
|
|
else
|
|
rowNum = numFirstRowInSet-ulIndex;
|
|
|
|
//Verify data value, length and status are what is expected.
|
|
TESTC(CompareData(cColumns, rgColumnsOrd, rowNum,
|
|
pData, cBindings, rgBindings, pTable,
|
|
m_pIMalloc, PRIMARY, COMPARE_ONLY))
|
|
|
|
CHECK(ReleaseInputBindingsMemory(cBindings, rgBindings,
|
|
pData), S_OK);
|
|
}
|
|
|
|
bSuccess = TRUE;
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(pData);
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
return bSuccess;
|
|
} //GetDataAndCompare
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Get the bookmark for a given row number. Row nums are 1 based.
|
|
//Memory allocated for bookmark is freed by caller of this function.
|
|
//
|
|
BOOL CQuickTest::GetBookmark(
|
|
DBCOUNTITEM ulRow, //[IN] row number for which to get bookmark (1 based)
|
|
DBLENGTH cbRowSize, //[IN] row size
|
|
HACCESSOR hAccessor, //[IN] handle to accessor
|
|
DBCOUNTITEM cBindings, //[IN] number of bindings
|
|
DBBINDING* rgBindings, //[IN] binding structs
|
|
IUnknown* pIUnkRowset, //[IN] pointer to the rowset
|
|
DBBKMARK *pcbBookmark, //[OUT] size of bookmark
|
|
BYTE **ppBookmark //[OUT] value of bookmark
|
|
)
|
|
{
|
|
BOOL bSuccess = FALSE;
|
|
HRESULT hr = S_OK;
|
|
HROW* rghRows = NULL;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DBBKMARK dwAddr = 0;
|
|
IRowset* pIRowset = NULL;
|
|
BYTE* pData = NULL;
|
|
|
|
if(!pcbBookmark || !ppBookmark)
|
|
return FALSE;
|
|
|
|
//Row numbers are 1 based.
|
|
if(ulRow < 1)
|
|
return FALSE;
|
|
|
|
//VerifyInterface
|
|
if(!VerifyInterface(pIUnkRowset,IID_IRowset,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRowset))
|
|
{
|
|
odtLog<<L"INFO: Could not get IRowset interface.\n";
|
|
return FALSE;
|
|
}
|
|
|
|
//Allocate a new data buffer.
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
|
|
//restart the cursor position
|
|
TESTC_(RestartPosition(pIRowset), S_OK)
|
|
|
|
//fetch the row
|
|
TESTC_(GetNextRows(pIRowset, NULL,(ulRow-1),1,&cRowsObtained,&rghRows),S_OK)
|
|
|
|
//get the data
|
|
TESTC_(pIRowset->GetData(*rghRows, hAccessor, pData),S_OK)
|
|
|
|
//make sure the 0 column is for bookmark
|
|
TESTC(rgBindings[0].iOrdinal == 0)
|
|
|
|
//get the starting pointer of the consumer's buffer
|
|
dwAddr = (DBBKMARK) pData;
|
|
|
|
//get the length of the bookmark
|
|
*pcbBookmark = *((DBBKMARK *)(dwAddr+rgBindings[0].obLength));
|
|
|
|
//allocate memory for bookmark
|
|
SAFE_ALLOC(*ppBookmark, BYTE, *pcbBookmark);
|
|
|
|
if(!(*ppBookmark))
|
|
goto CLEANUP;
|
|
|
|
//copy the value of the bookmark into the consumer's buffer
|
|
memcpy(*ppBookmark, (void *)(dwAddr+rgBindings[0].obValue), (size_t)*pcbBookmark);
|
|
|
|
bSuccess=TRUE;
|
|
|
|
CLEANUP:
|
|
if(!bSuccess)
|
|
odtLog<<L"INFO: Could not get bookmark for row "<<ulRow<<L".\n";
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData);
|
|
SAFE_FREE(pData);
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
//restart the cursor position
|
|
if(!CHECK(RestartPosition(pIRowset), S_OK))
|
|
bSuccess = FALSE;
|
|
SAFE_RELEASE(pIRowset);
|
|
return bSuccess;
|
|
} //GetBookmark
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Compare 2 column descriptions.
|
|
//
|
|
BOOL CQuickTest::CompareColumnDesc(
|
|
DBCOLUMNDESC* oldCD, //[IN] column description
|
|
DBCOLUMNDESC* newCD //[IN] column description
|
|
)
|
|
{
|
|
ULONG cPropSet, cProp;
|
|
BOOL bSuccess = FALSE;
|
|
DBPROPSET *pNewPropSet = NULL;
|
|
DBPROPSET *pOldPropSet = NULL;
|
|
DBPROP *pNewProp = NULL;
|
|
DBPROP *pOldProp = NULL;
|
|
|
|
//compare everything in the structure
|
|
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(CompareDBID(oldCD->dbcid, newCD->dbcid));
|
|
|
|
//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 )
|
|
|| (pNewProp->dwPropertyID == DBPROP_COL_DEFAULT )
|
|
|| (pNewProp->dwPropertyID == DBPROP_COL_UNIQUE )
|
|
)
|
|
continue;
|
|
|
|
TESTC(pOldProp->dwPropertyID == pNewProp->dwPropertyID);
|
|
TESTC(CompareVariant(&(pOldProp->vValue), &(pNewProp->vValue)));
|
|
}
|
|
}
|
|
bSuccess = TRUE;
|
|
|
|
CLEANUP:
|
|
return bSuccess;
|
|
} //CompareColumnDesc
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Allocate memory for m_rgProviderTypes, and fill it with the
|
|
//provider types obtained from the tables column info. Each time this
|
|
//function is called, the caller has to free the memory for
|
|
//m_rgProviderTypes. This func is used by IConvertType test.
|
|
//
|
|
void CQuickTest::GetProviderTypes(CTable* pTable)
|
|
{
|
|
DBORDINAL cColumns = 0;
|
|
DBORDINAL iCol = 0;
|
|
CCol colTmp;
|
|
|
|
//If m_rgProviderTypes exists, then return.
|
|
if(m_rgProviderTypes)
|
|
return;
|
|
|
|
cColumns = pTable->CountColumnsOnTable();
|
|
|
|
//Allocate memory for storing the provider types.
|
|
SAFE_ALLOC(m_rgProviderTypes, DBTYPE, cColumns);
|
|
m_cProviderTypes = (ULONG) cColumns; // small no.
|
|
|
|
//Copy the provider types from the tables column info.
|
|
for(iCol=0; iCol<cColumns; iCol++)
|
|
{
|
|
if(S_OK == pTable->GetColInfo(iCol+1, colTmp))
|
|
{
|
|
m_rgProviderTypes[iCol] = colTmp.GetProviderType();
|
|
}
|
|
}
|
|
|
|
CLEANUP:
|
|
return;
|
|
} //GetProviderTypes
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Check if the given type is in the list of provider types
|
|
//m_rgProviderTypes. This func is used by IConvertType test.
|
|
//
|
|
BOOL CQuickTest::IsSupportedType(DBTYPE dwType)
|
|
{
|
|
ULONG ulIndex = 0;
|
|
|
|
if(m_rgProviderTypes == NULL)
|
|
return FALSE;
|
|
|
|
for(ulIndex=0; ulIndex<m_cProviderTypes; ulIndex++)
|
|
{
|
|
if(m_rgProviderTypes[ulIndex] == dwType)
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
} //IsSupportedType
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Use the DBSCHEMA_INDEXES alongwith the restrictions to determine
|
|
//if the given index exists. Return codes are interpreted as follows:
|
|
//TEST_PASS: check fExists to see if Index exists or not.
|
|
//TEST_SKIPPED: the schema or restrictions were not supported.
|
|
//TEST_FAIL: an unexpected error occurred.
|
|
//
|
|
TESTRESULT CQuickTest::DoesIndexExist(
|
|
IDBSchemaRowset* pIDSR, //[IN] pointer to interface
|
|
DBID* pTableID, //[IN] table ID
|
|
DBID* pIndexID, //[IN] Index ID
|
|
BOOL* pfExists //[OUT] does index exist
|
|
)
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex = 0; //no. of schemas
|
|
ULONG cRest = 5;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW* rghRows = NULL;
|
|
ULONG cSchema = 0;
|
|
ULONG *prgRestrictions= NULL;
|
|
GUID *prgSchemas = NULL;
|
|
BOOL bIsSchemaSupported = FALSE;
|
|
VARIANT rgRestrictIndexes[5];
|
|
IRowset* pIndexRowset = NULL;
|
|
|
|
//Call VariantInit.
|
|
for(ulIndex=0;ulIndex<cRest;ulIndex++)
|
|
VariantInit(&rgRestrictIndexes[ulIndex]);
|
|
|
|
TESTC(pfExists != NULL)
|
|
*pfExists = FALSE;
|
|
|
|
//Check to see if the schema is supported
|
|
TESTC_(hr = pIDSR->GetSchemas(&cSchema, &prgSchemas,
|
|
&prgRestrictions),S_OK)
|
|
|
|
//Check to see if DBSCHEMA_INDEXES is supported
|
|
for(ulIndex=0, bIsSchemaSupported=FALSE; ulIndex<cSchema && !bIsSchemaSupported;)
|
|
{
|
|
if(prgSchemas[ulIndex] == DBSCHEMA_INDEXES)
|
|
bIsSchemaSupported = TRUE;
|
|
else
|
|
ulIndex++;
|
|
}
|
|
|
|
//The schema has to be supported. Also the table name and Index
|
|
//name restrictions have to be supported.
|
|
if(!bIsSchemaSupported || !(prgRestrictions[ulIndex] & 0x4) || !(prgRestrictions[ulIndex] & 0x10))
|
|
{
|
|
odtLog<<L"Index Schema Rowset or the required constraints are not supported\n";
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Set the restrictions.
|
|
rgRestrictIndexes[2].vt = VT_BSTR;
|
|
rgRestrictIndexes[2].bstrVal = SysAllocString(pIndexID->uName.pwszName);
|
|
rgRestrictIndexes[4].vt = VT_BSTR;
|
|
rgRestrictIndexes[4].bstrVal = SysAllocString(pTableID->uName.pwszName);
|
|
|
|
//Get the Index schema rowset.
|
|
TESTC_(hr = pIDSR->GetRowset(NULL, DBSCHEMA_INDEXES, cRest,
|
|
rgRestrictIndexes, IID_IRowset, 0, NULL, (IUnknown**)
|
|
&pIndexRowset),S_OK)
|
|
|
|
TESTC(pIndexRowset != NULL)
|
|
|
|
//Fetch rows. There should be only 1 row or no rows.
|
|
hr = GetNextRows(pIndexRowset, 0, 0, 3, &cRowsObtained, &rghRows) ;
|
|
if(FAILED(hr))
|
|
{
|
|
CHECK(hr, S_OK);
|
|
goto CLEANUP; //TEST_FAIL.
|
|
}
|
|
|
|
if(cRowsObtained == 0 && rghRows == NULL)
|
|
{
|
|
//Index does not exist.
|
|
tTestResult = TEST_PASS;
|
|
*pfExists = FALSE;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
if(cRowsObtained == 0 || rghRows == NULL)
|
|
{
|
|
//An error occurred.
|
|
COMPARE(cRowsObtained, 1);
|
|
COMPARE(rghRows != NULL, TRUE);
|
|
tTestResult = TEST_FAIL;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//If we got here, then Index exists.
|
|
TESTC(cRowsObtained == 1 && rghRows)
|
|
TESTC(*rghRows != DB_NULL_HROW)
|
|
*pfExists = TRUE;
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
CHECK(ReleaseRows(&pIndexRowset, &cRowsObtained, &rghRows), S_OK);
|
|
for(ulIndex=0; ulIndex<5; ulIndex++)
|
|
VariantClear(&rgRestrictIndexes[ulIndex]);
|
|
PROVIDER_FREE(prgSchemas);
|
|
PROVIDER_FREE(prgRestrictions);
|
|
SAFE_RELEASE(pIndexRowset);
|
|
return tTestResult;
|
|
} //DoesIndexExist
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
//@mfunc Get the optional columns through IColumnsRowset.
|
|
//
|
|
HRESULT CQuickTest::GetAvailableColumns(
|
|
IUnknown* pUnk, //[IN] Pointer to the object.
|
|
DBORDINAL* pcOptCols, //[OUT] Number of optional columns.
|
|
DBID** prgOptCols //[OUT] DBIDs of optional columns.
|
|
)
|
|
{
|
|
HRESULT hrRet = E_FAIL;
|
|
IColumnsRowset* pIColumnsRowset = NULL;
|
|
|
|
HRESULT hr = pUnk->QueryInterface(IID_IColumnsRowset, (void **)
|
|
&pIColumnsRowset);
|
|
|
|
if(hr == E_NOINTERFACE)
|
|
{
|
|
odtLog<<L"IColumnsRowset is not supported.\n";
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
TESTC_(hr, S_OK)
|
|
TESTC(pIColumnsRowset != NULL)
|
|
|
|
TESTC_(hrRet=pIColumnsRowset->GetAvailableColumns(pcOptCols,
|
|
prgOptCols), S_OK)
|
|
|
|
if((*pcOptCols==0) && (*prgOptCols==NULL))
|
|
{
|
|
//Issue a warning.
|
|
COMPAREW(*pcOptCols, 1);
|
|
odtLog<<"WARNING: No Optional Metadata columns were returned.\n";
|
|
}
|
|
else
|
|
{
|
|
TESTC((*pcOptCols !=0) && (*prgOptCols !=NULL))
|
|
}
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIColumnsRowset);
|
|
return hrRet;
|
|
} //GetAvailableColumns
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Check if there are any mandatory columns in the list of
|
|
//columns returned by IColumnsRowset::GetAvailableColumns.
|
|
//
|
|
BOOL CQuickTest::CheckOptColumns(
|
|
const DBORDINAL cOptCols, //[IN] num of optional columns
|
|
const DBID* rgOptCols //[IN] array of optional columns
|
|
)
|
|
{
|
|
BOOL bSuccess = TRUE;
|
|
DBORDINAL iOpt = 0;
|
|
ULONG iMand = 0; //there are a fixed no. of mand cols
|
|
|
|
// Check if a mandatory column was returned
|
|
for(iOpt=0; iOpt<cOptCols; iOpt++)
|
|
{
|
|
for(iMand=0 ;iMand<g_cMandCols; iMand++)
|
|
{
|
|
if(memcmp(&(rgOptCols[iOpt]),g_rgMandCols[iMand].pDbid,sizeof(DBID)) == 0)
|
|
{
|
|
odtLog<<L"ERROR: Mandatory Column found at " << iOpt<< ENDL;
|
|
bSuccess = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bSuccess;
|
|
} //CheckOptColumns
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc For the given columns rowset, fetch one row at a time and verify
|
|
//them.
|
|
//
|
|
BOOL CQuickTest::CheckColumnsRowset(
|
|
IUnknown* pIUnk, //[IN] pointer to the columns rowset
|
|
const DBORDINAL cOptCols, //[IN] num of optional columns
|
|
const BOOL bOrgRowsetHasBookmark //[IN] does the original rowset have bookmark column
|
|
)
|
|
{
|
|
BOOL bSuccess = FALSE;
|
|
BOOL bStatus = FALSE;
|
|
HRESULT hr = S_OK;
|
|
HACCESSOR hAccessor = NULL;
|
|
USHORT usBookmark = 0; // 0 = Doesn't exist, 1 = Exists.
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM iRow = 0;
|
|
DBORDINAL iCol = 0;
|
|
DBCOUNTITEM iBind = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DBCOUNTITEM cTotalRows = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
DBORDINAL cColumns = 0;
|
|
CCol col;
|
|
DBCOLUMNINFO* rgInfo = NULL;
|
|
DBBINDING * rgBindings = NULL;
|
|
BYTE * pData = NULL;
|
|
DATA* pColumn = NULL;
|
|
HROW* rghRows = NULL;
|
|
WCHAR* pStrBuf = NULL;
|
|
IRowset * pIRowset = NULL;
|
|
IAccessor * pIAccessor = NULL;
|
|
|
|
//Obtain IAccessor interface.
|
|
if(!VerifyInterface(pIUnk,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown **)&pIAccessor))
|
|
return TEST_FAIL;
|
|
|
|
//Obtain IRowset interface.
|
|
TESTC(VerifyInterface(pIUnk,IID_IRowset,
|
|
ROWSET_INTERFACE,(IUnknown **)&pIRowset))
|
|
|
|
// Get bindings and column info
|
|
TESTC_(hr=GetAccessorAndBindings(pIUnk, DBACCESSOR_ROWDATA,
|
|
&hAccessor, &rgBindings, &cBindings, &cbRowSize,
|
|
DBPART_VALUE|DBPART_STATUS |DBPART_LENGTH, ALL_COLS_BOUND,
|
|
FORWARD, NO_COLS_BY_REF, &rgInfo, &cColumns, &pStrBuf), S_OK)
|
|
|
|
TESTC(rgInfo != NULL)
|
|
|
|
//Check if the columns rowset has bookmark column.
|
|
if(rgInfo[0].iOrdinal == 0)
|
|
usBookmark = 1;
|
|
|
|
//Check the number of columns in the columns rowset.
|
|
TESTC(cColumns == g_cMandCols + cOptCols + usBookmark)
|
|
|
|
//For each mandatory column ...
|
|
for(iCol=0; iCol<g_cMandCols; iCol++)
|
|
{
|
|
//Check the type.
|
|
COMPARE(rgInfo[iCol+usBookmark].wType , g_rgMandCols[iCol].wType);
|
|
|
|
//Check the name.
|
|
TESTC(wcscmp(rgInfo[iCol+usBookmark].pwszName,
|
|
g_rgMandCols[iCol].pwszName) == 0)
|
|
}
|
|
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
|
|
//Make sure we are on the first row.
|
|
TESTC_(RestartPosition(pIRowset), S_OK)
|
|
|
|
//Get one row at a time from the columns rowset.
|
|
while(S_OK==(hr=GetNextRows(pIRowset, NULL,0,1,&cRowsObtained,&rghRows)))
|
|
{
|
|
//If it is a row corresponding to a bookmark column in the
|
|
//original rowset, then release the row and fetch next row.
|
|
if((iRow==0)&&(bOrgRowsetHasBookmark))
|
|
goto RELEASEROW;
|
|
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
|
|
//From the table, get the column info for the column corresponding
|
|
//to this row.
|
|
TESTC_(hr=m_pTable->GetColInfo(iRow+ !bOrgRowsetHasBookmark, col), S_OK)
|
|
|
|
//Get the row data.
|
|
TESTC_(hr=pIRowset->GetData(rghRows[0],hAccessor, pData),S_OK)
|
|
|
|
//Check the first 6 mandatory columns of this row.
|
|
for(iBind=0; iBind < cBindings; iBind++)
|
|
{
|
|
if((iBind==0) && usBookmark)
|
|
continue;
|
|
|
|
//Grab one column.
|
|
pColumn = (DATA *) (pData + rgBindings[iBind].obStatus);
|
|
|
|
// Mandatory columns :-
|
|
|
|
if( CompareDBID(rgInfo[iBind].columnid, DBCOLUMN_IDNAME))
|
|
{
|
|
if( (DBSTATUS)pColumn->sStatus == DBSTATUS_S_OK )
|
|
{
|
|
bStatus = TRUE;
|
|
COMPARE(wcscmp(col.GetColName(),
|
|
(WCHAR*)pColumn->bValue),0) ;
|
|
}
|
|
}
|
|
else if( CompareDBID(rgInfo[iBind].columnid, DBCOLUMN_GUID))
|
|
{
|
|
if( (DBSTATUS)pColumn->sStatus == DBSTATUS_S_OK )
|
|
{
|
|
bStatus = TRUE;
|
|
COMPARE((col.GetColID())->uGuid.guid,
|
|
*((GUID*)pColumn->bValue)) ;
|
|
}
|
|
}
|
|
else if( CompareDBID(rgInfo[iBind].columnid, DBCOLUMN_PROPID))
|
|
{
|
|
if( (DBSTATUS)pColumn->sStatus == DBSTATUS_S_OK )
|
|
{
|
|
bStatus = TRUE;
|
|
COMPARE((col.GetColID())->uName.ulPropid,
|
|
*((ULONG*)pColumn->bValue)) ; //propid is ULONG
|
|
}
|
|
}
|
|
else if( CompareDBID(rgInfo[iBind].columnid, DBCOLUMN_NAME))
|
|
{
|
|
if((DBSTATUS)pColumn->sStatus == DBSTATUS_S_OK)
|
|
{
|
|
if(!COMPAREW(wcscmp(col.GetColName(),
|
|
(WCHAR*)pColumn->bValue),0))
|
|
{
|
|
odtLog<<L"WARNING: Column names don't match.\n"
|
|
<<L"Expected: "<<col.GetColName()
|
|
<<L" Got: "<<(WCHAR*)pColumn->bValue<<"\n";
|
|
}
|
|
|
|
}
|
|
}
|
|
else if( CompareDBID(rgInfo[iBind].columnid, DBCOLUMN_NUMBER))
|
|
{
|
|
TESTC((DBSTATUS)pColumn->sStatus == DBSTATUS_S_OK)
|
|
COMPARE(*((ULONG*)pColumn->bValue) ,
|
|
iRow+ !bOrgRowsetHasBookmark);
|
|
}
|
|
else if( CompareDBID(rgInfo[iBind].columnid, DBCOLUMN_TYPE))
|
|
{
|
|
TESTC((DBSTATUS)pColumn->sStatus == DBSTATUS_S_OK)
|
|
COMPARE(*((USHORT*)pColumn->bValue),
|
|
col.GetProviderType()) ;
|
|
}
|
|
}
|
|
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData);
|
|
|
|
//This is used to check if at least one of the three columns
|
|
//(DBCOLUMN_IDNAME, DBCOLUMN_GUID and DBCOLUMN_PROPID) has a
|
|
//status of DBSTATUS_S_OK.
|
|
TESTC(bStatus)
|
|
|
|
RELEASEROW:
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
bStatus = FALSE;
|
|
cTotalRows++;
|
|
iRow++;
|
|
}
|
|
|
|
TESTC_(hr, DB_S_ENDOFROWSET)
|
|
|
|
//Check the total number of rows fetched from the columns rowset.
|
|
TESTC(cTotalRows == m_pTable->CountColumnsOnTable()+ bOrgRowsetHasBookmark)
|
|
|
|
bSuccess = TRUE;
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(pData);
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
PROVIDER_FREE(rgInfo);
|
|
PROVIDER_FREE(pStrBuf);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowset);
|
|
return bSuccess;
|
|
} //CheckColumnsRowset
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Create an instance of the Root Binder, requesting IBindResource.
|
|
//Then QI for IDBBinderProperties and set the initialization properties,
|
|
//and some rowset properties. Then get the rowset URL from INI file.
|
|
//
|
|
BOOL CQuickTest::CreateRootBinder()
|
|
{
|
|
TBEGIN
|
|
ULONG cPropSets = 0;
|
|
DBPROPSET* rgPropSets = NULL;
|
|
IBindResource* pIBR = NULL;
|
|
IDBBinderProperties* pIDBBProp = NULL;
|
|
|
|
pIBR = GetModInfo()->GetRootBinder();
|
|
TESTC_PROVIDER(pIBR != NULL)
|
|
|
|
if(GetModInfo()->GetParseObject()->GetURL(ROWSET_INTERFACE))
|
|
m_pwszRowsetURL = wcsDuplicate(GetModInfo()->GetParseObject()->GetURL(ROWSET_INTERFACE));
|
|
else if(GetModInfo()->GetRootURL())
|
|
m_pwszRowsetURL = wcsDuplicate(GetModInfo()->GetRootURL());
|
|
|
|
//There may not be an INI file, or the INI file may not have a
|
|
//[URL] section. In these cases we would want to skip.
|
|
TESTC_PROVIDER(m_pwszRowsetURL != NULL)
|
|
|
|
//URLs are of the form "scheme:<prefix>". Cannot have a valid URL
|
|
//with less than 2 characters.
|
|
TESTC(wcslen(m_pwszRowsetURL) > 1)
|
|
|
|
TESTC(VerifyInterface(pIBR, IID_IBindResource,
|
|
BINDER_INTERFACE,(IUnknown**)&m_pIBindResource))
|
|
|
|
TESTC(VerifyInterface(m_pIBindResource, IID_IDBBinderProperties,
|
|
BINDER_INTERFACE,(IUnknown**)&pIDBBProp))
|
|
|
|
TESTC(GetInitProps(&cPropSets, &rgPropSets))
|
|
|
|
SetProperty(DBPROP_CANFETCHBACKWARDS, DBPROPSET_ROWSET,
|
|
&cPropSets, &rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetProperty(DBPROP_IRowsetIdentity, DBPROPSET_ROWSET,
|
|
&cPropSets, &rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
//SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &cPropSets,
|
|
// &rgPropSets) ;
|
|
|
|
TESTC_(pIDBBProp->SetProperties(cPropSets, rgPropSets), S_OK)
|
|
|
|
CLEANUP:
|
|
FreeProperties(&cPropSets, &rgPropSets);
|
|
SAFE_RELEASE(pIDBBProp);
|
|
TRETURN
|
|
} //CreateRootBinder
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
//@mfunc Get the properties specified in the property ID sets created in
|
|
//the function InitPropIDStructs. Check for the property ID and status of
|
|
//returned property sets. For the properties which show NOTSUPPORTED,
|
|
//verify that they are indeed not supported.
|
|
//
|
|
TESTRESULT CQuickTest::testGetProperties()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG ulSupported = 0;
|
|
ULONG iSet=0, iProp=0 ;
|
|
ULONG cPropSets = 0;
|
|
DBPROPSET* rgPropSets = NULL;
|
|
|
|
if(m_pIDBProperties == NULL)
|
|
{
|
|
odtLog<<L"IDBProperties pointer is NULL.\n";
|
|
return TEST_FAIL;
|
|
}
|
|
|
|
//IDBProperties::GetProperties may return S_OK if all properties in
|
|
//our DBPROPIDSET structures are supported. If some of them are not
|
|
//supported it may return DB_S_ERRORSOCCURRED.
|
|
hr = m_pIDBProperties->GetProperties(m_cPropIDSets,
|
|
m_rgPropIDSets, &cPropSets, &rgPropSets) ;
|
|
|
|
if(hr==DB_E_ERRORSOCCURRED)
|
|
{
|
|
odtLog<<L"WARNING: None of the properties used were supported.\n";
|
|
CHECKW(hr, S_OK);
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
if((hr != S_OK) && (hr != DB_S_ERRORSOCCURRED))
|
|
{
|
|
CHECK(hr, S_OK);
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// Verify returned variables have valid values
|
|
if(!COMPARE(cPropSets, m_cPropIDSets) ||
|
|
(rgPropSets==NULL) ||
|
|
!COMPARE(rgPropSets[0].cProperties, m_rgPropIDSets[0].cPropertyIDs) ||
|
|
(rgPropSets[0].rgProperties==NULL) ||
|
|
!COMPARE(rgPropSets[1].cProperties, m_rgPropIDSets[1].cPropertyIDs) ||
|
|
(rgPropSets[1].rgProperties==NULL ))
|
|
goto CLEANUP;
|
|
|
|
//Compare property IDs and check status for verification.
|
|
for(iSet=0; iSet<cPropSets; iSet++)
|
|
{
|
|
for(iProp=0; iProp<rgPropSets[iSet].cProperties ; iProp++)
|
|
{
|
|
//Comparing property IDs
|
|
TESTC(rgPropSets[iSet].rgProperties[iProp].dwPropertyID ==
|
|
m_rgPropIDSets[iSet].rgPropertyIDs[iProp])
|
|
|
|
//Check if the variant type matches the type we had set
|
|
//to in InitPropIDStructs, or VT_EMPTY.
|
|
COMPARE(((V_VT(& rgPropSets[iSet].rgProperties[iProp].vValue) ==
|
|
m_rgPropInfoSets[iSet].rgPropertyInfos[iProp].vtType) ||
|
|
(V_VT(& rgPropSets[iSet].rgProperties[iProp].vValue) ==
|
|
VT_EMPTY)), TRUE) ;
|
|
|
|
//Check status.
|
|
if(hr==S_OK)
|
|
{
|
|
//The status should be DBPROPSTATUS_OK.
|
|
COMPARE(rgPropSets[iSet].rgProperties[iProp].dwStatus,
|
|
DBPROPSTATUS_OK) ;
|
|
}
|
|
if(hr==DB_S_ERRORSOCCURRED)
|
|
{
|
|
//The status should be either DBPROPSTATUS_OK or
|
|
//DBPROPSTATUS_NOTSUPPORTED.
|
|
COMPARE(((rgPropSets[iSet].rgProperties[iProp].dwStatus==
|
|
DBPROPSTATUS_OK) ||
|
|
(rgPropSets[iSet].rgProperties[iProp].dwStatus==
|
|
DBPROPSTATUS_NOTSUPPORTED)), TRUE) ;
|
|
|
|
if(rgPropSets[iSet].rgProperties[iProp].dwStatus==
|
|
DBPROPSTATUS_OK)
|
|
ulSupported++;
|
|
}
|
|
|
|
//If the obtained property shows that it is not supported,
|
|
//then verify that the flag was set to NOT_SUPPORTED in
|
|
//InitSupInfo.
|
|
if(rgPropSets[iSet].rgProperties[iProp].dwStatus ==
|
|
DBPROPSTATUS_NOTSUPPORTED)
|
|
{
|
|
COMPARE(m_rgPropInfoSets[iSet].rgPropertyInfos[iProp].dwFlags,
|
|
DBPROPFLAGS_NOTSUPPORTED) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(hr==DB_S_ERRORSOCCURRED)
|
|
TESTC(ulSupported > 0)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
FreeProperties(&cPropSets, &rgPropSets);
|
|
return tTestResult;
|
|
} //testGetProperties
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Get ALL properties supported by a provider. For the returned
|
|
//properties, check if the status is DBPROPSTATUS_OK. For a bunch of
|
|
//properties check if the variant type of the variant in DBPROP is the
|
|
//same as property type or VT_EMPTY.
|
|
//
|
|
TESTRESULT CQuickTest::testGetAllProperties(IDBProperties* pIDBProperties)
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG iSet=0, iProp=0 ;
|
|
ULONG cPropSets = 0;
|
|
DBPROP* pProp = NULL;
|
|
DBPROPSET* rgPropSets = NULL;
|
|
|
|
if(pIDBProperties == NULL)
|
|
{
|
|
odtLog<<L"IDBProperties pointer is NULL.\n";
|
|
return TEST_FAIL;
|
|
}
|
|
|
|
//IDBProperties::GetProperties(0,NULL)
|
|
TESTC_(hr=pIDBProperties->GetProperties(0, NULL, &cPropSets,
|
|
&rgPropSets), S_OK)
|
|
|
|
//At least CANHOLDROWS has to be supported.
|
|
TESTC((cPropSets != 0) && (rgPropSets != NULL))
|
|
|
|
//Check the DBPROP structures for certain selected properties in the
|
|
//Data Source Information and Data Source Initialization groups.
|
|
for(iSet=0; iSet<cPropSets; iSet++)
|
|
{
|
|
//If the property belongs to the Data Source Information group.
|
|
if(rgPropSets[iSet].guidPropertySet==DBPROPSET_DATASOURCEINFO)
|
|
{
|
|
for(iProp=0; iProp<rgPropSets[iSet].cProperties; iProp++)
|
|
{
|
|
pProp = &(rgPropSets[iSet].rgProperties[iProp]);
|
|
|
|
//Check if status of property is DBPROPSTATUS_OK.
|
|
COMPARE(pProp->dwStatus, DBPROPSTATUS_OK) ;
|
|
|
|
//The variant type of the vValue field in DBPROP should
|
|
//either match the type of the property, or VT_EMPTY.
|
|
switch(pProp->dwPropertyID)
|
|
{
|
|
case DBPROP_ACTIVESESSIONS:
|
|
case DBPROP_MAXROWSIZE:
|
|
case DBPROP_MAXTABLESINSELECT:
|
|
case DBPROP_SQLSUPPORT:
|
|
COMPARE(VT_I4, V_VT(& pProp->vValue)) ;
|
|
break;
|
|
|
|
case DBPROP_CATALOGLOCATION:
|
|
COMPARE(VT_I4, V_VT(& pProp->vValue)) ;
|
|
COMPARE((V_I4(&pProp->vValue)==DBPROPVAL_CL_START ||
|
|
V_I4(&pProp->vValue)==DBPROPVAL_CL_END), TRUE) ;
|
|
break;
|
|
|
|
case DBPROP_COLUMNDEFINITION:
|
|
COMPARE(VT_I4, V_VT(& pProp->vValue)) ;
|
|
COMPARE((V_I4(&pProp->vValue)==0 ||
|
|
V_I4(&pProp->vValue)==DBPROPVAL_CD_NOTNULL), TRUE) ;
|
|
break;
|
|
|
|
case DBPROP_DATASOURCENAME:
|
|
case DBPROP_DBMSNAME:
|
|
case DBPROP_DBMSVER:
|
|
case DBPROP_PROVIDERNAME:
|
|
case DBPROP_USERNAME:
|
|
COMPARE((VT_BSTR == V_VT(&pProp->vValue) ||
|
|
VT_EMPTY == V_VT(&pProp->vValue)),TRUE);
|
|
//COMPARE(VT_BSTR, V_VT(& pProp->vValue));
|
|
COMPARE(CheckVariant(& pProp->vValue),TRUE);
|
|
break;
|
|
|
|
case DBPROP_DATASOURCEREADONLY:
|
|
case DBPROP_ROWSETCONVERSIONSONCOMMAND:
|
|
COMPARE(VT_BOOL, V_VT(& pProp->vValue));
|
|
COMPARE(CheckVariant(& pProp->vValue),TRUE);
|
|
break;
|
|
|
|
case DBPROP_IDENTIFIERCASE:
|
|
COMPARE(VT_I4, V_VT(& pProp->vValue));
|
|
COMPARE((V_I4(&pProp->vValue)==DBPROPVAL_IC_UPPER ||
|
|
V_I4(&pProp->vValue)==DBPROPVAL_IC_LOWER ||
|
|
V_I4(&pProp->vValue)==DBPROPVAL_IC_SENSITIVE ||
|
|
V_I4(&pProp->vValue)==DBPROPVAL_IC_MIXED),TRUE);
|
|
break;
|
|
|
|
case DBPROP_QUOTEDIDENTIFIERCASE:
|
|
COMPARE(VT_I4, V_VT(& pProp->vValue));
|
|
COMPARE((V_I4(&pProp->vValue)==DBPROPVAL_IC_UPPER ||
|
|
V_I4(&pProp->vValue)==DBPROPVAL_IC_LOWER ||
|
|
V_I4(&pProp->vValue)==DBPROPVAL_IC_SENSITIVE ||
|
|
V_I4(&pProp->vValue)==DBPROPVAL_IC_MIXED),TRUE);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//If property belongs to the Data Source Initialization group.
|
|
else if(rgPropSets[iSet].guidPropertySet==DBPROPSET_DBINIT)
|
|
{
|
|
for(iProp=0; iProp<rgPropSets[iSet].cProperties; iProp++)
|
|
{
|
|
pProp = &(rgPropSets[iSet].rgProperties[iProp]);
|
|
|
|
//Check if status of property is DBPROPSTATUS_OK.
|
|
COMPARE(pProp->dwStatus, DBPROPSTATUS_OK);
|
|
|
|
//The variant type of the vValue field in DBPROP should
|
|
//either match the type of the property, or VT_EMPTY.
|
|
switch(pProp->dwPropertyID)
|
|
{
|
|
case DBPROP_AUTH_PASSWORD:
|
|
case DBPROP_AUTH_USERID:
|
|
case DBPROP_INIT_DATASOURCE:
|
|
case DBPROP_INIT_LOCATION:
|
|
case DBPROP_INIT_PROVIDERSTRING:
|
|
COMPARE((VT_BSTR == V_VT(&pProp->vValue) ||
|
|
VT_EMPTY == V_VT(&pProp->vValue)),TRUE);
|
|
if(VT_EMPTY != V_VT(&pProp->vValue))
|
|
COMPARE(CheckVariant(&pProp->vValue),TRUE);
|
|
break;
|
|
|
|
case DBPROP_INIT_LCID:
|
|
case DBPROP_INIT_MODE:
|
|
case DBPROP_INIT_TIMEOUT:
|
|
COMPARE((VT_I4 == V_VT(&pProp->vValue) ||
|
|
VT_EMPTY == V_VT(&pProp->vValue)),TRUE);
|
|
break;
|
|
|
|
case DBPROP_INIT_PROMPT:
|
|
COMPARE((VT_I2 == V_VT(&pProp->vValue) ||
|
|
VT_EMPTY == V_VT(&pProp->vValue)),TRUE);
|
|
if(VT_EMPTY != V_VT(&pProp->vValue))
|
|
COMPARE(checkPositive_I2(&pProp->vValue),TRUE);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//for any other property sets (and provider specific sets)
|
|
else
|
|
{
|
|
for(iProp=0; iProp<rgPropSets[iSet].cProperties; iProp++)
|
|
{
|
|
pProp = &(rgPropSets[iSet].rgProperties[iProp]);
|
|
|
|
//Check if status of property is DBPROPSTATUS_OK.
|
|
COMPARE(pProp->dwStatus, DBPROPSTATUS_OK);
|
|
|
|
//Check the variant value for some variant types.
|
|
COMPARE(CheckVariant(&pProp->vValue), TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
FreeProperties(&cPropSets, &rgPropSets);
|
|
return tTestResult;
|
|
} //testGetAllProperties
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Get the property info for the property ID sets created in
|
|
//the function InitPropIDStructs. Check the property ID and flags of
|
|
//returned property Info sets.
|
|
//
|
|
TESTRESULT CQuickTest::testGetPropInfo()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG iSet=0, iInfo=0 ;
|
|
ULONG cPropInfoSets = 0;
|
|
DBPROPINFOSET * rgPropInfoSets = NULL;
|
|
WCHAR* pwszStringBuffer = NULL;
|
|
|
|
if(m_pIDBProperties == NULL)
|
|
{
|
|
odtLog<<L"IDBProperties pointer is NULL.\n";
|
|
return TEST_FAIL;
|
|
}
|
|
|
|
//IDBPropertiesGetPropertyInfo may return S_OK if all properties in
|
|
//our DBPROPIDSET structures are supported. If some of them are not
|
|
//supported it may return DB_S_ERRORSOCCURRED.
|
|
hr = m_pIDBProperties->GetPropertyInfo(m_cPropIDSets, m_rgPropIDSets,
|
|
&cPropInfoSets, &rgPropInfoSets, &pwszStringBuffer) ;
|
|
|
|
if(hr==DB_E_ERRORSOCCURRED)
|
|
{
|
|
odtLog<<L"CANHOLDROWS has to be supported.\n";
|
|
tTestResult = TEST_FAIL;
|
|
goto CLEANUP;
|
|
}
|
|
if((hr != S_OK) && (hr != DB_S_ERRORSOCCURRED))
|
|
{
|
|
CHECK(hr, S_OK);
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Check if the returned variables have valid values
|
|
if(!COMPARE(cPropInfoSets,m_cPropIDSets) ||
|
|
(rgPropInfoSets==NULL) ||
|
|
!COMPARE(rgPropInfoSets[0].cPropertyInfos,m_rgPropIDSets[0].cPropertyIDs) ||
|
|
(rgPropInfoSets[0].rgPropertyInfos==NULL) ||
|
|
!COMPARE(rgPropInfoSets[1].cPropertyInfos,m_rgPropIDSets[1].cPropertyIDs) ||
|
|
(rgPropInfoSets[1].rgPropertyInfos==NULL) )
|
|
goto CLEANUP;
|
|
|
|
//Compare Descriptions and property IDs for verification.
|
|
for(iSet=0; iSet<cPropInfoSets; iSet++)
|
|
{
|
|
for(iInfo=0; iInfo<rgPropInfoSets[iSet].cPropertyInfos ; iInfo++)
|
|
{
|
|
//Check property ID
|
|
COMPARE(rgPropInfoSets[iSet].rgPropertyInfos[iInfo].dwPropertyID,
|
|
m_rgPropIDSets[iSet].rgPropertyIDs[iInfo]);
|
|
|
|
//Verify the flags are the same as that initialized in the
|
|
//function InitSupInfo.
|
|
COMPARE(rgPropInfoSets[iSet].rgPropertyInfos[iInfo].dwFlags,
|
|
m_rgPropInfoSets[iSet].rgPropertyInfos[iInfo].dwFlags);
|
|
}
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
FreeProperties(&cPropInfoSets, &rgPropInfoSets, &pwszStringBuffer);
|
|
return tTestResult;
|
|
} //testGetPropInfo
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
//@mfunc Get property Info for all properties supported by a provider. For
|
|
//the returned properties, check the flags in the field dwFlags of
|
|
//DBPROPINFO. For a bunch of properties check if the variant type (vtType)
|
|
//of the DBPROPINFO matches that of the property.
|
|
//
|
|
TESTRESULT CQuickTest::testGetAllPropInfo(IDBProperties* pIDBProperties)
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG iSet=0, iInfo=0 ;
|
|
ULONG cPropInfoSets = 0;
|
|
DBPROPINFO* pPropInfo = NULL;
|
|
DBPROPINFOSET * rgPropInfoSets = NULL;
|
|
WCHAR* pwszStringBuffer = NULL;
|
|
|
|
if(pIDBProperties == NULL)
|
|
{
|
|
odtLog<<L"IDBProperties pointer is NULL.\n";
|
|
return TEST_FAIL;
|
|
}
|
|
|
|
//IDBProperties::GetPropertyInfo(0,NULL)
|
|
TESTC_(hr=pIDBProperties->GetPropertyInfo(0, NULL, &cPropInfoSets,
|
|
&rgPropInfoSets, &pwszStringBuffer), S_OK)
|
|
|
|
//At least CANHOLDROWS has to be supported.
|
|
TESTC((cPropInfoSets!=0) && (rgPropInfoSets!=NULL))
|
|
|
|
//for all property info sets...
|
|
for(iSet=0; iSet<cPropInfoSets; iSet++)
|
|
{
|
|
//If property belongs to the Data Source Information group.
|
|
if(rgPropInfoSets[iSet].guidPropertySet==DBPROPSET_DATASOURCEINFO)
|
|
{
|
|
for(iInfo=0; iInfo<rgPropInfoSets[iSet].cPropertyInfos; iInfo++)
|
|
{
|
|
pPropInfo = &(rgPropInfoSets[iSet].rgPropertyInfos[iInfo]);
|
|
|
|
// Check flag field of DBPROPINFO struct.
|
|
COMPARE((pPropInfo->dwFlags & DBPROPFLAGS_DATASOURCEINFO),
|
|
DBPROPFLAGS_DATASOURCEINFO);
|
|
|
|
//Verify description exists.
|
|
COMPARE((wcslen(pPropInfo->pwszDescription)>0),TRUE);
|
|
|
|
//Check if the variant type in DBPROPINFO matches that of
|
|
//the property.
|
|
switch(pPropInfo->dwPropertyID)
|
|
{
|
|
case DBPROP_ACTIVESESSIONS:
|
|
case DBPROP_CATALOGLOCATION:
|
|
case DBPROP_COLUMNDEFINITION:
|
|
case DBPROP_IDENTIFIERCASE:
|
|
case DBPROP_MAXROWSIZE:
|
|
case DBPROP_MAXTABLESINSELECT:
|
|
case DBPROP_QUOTEDIDENTIFIERCASE:
|
|
case DBPROP_SQLSUPPORT:
|
|
COMPARE(VT_I4, pPropInfo->vtType);
|
|
break;
|
|
|
|
case DBPROP_DATASOURCENAME:
|
|
case DBPROP_DBMSNAME:
|
|
case DBPROP_DBMSVER:
|
|
case DBPROP_PROVIDERNAME:
|
|
case DBPROP_USERNAME:
|
|
COMPARE(VT_BSTR, pPropInfo->vtType);
|
|
break;
|
|
|
|
case DBPROP_DATASOURCEREADONLY:
|
|
case DBPROP_ROWSETCONVERSIONSONCOMMAND:
|
|
COMPARE(VT_BOOL, pPropInfo->vtType);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//If property belongs to the Data Source Initialization group.
|
|
else if(rgPropInfoSets[iSet].guidPropertySet==DBPROPSET_DBINIT)
|
|
{
|
|
for(iInfo=0; iInfo<rgPropInfoSets[iSet].cPropertyInfos; iInfo++)
|
|
{
|
|
pPropInfo = &(rgPropInfoSets[iSet].rgPropertyInfos[iInfo]);
|
|
|
|
// Check flag field of DBPROPINFO struct.
|
|
COMPARE((pPropInfo->dwFlags & DBPROPFLAGS_DBINIT) ,
|
|
DBPROPFLAGS_DBINIT);
|
|
|
|
//Verify description exists.
|
|
COMPARE((wcslen(pPropInfo->pwszDescription)>0),TRUE);
|
|
|
|
//Check if the variant type in DBPROPINFO matches that of
|
|
//the property.
|
|
switch(pPropInfo->dwPropertyID)
|
|
{
|
|
case DBPROP_AUTH_PASSWORD:
|
|
case DBPROP_AUTH_USERID:
|
|
case DBPROP_INIT_DATASOURCE:
|
|
case DBPROP_INIT_LOCATION:
|
|
case DBPROP_INIT_PROVIDERSTRING:
|
|
COMPARE(VT_BSTR, pPropInfo->vtType);
|
|
break;
|
|
|
|
case DBPROP_INIT_LCID:
|
|
case DBPROP_INIT_MODE:
|
|
case DBPROP_INIT_TIMEOUT:
|
|
COMPARE(VT_I4, pPropInfo->vtType);
|
|
break;
|
|
|
|
case DBPROP_INIT_PROMPT:
|
|
COMPARE(VT_I2, pPropInfo->vtType);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//for other property groups (and provider specific groups)
|
|
else
|
|
{
|
|
for(iInfo=0; iInfo<rgPropInfoSets[iSet].cPropertyInfos; iInfo++)
|
|
COMPARE((wcslen(rgPropInfoSets[iSet].rgPropertyInfos[iInfo].pwszDescription)>0),TRUE);
|
|
}
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
FreeProperties(&cPropInfoSets, &rgPropInfoSets, &pwszStringBuffer);
|
|
return tTestResult;
|
|
} //testGetAllPropInfo
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Set the property DBPROP_INIT_PROMPT to DBPROMPT_NOPROMPT and
|
|
//DBPROP_INIT_ASYNCH to 0. Then call GetProperty to verify.
|
|
//
|
|
TESTRESULT CQuickTest::testSetProperties1()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG ulSupported = 0;
|
|
SHORT sPrompt = DBPROMPT_NOPROMPT;
|
|
LONG lAsynch = 0;
|
|
ULONG cPropSetsEx=0;
|
|
DBPROPSET* rgPropSetsEx = NULL;
|
|
IDBInitialize* pIDBInitialize = NULL;
|
|
IDBProperties* pIDBProperties = NULL;
|
|
|
|
//Initialize the variant to pass as an [OUT] parameter to GetProperty.
|
|
VARIANT vVar;
|
|
VariantInit(&vVar);
|
|
VARIANT vVar2;
|
|
VariantInit(&vVar2);
|
|
|
|
//Create a new DSO.
|
|
TESTC_(hr = GetModInfo()->CreateProvider(NULL, IID_IDBInitialize,
|
|
(IUnknown**)&pIDBInitialize), S_OK)
|
|
if(pIDBInitialize==NULL)
|
|
{
|
|
odtLog<<L"INFO: Could not create another DSO.\n";
|
|
return TEST_FAIL;
|
|
}
|
|
|
|
//Used in the Extralib property functions.
|
|
g_pIDBInitialize = pIDBInitialize;
|
|
|
|
//Obtain the IDBProperties interface.
|
|
if(!VerifyInterface(pIDBInitialize, IID_IDBProperties,
|
|
DATASOURCE_INTERFACE, (IUnknown**)&pIDBProperties))
|
|
goto CLEANUP;
|
|
|
|
//Get the initialization properties, and set them.
|
|
GetInitProps(&cPropSetsEx, &rgPropSetsEx);
|
|
TESTC_(hr = pIDBProperties->SetProperties(cPropSetsEx, rgPropSetsEx),
|
|
S_OK)
|
|
|
|
//Set the 2 properties.
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
SetProperty(DBPROP_INIT_PROMPT, DBPROPSET_DBINIT,
|
|
&m_cPropSets, &m_rgPropSets,
|
|
(void*)sPrompt, DBTYPE_I2);
|
|
SetProperty(DBPROP_INIT_ASYNCH, DBPROPSET_DBINIT,
|
|
&m_cPropSets, &m_rgPropSets,
|
|
(void*)(LONG_PTR)lAsynch, DBTYPE_I4); //cast modified
|
|
|
|
//Call SetProperties method.
|
|
hr = pIDBProperties->SetProperties(m_cPropSets, m_rgPropSets);
|
|
|
|
//check status.
|
|
if(hr==S_OK)
|
|
{
|
|
//Status should be OK for both properties.
|
|
COMPARE(m_rgPropSets[0].rgProperties[0].dwStatus,
|
|
DBPROPSTATUS_OK);
|
|
|
|
COMPARE(m_rgPropSets[0].rgProperties[1].dwStatus,
|
|
DBPROPSTATUS_OK);
|
|
}
|
|
else if(hr==DB_S_ERRORSOCCURRED)
|
|
{
|
|
//If the status was not OK, then make sure the property was
|
|
//not supported or settable.
|
|
if(m_rgPropSets[0].rgProperties[0].dwStatus != DBPROPSTATUS_OK)
|
|
{
|
|
COMPARE(SettableProperty(DBPROP_INIT_PROMPT,
|
|
DBPROPSET_DBINIT), FALSE);
|
|
}
|
|
else
|
|
{
|
|
ulSupported++;
|
|
}
|
|
|
|
if(m_rgPropSets[0].rgProperties[1].dwStatus != DBPROPSTATUS_OK)
|
|
{
|
|
COMPARE(SettableProperty(DBPROP_INIT_ASYNCH,
|
|
DBPROPSET_DBINIT), FALSE);
|
|
}
|
|
else
|
|
{
|
|
ulSupported++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Both properties were not supported or settable.
|
|
TESTC_(hr, DB_E_ERRORSOCCURRED)
|
|
|
|
COMPARE(SettableProperty(DBPROP_INIT_PROMPT,
|
|
DBPROPSET_DBINIT), FALSE);
|
|
|
|
COMPARE(SettableProperty(DBPROP_INIT_ASYNCH,
|
|
DBPROPSET_DBINIT), FALSE);
|
|
|
|
odtLog<<L"INFO: None of the properties used (DBPROP_INIT_PROMPT & DBPROP_INIT_ASYNCH) were supported or settable.\n";
|
|
}
|
|
|
|
if(hr==DB_S_ERRORSOCCURRED)
|
|
COMPARE(ulSupported, 1);
|
|
|
|
if(m_rgPropSets[0].rgProperties[0].dwStatus == DBPROPSTATUS_OK)
|
|
{
|
|
//Call GetProperty to get the variant value of DBPROP_INIT_PROMPT.
|
|
TESTC(GetProperty(DBPROP_INIT_PROMPT,DBPROPSET_DBINIT,
|
|
(IUnknown*)pIDBInitialize, &vVar))
|
|
|
|
//Compare the variant value got by above call to GetProperty and the
|
|
//one created (pVar) to pass in to SetProperty.
|
|
COMPARE(V_VT(&vVar), DBTYPE_I2);
|
|
COMPARE(V_I2(&vVar), DBPROMPT_NOPROMPT);
|
|
}
|
|
|
|
if(m_rgPropSets[0].rgProperties[1].dwStatus == DBPROPSTATUS_OK)
|
|
{
|
|
//Call GetProperty to get the variant value of DBPROP_INIT_ASYNCH.
|
|
TESTC(GetProperty(DBPROP_INIT_ASYNCH,DBPROPSET_DBINIT,
|
|
(IUnknown*)pIDBInitialize, &vVar2))
|
|
|
|
//Compare the variant value got by above call to GetProperty and the
|
|
//one created (pVar) to pass in to SetProperty.
|
|
COMPARE(V_VT(&vVar2), DBTYPE_I4);
|
|
COMPARE(V_I4(&vVar2), 0);
|
|
}
|
|
|
|
//Initialize the DSO.
|
|
CHECK(hr = pIDBInitialize->Initialize(), S_OK);
|
|
if(hr != S_OK)
|
|
goto CLEANUP;
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
VariantClear(&vVar);
|
|
VariantClear(&vVar2);
|
|
FreeProperties(&cPropSetsEx, &rgPropSetsEx);
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
//Release the DSO.
|
|
SAFE_RELEASE(pIDBProperties);
|
|
SAFE_RELEASE(pIDBInitialize);
|
|
return tTestResult;
|
|
} //testSetProperties1
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
//@mfunc Set the variant of properties DBPROP_INIT_PROMPT and
|
|
//DBPROP_INIT_ASYNCH to VT_EMPTY. When SetProperties is called,
|
|
//these should be set to their default values. Call GetProperty to
|
|
//verify.
|
|
//
|
|
TESTRESULT CQuickTest::testSetProperties2()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL; //Test Return Value
|
|
HRESULT hr = S_OK;
|
|
ULONG ulSupported = 0;
|
|
ULONG cPropSets = 1;
|
|
DBPROPSET rgPropSets[1];
|
|
ULONG cPropSetsEx=0;
|
|
DBPROPSET* rgPropSetsEx = NULL;
|
|
DBPROP dwProp[2];
|
|
IDBInitialize* pIDBInitialize = NULL;
|
|
IDBProperties* pIDBProperties = NULL;
|
|
|
|
//Initialize the variant to pass as an [OUT] parameter to GetProperty.
|
|
VARIANT vVar;
|
|
VariantInit(&vVar);
|
|
VARIANT vVar2;
|
|
VariantInit(&vVar2);
|
|
|
|
//Create a new DSO.
|
|
TESTC_(hr = GetModInfo()->CreateProvider(NULL, IID_IDBInitialize,
|
|
(IUnknown**)&pIDBInitialize), S_OK)
|
|
if(pIDBInitialize==NULL)
|
|
{
|
|
odtLog<<L"INFO: Could not create another DSO.\n";
|
|
return TEST_FAIL;
|
|
}
|
|
|
|
//Used in the Extralib property functions.
|
|
g_pIDBInitialize = pIDBInitialize;
|
|
|
|
//Obtain the IDBProperties interface.
|
|
if(!VerifyInterface(pIDBInitialize, IID_IDBProperties,
|
|
DATASOURCE_INTERFACE, (IUnknown**)&pIDBProperties))
|
|
goto CLEANUP;
|
|
|
|
//Get the initialization properties, and set them.
|
|
GetInitProps(&cPropSetsEx, &rgPropSetsEx);
|
|
TESTC_(hr = pIDBProperties->SetProperties(cPropSetsEx, rgPropSetsEx),
|
|
S_OK)
|
|
|
|
//Set DBPROP for PROMPT.
|
|
memset(&dwProp[0], 0, sizeof(DBPROP)) ;
|
|
dwProp[0].dwPropertyID = DBPROP_INIT_PROMPT;
|
|
dwProp[0].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
VariantInit(&dwProp[0].vValue);
|
|
|
|
//Set DBPROP for ASYNCH.
|
|
memset(&dwProp[1], 0, sizeof(DBPROP)) ;
|
|
dwProp[1].dwPropertyID = DBPROP_INIT_ASYNCH;
|
|
dwProp[1].dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
VariantInit(&dwProp[1].vValue);
|
|
|
|
//Set the DBPROPSET.
|
|
rgPropSets[0].rgProperties = dwProp;
|
|
rgPropSets[0].cProperties = 2;
|
|
rgPropSets[0].guidPropertySet = DBPROPSET_DBINIT;
|
|
|
|
//Call SetProperties method.
|
|
hr = pIDBProperties->SetProperties(cPropSets, rgPropSets);
|
|
|
|
//check status.
|
|
if(hr==S_OK)
|
|
{
|
|
//status should be OK for both props.
|
|
COMPARE(rgPropSets[0].rgProperties[0].dwStatus,
|
|
DBPROPSTATUS_OK);
|
|
|
|
COMPARE(rgPropSets[0].rgProperties[1].dwStatus,
|
|
DBPROPSTATUS_OK);
|
|
}
|
|
else if(hr==DB_S_ERRORSOCCURRED)
|
|
{
|
|
//if status is not OK, then make sure the property was not
|
|
//supported or settable.
|
|
if(rgPropSets[0].rgProperties[0].dwStatus != DBPROPSTATUS_OK)
|
|
{
|
|
COMPARE(SettableProperty(DBPROP_INIT_PROMPT,
|
|
DBPROPSET_DBINIT), FALSE);
|
|
}
|
|
else
|
|
{
|
|
ulSupported++;
|
|
}
|
|
|
|
if(rgPropSets[0].rgProperties[1].dwStatus != DBPROPSTATUS_OK)
|
|
{
|
|
COMPARE(SettableProperty(DBPROP_INIT_ASYNCH,
|
|
DBPROPSET_DBINIT), FALSE);
|
|
}
|
|
else
|
|
{
|
|
ulSupported++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Both properties were not supported or settable.
|
|
TESTC_(hr, DB_E_ERRORSOCCURRED)
|
|
|
|
COMPARE(SettableProperty(DBPROP_INIT_PROMPT,
|
|
DBPROPSET_DBINIT), FALSE);
|
|
|
|
COMPARE(SettableProperty(DBPROP_INIT_ASYNCH,
|
|
DBPROPSET_DBINIT), FALSE);
|
|
|
|
odtLog<<L"INFO: None of the properties used (DBPROP_INIT_PROMPT & DBPROP_INIT_ASYNCH) were supported or settable.\n";
|
|
}
|
|
|
|
if(hr==DB_S_ERRORSOCCURRED)
|
|
COMPARE(ulSupported, 1);
|
|
|
|
if(rgPropSets[0].rgProperties[0].dwStatus == DBPROPSTATUS_OK)
|
|
{
|
|
//Call GetProperty to get the variant value of DBPROP_INIT_PROMPT.
|
|
TESTC(GetProperty(DBPROP_INIT_PROMPT,DBPROPSET_DBINIT,
|
|
(IUnknown*)pIDBInitialize, &vVar))
|
|
|
|
//The variant should be set to its default value, which will be
|
|
//one of the following.
|
|
COMPARE(V_VT(&vVar) , DBTYPE_I2);
|
|
|
|
COMPARE((V_I2(&vVar) == DBPROMPT_PROMPT) ||
|
|
(V_I2(&vVar) == DBPROMPT_COMPLETE) ||
|
|
(V_I2(&vVar) == DBPROMPT_COMPLETEREQUIRED) ||
|
|
(V_I2(&vVar) == DBPROMPT_NOPROMPT), TRUE);
|
|
}
|
|
|
|
if(rgPropSets[0].rgProperties[1].dwStatus == DBPROPSTATUS_OK)
|
|
{
|
|
//Call GetProperty to get the variant value of DBPROP_INIT_ASYNCH.
|
|
TESTC(GetProperty(DBPROP_INIT_ASYNCH,DBPROPSET_DBINIT,
|
|
(IUnknown*)pIDBInitialize, &vVar2))
|
|
|
|
COMPARE(V_VT(&vVar2) , DBTYPE_I4);
|
|
|
|
//The variant should be set to its default value.
|
|
COMPARE(V_I4(&vVar2) >= 0 , TRUE);
|
|
}
|
|
|
|
//Initialize the DSO.
|
|
CHECK(hr = pIDBInitialize->Initialize(), S_OK);
|
|
if(hr != S_OK)
|
|
goto CLEANUP;
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
VariantClear(&vVar);
|
|
VariantClear(&vVar2);
|
|
FreeProperties(&cPropSetsEx, &rgPropSetsEx);
|
|
//Release the DSO.
|
|
SAFE_RELEASE(pIDBProperties);
|
|
SAFE_RELEASE(pIDBInitialize);
|
|
return tTestResult;
|
|
} //testSetProperties2
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Test the GetProperties and GetPropertyInfo methods when the DSO
|
|
//is in Uninitialized state.
|
|
//
|
|
TESTRESULT CQuickTest::testGetPropBeforeInit()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
IDBProperties* pIDBProp = NULL;
|
|
|
|
//Create a new DSO.
|
|
TESTC_(hr = GetModInfo()->CreateProvider(NULL, IID_IDBProperties,
|
|
(IUnknown**)&pIDBProp), S_OK)
|
|
|
|
if(pIDBProp==NULL)
|
|
{
|
|
odtLog<<L"INFO: Could not create another DSO.\n";
|
|
return TEST_FAIL;
|
|
}
|
|
|
|
//Conduct Property Tests while DSO is uninitialized.
|
|
TESTC(testGetAllProperties(pIDBProp)==TEST_PASS)
|
|
|
|
TESTC(testGetAllPropInfo(pIDBProp)==TEST_PASS)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIDBProp);
|
|
return tTestResult;
|
|
} //testGetPropBeforeInit
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Get a comma-separated list of provider-specific keywords. Make
|
|
//sure the list does not contain any keywords from OLE DB.
|
|
//
|
|
TESTRESULT CQuickTest::testGetKeywords()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG i = 0;
|
|
WCHAR* pwszKeywords = NULL;
|
|
WCHAR* wtoken = NULL;
|
|
IDBInfo* pIDBInfo = NULL;
|
|
|
|
//Get pointer to IDBInfo.
|
|
if(!VerifyInterface(m_pIDBInitialize,IID_IDBInfo,
|
|
DATASOURCE_INTERFACE,(IUnknown**)&pIDBInfo))
|
|
{
|
|
odtLog<<L"IDBInfo is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
//Call GetKeywords method.
|
|
TESTC_(hr=pIDBInfo->GetKeywords(&pwszKeywords), S_OK)
|
|
|
|
if(!pwszKeywords)
|
|
{
|
|
//Issue a warning.
|
|
odtLog<<L"The Provider returned no Keywords.\n" ;
|
|
COMPAREW(pwszKeywords!=NULL, TRUE);
|
|
tTestResult = TEST_PASS;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// Find the first keyword and loop thru all the Keywords
|
|
wtoken = wcstok(pwszKeywords, L",");
|
|
|
|
//If pwszKeywords is an empty string, FAIL test.
|
|
if(!wtoken)
|
|
{
|
|
odtLog<<L"The Provider should have returned a NULL instead of <EMPTY> for pwszKeywords." <<L"\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// Loop thru all the Keywords
|
|
while(wtoken)
|
|
{
|
|
// Static Keywords should not be in the list.
|
|
for( i=0; i < (sizeof(g_rgpwszKeywords)/sizeof(g_rgpwszKeywords[0])); i++)
|
|
{
|
|
if(!(_wcsicmp(g_rgpwszKeywords[i], wtoken)))
|
|
{
|
|
odtLog<<ENDL <<g_rgpwszKeywords[i]
|
|
<<L" should not be returned in the list." <<ENDL;
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
//Get the next keyword
|
|
wtoken = wcstok(NULL, L",");
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pwszKeywords);
|
|
SAFE_RELEASE(pIDBInfo);
|
|
return tTestResult;
|
|
} //testGetKeywords
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Get the Literal information through IDBInfo and verify it.
|
|
//
|
|
TESTRESULT CQuickTest::testGetLiteralInfo()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG cErrors = 0;
|
|
ULONG ulIndex=0;
|
|
ULONG ulSupported = 0;
|
|
ULONG cLiteralInfo = 0;
|
|
DBLITERALINFO* rgLiteralInfo = NULL;
|
|
WCHAR* pCharBuffer = NULL;
|
|
IDBInfo* pIDBInfo = NULL;
|
|
|
|
if(!VerifyInterface(m_pIDBInitialize,IID_IDBInfo,
|
|
DATASOURCE_INTERFACE,(IUnknown**)&pIDBInfo))
|
|
{
|
|
odtLog<<L"IDBInfo is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
//Get information about ALL supported literals.
|
|
TESTC_(hr=pIDBInfo->GetLiteralInfo(0, NULL, &cLiteralInfo,
|
|
&rgLiteralInfo, &pCharBuffer), S_OK)
|
|
|
|
if((cLiteralInfo==0) && (rgLiteralInfo==NULL))
|
|
{
|
|
//Issue a warning.
|
|
odtLog<<L"WARNING:No literals are supported by this provider.\n";
|
|
COMPAREW(cLiteralInfo > 0, TRUE);
|
|
tTestResult = TEST_PASS;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC((cLiteralInfo !=0) && (rgLiteralInfo !=NULL))
|
|
|
|
// Count the supported Literals
|
|
for(ulIndex=0; ulIndex < cLiteralInfo; ulIndex++)
|
|
if(rgLiteralInfo[ulIndex].fSupported)
|
|
ulSupported++;
|
|
|
|
//All the fSupported flags should have been TRUE.
|
|
COMPARE(cLiteralInfo, ulSupported);
|
|
|
|
// Check the pCharBuffer
|
|
COMPARE(!pCharBuffer, NULL);
|
|
|
|
// Check the Data returned
|
|
for(ulIndex=0; ulIndex < cLiteralInfo; ulIndex++)
|
|
{
|
|
// These are the only 8 that should modify pwszLiteralValue and cchMaxLen,
|
|
// and not modify pwszInvalidChar and pwszInvalidStartingChar.
|
|
if( (rgLiteralInfo[ulIndex].lt == DBLITERAL_CATALOG_SEPARATOR) ||
|
|
(rgLiteralInfo[ulIndex].lt == DBLITERAL_ESCAPE_PERCENT_PREFIX)||
|
|
(rgLiteralInfo[ulIndex].lt == DBLITERAL_ESCAPE_PERCENT_SUFFIX)||
|
|
(rgLiteralInfo[ulIndex].lt == DBLITERAL_ESCAPE_UNDERSCORE_PREFIX)||
|
|
(rgLiteralInfo[ulIndex].lt == DBLITERAL_ESCAPE_UNDERSCORE_SUFFIX)||
|
|
(rgLiteralInfo[ulIndex].lt == DBLITERAL_LIKE_PERCENT) ||
|
|
(rgLiteralInfo[ulIndex].lt == DBLITERAL_LIKE_UNDERSCORE) ||
|
|
(rgLiteralInfo[ulIndex].lt == DBLITERAL_QUOTE_PREFIX) ||
|
|
(rgLiteralInfo[ulIndex].lt == DBLITERAL_QUOTE_SUFFIX) ||
|
|
(rgLiteralInfo[ulIndex].lt == DBLITERAL_SCHEMA_SEPARATOR) )
|
|
{
|
|
// Check pwszLiteralValue exceptions
|
|
if(!rgLiteralInfo[ulIndex].pwszLiteralValue)
|
|
{
|
|
odtLog<<L"ERROR: "<<g_rgpwszLiterals[rgLiteralInfo[ulIndex].lt]
|
|
<<L" should not be NULL."<<"\n";
|
|
cErrors++;
|
|
}
|
|
|
|
// Check pwszInvalidChar exceptions
|
|
if(rgLiteralInfo[ulIndex].pwszInvalidChars)
|
|
{
|
|
odtLog<<L"ERROR: "<<g_rgpwszLiterals[rgLiteralInfo[ulIndex].lt]
|
|
<<L" should be NULL."<<"\n";
|
|
cErrors++;
|
|
}
|
|
|
|
// Check pwszInvalidStartingChar exceptions
|
|
if(rgLiteralInfo[ulIndex].pwszInvalidStartingChars)
|
|
{
|
|
odtLog<<L"ERROR: "<<g_rgpwszLiterals[rgLiteralInfo[ulIndex].lt]
|
|
<<L" should be NULL."<<"\n";
|
|
cErrors++;
|
|
}
|
|
|
|
// Check cchMaxLen exceptions
|
|
if( (rgLiteralInfo[ulIndex].pwszLiteralValue) &&
|
|
(rgLiteralInfo[ulIndex].cchMaxLen != wcslen(rgLiteralInfo[ulIndex].pwszLiteralValue)))
|
|
{
|
|
odtLog<<L"ERROR: "<<g_rgpwszLiterals[rgLiteralInfo[ulIndex].lt]
|
|
<<L" expect " <<rgLiteralInfo[ulIndex].cchMaxLen
|
|
<<L" but returned "<< wcslen(rgLiteralInfo[ulIndex].pwszLiteralValue)
|
|
<<L" character(s)."<<"\n";
|
|
cErrors++;
|
|
}
|
|
}
|
|
else if(rgLiteralInfo[ulIndex].pwszLiteralValue)
|
|
{
|
|
odtLog<<L"ERROR: "<<g_rgpwszLiterals[rgLiteralInfo[ulIndex].lt]
|
|
<<L" should be NULL."<<"\n";
|
|
cErrors++;
|
|
}
|
|
}
|
|
|
|
TESTC(cErrors == 0)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pCharBuffer);
|
|
PROVIDER_FREE(rgLiteralInfo);
|
|
SAFE_RELEASE(pIDBInfo);
|
|
return tTestResult;
|
|
} //testGetLiteralInfo
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Get a sources rowset and verify its columns and rows..
|
|
//
|
|
TESTRESULT CQuickTest::testISrcRowset()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
USHORT usBkmExists = 0; // 0=FALSE, 1=TRUE.
|
|
USHORT cCol = 0;
|
|
DBORDINAL cColumns = 0;
|
|
DBCOLUMNINFO* rgInfo = NULL;
|
|
WCHAR* pStringsBuffer = NULL;
|
|
CLSID clsid = CLSID_OLEDB_ENUMERATOR;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
DBBINDING* rgBindings = NULL;
|
|
BYTE* pData = NULL;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW* rghRows = NULL;
|
|
WCHAR* pwszSourceParseName = NULL;
|
|
USHORT usSourceType = 0;
|
|
DBCOUNTITEM cTotalRows = 0;
|
|
IRowset* pIRowset = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
IColumnsInfo* pICI = NULL;
|
|
ISourcesRowset* pISR = NULL;
|
|
|
|
|
|
//Create an enumerator Object.
|
|
hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_ISourcesRowset,(void **)&pISR) ;
|
|
|
|
if(hr != S_OK)
|
|
{
|
|
TESTC(!pISR)
|
|
odtLog<<L"Could not create enumerator object.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
TESTC(pISR != NULL)
|
|
|
|
//Open Sources Rowset and obtain IColumnsInfo.
|
|
TESTC_(hr = pISR->GetSourcesRowset(NULL, IID_IColumnsInfo,
|
|
0, NULL, (IUnknown **) &pICI), S_OK)
|
|
|
|
TESTC(VerifyInterface(pICI,IID_IRowset,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRowset))
|
|
|
|
TESTC(VerifyInterface(pICI,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
TESTC_(pICI->GetColumnInfo(&cColumns, &rgInfo,
|
|
&pStringsBuffer), S_OK)
|
|
|
|
// Check to see if the Bookmark Property is on
|
|
if (rgInfo[0].iOrdinal == 0)
|
|
{
|
|
COMPARE(GetProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET,
|
|
pICI), TRUE);
|
|
usBkmExists = 1;
|
|
}
|
|
|
|
//Skip bookmark column, check each column info.
|
|
//For each column check the position, column name and type.
|
|
for(cCol=0; cCol<cColumns; cCol++)
|
|
{
|
|
switch(rgInfo[cCol].iOrdinal)
|
|
{
|
|
case 0:
|
|
//Bookmark Column. Do nothing.
|
|
break;
|
|
case 1:
|
|
COMPARE(cCol, 0+usBkmExists);
|
|
COMPARE(wcscmp(rgInfo[cCol].pwszName, L"SOURCES_NAME"),0);
|
|
COMPARE(rgInfo[cCol].wType, DBTYPE_WSTR);
|
|
break;
|
|
case 2:
|
|
COMPARE(cCol, 1+usBkmExists);
|
|
COMPARE(wcscmp(rgInfo[cCol].pwszName, L"SOURCES_PARSENAME"),0);
|
|
COMPARE(rgInfo[cCol].wType, DBTYPE_WSTR);
|
|
break;
|
|
case 3:
|
|
COMPARE(cCol, 2+usBkmExists);
|
|
COMPARE(wcscmp(rgInfo[cCol].pwszName, L"SOURCES_DESCRIPTION"),0);
|
|
COMPARE(rgInfo[cCol].wType, DBTYPE_WSTR);
|
|
break;
|
|
case 4:
|
|
COMPARE(cCol, 3+usBkmExists);
|
|
COMPARE(wcscmp(rgInfo[cCol].pwszName, L"SOURCES_TYPE"),0);
|
|
COMPARE(rgInfo[cCol].wType, DBTYPE_UI2);
|
|
break;
|
|
case 5:
|
|
COMPARE(cCol, 4+usBkmExists);
|
|
COMPARE(wcscmp(rgInfo[cCol].pwszName, L"SOURCES_ISPARENT"),0);
|
|
COMPARE(rgInfo[cCol].wType, DBTYPE_BOOL);
|
|
break;
|
|
default:
|
|
break;
|
|
}//switch
|
|
}
|
|
|
|
//Create an accessor on the sources rowset and make bindings
|
|
TESTC_(GetAccessorAndBindings(pIAccessor,DBACCESSOR_ROWDATA,&hAccessor,
|
|
&rgBindings,&cBindings,&cbRowSize,
|
|
DBPART_VALUE|DBPART_STATUS|DBPART_LENGTH,
|
|
ALL_COLS_EXCEPTBOOKMARK,FORWARD,NO_COLS_BY_REF,NULL,NULL,
|
|
NULL,DBTYPE_EMPTY,0,NULL,NULL,
|
|
NO_COLS_OWNED_BY_PROV,DBPARAMIO_NOTPARAM,NO_BLOB_COLS),S_OK)
|
|
|
|
// Allocate memory for the row data.
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize);
|
|
|
|
// Loop over the rows and get data.
|
|
while(GetNextRows(pIRowset, NULL,0,1,&cRowsObtained,&rghRows) == S_OK)
|
|
{
|
|
//Clear pData.
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
|
|
// Get the next row
|
|
TESTC_(hr=pIRowset->GetData(rghRows[0],hAccessor,pData), S_OK)
|
|
|
|
cTotalRows++;
|
|
|
|
//Get name, description and type of the source.
|
|
pwszSourceParseName = (WCHAR*)(pData + rgBindings[1].obValue) ;
|
|
usSourceType = *(USHORT*)(pData + rgBindings[3].obValue) ;
|
|
|
|
TESTC(wcslen(pwszSourceParseName) > 0)
|
|
|
|
TESTC(usSourceType==DBSOURCETYPE_DATASOURCE ||
|
|
usSourceType==DBSOURCETYPE_ENUMERATOR ||
|
|
usSourceType==DBSOURCETYPE_DATASOURCE_TDP ||
|
|
usSourceType==DBSOURCETYPE_DATASOURCE_MDP )
|
|
|
|
//Release the row handle
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData);
|
|
}//while ends.
|
|
|
|
odtLog<<L"INFO: Total rows in Sources Rowset = "<<cTotalRows<<"\n" ;
|
|
|
|
TESTC(cTotalRows >= 1)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(pData);
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
PROVIDER_FREE(rgInfo);
|
|
PROVIDER_FREE(pStringsBuffer);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pICI);
|
|
SAFE_RELEASE(pISR);
|
|
return tTestResult;
|
|
} //testISrcRowset
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Create a data source object using IDataInitialize::CreateDBInstance
|
|
//and verify it.
|
|
//
|
|
TESTRESULT CQuickTest::testIDataIzCreateDBIns()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
CLSID clsidProv, clsid;
|
|
ULONG cPropInfoSets = 0;
|
|
DBPROPINFOSET* rgPropInfoSets = NULL;
|
|
IDataInitialize* pIDI = NULL;
|
|
IDBInitialize* pIDBI = NULL;
|
|
IDBProperties* pIDBProperties = NULL;
|
|
IPersist* pIPersist = NULL;
|
|
|
|
hr = CoCreateInstance(CLSID_MSDAINITIALIZE, NULL,
|
|
CLSCTX_INPROC_SERVER, IID_IDataInitialize,
|
|
(void**)&pIDI) ;
|
|
|
|
if(hr != S_OK)
|
|
{
|
|
TESTC(!pIDI)
|
|
odtLog<<L"Could not create the DataInitialize object.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
TESTC(pIDI != NULL)
|
|
|
|
TESTC(VerifyOutputInterface(S_OK, IID_IDataInitialize,
|
|
(IUnknown**)&pIDI))
|
|
|
|
clsidProv = GetModInfo()->GetThisTestModule()->m_ProviderClsid ;
|
|
|
|
//Create the DSO. Request IDBInitialize.
|
|
TESTC_(hr = pIDI->CreateDBInstance(clsidProv, NULL,
|
|
CLSCTX_INPROC_SERVER, NULL, IID_IDBInitialize,
|
|
(IUnknown**)&pIDBI), S_OK)
|
|
|
|
TESTC(pIDBI != NULL)
|
|
|
|
//Get IDBProperties.
|
|
TESTC(VerifyInterface(pIDBI,IID_IDBProperties,
|
|
DATASOURCE_INTERFACE,(IUnknown**)&pIDBProperties))
|
|
|
|
TESTC(pIDBProperties != NULL)
|
|
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
|
|
//Obtain Required Init Properties (from the Init String)
|
|
TESTC(GetModInfo()->GetInitProps(&m_cPropSets, &m_rgPropSets))
|
|
|
|
//Set the Init properties.
|
|
TESTC_(hr = pIDBProperties->SetProperties(m_cPropSets, m_rgPropSets),
|
|
S_OK)
|
|
|
|
//Initialize the DSO.
|
|
TESTC_(hr = pIDBI->Initialize(), S_OK)
|
|
|
|
//GetPropertyInfo.
|
|
TESTC_(hr = pIDBProperties->GetPropertyInfo(0, NULL, &cPropInfoSets,
|
|
&rgPropInfoSets, NULL), S_OK)
|
|
|
|
if(cPropInfoSets == 0 && rgPropInfoSets == NULL)
|
|
{
|
|
odtLog<<L"No PropertyInfo sets were returned.\n";
|
|
COMPAREW(cPropInfoSets, 1);
|
|
}
|
|
else
|
|
{
|
|
TESTC(cPropInfoSets > 0 && rgPropInfoSets != NULL)
|
|
}
|
|
|
|
//Create another DSO. This time request IPersist.
|
|
TESTC_(hr = pIDI->CreateDBInstance(clsidProv, NULL,
|
|
CLSCTX_INPROC_SERVER, NULL, IID_IPersist,
|
|
(IUnknown**)&pIPersist), S_OK)
|
|
|
|
TESTC(pIPersist != NULL)
|
|
|
|
//Get class ID and verify that CLSID returned is identical to
|
|
//the Provider CLSID.
|
|
TESTC_(pIPersist->GetClassID(&clsid), S_OK)
|
|
|
|
TESTC(clsid == GetModInfo()->GetThisTestModule()->m_ProviderClsid)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
FreeProperties(&cPropInfoSets, &rgPropInfoSets);
|
|
SAFE_RELEASE(pIDBI);
|
|
SAFE_RELEASE(pIDBProperties);
|
|
SAFE_RELEASE(pIPersist);
|
|
SAFE_RELEASE(pIDI);
|
|
return tTestResult;
|
|
} //testIDataIzCreateDBIns
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Construct an initialization string from the init properties and
|
|
//pass that in to IDataInitialize::GetDataSource. Check the obtained DSO.
|
|
//Then call ::GetInitializationString (requesting password) and make sure
|
|
//it contains the password.
|
|
//
|
|
TESTRESULT CQuickTest::testIDataIzGetDS()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG i, j;
|
|
CLSID clsid;
|
|
BOOL bDefault = FALSE;
|
|
DBPROPSET* pPropSet = NULL;
|
|
DBPROP* pProp = NULL;
|
|
ULONG cPropInfoSets = 0;
|
|
DBPROPINFOSET* rgPropInfoSets = NULL;
|
|
ULONG cPropSets = 0;
|
|
DBPROPSET* rgPropSets = NULL;
|
|
WCHAR* pwszProgID = NULL;
|
|
WCHAR* pwszInitStr1 = NULL;
|
|
WCHAR* pwszInitStr2 = NULL;
|
|
WCHAR* pwszInitString = NULL;
|
|
WCHAR* pwszValue = NULL;
|
|
WCHAR* pwszValue1 = NULL;
|
|
WCHAR* pwszDefPassword = NULL;
|
|
IDataInitialize* pIDI = NULL;
|
|
IDBInitialize* pIDBI = NULL;
|
|
IDBProperties* pIDBProperties = NULL;
|
|
IUnknown* pIUnknown = NULL;
|
|
|
|
hr = CoCreateInstance(CLSID_MSDAINITIALIZE, NULL,
|
|
CLSCTX_INPROC_SERVER, IID_IDataInitialize,
|
|
(void**)&pIDI) ;
|
|
|
|
if(hr != S_OK)
|
|
{
|
|
TESTC(!pIDI)
|
|
odtLog<<L"Could not create the DataInitialize object.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
TESTC(pIDI != NULL)
|
|
|
|
TESTC(VerifyOutputInterface(S_OK, IID_IDataInitialize,
|
|
(IUnknown**)&pIDI))
|
|
|
|
//Get Init props to construct the Init string.
|
|
TESTC(GetModInfo()->GetInitProps(&cPropSets, &rgPropSets))
|
|
|
|
//Required for the function SetSupportedProperty.
|
|
g_pIDBInitialize = m_pIDBInitialize ;
|
|
|
|
//Required for obtaining the Password. This will be added
|
|
//to the init string. If this property is not supported,
|
|
//then the password will be visible anyway.
|
|
SetSettableProperty(DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO,
|
|
DBPROPSET_DBINIT, &cPropSets, &rgPropSets) ;
|
|
|
|
clsid = GetModInfo()->GetThisTestModule()->m_ProviderClsid ;
|
|
|
|
TESTC_(ProgIDFromCLSID(clsid, &pwszProgID),S_OK);
|
|
|
|
//Add the provider keyword and value to Init string.
|
|
pwszInitString = CreateString(L"Provider = %s; ", pwszProgID);
|
|
|
|
//Loop through specified properties and construct the String
|
|
for(i=0; i<cPropSets; i++)
|
|
{
|
|
pPropSet = &rgPropSets[i];
|
|
for(j=0; j<pPropSet->cProperties; j++)
|
|
{
|
|
pProp = &pPropSet->rgProperties[j];
|
|
|
|
//Now Add this Property
|
|
AppendToInitString(&pwszInitString, pProp->dwPropertyID, pPropSet->guidPropertySet, &pProp->vValue);
|
|
TESTC(pwszInitString != NULL);
|
|
}
|
|
}
|
|
|
|
//If no properties, just use an empty string, since GetDataSource
|
|
//fails on NULL
|
|
AppendString(&pwszInitString, cPropSets ? L";" : L"");
|
|
|
|
|
|
|
|
TESTC(pwszInitString != NULL)
|
|
odtLog<<L"Init String: "<<pwszInitString<<L"\n";
|
|
//Create the DSO.
|
|
TESTC_(hr = pIDI->GetDataSource(NULL, CLSCTX_INPROC_SERVER,
|
|
pwszInitString, IID_IDBInitialize, (IUnknown**) &pIDBI), S_OK)
|
|
|
|
TESTC(pIDBI != NULL)
|
|
|
|
//Call Initilize().
|
|
TESTC_(hr = pIDBI->Initialize(), S_OK)
|
|
|
|
//Get IDBProperties.
|
|
TESTC(VerifyInterface(pIDBI,IID_IDBProperties,
|
|
DATASOURCE_INTERFACE,(IUnknown**)&pIDBProperties))
|
|
|
|
TESTC(pIDBProperties != NULL)
|
|
|
|
//Call GetPropertyInfo.
|
|
TESTC_(hr = pIDBProperties->GetPropertyInfo(0, NULL, &cPropInfoSets,
|
|
&rgPropInfoSets, NULL), S_OK)
|
|
|
|
//Check returned values.
|
|
if(cPropInfoSets == 0 && rgPropInfoSets == NULL)
|
|
{
|
|
COMPAREW(cPropInfoSets, 1);
|
|
odtLog<<L"No PropertyInfo sets were returned.\n";
|
|
}
|
|
else
|
|
{
|
|
TESTC(cPropInfoSets > 0 && rgPropInfoSets != NULL)
|
|
}
|
|
|
|
//Call GetInitializationString with fIncludePassword=TRUE.
|
|
TESTC_(hr = pIDI->GetInitializationString((IUnknown*)pIDBI,
|
|
TRUE, &pwszInitStr1), S_OK)
|
|
|
|
TESTC(pwszInitStr1 != NULL)
|
|
TESTC(wcslen(pwszInitStr1) > 0)
|
|
|
|
//Make sure the password is the same as the one we had used to
|
|
//create the DSO.
|
|
if(GetModInfo()->GetStringKeywordValue(pwszInitString, L"Password",
|
|
&pwszValue) && pwszValue)
|
|
{
|
|
TESTC_(GetModInfo()->CreateProvider(clsid, NULL, IID_IUnknown, &pIUnknown),S_OK);
|
|
|
|
//Verify this property is the default on the DataSource
|
|
COMPARE(GetProperty(DBPROP_AUTH_PASSWORD, DBPROPSET_DBINIT, pIUnknown, &pwszDefPassword), TRUE);
|
|
|
|
if((wcscmp(pwszValue, L"")==0) ||
|
|
(pwszDefPassword && (wcscmp(pwszDefPassword, pwszValue)==0)))
|
|
bDefault = TRUE;
|
|
|
|
if(!bDefault)
|
|
{
|
|
TESTC(GetModInfo()->GetStringKeywordValue(pwszInitStr1,
|
|
L"Password", &pwszValue1))
|
|
|
|
TESTC(wcscmp(pwszValue, pwszValue1) == 0)
|
|
}
|
|
}
|
|
|
|
//Write the Init string into a file.
|
|
TESTC_(hr = pIDI->WriteStringToStorage(L"This is a long file name for QuikTest.tst",
|
|
pwszInitStr1, CREATE_ALWAYS), S_OK)
|
|
|
|
//Load the init string from the file.
|
|
TESTC_(hr = pIDI->LoadStringFromStorage(L"This is a long file name for QuikTest.tst",
|
|
&pwszInitStr2), S_OK)
|
|
|
|
//Make sure they are the same.
|
|
TESTC(wcscmp(pwszInitStr1, pwszInitStr2) == 0)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
remove("This is a long file name for QuikTest.tst");
|
|
FreeProperties(&cPropInfoSets, &rgPropInfoSets);
|
|
FreeProperties(&cPropSets, &rgPropSets);
|
|
SAFE_FREE(pwszDefPassword);
|
|
SAFE_FREE(pwszProgID);
|
|
SAFE_FREE(pwszInitString);
|
|
SAFE_FREE(pwszInitStr1);
|
|
SAFE_FREE(pwszInitStr2);
|
|
SAFE_FREE(pwszValue);
|
|
SAFE_FREE(pwszValue1);
|
|
SAFE_RELEASE(pIDBProperties);
|
|
SAFE_RELEASE(pIUnknown);
|
|
SAFE_RELEASE(pIDBI);
|
|
SAFE_RELEASE(pIDI);
|
|
return tTestResult;
|
|
} //testIDataIzGetDS
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Use the IGetDataSource::GetDataSource method to obtain pointers
|
|
//to IDBInitialize, IDBProperties and IPersist interfaces. Verify the
|
|
//obtained interfaces. Check if the obtained IDBInitialize is the same
|
|
//the one we had used to initialize the Data Source Object. Use the
|
|
//obtained IPersist interface to get the class ID and compare it to the
|
|
//provider class ID. Use the IDBProperties to get the value of
|
|
//DBPROP_INIT_PROMPT property.
|
|
//
|
|
TESTRESULT CQuickTest::testGetDataSource()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
CLSID clsid;
|
|
IGetDataSource* pIGetDataSource = NULL;
|
|
IDBInitialize* pIDBInitialize=NULL;
|
|
IDBProperties* pIDBProperties=NULL;
|
|
IDBProperties* pIDBProp2=NULL;
|
|
IPersist* pIPersist=NULL;
|
|
|
|
VARIANT vVar;
|
|
VariantInit(&vVar);
|
|
|
|
//Obtain the IGetDataSource interface.
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_IGetDataSource,
|
|
SESSION_INTERFACE,(IUnknown **)&pIGetDataSource))
|
|
{
|
|
odtLog<<L"INFO: Could not get IGetDataSource interface.\n";
|
|
return TEST_FAIL;
|
|
}
|
|
|
|
//Use method to get IDBInitialize.
|
|
TESTC_(pIGetDataSource->GetDataSource(IID_IDBInitialize,
|
|
(IUnknown**)&pIDBInitialize), S_OK)
|
|
|
|
//The IDBInitialize obtained through this method should be the
|
|
//same as m_pIDBInitialize.
|
|
COMPARE(VerifyEqualInterface((IUnknown*)pIDBInitialize,
|
|
(IUnknown*)m_pIDBInitialize), TRUE);
|
|
|
|
//Use method to get IPersist.
|
|
TESTC_(pIGetDataSource->GetDataSource(IID_IPersist,
|
|
(IUnknown**)&pIPersist), S_OK)
|
|
|
|
//Use the obtained IPersist interface to get class ID.
|
|
//Verify that CLSID returned is identical to the Provider CLSID
|
|
CHECK(pIPersist->GetClassID(&clsid), S_OK);
|
|
COMPARE(clsid, GetModInfo()->GetThisTestModule()->m_ProviderClsid);
|
|
|
|
//Use method to get IDBProperties. Then use the obtained IDBProperties
|
|
//to get the DBPROP_INIT_PROMPT property and check its variant value.
|
|
TESTC_(pIGetDataSource->GetDataSource(IID_IDBProperties,
|
|
(IUnknown**)&pIDBProperties), S_OK)
|
|
|
|
//Obtain the IGetDataSource interface.
|
|
TESTC(VerifyInterface(m_pIDBInitialize,IID_IDBProperties,
|
|
DATASOURCE_INTERFACE,(IUnknown **)&pIDBProp2))
|
|
|
|
//Verify the interface.
|
|
COMPARE(VerifyEqualInterface(pIDBProperties, pIDBProp2), TRUE);
|
|
|
|
//Try to get the PROMPT property using the obtained IDBProperties.
|
|
if(GetProperty(DBPROP_INIT_PROMPT, DBPROPSET_DBINIT,
|
|
pIDBProperties, &vVar))
|
|
TESTC(checkPositive_I2(&vVar))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
VariantClear(&vVar);
|
|
SAFE_RELEASE(pIGetDataSource);
|
|
SAFE_RELEASE(pIDBProperties);
|
|
SAFE_RELEASE(pIDBProp2);
|
|
SAFE_RELEASE(pIPersist);
|
|
SAFE_RELEASE(pIDBInitialize);
|
|
return tTestResult;
|
|
} //testGetDataSource
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Create a table. Set two properties (BOOKMARKS, CANFETCHBACKWARDS).
|
|
//Generate a rowset on the table with these properties. Then set three
|
|
//properties (BOOKMARKS, CANSCROLLBACKWARDS, OWNUPDATEDELETE). Generate
|
|
//a second rowset on the same table, with these three properties. Verify
|
|
//the two rowsets exist and are different. Also open rowsets with each
|
|
//of the mandatory interfaces of Rowset object.
|
|
//
|
|
TESTRESULT CQuickTest::testOpenRowset()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
IRowset* pIRowset = NULL;
|
|
IRowsetInfo* pIRowsetInfo = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
IColumnsInfo* pIColumnsInfo = NULL;
|
|
IConvertType* pIConvertType = NULL;
|
|
|
|
TESTC(m_pTable != NULL)
|
|
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
|
|
//Set 2 properties.
|
|
SetSettableProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET, &m_cPropSets,
|
|
&m_rgPropSets);
|
|
SetSettableProperty(DBPROP_CANFETCHBACKWARDS, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets);
|
|
|
|
//Call OpenRowset #1
|
|
hr = CreateOpenRowset(m_pTable, IID_IRowset,(IUnknown**)&pIRowset);
|
|
CHECK(hr, S_OK);
|
|
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
|
|
//Set 3 properties
|
|
SetSettableProperty(DBPROP_OWNUPDATEDELETE, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets);
|
|
SetSettableProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets);
|
|
SetSettableProperty(DBPROP_CANSCROLLBACKWARDS, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets);
|
|
|
|
//Call OpenRowset #2
|
|
hr = CreateOpenRowset(m_pTable, IID_IRowsetInfo,(IUnknown**)
|
|
&pIRowsetInfo);
|
|
CHECK(hr, S_OK);
|
|
|
|
//Verify different rowset pointers
|
|
COMPARE(VerifyEqualInterface(pIRowset, pIRowsetInfo), FALSE);
|
|
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
|
|
//Call OpenRowset #3
|
|
hr = CreateOpenRowset(m_pTable, IID_IAccessor,(IUnknown**)
|
|
&pIAccessor);
|
|
CHECK(hr, S_OK);
|
|
|
|
//Call OpenRowset #4
|
|
hr = CreateOpenRowset(m_pTable, IID_IColumnsInfo,(IUnknown**)
|
|
&pIColumnsInfo);
|
|
CHECK(hr, S_OK);
|
|
|
|
//Call OpenRowset #5
|
|
hr = CreateOpenRowset(m_pTable, IID_IConvertType,(IUnknown**)
|
|
&pIConvertType);
|
|
CHECK(hr, S_OK);
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
SAFE_RELEASE(pIAccessor);
|
|
SAFE_RELEASE(pIColumnsInfo);
|
|
SAFE_RELEASE(pIConvertType);
|
|
return tTestResult;
|
|
} //testOpenRowset
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
//@mfunc Get the DBPROP_SESS_AUTOCOMMITISOLEVELS property by creating
|
|
//an appropriate PROPIDSET and passing it to the GetProperties method
|
|
//call. Verify the returned property and values. Then call the
|
|
//GetProperties method with (0,NULL) to get all supported session
|
|
//properties. Verify the returned values and properties.
|
|
//
|
|
TESTRESULT CQuickTest::testSessGetProp()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG cPropSets = 0;
|
|
ULONG iSet=0, iProp=0 ;
|
|
DBPROP* pProp = NULL;
|
|
DBPROPSET* rgPropSets = NULL;
|
|
ISessionProperties* pISessProp = NULL;
|
|
|
|
//Obtain ISessionProperties interface.
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_ISessionProperties,
|
|
SESSION_INTERFACE,(IUnknown **)&pISessProp))
|
|
{
|
|
odtLog<<L"Could not get ISessionProperties interface.\n";
|
|
return TEST_FAIL;
|
|
}
|
|
|
|
//make DBPROPIDSET with one property in it.
|
|
SetPropID(DBPROP_SESS_AUTOCOMMITISOLEVELS, DBPROPSET_SESSION);
|
|
|
|
//Call GetProperties with the above made DBPROPIDSET.
|
|
hr = pISessProp->GetProperties(m_cPropIDSets, m_rgPropIDSets,
|
|
&cPropSets, &rgPropSets) ;
|
|
|
|
//Verify that 1 DBPROPSET was returned.
|
|
TESTC((cPropSets==1)&&(rgPropSets != NULL))
|
|
|
|
//Verify the guid of PropertySet.
|
|
COMPARE(rgPropSets[0].guidPropertySet, DBPROPSET_SESSION);
|
|
|
|
//Verify number of properties.
|
|
COMPARE(rgPropSets[0].cProperties, 1);
|
|
|
|
if(hr==S_OK)
|
|
{
|
|
//Verify status.
|
|
COMPARE(rgPropSets[0].rgProperties[0].dwStatus,
|
|
DBPROPSTATUS_OK);
|
|
|
|
//Verify the variant.
|
|
COMPARE((V_VT(&rgPropSets[0].rgProperties[0].vValue)
|
|
== VT_I4), TRUE);
|
|
|
|
//The value is a bitmask. So check if it is >= 0.
|
|
COMPARE((V_I4(&rgPropSets[0].rgProperties[0].vValue)
|
|
>= 0), TRUE);
|
|
}
|
|
else
|
|
{
|
|
odtLog<<L"DBPROP_SESS_AUTOCOMMITISOLEVELS is not supported.\n";
|
|
CHECK(hr, DB_E_ERRORSOCCURRED);
|
|
COMPARE(SupportedProperty(DBPROP_SESS_AUTOCOMMITISOLEVELS,
|
|
DBPROPSET_SESSION), FALSE);
|
|
}
|
|
|
|
FreeProperties(&cPropSets, &rgPropSets);
|
|
|
|
//Get ALL session properties.
|
|
TESTC_(pISessProp->GetProperties(0, NULL, &cPropSets,
|
|
&rgPropSets), S_OK)
|
|
|
|
//Check return values.
|
|
if(cPropSets==0 && rgPropSets==NULL)
|
|
{
|
|
//Issue a warning since no Property Sets were returned.
|
|
odtLog<<L"WARNING: No Property Sets were returned.\n";
|
|
COMPAREW(cPropSets, 1);
|
|
tTestResult = TEST_PASS;
|
|
goto CLEANUP;
|
|
}
|
|
TESTC((cPropSets!=0) && (rgPropSets!=NULL))
|
|
|
|
//Loop through the property sets.
|
|
for(iSet=0; iSet<cPropSets; iSet++)
|
|
{
|
|
//Check to see if the Provider has returned an invalid PropSets
|
|
if( (rgPropSets[iSet].guidPropertySet == DBPROPSET_COLUMN) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_DATASOURCE) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_DATASOURCEINFO)||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_DBINIT) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_INDEX) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_ROWSET) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_TABLE) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_DATASOURCEALL) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_ROWSETALL) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_SESSIONALL) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_DBINITALL))
|
|
{
|
|
odtLog<<L"ERROR: An Invalid OLEDB PropertySet has been returned by ISessionProperties::GetProperties!\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
if(rgPropSets[iSet].guidPropertySet != DBPROPSET_SESSION)
|
|
{
|
|
odtLog<<L"INFO: Found a provider specific property set.\n";
|
|
}
|
|
|
|
//Loop through the properties.
|
|
for(iProp=0; iProp<rgPropSets[iSet].cProperties; iProp++)
|
|
{
|
|
pProp = &(rgPropSets[iSet].rgProperties[iProp]) ;
|
|
|
|
//Verify if status is DBPROPSTATUS_OK.
|
|
COMPARE(pProp->dwStatus, DBPROPSTATUS_OK);
|
|
|
|
//For the property DBPROP_SESS_AUTOCOMMITISOLEVELS, verify
|
|
//if the variant type is VT_I4 or VT_EMPTY.
|
|
if((rgPropSets[iSet].guidPropertySet == DBPROPSET_SESSION)&&
|
|
(pProp->dwPropertyID==DBPROP_SESS_AUTOCOMMITISOLEVELS))
|
|
{
|
|
COMPARE((V_VT(&pProp->vValue) == VT_I4), TRUE);
|
|
}
|
|
|
|
//For certain variant types do some checking.
|
|
COMPARE(CheckVariant(&pProp->vValue), TRUE);
|
|
}
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
FreeProperties(&cPropSets, &rgPropSets);
|
|
FreeProperties(&m_cPropIDSets, &m_rgPropIDSets);
|
|
SAFE_RELEASE(pISessProp);
|
|
return tTestResult;
|
|
} //testSessGetProp
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
//@mfunc Set the property DBPROP_SESS_AUTOCOMMITISOLEVELS to a valid
|
|
//value. After setting the property call GetProperty on it and verify.
|
|
//
|
|
TESTRESULT CQuickTest::testSessSetProp()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL; //Test Return Value
|
|
HRESULT hr = S_OK;
|
|
ULONG cPropSets = 1;
|
|
DBPROP dwProp;
|
|
DBPROPSET rgPropSets[1];
|
|
ISessionProperties* pISessProp = NULL;
|
|
|
|
//Initialize the variant to pass as an [OUT] parameter to GetProperty.
|
|
VARIANT vVar;
|
|
VariantInit(&vVar);
|
|
|
|
//Obtain ISessionProperties Interface.
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_ISessionProperties,
|
|
SESSION_INTERFACE,(IUnknown **)&pISessProp))
|
|
{
|
|
odtLog<<L"Could not get ISessionProperties interface.\n";
|
|
return TEST_FAIL;
|
|
}
|
|
|
|
//Create and initialize the DBPROPSET to pass in to SetProperties.
|
|
memset(&dwProp, 0, sizeof(DBPROP)) ;
|
|
dwProp.dwPropertyID = DBPROP_SESS_AUTOCOMMITISOLEVELS;
|
|
dwProp.dwOptions = DBPROPOPTIONS_REQUIRED;
|
|
VariantInit(&dwProp.vValue);
|
|
V_VT(&dwProp.vValue) = DBTYPE_I4;
|
|
V_I4(&dwProp.vValue) = DBPROPVAL_TI_READCOMMITTED;
|
|
rgPropSets[0].rgProperties = &dwProp;
|
|
rgPropSets[0].cProperties = 1;
|
|
rgPropSets[0].guidPropertySet = DBPROPSET_SESSION;
|
|
|
|
//Set the property.
|
|
hr = pISessProp->SetProperties(cPropSets, rgPropSets);
|
|
|
|
if(hr==S_OK)
|
|
{
|
|
//Check if the status is DBPROPSTATUS_OK.
|
|
COMPARE(rgPropSets[0].rgProperties[0].dwStatus,
|
|
DBPROPSTATUS_OK);
|
|
|
|
//Call GetProperty to get the variant value of
|
|
//DBPROP_SESS_AUTOCOMMITISOLEVELS.
|
|
COMPARE(GetProperty(DBPROP_SESS_AUTOCOMMITISOLEVELS,
|
|
DBPROPSET_SESSION, (IUnknown*)pISessProp, &vVar), TRUE);
|
|
|
|
//Compare the variant value got by above call to GetProperty
|
|
//and the one created (pVar) to pass in to SetProperty.
|
|
COMPARE(CompareVariant(&vVar, &dwProp.vValue), TRUE);
|
|
}
|
|
else
|
|
{
|
|
odtLog<<L"DBPROP_SESS_AUTOCOMMITISOLEVELS is not supported or not settable.\n";
|
|
|
|
TESTC_(hr, DB_E_ERRORSOCCURRED)
|
|
|
|
//The status should be NOTSUPPORTED or NOTSETTABLE.
|
|
COMPARE((rgPropSets[0].rgProperties[0].dwStatus ==
|
|
DBPROPSTATUS_NOTSUPPORTED) ||
|
|
(rgPropSets[0].rgProperties[0].dwStatus ==
|
|
DBPROPSTATUS_NOTSETTABLE), TRUE);
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
VariantClear(&vVar);
|
|
SAFE_RELEASE(pISessProp);
|
|
return tTestResult;
|
|
} //testSessSetProp
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Create multiple command objects using method CreateCommand. Each
|
|
//time request a different Command interface. Do this for all mandatory
|
|
//command interfaces.
|
|
//
|
|
TESTRESULT CQuickTest::testCreateCommand()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ICommand* pICommand = NULL;
|
|
ICommandText* pICommandText = NULL;
|
|
IColumnsInfo* pIColumnsInfo = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
IConvertType* pIConvertType = NULL;
|
|
ICommandProperties* pICommandProperties = NULL;
|
|
|
|
if(m_pIDBCreateCommand == NULL)
|
|
{
|
|
odtLog<<L"IDBCreateCommand pointer is NULL.\n";
|
|
return TEST_FAIL;
|
|
}
|
|
|
|
// CreateCommand with IID_ICommand
|
|
CHECK(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand,
|
|
(IUnknown**)&pICommand), S_OK);
|
|
TESTC(pICommand != NULL)
|
|
|
|
// CreateCommand with IID_ICommandText
|
|
CHECK(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommandText,
|
|
(IUnknown**)&pICommandText), S_OK);
|
|
TESTC(pICommandText != NULL)
|
|
|
|
// CreateCommand with IID_IColumnsInfo
|
|
CHECK(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_IColumnsInfo,
|
|
(IUnknown**)&pIColumnsInfo), S_OK);
|
|
TESTC(pIColumnsInfo != NULL)
|
|
|
|
// CreateCommand with IID_IAccessor
|
|
CHECK(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_IAccessor,
|
|
(IUnknown**)&pIAccessor), S_OK);
|
|
TESTC(pIAccessor != NULL)
|
|
|
|
// CreateCommand with IID_IConvertType
|
|
CHECK(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_IConvertType,
|
|
(IUnknown**)&pIConvertType), S_OK);
|
|
TESTC(pIConvertType != NULL)
|
|
|
|
// CreateCommand with IID_ICommandProperties
|
|
CHECK(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommandProperties,
|
|
(IUnknown**)&pICommandProperties), S_OK);
|
|
TESTC(pICommandProperties != NULL)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pICommand);
|
|
SAFE_RELEASE(pICommandText);
|
|
SAFE_RELEASE(pIColumnsInfo);
|
|
SAFE_RELEASE(pIAccessor);
|
|
SAFE_RELEASE(pIConvertType);
|
|
SAFE_RELEASE(pICommandProperties);
|
|
return tTestResult;
|
|
} //testCreateCommand
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Get the supported schemas. Make sure the 3 mandatory ones
|
|
//(DBSCHEMA_TABLES, DBSCHEMA_COLUMNS and DBSCHEMA_PROVIDER_TYPES) are
|
|
//there.
|
|
//
|
|
TESTRESULT CQuickTest::testGetSchemas()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
ULONG fRequired = 0; //a bit mask to mark existing schema.
|
|
ULONG ulIndex = 0;
|
|
GUID * rgSchemas = NULL;
|
|
ULONG cSchemas = 0;
|
|
ULONG * rgRestrictionSupport = NULL;
|
|
IDBSchemaRowset* pIDBSR = NULL;
|
|
|
|
//Obtain IDBSchemaRowset interface
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_IDBSchemaRowset,
|
|
SESSION_INTERFACE,(IUnknown**)&pIDBSR))
|
|
{
|
|
odtLog<<L"IDBSchemaRowset is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
//Call the method.
|
|
TESTC_(pIDBSR->GetSchemas(&cSchemas,&rgSchemas,
|
|
&rgRestrictionSupport),S_OK)
|
|
|
|
TESTC((cSchemas > 2) && (rgSchemas) && (rgRestrictionSupport))
|
|
|
|
for(ulIndex=0; ulIndex<cSchemas; ulIndex++)
|
|
{
|
|
if(IsEqualGUID(rgSchemas[ulIndex], DBSCHEMA_TABLES))
|
|
{
|
|
COMPARE(fRequired & 0x1, 0);
|
|
|
|
fRequired |= 0x1 ; //Mark "This schema exists".
|
|
|
|
//There can be a maximum of 4 restrictions. Hence the
|
|
//bitmask can have a max value of 15.
|
|
COMPARE(rgRestrictionSupport[ulIndex] < 16, TRUE);
|
|
}
|
|
if(IsEqualGUID(rgSchemas[ulIndex], DBSCHEMA_COLUMNS))
|
|
{
|
|
COMPARE(fRequired & 0x2, 0);
|
|
|
|
fRequired |= 0x2 ;
|
|
//There can be a maximum of 4 restrictions. Hence the
|
|
//bitmask can have a max value of 15.
|
|
COMPARE(rgRestrictionSupport[ulIndex] < 16, TRUE);
|
|
}
|
|
if(IsEqualGUID(rgSchemas[ulIndex], DBSCHEMA_PROVIDER_TYPES))
|
|
{
|
|
COMPARE(fRequired & 0x4, 0);
|
|
|
|
fRequired |= 0x4 ;
|
|
//There can be a maximum of 2 restrictions. Hence the
|
|
//bitmask can have a max value of 3.
|
|
COMPARE(rgRestrictionSupport[ulIndex] < 4, TRUE);
|
|
}
|
|
}
|
|
|
|
//Make sure all 3 required schemas were found.
|
|
TESTC(fRequired == 7)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(rgSchemas);
|
|
PROVIDER_FREE(rgRestrictionSupport);
|
|
SAFE_RELEASE(pIDBSR);
|
|
return tTestResult;
|
|
} //testGetSchemas
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Get the DBSCHEMA_COLUMNS rowset with certain restrictions.
|
|
//Verify the obtained rowset.
|
|
//
|
|
TESTRESULT CQuickTest::testColumnsSchemaRowset()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DBCOUNTITEM cGotRows = 0;
|
|
DBCOUNTITEM ulIndex = 0;
|
|
HROW* rghRows = NULL;
|
|
BYTE* pData = NULL;
|
|
LONG_PTR rgColsToBind[1];
|
|
VARIANT rgRestrictions[4];
|
|
WCHAR* pwszTableName = NULL;
|
|
ULONG ulRestrictCOL = 0;
|
|
GUID * rgSchemas = NULL;
|
|
ULONG cSchemas = 0;
|
|
ULONG * rgRestrictionSupport = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBBINDING* rgBindings = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowset* pIRowset = NULL;
|
|
IDBSchemaRowset* pIDBSR = NULL;
|
|
|
|
for(ulIndex=0; ulIndex<4; ulIndex++)
|
|
VariantInit(&rgRestrictions[ulIndex]);
|
|
|
|
//Obtain IDBSchemaRowset interface
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_IDBSchemaRowset,
|
|
SESSION_INTERFACE,(IUnknown**)&pIDBSR))
|
|
{
|
|
odtLog<<L"IDBSchemaRowset is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
//Call the method.
|
|
TESTC_(hr=pIDBSR->GetSchemas(&cSchemas,&rgSchemas,
|
|
&rgRestrictionSupport),S_OK)
|
|
|
|
TESTC((cSchemas > 2) && (rgSchemas) && (rgRestrictionSupport))
|
|
|
|
//Get the restiction support.
|
|
for(ulIndex=0; ulIndex<cSchemas; ulIndex++)
|
|
if(IsEqualGUID(rgSchemas[ulIndex], DBSCHEMA_COLUMNS))
|
|
ulRestrictCOL = rgRestrictionSupport[ulIndex];
|
|
|
|
TESTC(m_pTable != NULL)
|
|
|
|
//Table name to be used as restriction.
|
|
pwszTableName = m_pTable->GetTableName();
|
|
|
|
//Bind only 3rd column. This is the column on which we will have the
|
|
//restriction.
|
|
rgColsToBind[0] = 3;
|
|
|
|
//If the table name restriction is supported ...
|
|
if(ulRestrictCOL & 0x4)
|
|
{
|
|
rgRestrictions[2].vt = VT_BSTR;
|
|
|
|
//Allocate memory for BSTR. Will be freed by VariantClear.
|
|
SAFE_SYSALLOC(rgRestrictions[2].bstrVal, pwszTableName);
|
|
}
|
|
|
|
//Get the schema rowset with 1 restriction (if supported).
|
|
TESTC_(hr=pIDBSR->GetRowset(NULL, DBSCHEMA_COLUMNS,4,rgRestrictions,
|
|
IID_IRowset, 0, NULL, (IUnknown**)
|
|
&pIRowset), S_OK)
|
|
|
|
TESTC(pIRowset != NULL)
|
|
|
|
TESTC(VerifyInterface(pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create Accessor with a binding using only value.
|
|
//This binds the 3rd column only.
|
|
TESTC_(hr=GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_VALUE,
|
|
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF,
|
|
NULL, NULL, NULL, DBTYPE_EMPTY, 1, rgColsToBind,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Make sure we are on the first row.
|
|
TESTC_(RestartPosition(pIRowset), S_OK)
|
|
|
|
//Allocate a new data buffer
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
|
|
while(S_OK==(hr=GetNextRows(pIRowset, NULL, 0, 1, &cRowsObtained, &rghRows)))
|
|
{
|
|
//Initialize pData and call GetData for a row.
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
TESTC_(hr = pIRowset->GetData(*rghRows, hAccessor,
|
|
pData),S_OK)
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
|
|
//If the restriction was supported, make sure it was followed.
|
|
if(ulRestrictCOL & 0x4)
|
|
TESTC(wcsstr((WCHAR*)((BYTE *)pData+rgBindings[0].obValue),
|
|
pwszTableName) != NULL)
|
|
|
|
CHECK(ReleaseInputBindingsMemory(cBindings, rgBindings,
|
|
pData), S_OK);
|
|
|
|
cGotRows++;
|
|
}
|
|
|
|
TESTC_(hr, DB_S_ENDOFROWSET)
|
|
TESTC(cGotRows > 0)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(pData);
|
|
for(ulIndex=0; ulIndex<4; ulIndex++)
|
|
VariantClear(&rgRestrictions[ulIndex]);
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
PROVIDER_FREE(rgSchemas);
|
|
PROVIDER_FREE(rgRestrictionSupport);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIDBSR);
|
|
return tTestResult;
|
|
} //testColumnsSchemaRowset
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Get the DBSCHEMA_TABLES rowset with certain restrictions.
|
|
//Verify the obtained rowset.
|
|
//
|
|
TESTRESULT CQuickTest::testTablesSchemaRowset()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DBCOUNTITEM cGotRows = 0;
|
|
DBCOUNTITEM ulIndex = 0;
|
|
HROW* rghRows = NULL;
|
|
BYTE* pData = NULL;
|
|
LONG_PTR rgColsToBind[2];
|
|
VARIANT rgRestrictions[4];
|
|
WCHAR* pwszTableName = NULL;
|
|
ULONG ulRestrictTBL = 0;
|
|
GUID * rgSchemas = NULL;
|
|
ULONG cSchemas = 0;
|
|
ULONG * rgRestrictionSupport = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBBINDING* rgBindings = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowset* pIRowset = NULL;
|
|
IDBSchemaRowset* pIDBSR = NULL;
|
|
|
|
for(ulIndex=0; ulIndex<4; ulIndex++)
|
|
VariantInit(&rgRestrictions[ulIndex]);
|
|
|
|
//Obtain IDBSchemaRowset interface
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_IDBSchemaRowset,
|
|
SESSION_INTERFACE,(IUnknown**)&pIDBSR))
|
|
{
|
|
odtLog<<L"IDBSchemaRowset is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
//Call the method.
|
|
TESTC_(hr=pIDBSR->GetSchemas(&cSchemas,&rgSchemas,
|
|
&rgRestrictionSupport),S_OK)
|
|
|
|
TESTC((cSchemas > 2) && (rgSchemas) && (rgRestrictionSupport))
|
|
|
|
//Get the restriction support.
|
|
for(ulIndex=0; ulIndex<cSchemas; ulIndex++)
|
|
if(IsEqualGUID(rgSchemas[ulIndex], DBSCHEMA_TABLES))
|
|
ulRestrictTBL = rgRestrictionSupport[ulIndex];
|
|
|
|
TESTC(m_pTable != NULL)
|
|
|
|
//Table name to use for restriction.
|
|
pwszTableName = m_pTable->GetTableName();
|
|
|
|
//Bind only 3rd and 4th columns.
|
|
rgColsToBind[0] = 3;
|
|
rgColsToBind[1] = 4;
|
|
|
|
//If the table name restriction is supported ...
|
|
if(ulRestrictTBL & 0x4)
|
|
{
|
|
rgRestrictions[2].vt = VT_BSTR;
|
|
|
|
//Allocate memory for BSTR. Will be freed by VariantClear.
|
|
SAFE_SYSALLOC(rgRestrictions[2].bstrVal, pwszTableName);
|
|
}
|
|
|
|
//If the table type restriction is supported ...
|
|
if(ulRestrictTBL & 0x8)
|
|
{
|
|
rgRestrictions[3].vt = VT_BSTR;
|
|
|
|
//Allocate memory for BSTR. Will be freed by VariantClear.
|
|
SAFE_SYSALLOC(rgRestrictions[3].bstrVal, L"TABLE");
|
|
}
|
|
|
|
//Get the schema rowset with 2 restrictions (if supported).
|
|
TESTC_(hr=pIDBSR->GetRowset(NULL, DBSCHEMA_TABLES,4,rgRestrictions,
|
|
IID_IRowset, 0, NULL, (IUnknown**)
|
|
&pIRowset), S_OK)
|
|
|
|
TESTC(pIRowset != NULL)
|
|
|
|
TESTC(VerifyInterface(pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create Accessor with a binding using only value.
|
|
//This binds the 3rd column only.
|
|
TESTC_(hr=GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_VALUE,
|
|
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF,
|
|
NULL, NULL, NULL, DBTYPE_EMPTY, 2, rgColsToBind,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Make sure we are on the first row.
|
|
TESTC_(RestartPosition(pIRowset), S_OK)
|
|
|
|
//Allocate a new data buffer
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
|
|
while(S_OK==(hr=GetNextRows(pIRowset, NULL, 0, 1, &cRowsObtained, &rghRows)))
|
|
{
|
|
//Initialize pData and call GetData for a row.
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
TESTC_(hr = pIRowset->GetData(*rghRows, hAccessor,
|
|
pData),S_OK)
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
|
|
//If the restriction was supported, make sure it was followed.
|
|
if(ulRestrictTBL & 0x4)
|
|
TESTC(wcsstr((WCHAR*)((BYTE *)pData+rgBindings[0].obValue),
|
|
pwszTableName) != NULL)
|
|
|
|
//If the restriction was supported, make sure it was followed.
|
|
if(ulRestrictTBL & 0x8)
|
|
TESTC(wcsstr((WCHAR*)((BYTE *)pData+rgBindings[1].obValue),
|
|
L"TABLE") != NULL)
|
|
|
|
CHECK(ReleaseInputBindingsMemory(cBindings, rgBindings,
|
|
pData), S_OK);
|
|
|
|
cGotRows++;
|
|
}
|
|
|
|
TESTC_(hr, DB_S_ENDOFROWSET)
|
|
if(cGotRows == 0)
|
|
{
|
|
odtLog<<L"WARNING: The number of rows in the Tables Schema Rowset with restrictions TableName = "<<pwszTableName<<L" and TableType = TABLE was "<<cGotRows<<".\n";
|
|
COMPAREW(cGotRows > 0, TRUE);
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(pData);
|
|
for(ulIndex=0; ulIndex<4; ulIndex++)
|
|
VariantClear(&rgRestrictions[ulIndex]);
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
PROVIDER_FREE(rgSchemas);
|
|
PROVIDER_FREE(rgRestrictionSupport);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIDBSR);
|
|
return tTestResult;
|
|
} //testTablesSchemaRowset
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Get the DBSCHEMA_PROVIDER_TYPES rowset with certain restrictions.
|
|
//Verify the obtained rowset.
|
|
//
|
|
TESTRESULT CQuickTest::testProvTypesSchemaRowset()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW* rghRows = NULL;
|
|
BYTE* pData = NULL;
|
|
LONG_PTR rgColsToBind[1];
|
|
VARIANT rgRestrictions[2];
|
|
ULONG ulIndex = 0; //index for no. of schemas
|
|
ULONG ulRestrictPTY = 0;
|
|
GUID * rgSchemas = NULL;
|
|
ULONG cSchemas = 0;
|
|
ULONG * rgRestrictionSupport = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBBINDING* rgBindings = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowset* pIRowset = NULL;
|
|
IDBSchemaRowset* pIDBSR = NULL;
|
|
|
|
VariantInit(&rgRestrictions[0]);
|
|
VariantInit(&rgRestrictions[1]);
|
|
|
|
//Obtain IDBSchemaRowset interface
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_IDBSchemaRowset,
|
|
SESSION_INTERFACE,(IUnknown**)&pIDBSR))
|
|
{
|
|
odtLog<<L"IDBSchemaRowset is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
//Call the method.
|
|
TESTC_(hr=pIDBSR->GetSchemas(&cSchemas,&rgSchemas,
|
|
&rgRestrictionSupport),S_OK)
|
|
|
|
TESTC((cSchemas > 2) && (rgSchemas) && (rgRestrictionSupport))
|
|
|
|
for(ulIndex=0; ulIndex<cSchemas; ulIndex++)
|
|
if(IsEqualGUID(rgSchemas[ulIndex], DBSCHEMA_PROVIDER_TYPES))
|
|
ulRestrictPTY = rgRestrictionSupport[ulIndex];
|
|
|
|
//Bind only 2nd column.
|
|
rgColsToBind[0] = 2;
|
|
|
|
//If the data type restriction is supported.
|
|
if(ulRestrictPTY & 0x1)
|
|
{
|
|
rgRestrictions[0].vt = VT_UI2;
|
|
V_UI2(&(rgRestrictions[0])) = DBTYPE_BYTES ;
|
|
}
|
|
|
|
//Get the schema rowset with 1 restriction (if supported).
|
|
TESTC_(hr=pIDBSR->GetRowset(NULL, DBSCHEMA_PROVIDER_TYPES,2,
|
|
rgRestrictions, IID_IRowset, 0, NULL, (IUnknown**)
|
|
&pIRowset), S_OK)
|
|
|
|
TESTC(pIRowset != NULL)
|
|
|
|
TESTC(VerifyInterface(pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create Accessor with a binding using only value.
|
|
//Bind only the 2nd column.
|
|
TESTC_(hr=GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_VALUE,
|
|
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF,
|
|
NULL, NULL, NULL, DBTYPE_EMPTY, 1, rgColsToBind,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Make sure we are on the first row.
|
|
TESTC_(RestartPosition(pIRowset), S_OK)
|
|
|
|
//Allocate a new data buffer
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
|
|
while(S_OK==(hr=GetNextRows(pIRowset, NULL, 0, 1, &cRowsObtained, &rghRows)))
|
|
{
|
|
//Initialize pData and call GetData for a row.
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
TESTC_(hr = pIRowset->GetData(*rghRows, hAccessor,
|
|
pData),S_OK)
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
|
|
//If the restriction was supported, make sure it was followed.
|
|
if(ulRestrictPTY & 0x1)
|
|
TESTC(*(USHORT*)((BYTE *)pData+rgBindings[0].obValue)
|
|
== DBTYPE_BYTES)
|
|
|
|
CHECK(ReleaseInputBindingsMemory(cBindings, rgBindings,
|
|
pData), S_OK);
|
|
}
|
|
|
|
TESTC_(hr, DB_S_ENDOFROWSET)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(pData);
|
|
VariantClear(&rgRestrictions[0]);
|
|
VariantClear(&rgRestrictions[1]);
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
PROVIDER_FREE(rgSchemas);
|
|
PROVIDER_FREE(rgRestrictionSupport);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIDBSR);
|
|
return tTestResult;
|
|
} //testProvTypesSchemaRowset
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Add a column using ITableDefinition and verify that it was
|
|
//added.
|
|
//
|
|
TESTRESULT CQuickTest::testAddColumn()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
BOOL fNewColumn=FALSE;
|
|
DBORDINAL cOldCol = 0;
|
|
DBORDINAL cNewCol = 0;
|
|
DBID* pColumnID = NULL;
|
|
DBID* pTableID = NULL;
|
|
DBCOLUMNDESC* rgColumnDesc = NULL;
|
|
DBCOLUMNDESC* rgColDesc1 = NULL;
|
|
DBCOLUMNDESC* rgColDesc2 = NULL;
|
|
DBCOLUMNDESC* pColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = 0;
|
|
DBORDINAL cColDesc1 = 0;
|
|
DBORDINAL cColDesc2 = 0;
|
|
CTable* pTable = NULL;
|
|
CList <WCHAR*, WCHAR*> ListNativeTemp;
|
|
CList <DBTYPE, DBTYPE> ListDataTypes;
|
|
ITableDefinition* pITableDefinition = NULL;
|
|
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_ITableDefinition,
|
|
SESSION_INTERFACE,(IUnknown**)&pITableDefinition))
|
|
{
|
|
odtLog<<L"ITableDefinition is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
pTable = new CTable(m_pIOpenRowset, (LPWSTR)gwszModuleName);
|
|
TESTC(pTable != NULL)
|
|
|
|
//Create column information, initializes column list with columns
|
|
//of specified types.
|
|
TESTC_(hr=pTable->CreateColInfo(ListNativeTemp, ListDataTypes,
|
|
ALLTYPES), S_OK)
|
|
|
|
//build the column description array
|
|
hr=pTable->BuildColumnDescs(&rgColumnDesc);
|
|
TESTC(SUCCEEDED(hr))
|
|
|
|
cColumnDesc = pTable->CountColumnsOnTable();
|
|
|
|
//Set cColumnDesc-1 column descriptions.
|
|
pTable->SetColumnDesc(rgColumnDesc, cColumnDesc-1);
|
|
pTable->SetBuildColumnDesc(FALSE);
|
|
|
|
//Create table with one less column.
|
|
TESTC_(pTable->CreateTable(0, 0), S_OK)
|
|
|
|
pTableID = &(pTable->GetTableIDRef()) ;
|
|
|
|
hr=pTable->GetTableColumnInfo(pTableID);
|
|
TESTC(SUCCEEDED(hr))
|
|
|
|
//Get column descs before calling AddColumn.
|
|
TESTC(pTable->ColList2ColumnDesc(&rgColDesc1, &cColDesc1))
|
|
|
|
//The column to be added.
|
|
pColumnDesc = &rgColumnDesc[cColumnDesc-1];
|
|
|
|
//Add the new column.
|
|
TESTC_(hr = pITableDefinition->AddColumn(pTableID,
|
|
pColumnDesc, &pColumnID), S_OK)
|
|
TESTC(pColumnID != NULL)
|
|
|
|
hr=pTable->GetTableColumnInfo(pTableID);
|
|
TESTC(SUCCEEDED(hr))
|
|
|
|
//Get column descs after AddColumn.
|
|
TESTC(pTable->ColList2ColumnDesc(&rgColDesc2, &cColDesc2))
|
|
|
|
//Number of columns should have increased by 1.
|
|
TESTC(cColDesc2 == cColDesc1+1);
|
|
|
|
//LOOP cColDesc1+1 times.
|
|
for (cOldCol=cNewCol=0; cNewCol<cColDesc2; cNewCol++)
|
|
{
|
|
//Its an old column.
|
|
//Added an extra condition cOldCol < cColDesc1 because that would prevent reading
|
|
//past rgColDesc1 max index.
|
|
|
|
if (cOldCol < cColDesc1 && CompareDBID(rgColDesc1[cOldCol].dbcid,
|
|
rgColDesc2[cNewCol].dbcid))
|
|
{
|
|
TESTC(CompareColumnDesc(&rgColDesc1[cOldCol],
|
|
&rgColDesc2[cNewCol]));
|
|
cOldCol++;
|
|
}
|
|
//It should be the new column which was added.
|
|
else
|
|
{
|
|
//Make sure the new column has not been found already.
|
|
TESTC(!fNewColumn);
|
|
//Check if this new column is the one we had added.
|
|
TESTC(pColumnDesc->pTypeInfo == rgColDesc2[cOldCol].pTypeInfo);
|
|
TESTC(pColumnDesc->wType == rgColDesc2[cOldCol].wType);
|
|
TESTC(CompareDBID(*pColumnID, rgColDesc2[cOldCol].dbcid));
|
|
//The new column has been found.
|
|
fNewColumn = TRUE;
|
|
}
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
if(pTable)
|
|
pTable->DropTable();
|
|
|
|
//rgColumnDesc gets freed above when pTable is deleted.
|
|
pTable->SetNoOfColumnDesc(cColumnDesc);
|
|
SAFE_DELETE(pTable);
|
|
ReleaseColumnDesc(rgColDesc1, cColDesc1);
|
|
ReleaseColumnDesc(rgColDesc2, cColDesc2);
|
|
ReleaseDBID(pColumnID, TRUE);
|
|
SAFE_RELEASE(pITableDefinition);
|
|
return tTestResult;
|
|
} //testAddColumn
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Create a table using ITableDefinition, and verify.
|
|
//
|
|
TESTRESULT CQuickTest::testCreateTable()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
BOOL fExists = FALSE;
|
|
DBID* pNewTableID = NULL;
|
|
DBCOLUMNDESC* rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = 0;
|
|
CTable* pTable = NULL;
|
|
CList <WCHAR*, WCHAR*> ListNativeTemp;
|
|
CList <DBTYPE, DBTYPE> ListDataTypes;
|
|
IRowsetInfo* pIRowsetInfo = NULL;
|
|
IOpenRowset* pIOpenRowset = NULL;
|
|
ITableDefinition* pITableDefinition = NULL;
|
|
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_ITableDefinition,
|
|
SESSION_INTERFACE,(IUnknown**)&pITableDefinition))
|
|
{
|
|
odtLog<<L"ITableDefinition is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
pTable = new CTable(m_pIOpenRowset, (LPWSTR)gwszModuleName);
|
|
TESTC(pTable != NULL)
|
|
|
|
//Create column information, initializes column list with columns
|
|
//of specified types. Can get DB_S_ENDOFROWSET.
|
|
TESTC_(hr=pTable->CreateColInfo(ListNativeTemp, ListDataTypes,
|
|
ALLTYPES), S_OK)
|
|
|
|
//build the column description array
|
|
TESTC_(hr=pTable->BuildColumnDescs(&rgColumnDesc), S_OK)
|
|
|
|
cColumnDesc = pTable->CountColumnsOnTable();
|
|
|
|
//Setting the following property is not required.
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &m_cPropSets,
|
|
&m_rgPropSets) ;
|
|
|
|
//Create table with the column descriptions obtained from pTable.
|
|
TESTC_(hr = pITableDefinition->CreateTable(NULL, NULL, cColumnDesc,
|
|
rgColumnDesc, IID_IRowsetInfo, m_cPropSets, m_rgPropSets,
|
|
&pNewTableID, (IUnknown**)&pIRowsetInfo), S_OK)
|
|
|
|
//Make sure the table exists.
|
|
CHECK(hr = pTable->DoesTableExist(pNewTableID, &fExists), S_OK) ;
|
|
TESTC(fExists)
|
|
|
|
TESTC(pIRowsetInfo != NULL)
|
|
|
|
//Make sure that the IRowsetInfo obtained from CreateTable is
|
|
//actually usable.
|
|
hr = pIRowsetInfo->GetSpecification(IID_IOpenRowset, (IUnknown**)
|
|
&pIOpenRowset) ;
|
|
|
|
if(hr==S_FALSE)
|
|
{
|
|
odtLog<<L"IRowsetInfo::GetSpecification returned S_FALSE.\n";
|
|
CHECKW(hr, S_OK);
|
|
}
|
|
else
|
|
{
|
|
TESTC_(hr, S_OK)
|
|
TESTC(VerifyEqualInterface(pIOpenRowset, m_pIOpenRowset))
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
SAFE_RELEASE(pIOpenRowset);
|
|
if(pNewTableID)
|
|
{
|
|
hr = pITableDefinition->DropTable(pNewTableID);
|
|
ReleaseDBID(pNewTableID, TRUE);
|
|
if(hr != S_OK)
|
|
{
|
|
CHECK(hr, S_OK);
|
|
tTestResult = TEST_FAIL;
|
|
}
|
|
}
|
|
SAFE_DELETE(pTable);
|
|
SAFE_RELEASE(pITableDefinition);
|
|
return tTestResult;
|
|
} //testCreateTable
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Drop a column from the table using ITableDefinition, and verify
|
|
//that it got removed.
|
|
//
|
|
TESTRESULT CQuickTest::testDropColumn()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBORDINAL ulIndex = 0;
|
|
BOOL bFound = FALSE;
|
|
DBID* pTableID = NULL ;
|
|
WCHAR* pwszNewName = NULL;
|
|
DBCOLUMNDESC *rgColumnDesc = NULL;
|
|
DBCOLUMNDESC *rgColDesc1 = NULL;
|
|
DBORDINAL cColumnDesc = 0;
|
|
DBORDINAL cColDesc1 = 0;
|
|
CTable* pTable = NULL;
|
|
CList <WCHAR*, WCHAR*> ListNativeTemp;
|
|
CList <DBTYPE, DBTYPE> ListDataTypes;
|
|
ITableDefinition* pITableDefinition = NULL;
|
|
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_ITableDefinition,
|
|
SESSION_INTERFACE,(IUnknown**)&pITableDefinition))
|
|
{
|
|
odtLog<<L"ITableDefinition is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
pTable = new CTable(m_pIOpenRowset, (LPWSTR)gwszModuleName);
|
|
TESTC(pTable != NULL)
|
|
|
|
//Create column information, initializes column list with columns
|
|
//of specified types. Can get DB_S_ENDOFROWSET.
|
|
TESTC_(hr=pTable->CreateColInfo(ListNativeTemp, ListDataTypes,
|
|
ALLTYPES), S_OK)
|
|
|
|
//build the column description array
|
|
hr=pTable->BuildColumnDescs(&rgColumnDesc);
|
|
TESTC(SUCCEEDED(hr))
|
|
|
|
cColumnDesc = pTable->CountColumnsOnTable();
|
|
|
|
//Create a table with the modified column description.
|
|
pTable->SetBuildColumnDesc(FALSE);
|
|
pTable->SetColumnDesc(rgColumnDesc, cColumnDesc);
|
|
TESTC_(hr = pTable->CreateTable(0, 0), S_OK);
|
|
|
|
pTableID = &(pTable->GetTableIDRef()) ;
|
|
|
|
//Drop the column whose DBID we had modified earlier.
|
|
hr = pITableDefinition->DropColumn(pTableID,
|
|
&(rgColumnDesc[0].dbcid)) ;
|
|
|
|
if(hr==E_NOTIMPL)
|
|
{
|
|
odtLog<<L"WARNING/FAIL: The method returned E_NOTIMPL. This is OK only if you are running against SQLServer6.5. Against anything else, this would be a FAILURE.\n";
|
|
CHECKW(hr, S_OK);
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC_(hr, S_OK)
|
|
|
|
//Obtain the column info and descriptions after dropping a
|
|
//column.
|
|
hr=pTable->GetTableColumnInfo(pTableID);
|
|
TESTC(SUCCEEDED(hr))
|
|
|
|
TESTC(pTable->ColList2ColumnDesc(&rgColDesc1, &cColDesc1))
|
|
|
|
//Make sure the column which was dropped does not exist in the
|
|
//new column desc list.
|
|
for(ulIndex=0; (ulIndex<cColDesc1 && bFound == FALSE); ulIndex++)
|
|
{
|
|
if(CompareDBID(rgColumnDesc[0].dbcid, rgColDesc1[ulIndex].dbcid))
|
|
bFound = TRUE;
|
|
}
|
|
|
|
TESTC(!bFound)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
ReleaseColumnDesc(rgColDesc1, cColDesc1);
|
|
if(pTable)
|
|
pTable->DropTable();
|
|
SAFE_DELETE(pTable);
|
|
//rgColumnDesc gets freed above when pTable is deleted.
|
|
SAFE_RELEASE(pITableDefinition);
|
|
return tTestResult;
|
|
} //testDropColumn
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Drop a table using ITableDefinition and verify.
|
|
//
|
|
TESTRESULT CQuickTest::testDropTable()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
BOOL fExists = TRUE;
|
|
CTable* pTable = NULL;
|
|
ITableDefinition* pITableDefinition = NULL;
|
|
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_ITableDefinition,
|
|
SESSION_INTERFACE,(IUnknown**)&pITableDefinition))
|
|
{
|
|
odtLog<<L"ITableDefinition is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
pTable = new CTable(m_pIOpenRowset, (LPWSTR)gwszModuleName);
|
|
TESTC(pTable != NULL)
|
|
|
|
pTable->SetBuildColumnDesc(TRUE);
|
|
|
|
//Create a table.
|
|
TESTC_(hr = pTable->CreateTable((DBCOUNTITEM)0, (DBORDINAL)0, NULL), S_OK);
|
|
|
|
TESTC_(hr = pITableDefinition->DropTable(&pTable->GetTableID()),
|
|
S_OK);
|
|
|
|
//Check if the table still exists.
|
|
CHECK(hr = pTable->DoesTableExist(&pTable->GetTableID(), &fExists),
|
|
S_OK) ;
|
|
|
|
TESTC(!fExists)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
if(pTable)
|
|
pTable->DropTable();
|
|
SAFE_DELETE(pTable);
|
|
SAFE_RELEASE(pITableDefinition);
|
|
return tTestResult;
|
|
} //testDropTable
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Create an Index and verify that it exists.
|
|
//
|
|
TESTRESULT CQuickTest::testIIndexDef()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
TESTRESULT tTR = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
BOOL bIndexExists = FALSE;
|
|
DBORDINAL cColumnDesc = 0;
|
|
DBCOLUMNDESC* rgColumnDesc = NULL;
|
|
DBINDEXCOLUMNDESC rgIndexColumnDesc[1];
|
|
DBINDEXCOLUMNDESC* rgIndexColumnDescOut = NULL;
|
|
DBID* pTableID = NULL;
|
|
DBID* pIndexID = NULL;
|
|
CTable* pTable = NULL;
|
|
IIndexDefinition* pIID = NULL;
|
|
IDBSchemaRowset* pIDSR = NULL;
|
|
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_IIndexDefinition,
|
|
SESSION_INTERFACE,(IUnknown**)&pIID))
|
|
{
|
|
odtLog<<L"IIndexDefinition is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
//Initialize this local variable to avoid releasing garbage pointer.
|
|
rgIndexColumnDesc[0].pColumnID = NULL;
|
|
|
|
pTable = new CTable(m_pIOpenRowset, (LPWSTR)gwszModuleName, NONULLS);
|
|
TESTC(pTable != NULL)
|
|
|
|
//Create a table with no index.
|
|
TESTC(SUCCEEDED(hr = pTable->CreateTable(MIN_ROWS, 0)))
|
|
|
|
//Get the column descs.
|
|
TESTC_(pTable->BuildColumnDescs(&rgColumnDesc), S_OK)
|
|
cColumnDesc = pTable->CountColumnsOnTable();
|
|
pTableID = &(pTable->GetTableIDRef());
|
|
|
|
//Create the index column desc.
|
|
SAFE_ALLOC(rgIndexColumnDesc[0].pColumnID, DBID, 1);
|
|
DuplicateDBID(rgColumnDesc[0].dbcid, rgIndexColumnDesc[0].pColumnID);
|
|
rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC;
|
|
|
|
//Create the index.
|
|
TESTC_(hr = pIID->CreateIndex(pTableID, NULL, 1, rgIndexColumnDesc,
|
|
0, NULL, &pIndexID), S_OK)
|
|
|
|
TESTC(pIndexID != NULL)
|
|
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_IDBSchemaRowset,
|
|
SESSION_INTERFACE,(IUnknown**)&pIDSR))
|
|
{
|
|
odtLog<<L"INFO: IDBSchemaRowset is not supported.\n";
|
|
pIDSR = NULL;
|
|
}
|
|
|
|
//check if the index exists.
|
|
if(pIDSR)
|
|
{
|
|
tTR = DoesIndexExist(pIDSR, pTableID, pIndexID, &bIndexExists);
|
|
if(tTR==TEST_PASS)
|
|
TESTC(bIndexExists)
|
|
else if(tTR==TEST_FAIL)
|
|
COMPARE(tTR, TEST_PASS);
|
|
}
|
|
|
|
//Try to create a duplicate index to verify.
|
|
TESTC_(hr = pIID->CreateIndex(pTableID, pIndexID, 1, rgIndexColumnDesc,
|
|
0, NULL, NULL), DB_E_DUPLICATEINDEXID)
|
|
|
|
//Drop the index.
|
|
TESTC_(hr = pIID->DropIndex(pTableID, pIndexID), S_OK)
|
|
|
|
//check if the index has been dropped.
|
|
if(pIDSR)
|
|
{
|
|
tTR = DoesIndexExist(pIDSR, pTableID, pIndexID, &bIndexExists);
|
|
if(tTR==TEST_PASS)
|
|
TESTC(!bIndexExists)
|
|
else if(tTR==TEST_FAIL)
|
|
COMPARE(tTR, TEST_PASS);
|
|
}
|
|
|
|
//Try to drop the index again, to verify.
|
|
TESTC_(hr = pIID->DropIndex(pTableID, pIndexID), DB_E_NOINDEX)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
if(pTable)
|
|
pTable->DropTable();
|
|
SAFE_DELETE(pTable);
|
|
ReleaseDBID(pIndexID, TRUE);
|
|
ReleaseDBID(rgIndexColumnDesc[0].pColumnID, TRUE);
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
PROVIDER_FREE(rgIndexColumnDescOut);
|
|
SAFE_RELEASE(pIDSR);
|
|
SAFE_RELEASE(pIID);
|
|
return tTestResult;
|
|
} //testIIndexDef
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Test IAlterIndex::AlterIndex.
|
|
//
|
|
TESTRESULT CQuickTest::testAlterIndex()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
TESTRESULT tTR = TEST_FAIL;
|
|
HRESULT hr = E_FAIL;
|
|
HRESULT hr1 = E_FAIL;
|
|
BOOL bIndexExists = FALSE;
|
|
DBORDINAL cColumnDesc = 0;
|
|
DBCOLUMNDESC* rgColumnDesc = NULL;
|
|
DBINDEXCOLUMNDESC rgIndexColumnDesc[1];
|
|
DBID* pTableID = NULL;
|
|
DBID* pIndexID = NULL;
|
|
DBID dbidNewIndex;
|
|
IAlterIndex* pIAI = NULL;
|
|
IIndexDefinition* pIID = NULL;
|
|
IDBSchemaRowset* pIDSR = NULL;
|
|
IRowsetIndex* pIRI = NULL;
|
|
|
|
DBORDINAL cKeyColumns = 0;
|
|
DBINDEXCOLUMNDESC * rgIndexColumnDesc2 = NULL;
|
|
ULONG cIndexProperties = 0;
|
|
DBPROPSET * rgIndexProperties = NULL;
|
|
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_IAlterIndex,
|
|
SESSION_INTERFACE,(IUnknown**)&pIAI))
|
|
{
|
|
odtLog<<L"IAlterIndex is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
TESTC(VerifyInterface(m_pIOpenRowset,IID_IIndexDefinition,
|
|
SESSION_INTERFACE,(IUnknown**)&pIID))
|
|
|
|
//Get the column descs.
|
|
TESTC_(m_pTable->BuildColumnDescs(&rgColumnDesc), S_OK)
|
|
cColumnDesc = m_pTable->CountColumnsOnTable();
|
|
pTableID = &(m_pTable->GetTableIDRef());
|
|
|
|
//Create the index column desc.
|
|
SAFE_ALLOC(rgIndexColumnDesc[0].pColumnID, DBID, 1);
|
|
DuplicateDBID(rgColumnDesc[0].dbcid, rgIndexColumnDesc[0].pColumnID);
|
|
rgIndexColumnDesc[0].eIndexColOrder = DBINDEX_COL_ORDER_ASC;
|
|
|
|
//See if IDBSchemaRowset is supported.
|
|
VerifyInterface(m_pIOpenRowset,IID_IDBSchemaRowset,
|
|
SESSION_INTERFACE,(IUnknown**)&pIDSR);
|
|
|
|
//Create the index.
|
|
TESTC_(hr = pIID->CreateIndex(pTableID, NULL, 1, rgIndexColumnDesc,
|
|
0, NULL, &pIndexID), S_OK)
|
|
TESTC(pIndexID != NULL)
|
|
|
|
//Duplicate index id.
|
|
DuplicateDBID(*pIndexID, &dbidNewIndex);
|
|
|
|
//check if the index exists.
|
|
if(pIDSR)
|
|
{
|
|
tTR = DoesIndexExist(pIDSR, pTableID, pIndexID, &bIndexExists);
|
|
if(tTR==TEST_PASS)
|
|
TESTC(bIndexExists)
|
|
else if(tTR==TEST_FAIL)
|
|
COMPARE(tTR, TEST_PASS);
|
|
}
|
|
|
|
//Modify the index name.
|
|
if(dbidNewIndex.eKind == DBKIND_GUID_NAME ||
|
|
dbidNewIndex.eKind == DBKIND_NAME ||
|
|
dbidNewIndex.eKind == DBKIND_PGUID_NAME)
|
|
{
|
|
TESTC(_wcsset(dbidNewIndex.uName.pwszName, 'x') != NULL)
|
|
}
|
|
else
|
|
{
|
|
dbidNewIndex.uName.ulPropid++;
|
|
}
|
|
|
|
//Set some props.
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
SetProperty(DBPROP_INDEX_FILLFACTOR, DBPROPSET_INDEX, &m_cPropSets,
|
|
&m_rgPropSets, (void*)66, DBTYPE_I4, DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
TEST2C_(hr1 = pIAI->AlterIndex(pTableID, pIndexID, &dbidNewIndex,
|
|
m_cPropSets, m_rgPropSets), S_OK, DB_S_ERRORSOCCURRED)
|
|
|
|
//check if the new index exists and old one doesn't exist.
|
|
if(pIDSR)
|
|
{
|
|
tTR = DoesIndexExist(pIDSR, pTableID, &dbidNewIndex, &bIndexExists);
|
|
if(tTR==TEST_PASS)
|
|
TESTC(bIndexExists)
|
|
|
|
tTR = DoesIndexExist(pIDSR, pTableID, pIndexID, &bIndexExists);
|
|
if(tTR==TEST_PASS)
|
|
TESTC(!bIndexExists)
|
|
}
|
|
|
|
//Verify using IRowsetIndex, if it is supported.
|
|
TEST3C_(hr=m_pIOpenRowset->OpenRowset(NULL, pTableID, &dbidNewIndex,
|
|
IID_IRowsetIndex, 0, NULL, (IUnknown**)&pIRI), S_OK, E_NOINTERFACE,
|
|
DB_E_NOINDEX)
|
|
|
|
if(hr == S_OK)
|
|
{
|
|
TESTC_(pIRI->GetIndexInfo(&cKeyColumns, &rgIndexColumnDesc2,
|
|
&cIndexProperties, &rgIndexProperties), S_OK)
|
|
|
|
COMPARE(cKeyColumns, 1);
|
|
COMPARE(rgIndexColumnDesc2[0].eIndexColOrder, rgIndexColumnDesc[0].eIndexColOrder);
|
|
COMPARE(CompareDBID(*rgIndexColumnDesc2[0].pColumnID, *rgIndexColumnDesc[0].pColumnID), TRUE);
|
|
|
|
if(hr1 == S_OK)
|
|
{
|
|
for(ULONG i=0; i<cIndexProperties; i++)
|
|
{
|
|
if(rgIndexProperties[i].guidPropertySet == DBPROPSET_INDEX)
|
|
for(ULONG j=0; j<rgIndexProperties[i].cProperties; j++)
|
|
{
|
|
if(rgIndexProperties[i].rgProperties[j].dwPropertyID == DBPROP_INDEX_FILLFACTOR)
|
|
COMPARE(V_I4(&rgIndexProperties[i].rgProperties[j].vValue), 66);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****
|
|
TEST2C_(hr = pIAI->AlterIndex(pTableID, &dbidNewIndex, pIndexID,
|
|
0, NULL), S_OK, DB_E_TABLEINUSE)
|
|
|
|
if(hr == DB_E_TABLEINUSE)
|
|
{
|
|
SAFE_RELEASE(pIRI);
|
|
TESTC_(hr = pIAI->AlterIndex(pTableID, &dbidNewIndex, pIndexID,
|
|
0, NULL), S_OK)
|
|
}
|
|
*****/
|
|
|
|
SAFE_RELEASE(pIRI);
|
|
TESTC_(hr = pIAI->AlterIndex(pTableID, &dbidNewIndex, pIndexID,
|
|
0, NULL), S_OK)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
ReleaseDBID(pIndexID, TRUE);
|
|
ReleaseDBID(&dbidNewIndex, FALSE);
|
|
ReleaseDBID(rgIndexColumnDesc[0].pColumnID, TRUE);
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
FreeProperties(&cIndexProperties, &rgIndexProperties);
|
|
SAFE_FREE(rgIndexColumnDesc2);
|
|
SAFE_RELEASE(pIRI);
|
|
SAFE_RELEASE(pIID);
|
|
SAFE_RELEASE(pIDSR);
|
|
SAFE_RELEASE(pIAI);
|
|
return tTestResult;
|
|
} //testAlterIndex
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Test IAlterTable::AlterColumn.
|
|
//
|
|
TESTRESULT CQuickTest::testAlterColumn()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = E_FAIL;
|
|
HRESULT hr1 = E_FAIL;
|
|
DBID* pTableID = NULL;
|
|
DBID dbidOld;
|
|
ULONG_PTR ulColFlags = 0;
|
|
DBORDINAL ulCol = 0;
|
|
DBORDINAL cColumns = 0;
|
|
WCHAR* pStringsBuffer = NULL;
|
|
DBCOLUMNINFO* rgInfo = NULL;
|
|
DBCOLUMNDESCFLAGS dwColFlags = 0;
|
|
DBCOLUMNDESC colDesc;
|
|
IColumnsInfo* pICI = NULL;
|
|
IAlterTable* pIAT = NULL;
|
|
|
|
memset(&colDesc, 0, sizeof(DBCOLUMNDESC));
|
|
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_IAlterTable,
|
|
SESSION_INTERFACE,(IUnknown**)&pIAT))
|
|
{
|
|
odtLog<<L"IAlterTable is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
TESTC(GetProperty(DBPROP_ALTERCOLUMN, DBPROPSET_DATASOURCEINFO,
|
|
m_pIDBInitialize, &ulColFlags))
|
|
|
|
pTableID = &(m_pTable->GetTableIDRef());
|
|
|
|
TESTC_(m_pIOpenRowset->OpenRowset(NULL, pTableID, NULL, IID_IColumnsInfo,
|
|
0, NULL, (IUnknown**)&pICI), S_OK)
|
|
|
|
//Call GetColumnInfo.
|
|
TESTC_(pICI->GetColumnInfo(&cColumns,&rgInfo,&pStringsBuffer),S_OK)
|
|
TESTC(cColumns!=0 && rgInfo!=NULL && pStringsBuffer!=NULL)
|
|
|
|
if(cColumns>1)
|
|
ulCol = 1;
|
|
|
|
if(ulColFlags & DBCOLUMNDESCFLAGS_PROPERTIES)
|
|
dwColFlags |= DBCOLUMNDESCFLAGS_PROPERTIES;
|
|
if(ulColFlags & DBCOLUMNDESCFLAGS_DBCID)
|
|
dwColFlags |= DBCOLUMNDESCFLAGS_DBCID;
|
|
|
|
//Duplicate column id.
|
|
DuplicateDBID(rgInfo[ulCol].columnid, &colDesc.dbcid);
|
|
DuplicateDBID(rgInfo[ulCol].columnid, &dbidOld);
|
|
|
|
//Modify the column id.
|
|
if(rgInfo[ulCol].columnid.eKind == DBKIND_GUID_NAME ||
|
|
rgInfo[ulCol].columnid.eKind == DBKIND_NAME ||
|
|
rgInfo[ulCol].columnid.eKind == DBKIND_PGUID_NAME)
|
|
{
|
|
TESTC(_wcsset(colDesc.dbcid.uName.pwszName, 'x') != NULL)
|
|
}
|
|
else
|
|
{
|
|
colDesc.dbcid.uName.ulPropid++;
|
|
}
|
|
|
|
//Set a column property.
|
|
SetProperty(DBPROP_COL_NULLABLE, DBPROPSET_COLUMN, &colDesc.cPropertySets,
|
|
&colDesc.rgPropertySets, (void*)VARIANT_FALSE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
//Release rowset so that the table is not in use.
|
|
SAFE_RELEASE(pICI);
|
|
|
|
TEST2C_(hr1 = pIAT->AlterColumn(pTableID, &rgInfo[ulCol].columnid, dwColFlags,
|
|
&colDesc), S_OK, DB_S_ERRORSOCCURRED)
|
|
|
|
TEST2C_(hr = pIAT->AlterColumn(pTableID, &rgInfo[ulCol].columnid, dwColFlags,
|
|
&colDesc), DB_E_NOCOLUMN, DB_E_DUPLICATECOLUMNID)
|
|
|
|
//Release old column info.
|
|
SAFE_FREE(rgInfo);
|
|
SAFE_FREE(pStringsBuffer);
|
|
|
|
//Call GetColumnInfo.
|
|
TESTC_(m_pIOpenRowset->OpenRowset(NULL, pTableID, NULL, IID_IColumnsInfo,
|
|
0, NULL, (IUnknown**)&pICI), S_OK)
|
|
TESTC_(pICI->GetColumnInfo(&cColumns,&rgInfo,&pStringsBuffer),S_OK)
|
|
TESTC(cColumns!=0 && rgInfo!=NULL && pStringsBuffer!=NULL)
|
|
|
|
COMPARE(CompareDBID(rgInfo[ulCol].columnid, colDesc.dbcid), TRUE);
|
|
if(hr1 == S_OK)
|
|
COMPARE(rgInfo[ulCol].dwFlags & DBCOLUMNFLAGS_ISNULLABLE, 0);
|
|
|
|
//Remove props from the col desc, and set to old col ID.
|
|
FreeProperties(&colDesc.cPropertySets, &colDesc.rgPropertySets);
|
|
colDesc.cPropertySets = 0;
|
|
ReleaseDBID(&colDesc.dbcid, FALSE);
|
|
DuplicateDBID(dbidOld, &colDesc.dbcid);
|
|
|
|
SAFE_RELEASE(pICI);
|
|
|
|
TESTC_(hr = pIAT->AlterColumn(pTableID, &rgInfo[ulCol].columnid, dwColFlags,
|
|
&colDesc), S_OK)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
ReleaseDBID(&dbidOld, FALSE);
|
|
ReleaseDBID(&colDesc.dbcid, FALSE);
|
|
FreeProperties(&colDesc.cPropertySets, &colDesc.rgPropertySets);
|
|
SAFE_FREE(rgInfo);
|
|
SAFE_FREE(pStringsBuffer);
|
|
SAFE_RELEASE(pICI);
|
|
SAFE_RELEASE(pIAT);
|
|
return tTestResult;
|
|
} //testAlterColumn
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Test IAlterTable::AlterTable.
|
|
//
|
|
TESTRESULT CQuickTest::testAlterTable()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = E_FAIL;
|
|
HRESULT hr1 = E_FAIL;
|
|
DBID* pTableID = NULL;
|
|
DBID dbidNew;
|
|
IAlterTable* pIAT = NULL;
|
|
IRowset* pIR = NULL;
|
|
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_IAlterTable,
|
|
SESSION_INTERFACE,(IUnknown**)&pIAT))
|
|
{
|
|
odtLog<<L"IAlterTable is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
pTableID = &(m_pTable->GetTableIDRef());
|
|
|
|
//Duplicate index id.
|
|
DuplicateDBID(*pTableID, &dbidNew);
|
|
|
|
//Modify the index name.
|
|
if(dbidNew.eKind == DBKIND_GUID_NAME ||
|
|
dbidNew.eKind == DBKIND_NAME ||
|
|
dbidNew.eKind == DBKIND_PGUID_NAME)
|
|
{
|
|
TESTC(_wcsset(dbidNew.uName.pwszName, 'x') != NULL)
|
|
}
|
|
else
|
|
{
|
|
dbidNew.uName.ulPropid++;
|
|
}
|
|
|
|
//Set some props.
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
SetProperty(DBPROP_TBL_TEMPTABLE, DBPROPSET_TABLE, &m_cPropSets,
|
|
&m_rgPropSets, (void*)VARIANT_FALSE, DBTYPE_BOOL, DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
TEST3C_(hr1 = pIAT->AlterTable(pTableID, &dbidNew,
|
|
m_cPropSets, m_rgPropSets), S_OK, DB_S_ERRORSOCCURRED,
|
|
DB_E_DUPLICATETABLEID)
|
|
|
|
//If table with that name exists, try once more with another name.
|
|
if(hr1 == DB_E_DUPLICATETABLEID)
|
|
{
|
|
if(dbidNew.eKind == DBKIND_GUID_NAME ||
|
|
dbidNew.eKind == DBKIND_NAME ||
|
|
dbidNew.eKind == DBKIND_PGUID_NAME)
|
|
{
|
|
odtLog<<L"INFO: A table with name "<<dbidNew.uName.pwszName<<L" already exists.\n";
|
|
TESTC(_wcsset(dbidNew.uName.pwszName, 'z') != NULL)
|
|
}
|
|
else
|
|
{
|
|
odtLog<<L"INFO: A table with propid "<<dbidNew.uName.ulPropid<<L" already exists.\n";
|
|
dbidNew.uName.ulPropid++;
|
|
}
|
|
|
|
TEST3C_(hr1 = pIAT->AlterTable(pTableID, &dbidNew,
|
|
m_cPropSets, m_rgPropSets), S_OK, DB_S_ERRORSOCCURRED,
|
|
DB_E_DUPLICATETABLEID)
|
|
|
|
if(hr1 == DB_E_DUPLICATETABLEID)
|
|
{
|
|
if(dbidNew.eKind == DBKIND_GUID_NAME ||
|
|
dbidNew.eKind == DBKIND_NAME ||
|
|
dbidNew.eKind == DBKIND_PGUID_NAME)
|
|
odtLog<<L"INFO: A table with name "<<dbidNew.uName.pwszName<<L" already exists.\n";
|
|
else
|
|
odtLog<<L"INFO: A table with propid "<<dbidNew.uName.ulPropid<<L" already exists.\n";
|
|
|
|
tTestResult = TEST_PASS;
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
//check if the new table exists and old one doesn't exist.
|
|
|
|
TESTC_(m_pIOpenRowset->OpenRowset(NULL, pTableID, NULL,
|
|
IID_IRowset, 0, NULL, (IUnknown**)&pIR), DB_E_NOTABLE)
|
|
TESTC_(m_pIOpenRowset->OpenRowset(NULL, &dbidNew, NULL,
|
|
IID_IRowset, 0, NULL, (IUnknown**)&pIR), S_OK)
|
|
|
|
/*****
|
|
//Restore old table name.
|
|
TEST2C_(hr1 = pIAT->AlterTable(&dbidNew, pTableID,
|
|
0, NULL), S_OK, DB_E_TABLEINUSE)
|
|
|
|
if(hr == DB_E_TABLEINUSE)
|
|
{
|
|
SAFE_RELEASE(pIR);
|
|
TESTC_(hr1 = pIAT->AlterTable(&dbidNew, pTableID,
|
|
0, NULL), S_OK)
|
|
}
|
|
*****/
|
|
|
|
SAFE_RELEASE(pIR);
|
|
TESTC_(hr1 = pIAT->AlterTable(&dbidNew, pTableID,
|
|
0, NULL), S_OK)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
ReleaseDBID(&dbidNew, FALSE);
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
SAFE_RELEASE(pIR);
|
|
SAFE_RELEASE(pIAT);
|
|
return tTestResult;
|
|
} //testAlterTable
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Test the ITableDefinitionWithConstraints interface.
|
|
//
|
|
TESTRESULT CQuickTest::testAddAndDropConstraint()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = E_FAIL;
|
|
HRESULT hr1 = E_FAIL;
|
|
DBID* pTableID = NULL;
|
|
DBID dbidCons;
|
|
DBCONSTRAINTDESC dbConDesc;
|
|
DBCOLUMNDESC* rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = 0;
|
|
CTable* pTable = NULL;
|
|
CList <WCHAR*, WCHAR*> ListNativeTemp;
|
|
CList <DBTYPE, DBTYPE> ListDataTypes;
|
|
ITableDefinitionWithConstraints* pITDWC = NULL;
|
|
|
|
memset(&dbConDesc, 0, sizeof(DBCONSTRAINTDESC));
|
|
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_ITableDefinitionWithConstraints,
|
|
SESSION_INTERFACE,(IUnknown**)&pITDWC))
|
|
{
|
|
odtLog<<L"ITableDefinitionWithConstraints is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
pTable = new CTable(m_pIOpenRowset, (LPWSTR)gwszModuleName);
|
|
TESTC(pTable != NULL)
|
|
|
|
//Create column information, initializes column list with columns
|
|
//of specified types. Can get DB_S_ENDOFROWSET.
|
|
TESTC_(hr=pTable->CreateColInfo(ListNativeTemp, ListDataTypes,
|
|
ALLTYPES), S_OK)
|
|
|
|
//build the column description array
|
|
TESTC_(hr=pTable->BuildColumnDescs(&rgColumnDesc), S_OK)
|
|
|
|
cColumnDesc = pTable->CountColumnsOnTable();
|
|
|
|
//Create table with the column descriptions obtained from pTable.
|
|
TESTC_(hr = pITDWC->CreateTable(NULL, NULL, cColumnDesc,
|
|
rgColumnDesc, IID_IRowsetInfo, 0, NULL,
|
|
&pTableID, NULL), S_OK)
|
|
|
|
TESTC(pTableID != NULL)
|
|
|
|
//Build the DBCONSTRAINTDESC structure.
|
|
dbidCons.eKind = DBKIND_NAME;
|
|
dbidCons.uName.pwszName = L"QuikTest_CN1";
|
|
dbConDesc.pConstraintID = &dbidCons;
|
|
dbConDesc.ConstraintType = DBCONSTRAINTTYPE_UNIQUE;
|
|
dbConDesc.cColumns = 1;
|
|
dbConDesc.rgColumnList = &(rgColumnDesc[0].dbcid);
|
|
|
|
TESTC_(hr1 = pITDWC->AddConstraint(pTableID, &dbConDesc), S_OK)
|
|
|
|
if(cColumnDesc>1)
|
|
{
|
|
dbConDesc.rgColumnList = &(rgColumnDesc[1].dbcid);
|
|
CHECK(hr1 = pITDWC->AddConstraint(pTableID, &dbConDesc), DB_E_DUPLICATECONSTRAINTID);
|
|
}
|
|
|
|
TESTC_(hr1 = pITDWC->DropConstraint(pTableID, &dbidCons), S_OK)
|
|
TESTC_(hr1 = pITDWC->DropConstraint(pTableID, &dbidCons), DB_E_NOCONSTRAINT)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
if(pTableID)
|
|
{
|
|
CHECK(hr=pITDWC->DropTable(pTableID), S_OK);
|
|
ReleaseDBID(pTableID, TRUE);
|
|
}
|
|
SAFE_RELEASE(pITDWC);
|
|
if(pTable)
|
|
pTable->DropTable();
|
|
SAFE_DELETE(pTable);
|
|
return tTestResult;
|
|
} //testAddAndDropConstraint
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Test the ITableDefinitionWithConstraints interface.
|
|
//
|
|
TESTRESULT CQuickTest::testCreateTableWithConstraints()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = E_FAIL;
|
|
DBID dbidCons;
|
|
DBID dbidCons2;
|
|
DBCONSTRAINTDESC rgdbConDesc[2];
|
|
BOOL fExists = FALSE;
|
|
DBID* pNewTableID = NULL;
|
|
DBCOLUMNDESC* rgColumnDesc = NULL;
|
|
DBORDINAL cColumnDesc = 0;
|
|
CTable* pTable = NULL;
|
|
CList <WCHAR*, WCHAR*> ListNativeTemp;
|
|
CList <DBTYPE, DBTYPE> ListDataTypes;
|
|
ITableDefinitionWithConstraints* pITDWC = NULL;
|
|
|
|
memset(rgdbConDesc, 0, 2*sizeof(DBCONSTRAINTDESC));
|
|
|
|
if(!VerifyInterface(m_pIOpenRowset,IID_ITableDefinitionWithConstraints,
|
|
SESSION_INTERFACE,(IUnknown**)&pITDWC))
|
|
{
|
|
odtLog<<L"ITableDefinitionWithConstraints is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
pTable = new CTable(m_pIOpenRowset, (LPWSTR)gwszModuleName);
|
|
TESTC(pTable != NULL)
|
|
|
|
//Create column information, initializes column list with columns
|
|
//of specified types. Can get DB_S_ENDOFROWSET.
|
|
TESTC_(hr=pTable->CreateColInfo(ListNativeTemp, ListDataTypes,
|
|
ALLTYPES), S_OK)
|
|
|
|
//build the column description array
|
|
TESTC_(hr=pTable->BuildColumnDescs(&rgColumnDesc), S_OK)
|
|
|
|
cColumnDesc = pTable->CountColumnsOnTable();
|
|
|
|
//Setting the following property is not required.
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &m_cPropSets,
|
|
&m_rgPropSets) ;
|
|
|
|
//Build the DBCONSTRAINTDESC structure.
|
|
dbidCons.eKind = DBKIND_NAME;
|
|
dbidCons.uName.pwszName = L"QuikTest_CN1";
|
|
rgdbConDesc[0].pConstraintID = &dbidCons;
|
|
rgdbConDesc[0].ConstraintType = DBCONSTRAINTTYPE_UNIQUE;
|
|
rgdbConDesc[0].cColumns = 1;
|
|
rgdbConDesc[0].rgColumnList = &(rgColumnDesc[0].dbcid);
|
|
|
|
dbidCons2.eKind = DBKIND_NAME;
|
|
dbidCons2.uName.pwszName = L"QuikTest_CN2";
|
|
rgdbConDesc[1].pConstraintID = &dbidCons2;
|
|
rgdbConDesc[1].ConstraintType = DBCONSTRAINTTYPE_UNIQUE;
|
|
rgdbConDesc[1].cColumns = 1;
|
|
rgdbConDesc[1].rgColumnList = &(rgColumnDesc[1].dbcid);
|
|
|
|
//Create table with the column descriptions obtained from pTable.
|
|
TESTC_(hr = pITDWC->CreateTableWithConstraints(NULL, NULL,
|
|
cColumnDesc, rgColumnDesc, 2, rgdbConDesc, IID_NULL, 0, NULL,
|
|
&pNewTableID, NULL), S_OK)
|
|
|
|
//Make sure the table exists.
|
|
CHECK(hr = pTable->DoesTableExist(pNewTableID, &fExists), S_OK) ;
|
|
TESTC(fExists)
|
|
|
|
TESTC_(hr = pITDWC->DropConstraint(pNewTableID, &dbidCons), S_OK)
|
|
TESTC_(hr = pITDWC->DropConstraint(pNewTableID, &dbidCons2), S_OK)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
ReleaseColumnDesc(rgColumnDesc, cColumnDesc);
|
|
if(pNewTableID)
|
|
{
|
|
CHECK(pITDWC->DropTable(pNewTableID), S_OK);
|
|
ReleaseDBID(pNewTableID, TRUE);
|
|
}
|
|
SAFE_DELETE(pTable);
|
|
SAFE_RELEASE(pITDWC);
|
|
return tTestResult;
|
|
} //testCreateTableWithConstraints
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Aggregate a session object and test it.
|
|
//
|
|
TESTRESULT CQuickTest::testAggregateSession(IDBCreateSession* pIDBCreateSession)
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
IUnknown* pIUnkInner = NULL;
|
|
|
|
CAggregate Aggregate(pIDBCreateSession);
|
|
|
|
//Aggregation
|
|
hr = CreateNewSession(NULL, IID_IUnknown, (IUnknown**)&pIUnkInner, &Aggregate);
|
|
Aggregate.SetUnkInner(pIUnkInner);
|
|
|
|
//Check if aggregation is supported.
|
|
if(hr==DB_E_NOAGGREGATION)
|
|
{
|
|
odtLog<<"Aggregation is not supported.\n";
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Verify Aggregation for this session...
|
|
TESTC(Aggregate.VerifyAggregationQI(hr, IID_IOpenRowset))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIUnkInner);
|
|
return tTestResult;
|
|
} //testAggregateSession
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Obtain the IConvertType interface from the IRowset interface or
|
|
//from ICommand interface. Use its CanConvert method to check for
|
|
//certain conversions.
|
|
//
|
|
TESTRESULT CQuickTest::testIConvertType()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
HRESULT Exphr = S_OK;
|
|
BOOL fRowsetCnvtOnCmd = FALSE;
|
|
BOOL bDBTIME = FALSE;
|
|
BOOL bNUMERIC = FALSE;
|
|
BOOL bSTR = FALSE;
|
|
BOOL bBYTES = FALSE;
|
|
IConvertType* pICT = NULL;
|
|
|
|
//COMMAND object.
|
|
if(m_pICommand)
|
|
{
|
|
if(!VerifyInterface(m_pICommand,IID_IConvertType,
|
|
COMMAND_INTERFACE,(IUnknown **)&pICT))
|
|
return TEST_FAIL;
|
|
|
|
// Check to see if conversion is supported on the command
|
|
if(GetProperty(DBPROP_ROWSETCONVERSIONSONCOMMAND,
|
|
DBPROPSET_DATASOURCEINFO, m_pIDBInitialize))
|
|
fRowsetCnvtOnCmd = TRUE;
|
|
}
|
|
//ROWSET object.
|
|
else if(m_pIRowset)
|
|
{
|
|
if(!VerifyInterface(m_pIRowset,IID_IConvertType,
|
|
ROWSET_INTERFACE,(IUnknown **)&pICT))
|
|
return TEST_FAIL;
|
|
|
|
fRowsetCnvtOnCmd = TRUE;
|
|
}
|
|
//ROW object.
|
|
else
|
|
{
|
|
TESTC(m_pIRow != NULL)
|
|
|
|
if(!VerifyInterface(m_pIRow,IID_IConvertType,
|
|
ROW_INTERFACE,(IUnknown **)&pICT))
|
|
return TEST_FAIL;
|
|
|
|
fRowsetCnvtOnCmd = TRUE;
|
|
}
|
|
|
|
TESTC(m_pTable != NULL)
|
|
|
|
GetProviderTypes(m_pTable);
|
|
|
|
if(IsSupportedType(DBTYPE_DBTIME))
|
|
bDBTIME = TRUE;
|
|
if(IsSupportedType(DBTYPE_NUMERIC))
|
|
bNUMERIC = TRUE;
|
|
if(IsSupportedType(DBTYPE_STR))
|
|
bSTR = TRUE;
|
|
if(IsSupportedType(DBTYPE_BYTES))
|
|
bBYTES = TRUE;
|
|
|
|
//S_FALSE: The following conversion should not be supported.
|
|
if(fRowsetCnvtOnCmd)
|
|
Exphr = S_FALSE;
|
|
else
|
|
Exphr = DB_E_BADCONVERTFLAG;
|
|
|
|
if(bNUMERIC && bDBTIME)
|
|
CHECK(hr=pICT->CanConvert(DBTYPE_NUMERIC, DBTYPE_DBTIME,
|
|
DBCONVERTFLAGS_COLUMN), Exphr);
|
|
|
|
//S_OK: The following conversions should be supported.
|
|
if(fRowsetCnvtOnCmd)
|
|
Exphr = S_OK;
|
|
else
|
|
Exphr = DB_E_BADCONVERTFLAG;
|
|
|
|
CHECK(hr=pICT->CanConvert(DBTYPE_WSTR, DBTYPE_WSTR,
|
|
DBCONVERTFLAGS_COLUMN),Exphr);
|
|
|
|
if(bSTR)
|
|
CHECK(hr=pICT->CanConvert(DBTYPE_STR, DBTYPE_WSTR,
|
|
DBCONVERTFLAGS_COLUMN),Exphr);
|
|
|
|
if(bBYTES)
|
|
CHECK(hr=pICT->CanConvert(DBTYPE_BYTES, DBTYPE_WSTR,
|
|
DBCONVERTFLAGS_COLUMN),Exphr);
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(m_rgProviderTypes);
|
|
SAFE_RELEASE(pICT);
|
|
return tTestResult;
|
|
} //testIConvertType
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc The IColumnsInfo interface passed in could belong to either a
|
|
//rowset or a command object. Get the column info by using the
|
|
//GetColumnInfo method. Verify the number of columns. Also verify the
|
|
//values in the DBCOLUMNINFO structures. Obtain CCol structures by
|
|
//calling CTable::GetCloInfo and use these to verify the column info
|
|
//returned by the GetColumnInfo method call.
|
|
//
|
|
TESTRESULT CQuickTest::testGetColumnInfo(IUnknown* pIUnknown)
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
BOOL fColIDWarning = FALSE;
|
|
DBORDINAL ulIndex = 0;
|
|
DBORDINAL cColumns = 0;
|
|
CCol rgCol;
|
|
WCHAR* pStringsBuffer = NULL;
|
|
DBCOLUMNINFO* rgInfo = NULL;
|
|
IColumnsInfo* pIColumnsInfo = NULL;
|
|
|
|
TESTC(pIUnknown != NULL)
|
|
|
|
//Get IColumnsInfo.
|
|
TESTC_(hr = pIUnknown->QueryInterface(IID_IColumnsInfo, (void**)
|
|
&pIColumnsInfo), S_OK)
|
|
|
|
//Call GetColumnInfo.
|
|
TESTC_(pIColumnsInfo->GetColumnInfo(&cColumns,&rgInfo,&pStringsBuffer)
|
|
,S_OK)
|
|
TESTC(cColumns!=0 && rgInfo!=NULL && pStringsBuffer!=NULL)
|
|
|
|
//Verify the number of columns.
|
|
if(rgInfo[0].iOrdinal==0)
|
|
TESTC(cColumns-1 == m_pTable->CountColumnsOnTable())
|
|
else
|
|
TESTC(cColumns == m_pTable->CountColumnsOnTable())
|
|
|
|
//Verify the DBCOLUMNINFO values.
|
|
for(ulIndex=0; ulIndex<cColumns; ulIndex++)
|
|
{
|
|
//Ignore the bookmarks column if it exists.
|
|
if((ulIndex==0)&&(rgInfo[ulIndex].iOrdinal==0))
|
|
{
|
|
// Check for the Bookmark FLAG.
|
|
TESTC(rgInfo[ulIndex].dwFlags & DBCOLUMNFLAGS_ISBOOKMARK)
|
|
|
|
continue;
|
|
}
|
|
|
|
//Verify the ordinal value.
|
|
TESTC(rgInfo[ulIndex].iOrdinal == ulIndex+rgInfo[0].iOrdinal)
|
|
|
|
//Get the CCol structure for this column.
|
|
TESTC_(hr=m_pTable->GetColInfo(rgInfo[ulIndex].iOrdinal, rgCol),
|
|
S_OK)
|
|
|
|
//Verify the column name.
|
|
if((rgInfo[ulIndex].pwszName)&&(rgCol.GetColName()))
|
|
TESTC(wcscmp(rgInfo[ulIndex].pwszName,
|
|
rgCol.GetColName()) == 0)
|
|
else
|
|
TESTC((rgInfo[ulIndex].pwszName == NULL)&&
|
|
(rgCol.GetColName() == NULL))
|
|
|
|
//ITypeInfo is reserved for future use.
|
|
TESTC(rgInfo[ulIndex].pTypeInfo == rgCol.GetTypeInfo())
|
|
|
|
//Verify the DBTYPE.
|
|
TESTC(rgInfo[ulIndex].wType == rgCol.GetProviderType())
|
|
|
|
//Compare the column IDs.
|
|
if(!CompareDBID(rgInfo[ulIndex].columnid, *(rgCol.GetColID())))
|
|
{
|
|
TESTC(rgInfo[ulIndex].columnid.eKind !=
|
|
(*(rgCol.GetColID())).eKind)
|
|
fColIDWarning = TRUE;
|
|
}
|
|
}
|
|
if(fColIDWarning)
|
|
{
|
|
//Issue a warning.
|
|
COMPAREW(fColIDWarning, FALSE);
|
|
odtLog<<L"WARNING: ColID returned is of different DBKIND.\n";
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIColumnsInfo);
|
|
PROVIDER_FREE(rgInfo);
|
|
PROVIDER_FREE(pStringsBuffer);
|
|
return tTestResult;
|
|
} //testGetColumnInfo
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc The IColumnsInfo interface passed in could belong to either a
|
|
//rowset or a command object. Get the column info and use
|
|
//it to make an array of DBIDs. The method MapColumnIDs is called with
|
|
//the constructed array of DBIDs. Verify the returned list of ordinals.
|
|
//
|
|
TESTRESULT CQuickTest::testMapColumnIDs(IUnknown* pIUnknown)
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBORDINAL ulIndex = 0;
|
|
DBORDINAL cColumns = 0;
|
|
DBCOLUMNINFO* rgInfo = NULL;
|
|
WCHAR* pStringsBuffer = NULL;
|
|
DBID* rgColumnIDs = NULL;
|
|
DBORDINAL* rgColumns = NULL;
|
|
IColumnsInfo* pIColumnsInfo = NULL;
|
|
|
|
TESTC(pIUnknown != NULL)
|
|
|
|
//Get IColumnsInfo.
|
|
TESTC_(hr = pIUnknown->QueryInterface(IID_IColumnsInfo, (void**)
|
|
&pIColumnsInfo), S_OK)
|
|
|
|
//Get the Column DBIDs
|
|
TESTC_(hr=pIColumnsInfo->GetColumnInfo(&cColumns, &rgInfo,
|
|
&pStringsBuffer),S_OK)
|
|
|
|
//Make array of DBIDs
|
|
TESTC((cColumns>0) && (rgInfo!=NULL))
|
|
|
|
//Allocate memory for the array of DBID's
|
|
SAFE_ALLOC(rgColumnIDs, DBID, sizeof(DBID) * cColumns)
|
|
|
|
//Copy values into members
|
|
for(ulIndex=0; ulIndex<cColumns; ulIndex++)
|
|
memcpy(&(rgColumnIDs[ulIndex]),&(rgInfo[ulIndex].columnid),
|
|
sizeof(DBID));
|
|
|
|
//Allocate memory for the array of DBID's
|
|
SAFE_ALLOC(rgColumns, DBORDINAL, sizeof(DBORDINAL) * cColumns)
|
|
|
|
//Initialize the values to invalid values.
|
|
for(ulIndex=0; ulIndex<cColumns; ulIndex++)
|
|
rgColumns[ulIndex] = DB_INVALIDCOLUMN;
|
|
|
|
//run testing interface, validate params
|
|
TESTC_(hr=pIColumnsInfo->MapColumnIDs(cColumns,
|
|
rgColumnIDs, rgColumns),S_OK)
|
|
|
|
//Loop thru the IDs to see if they are valid.
|
|
for(ulIndex = 0; ulIndex<cColumns; ulIndex++)
|
|
{
|
|
TESTC(rgColumns[ulIndex] != DB_INVALIDCOLUMN)
|
|
TESTC(rgColumns[ulIndex] < ULONG_MAX)
|
|
TESTC(rgColumns[ulIndex] == rgInfo[ulIndex].iOrdinal)
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIColumnsInfo);
|
|
PROVIDER_FREE(rgInfo);
|
|
PROVIDER_FREE(pStringsBuffer);
|
|
PROVIDER_FREE(rgColumnIDs);
|
|
PROVIDER_FREE(rgColumns);
|
|
return tTestResult;
|
|
} //testMapColumnIDs
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Obtain the IAccesssor interface through the IRowset interface.
|
|
//Create bindings and then create an accessor with this binding. The
|
|
//length, status and value fields are bound. All columns are bound
|
|
//including BLOB_LONG. Verify the status of the bindings after creating
|
|
//the accessor. Use this accessor to fetch all the rows of the table and
|
|
//verify their data. Then call the method GetBindings and verify that
|
|
//they are the same as the ones used to create the accessor. After the
|
|
//verifications, call the method ReleaseAccessor.
|
|
//
|
|
TESTRESULT CQuickTest::testIAccessor()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBCOUNTITEM ulIndex = 0;
|
|
DBROWCOUNT cRows = 0;
|
|
DBORDINAL cCols = 0;
|
|
DBORDINAL cRowsetCols = 0;
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
DBBINDSTATUS* rgStatus = NULL;
|
|
DBCOLUMNINFO* rgInfo = NULL;
|
|
WCHAR* pStringsBuffer = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
DBBINDING* rgBindings = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
IAccessor* pIAccessor = NULL;
|
|
|
|
//Obtain the IAccessor interface.
|
|
if(!VerifyInterface(m_pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
return TEST_FAIL;
|
|
|
|
//Create Accessor with a binding using length, status and value.
|
|
//All columns are bound including BLOB_LONG.
|
|
TESTC_(GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,
|
|
&hAccessor, &rgBindings, &cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, &rgInfo,
|
|
&cCols, &pStringsBuffer, DBTYPE_EMPTY, 0, NULL, NULL,
|
|
NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_LONG,
|
|
&rgStatus),S_OK)
|
|
|
|
//Verify status of bindings.
|
|
for(ulIndex=0; ulIndex<cBindings; ulIndex++)
|
|
TESTC(rgStatus[ulIndex] == DBBINDSTATUS_OK)
|
|
|
|
//Get list of ordinals.
|
|
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols,
|
|
&rgColumnsOrd, NULL, NULL, NULL, NULL))
|
|
|
|
//Get number of rows.
|
|
cRows = m_pTable->CountRowsOnTable();
|
|
|
|
//Donot call RestartPosition. We should be at the beginning of
|
|
//the rowset.
|
|
|
|
//For each row in the table, fetch the row, compare the data in the
|
|
//row and release the row.
|
|
for(ulIndex=0; ulIndex< (DBCOUNTITEM)cRows; ulIndex++)
|
|
TESTC(GetDataAndCompare(0, 1, ulIndex+1, cRowsetCols,
|
|
rgColumnsOrd, m_pIRowset, hAccessor, cBindings,
|
|
rgBindings, cbRowSize))
|
|
|
|
//Call the IAccessor::GetBindings method and verify.
|
|
TESTC(VerifyBindings(pIAccessor, hAccessor, cBindings, rgBindings,
|
|
DBACCESSOR_ROWDATA))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(rgInfo);
|
|
PROVIDER_FREE(pStringsBuffer);
|
|
PROVIDER_FREE(rgStatus);
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
return tTestResult;
|
|
} //testIAccessor
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc This function is used to test IRowsetInfo::GetProperties and
|
|
//ICommandProperties::GetProperties. Obtain the appropriate interface,
|
|
//IRowsetInfo or ICommandProperties. Construct a DBPROPIDSET with four
|
|
//properties. Call the GetProperties method with this DBPROPIDSET. Verify
|
|
//the returned values and properties. Then call the GetProperties method
|
|
//again with (0,NULL) to get ALL supported rowset properties. Verify the
|
|
//returned values and properties.
|
|
//
|
|
TESTRESULT CQuickTest::testRowsetGetProp(IUnknown* pIUnknown)
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG ulSupported = 0;
|
|
ULONG iSet=0, iProp=0;
|
|
ULONG cPropSets = 0;
|
|
DBPROP* pProp = NULL;
|
|
DBPROPSET* rgPropSets = NULL;
|
|
|
|
//IUnknown could either be IRowset or ICommand.
|
|
IRowsetInfo* pIRowsetInfo = NULL;
|
|
ICommandProperties* pICommandProperties = NULL;
|
|
|
|
if(!pIUnknown)
|
|
return TEST_FAIL;
|
|
|
|
//Get FOUR properties
|
|
FreeProperties(&m_cPropIDSets, &m_rgPropIDSets);
|
|
|
|
//make DBPROPIDSET with FOUR properties in it.
|
|
SetPropID(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET);
|
|
SetPropID(DBPROP_OWNUPDATEDELETE, DBPROPSET_ROWSET);
|
|
SetPropID(DBPROP_OWNINSERT, DBPROPSET_ROWSET);
|
|
SetPropID(DBPROP_REMOVEDELETED, DBPROPSET_ROWSET);
|
|
|
|
//Call GetProperties with the above made DBPROPIDSET.
|
|
|
|
// IID_IRowsetInfo
|
|
if((hr=pIUnknown->QueryInterface(IID_IRowsetInfo, (void **)
|
|
&pIRowsetInfo))==S_OK)
|
|
hr = pIRowsetInfo->GetProperties(m_cPropIDSets, m_rgPropIDSets,
|
|
&cPropSets, &rgPropSets);
|
|
// IID_ICommandProperties
|
|
else if((hr=pIUnknown->QueryInterface(IID_ICommandProperties,
|
|
(void **)&pICommandProperties))==S_OK)
|
|
hr = pICommandProperties->GetProperties(m_cPropIDSets,
|
|
m_rgPropIDSets, &cPropSets, &rgPropSets);
|
|
|
|
//Verify that 1 DBPROPSET was returned.
|
|
TESTC((cPropSets==1)&&(rgPropSets != NULL))
|
|
|
|
//Verify the guid of property set and count.
|
|
COMPARE(rgPropSets[0].guidPropertySet, DBPROPSET_ROWSET);
|
|
COMPARE(rgPropSets[0].cProperties, m_rgPropIDSets[0].cPropertyIDs);
|
|
|
|
//Check the status of properties against the return code.
|
|
if(hr == S_OK)
|
|
{
|
|
for(iProp=0; iProp<rgPropSets[0].cProperties; iProp++)
|
|
{
|
|
pProp = &(rgPropSets[0].rgProperties[iProp]) ;
|
|
|
|
//Verify status.
|
|
COMPARE(pProp->dwStatus, DBPROPSTATUS_OK);
|
|
|
|
//Verify the variant.
|
|
COMPARE((V_VT(&pProp->vValue) == VT_BOOL) ||
|
|
(V_VT(&pProp->vValue) == VT_EMPTY), TRUE);
|
|
}
|
|
}
|
|
else if(hr == DB_S_ERRORSOCCURRED)
|
|
{
|
|
for(iProp=0; iProp<rgPropSets[0].cProperties; iProp++)
|
|
{
|
|
pProp = &(rgPropSets[0].rgProperties[iProp]) ;
|
|
|
|
//Verify status.
|
|
if(pProp->dwStatus != DBPROPSTATUS_OK)
|
|
{
|
|
//SupportedProperty() should return FALSE.
|
|
COMPARE(SupportedProperty(pProp->dwPropertyID,
|
|
DBPROPSET_ROWSET), FALSE);
|
|
|
|
//CANHOLDROWS cannot be among the not supported props.
|
|
COMPARE(pProp->dwPropertyID != DBPROP_CANHOLDROWS, TRUE);
|
|
}
|
|
else
|
|
ulSupported++;
|
|
}
|
|
|
|
//At least one prop has to be supported for this return code.
|
|
//Also, all props cannot be supported for this return code.
|
|
COMPARE(ulSupported >0, TRUE);
|
|
COMPARE(ulSupported <4, TRUE);
|
|
}
|
|
else
|
|
{
|
|
//At least CANHOLDROWS has to be supported.
|
|
TESTC_(hr, S_OK)
|
|
}
|
|
FreeProperties(&cPropSets, &rgPropSets);
|
|
|
|
//Get ALL properties.
|
|
|
|
if(pIRowsetInfo != NULL)
|
|
hr = pIRowsetInfo->GetProperties(0, NULL, &cPropSets, &rgPropSets);
|
|
// IID_ICommandProperties
|
|
else
|
|
{
|
|
TESTC(pICommandProperties != NULL)
|
|
hr = pICommandProperties->GetProperties(0, NULL, &cPropSets,
|
|
&rgPropSets);
|
|
}
|
|
|
|
//At least CANHOLDROWS should be supported.
|
|
TESTC_(hr, S_OK)
|
|
|
|
//Check return values.
|
|
TESTC((cPropSets!=0) && (rgPropSets!=NULL))
|
|
|
|
//Loop through the property sets.
|
|
for(iSet=0; iSet<cPropSets; iSet++)
|
|
{
|
|
//Check to see if the Provider has returned an invalid PropSets
|
|
if( (rgPropSets[iSet].guidPropertySet == DBPROPSET_COLUMN) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_DATASOURCE) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_DATASOURCEINFO) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_DBINIT) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_INDEX) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_PROPERTIESINERROR) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_SESSION)||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_TABLE) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_DATASOURCEALL) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_ROWSETALL) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_SESSIONALL) ||
|
|
(rgPropSets[iSet].guidPropertySet == DBPROPSET_DBINITALL) )
|
|
{
|
|
odtLog<<L"ERROR: An Invalid OLEDB PropertySet has been returned by GetProperties!\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
if(rgPropSets[iSet].guidPropertySet != DBPROPSET_ROWSET)
|
|
{
|
|
odtLog<<L"INFO: Found a provider specific property set.\n";
|
|
}
|
|
|
|
//Loop through the properties.
|
|
for(iProp=0; iProp<rgPropSets[iSet].cProperties; iProp++)
|
|
{
|
|
pProp = &(rgPropSets[iSet].rgProperties[iProp]);
|
|
|
|
//Verify if status is DBPROPSTATUS_OK.
|
|
COMPARE(pProp->dwStatus, DBPROPSTATUS_OK);
|
|
|
|
//For the properties DBPROP_CANHOLDROWS, DBPROP_OWNINSERT,
|
|
//DBPROP_OWNUPDATEDELETE and DBPROP_REMOVEDELETED verify
|
|
//if the variant type is VT_BOOL or VT_EMPTY.
|
|
if((rgPropSets[iSet].guidPropertySet == DBPROPSET_ROWSET)&&
|
|
((pProp->dwPropertyID==DBPROP_CANHOLDROWS) ||
|
|
(pProp->dwPropertyID==DBPROP_OWNUPDATEDELETE) ||
|
|
(pProp->dwPropertyID==DBPROP_OWNINSERT) ||
|
|
(pProp->dwPropertyID==DBPROP_REMOVEDELETED)))
|
|
{
|
|
if(V_VT(&pProp->vValue) == VT_BOOL)
|
|
{
|
|
COMPARE(CheckVariant(&pProp->vValue), TRUE);
|
|
}
|
|
else
|
|
{
|
|
COMPARE(V_VT(&pProp->vValue), VT_EMPTY);
|
|
}
|
|
}
|
|
|
|
//For certain variant types do some checking.
|
|
COMPARE(CheckVariant(&pProp->vValue), TRUE);
|
|
}
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
FreeProperties(&cPropSets, &rgPropSets);
|
|
FreeProperties(&m_cPropIDSets, &m_rgPropIDSets);
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
SAFE_RELEASE(pICommandProperties);
|
|
return tTestResult;
|
|
} //testRowsetGetProp
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Obtain the IRowsetInfo interface. Call the method
|
|
//GetReferencedRowset. Pass it the ordinal of the bookmark column which
|
|
//is used to obtain the rowset corresponding to these
|
|
//bookmarks. Verify that the obtained IRowset interface is the same as
|
|
//the one we got on generating this rowset.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowsetInfoGetRefRowset()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
BOOL bBookmarksSupp = FALSE;
|
|
IRowset* pIRowset = NULL;
|
|
IRowsetInfo* pIRI = NULL;
|
|
|
|
//Obtain the IRowsetInfo interface.
|
|
if(!VerifyInterface(m_pIRowset,IID_IRowsetInfo,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRI))
|
|
return TEST_FAIL;
|
|
|
|
if(GetProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET,
|
|
(IUnknown*)m_pIRowset))
|
|
bBookmarksSupp = TRUE;
|
|
|
|
//Use the method to obtain the IRowset interface and verify it is
|
|
//the same as the one we got on creating the rowset.
|
|
hr = pIRI->GetReferencedRowset(0, IID_IRowset, (IUnknown**)
|
|
&pIRowset) ;
|
|
|
|
if(bBookmarksSupp)
|
|
{
|
|
TESTC_(hr, S_OK)
|
|
TESTC(VerifyEqualInterface((IUnknown*)pIRowset,(IUnknown*)m_pIRowset))
|
|
}
|
|
else
|
|
{
|
|
odtLog<<"Bookmarks are not supported.\n";
|
|
TESTC_(hr, DB_E_BADORDINAL)
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP ;
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIRI);
|
|
return tTestResult;
|
|
} //testIRowsetInfoGetRefRowset
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Obtain the IRowsetInfo interface. Use its GetSpecification
|
|
//method to obtain the IOpenRowset interface. Verify that this is the
|
|
//same interface which we had obtained on creating this DB Session. Use
|
|
//the GetSpecification method again to obtain the IGetDataSource
|
|
//interface. Verify this interface by using it to obtain the
|
|
//IDBInitialize interface (using IGetDataSource::GetDataSource) and
|
|
//verifying that it is the same as the IDBInitialize interface which
|
|
//was used to initialize the Data Source Object.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowsetInfoGetSpec()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
IOpenRowset* pIOR = NULL;
|
|
IGetDataSource* pIGDS = NULL;
|
|
IDBInitialize* pIDBI = NULL;
|
|
IRowsetInfo* pIRI = NULL;
|
|
|
|
//Obtain IRowsetInfo interface.
|
|
if(!VerifyInterface(m_pIRowset,IID_IRowsetInfo,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRI))
|
|
return TEST_FAIL;
|
|
|
|
//Use the method to obtain the IOpenRowset Interface.
|
|
TEST2C_(hr = pIRI->GetSpecification(IID_IOpenRowset,
|
|
(IUnknown**)&pIOR), S_OK, S_FALSE)
|
|
|
|
//The method can return S_FALSE if the provider does not have an
|
|
//object that created the rowset.
|
|
if(hr == S_OK)
|
|
{
|
|
COMPARE(VerifyEqualInterface((IUnknown*)pIOR,
|
|
(IUnknown*)m_pIOpenRowset), TRUE);
|
|
}
|
|
else
|
|
{
|
|
odtLog<<L"WARNING: S_FALSE was returned when asking for IOpenRowset.\n";
|
|
CHECKW(hr, S_OK);
|
|
COMPARE(pIOR, NULL);
|
|
}
|
|
|
|
//Use the method to obtain the IGetDataSource interface. Use that
|
|
//to then obtain the IDBInitialize interface.
|
|
TEST2C_(hr = pIRI->GetSpecification(IID_IGetDataSource,
|
|
(IUnknown**)&pIGDS), S_OK, S_FALSE)
|
|
|
|
if(hr == S_OK)
|
|
{
|
|
TESTC_(pIGDS->GetDataSource(IID_IDBInitialize, (IUnknown**)&pIDBI),
|
|
S_OK)
|
|
COMPARE(VerifyEqualInterface((IUnknown*)pIDBI,
|
|
(IUnknown*)m_pIDBInitialize), TRUE);
|
|
}
|
|
else
|
|
{
|
|
odtLog<<L"WARNING: S_FALSE was returned when asking for IGetDataSource.\n";
|
|
CHECKW(hr, S_OK);
|
|
COMPARE(pIGDS, NULL);
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIRI);
|
|
SAFE_RELEASE(pIOR);
|
|
SAFE_RELEASE(pIGDS);
|
|
SAFE_RELEASE(pIDBI);
|
|
return tTestResult;
|
|
} //testIRowsetInfoGetSpec
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Obtain the IRowsetInfo interface by executing a command. Use
|
|
//its GetSpecification method to obtain the IColumnsInfo interface.
|
|
//Verify that this belongs to the same command object which was used to
|
|
//create the rowset.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowsetInfoGetSpecCmd()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
IRowsetInfo* pIRI = NULL;
|
|
ICommand* pICommand = NULL;
|
|
IColumnsInfo* pIColumnsInfo = NULL;
|
|
|
|
if(m_pIDBCreateCommand)
|
|
{
|
|
TESTC_(hr = m_pIDBCreateCommand->CreateCommand(NULL,
|
|
IID_ICommand,(IUnknown **)&pICommand),S_OK)
|
|
}
|
|
else
|
|
{
|
|
odtLog<<L"Commands are NOT supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
TESTC(pICommand != NULL)
|
|
|
|
TESTC(m_pTable != NULL)
|
|
|
|
//Create SQL stmt and set command text and execute.
|
|
CHECK(m_pTable->ExecuteCommand(SELECT_ALLFROMTBL,
|
|
IID_IRowsetInfo, NULL, NULL, NULL, NULL,
|
|
EXECUTE_IFNOERROR, 0, NULL, NULL, (IUnknown**)&pIRI,
|
|
&pICommand), S_OK);
|
|
|
|
TESTC(pIRI != NULL)
|
|
|
|
//Use the method to obtain the IColumnsInfo Interface.
|
|
TEST2C_(hr = pIRI->GetSpecification(IID_IColumnsInfo,
|
|
(IUnknown**)&pIColumnsInfo), S_OK, S_FALSE)
|
|
|
|
//The method can return S_FALSE if the provider does not have an
|
|
//object that created the rowset.
|
|
if(hr == S_OK)
|
|
{
|
|
TESTC(VerifyEqualInterface(pICommand, pIColumnsInfo))
|
|
}
|
|
else
|
|
{
|
|
odtLog<<L"WARNING: S_FALSE was returned.\n";
|
|
CHECKW(hr, S_OK);
|
|
COMPARE(pIColumnsInfo, NULL);
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pICommand);
|
|
SAFE_RELEASE(pIColumnsInfo);
|
|
SAFE_RELEASE(pIRI);
|
|
return tTestResult;
|
|
} //testIRowsetInfoGetSpec
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Generate a rowset on the table with NO properties set. Get the
|
|
//accessor and bindings. Call the method RestartPosition to make sure
|
|
//the cursor is on the first row. Fetch one row at a time, skipping rows
|
|
//in the forward direction. This is done using the method GetNextRows.
|
|
//Each time a row is fetched, obtain its data using the method GetData
|
|
//and verify it. Release the row using method ReleaseRows before fetching
|
|
//another row.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowset2()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBCOUNTITEM cRows = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW* rghRows = NULL;
|
|
DBORDINAL cRowsetCols = 0;
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
DBBINDING* rgBindings = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowset* pIRowset = NULL;
|
|
|
|
//Make sure NO properties are set.
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
|
|
//Open a rowset with NO properties set.
|
|
if(!CHECK(hr=CreateOpenRowset(m_pTable, IID_IRowset,
|
|
(IUnknown**)&pIRowset), S_OK))
|
|
return TEST_FAIL;
|
|
|
|
TESTC(VerifyInterface(pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create Accessor with a binding using length,
|
|
//status and value. This accessor binds the Index
|
|
//column also.
|
|
TESTC_(GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF,
|
|
NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Get list of ordinals.
|
|
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols,
|
|
&rgColumnsOrd, NULL, NULL, NULL, NULL))
|
|
|
|
//Count number of rows on the table
|
|
cRows = m_pTable->CountRowsOnTable();
|
|
TESTC(cRows >= MIN_ROWS)
|
|
|
|
//Make sure we are on the first row.
|
|
TESTC_(RestartPosition(pIRowset), S_OK)
|
|
|
|
//Skip the 1st row and fetch the 2nd row.
|
|
TESTC(GetDataAndCompare(1, 1, 2, cRowsetCols,
|
|
rgColumnsOrd, pIRowset, hAccessor, cBindings,
|
|
rgBindings, cbRowSize))
|
|
|
|
//Skip 2 more rows and fetch the 5th row.
|
|
TESTC(GetDataAndCompare(2, 1, 5, cRowsetCols,
|
|
rgColumnsOrd, pIRowset, hAccessor, cBindings,
|
|
rgBindings, cbRowSize))
|
|
|
|
//Restart position.
|
|
TESTC_(RestartPosition(pIRowset), S_OK)
|
|
|
|
//Skip 3 rows and fetch the 4th row.
|
|
TESTC(GetDataAndCompare(3, 1, 4, cRowsetCols,
|
|
rgColumnsOrd, pIRowset, hAccessor, cBindings,
|
|
rgBindings, cbRowSize))
|
|
|
|
//Skip 0 and fetch the 5th row.
|
|
TESTC(GetDataAndCompare(0, 1, 5, cRowsetCols,
|
|
rgColumnsOrd, pIRowset, hAccessor, cBindings,
|
|
rgBindings, cbRowSize))
|
|
|
|
//Restart position.
|
|
TESTC_(RestartPosition(pIRowset), S_OK)
|
|
|
|
//Try to open more than 2 rows at a time if the MAXOPENROWS property
|
|
//permits this.
|
|
if(m_ulMaxOpenRows>1 || m_ulMaxOpenRows==0)
|
|
{
|
|
TESTC_(hr = GetNextRows(pIRowset, NULL, 0, 2, &cRowsObtained,
|
|
(HROW**)&rghRows), S_OK)
|
|
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowset);
|
|
return tTestResult;
|
|
} //testIRowset2
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Set the properties CANHOLDROWS and CANSCROLLBACKWARDS. Generate
|
|
//a rowset on the table using these properties. Get the accessor and
|
|
//bindings. Call method RestartPosition. Skip 4 rows in the forward
|
|
//direction and fetch the 5th row (method GetNextRows). Get its data
|
|
//(method GetData) and compare. Scroll backwards 2 rows and fetch the
|
|
//3rd row. Compare its data. Scroll backwards again 1 row to fetch the
|
|
//2nd row. Compare its data. Finally release all the rows we obtained
|
|
//above.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowset3()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBCOUNTITEM cRows = 0;
|
|
DBORDINAL cColumns = 0;
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
DBBINDING* rgBindings = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
IAccessor* pIAccessor = NULL;
|
|
|
|
//The properties DBPROP_CANHOLDROWS and DBPROP_CANSCROLLBACKWARDS
|
|
//have been set.
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create Accessor with a binding using length,
|
|
//status and value. This accessor binds the Index
|
|
//column also.
|
|
TESTC_(hr=GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF,
|
|
NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Get list of ordinals.
|
|
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cColumns,
|
|
&rgColumnsOrd, NULL, NULL, NULL, NULL))
|
|
|
|
//Count number of rows on the table
|
|
cRows = m_pTable->CountRowsOnTable();
|
|
TESTC(cRows >= MIN_ROWS);
|
|
|
|
//Make sure we are on the first row.
|
|
TESTC_(RestartPosition(m_pIRowset), S_OK)
|
|
|
|
//Skip 4 rows and fetch the 5th row. Compare its data.
|
|
TESTC(GetDataAndCompare(4, 1, 5, cColumns,
|
|
rgColumnsOrd, m_pIRowset, hAccessor, cBindings,
|
|
rgBindings, cbRowSize))
|
|
|
|
//Scroll backwards 2 rows and fetch the 3rd row. Compare its data.
|
|
TESTC(GetDataAndCompare(-3, 1, 3, cColumns,
|
|
rgColumnsOrd, m_pIRowset, hAccessor, cBindings,
|
|
rgBindings, cbRowSize))
|
|
|
|
//Scroll backwards 1 row and fetch the 2rd row. Compare its data.
|
|
TESTC(GetDataAndCompare(-2, 1, 2, cColumns,
|
|
rgColumnsOrd, m_pIRowset, hAccessor, cBindings,
|
|
rgBindings, cbRowSize))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
return tTestResult;
|
|
} //testIRowset3
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Get bookmarks for rows 1, 2 and 4. Use IRowsetLocate::Compare
|
|
//to compare them.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowsetLocateCompare()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBBKMARK rgcbBookmarks[3];
|
|
BYTE *rgpBookmarks[3]={NULL,NULL,NULL};
|
|
DBBOOKMARK dbBkm = DBBMK_FIRST;
|
|
BYTE* pBkm = (BYTE*) &dbBkm;
|
|
DBBOOKMARK dbBkm2 = DBBMK_LAST;
|
|
BYTE* pBkm2 = (BYTE*) &dbBkm;
|
|
DBCOMPARE dwComparison1 = DBCOMPARE_NOTCOMPARABLE;
|
|
DBCOMPARE dwComparison2 = DBCOMPARE_NOTCOMPARABLE;
|
|
DBCOMPARE dwComparison3 = DBCOMPARE_NOTCOMPARABLE;
|
|
DBCOMPARE dwComparison4 = DBCOMPARE_NOTCOMPARABLE;
|
|
DBCOMPARE dwComparison5 = DBCOMPARE_NOTCOMPARABLE;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
DBBINDING* rgBindings = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowsetLocate* pIRowsetLocate = NULL;
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IRowsetLocate,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRowsetLocate))
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create an accessor.
|
|
TESTC_(hr=GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF,
|
|
NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
BLOB_LONG, NULL),S_OK)
|
|
|
|
//get the bookmark for the 1st row
|
|
TESTC(GetBookmark(1,cbRowSize,hAccessor,cBindings, rgBindings,
|
|
(IUnknown*)m_pIRowset, &rgcbBookmarks[0],&rgpBookmarks[0]))
|
|
|
|
//get the bookmark for the 2nd row
|
|
TESTC(GetBookmark(2,cbRowSize,hAccessor,cBindings, rgBindings,
|
|
(IUnknown*)m_pIRowset, &rgcbBookmarks[1],&rgpBookmarks[1]))
|
|
|
|
//get the bookmark for the 4th row
|
|
TESTC(GetBookmark(4,cbRowSize,hAccessor,cBindings, rgBindings,
|
|
(IUnknown*)m_pIRowset, &rgcbBookmarks[2],&rgpBookmarks[2]))
|
|
|
|
//Compare rows 2 and 4.
|
|
TESTC_(hr=pIRowsetLocate->Compare(NULL,rgcbBookmarks[1],rgpBookmarks[1],
|
|
rgcbBookmarks[2],rgpBookmarks[2],&dwComparison1),S_OK)
|
|
//Compare rows 4 and 1.
|
|
TESTC_(hr=pIRowsetLocate->Compare(NULL,rgcbBookmarks[2],rgpBookmarks[2],
|
|
rgcbBookmarks[0],rgpBookmarks[0],&dwComparison2),S_OK)
|
|
//Compare rows 2 and DBBMK_FIRST.
|
|
TESTC_(hr=pIRowsetLocate->Compare(NULL,rgcbBookmarks[1],rgpBookmarks[1],
|
|
STD_BOOKMARKLENGTH,pBkm,&dwComparison3),S_OK)
|
|
//Compare rows 4 and 4.
|
|
TESTC_(hr=pIRowsetLocate->Compare(NULL,rgcbBookmarks[2],rgpBookmarks[2],
|
|
rgcbBookmarks[2],rgpBookmarks[2],&dwComparison4),S_OK)
|
|
//Compare rows 2 and DBBMK_LAST.
|
|
TESTC_(hr=pIRowsetLocate->Compare(NULL,rgcbBookmarks[1],rgpBookmarks[1],
|
|
STD_BOOKMARKLENGTH,pBkm2,&dwComparison5),S_OK)
|
|
|
|
//check the comparisons.
|
|
|
|
//If ordered-bookmarks are supported.
|
|
if(GetProperty(DBPROP_ORDEREDBOOKMARKS, DBPROPSET_ROWSET,
|
|
(IUnknown*)m_pIRowset))
|
|
{
|
|
COMPARE(dwComparison1, DBCOMPARE_LT);
|
|
COMPARE(dwComparison2, DBCOMPARE_GT);
|
|
COMPARE(dwComparison3, DBCOMPARE_NE);
|
|
COMPARE(dwComparison4, DBCOMPARE_EQ);
|
|
COMPARE(dwComparison5, DBCOMPARE_NE);
|
|
}
|
|
else
|
|
{
|
|
COMPARE(dwComparison1, DBCOMPARE_NE);
|
|
COMPARE(dwComparison2, DBCOMPARE_NE);
|
|
COMPARE(dwComparison3, DBCOMPARE_NE);
|
|
COMPARE(dwComparison4, DBCOMPARE_EQ);
|
|
COMPARE(dwComparison5, DBCOMPARE_NE);
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(rgpBookmarks[0]);
|
|
PROVIDER_FREE(rgpBookmarks[1]);
|
|
PROVIDER_FREE(rgpBookmarks[2]);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowsetLocate);
|
|
return tTestResult;
|
|
} //testIRowsetLocateCompare
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Use IRowsetLocate::GetRowsAt to fetch rows with respect to a
|
|
//row whose bookmark is provided.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowsetLocateGetRowsAt()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex = 0; //small no.
|
|
DBBKMARK rgcbBookmarks[1];
|
|
BYTE *rgpBookmarks[1] = {NULL};
|
|
DBBOOKMARK dbBkm = DBBMK_FIRST;
|
|
BYTE* pBkm = (BYTE*) &dbBkm;
|
|
BYTE* pData = NULL;
|
|
HROW* rghRows = NULL;
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
DBORDINAL cColumns = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
DBBINDING* rgBindings = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowsetLocate* pIRowsetLocate = NULL;
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IRowsetLocate,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRowsetLocate))
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create an accessor.
|
|
TESTC_(hr=GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF,
|
|
NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
BLOB_LONG, NULL),S_OK)
|
|
|
|
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cColumns,
|
|
&rgColumnsOrd, NULL,NULL,NULL,NULL))
|
|
|
|
//get the bookmark for the 2nd row
|
|
TESTC(GetBookmark(2,cbRowSize,hAccessor,cBindings, rgBindings,
|
|
(IUnknown*)m_pIRowset, &rgcbBookmarks[0],&rgpBookmarks[0]))
|
|
|
|
//Fetch 3rd and 4th rows.
|
|
TESTC_(hr=pIRowsetLocate->GetRowsAt(NULL, NULL, rgcbBookmarks[0],
|
|
rgpBookmarks[0], 1, 2, &cRowsObtained, &rghRows), S_OK)
|
|
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize);
|
|
|
|
TESTC(cRowsObtained==2 && rghRows)
|
|
|
|
for(ulIndex=0; ulIndex<cRowsObtained; ulIndex++)
|
|
{
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
|
|
TESTC_(hr=m_pIRowset->GetData(rghRows[ulIndex], hAccessor,
|
|
pData), S_OK)
|
|
|
|
TESTC(CompareData(cColumns, rgColumnsOrd, 3+ulIndex, pData,
|
|
cBindings, rgBindings, m_pTable, m_pIMalloc, PRIMARY))
|
|
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData);
|
|
}
|
|
|
|
CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
|
|
//Fetch the 3rd and 4th rows using standard bookmarks.
|
|
TESTC_(hr=pIRowsetLocate->GetRowsAt(NULL, NULL, STD_BOOKMARKLENGTH,
|
|
pBkm, 2, 2, &cRowsObtained, &rghRows), S_OK)
|
|
|
|
TESTC(cRowsObtained==2 && rghRows)
|
|
|
|
for(ulIndex=0; ulIndex<cRowsObtained; ulIndex++)
|
|
{
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
|
|
TESTC_(hr=m_pIRowset->GetData(rghRows[ulIndex], hAccessor,
|
|
pData), S_OK)
|
|
|
|
TESTC(CompareData(cColumns, rgColumnsOrd, 3+ulIndex, pData,
|
|
cBindings, rgBindings, m_pTable, m_pIMalloc, PRIMARY))
|
|
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData);
|
|
}
|
|
|
|
CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
|
|
//SCROLL_BACKWARDS
|
|
|
|
//Fetch 1st, 2nd, and 3rd rows using SCROLL_BACKWARDS.
|
|
hr = pIRowsetLocate->GetRowsAt(NULL, NULL, rgcbBookmarks[0],
|
|
rgpBookmarks[0], -1, 3, &cRowsObtained, &rghRows) ;
|
|
|
|
if(GetProperty(DBPROP_CANSCROLLBACKWARDS, DBPROPSET_ROWSET,
|
|
(IUnknown*)m_pIRowset))
|
|
{
|
|
TESTC_(hr, S_OK)
|
|
TESTC(cRowsObtained==3 && rghRows)
|
|
}
|
|
else
|
|
{
|
|
CHECK(hr, DB_E_CANTSCROLLBACKWARDS);
|
|
tTestResult = TEST_PASS;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
for(ulIndex=0; ulIndex<cRowsObtained; ulIndex++)
|
|
{
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
|
|
TESTC_(hr=m_pIRowset->GetData(rghRows[ulIndex], hAccessor,
|
|
pData), S_OK)
|
|
|
|
TESTC(CompareData(cColumns, rgColumnsOrd, 1+ulIndex, pData,
|
|
cBindings, rgBindings, m_pTable, m_pIMalloc, PRIMARY))
|
|
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData);
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(pData);
|
|
CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
PROVIDER_FREE(rgpBookmarks[0]);
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowsetLocate);
|
|
return tTestResult;
|
|
} //testIRowsetLocateGetRowsAt
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Get bookmarks to some rows and pass this in to IRowsetLocate::
|
|
//GetRowsByBookmark. Verify the returned rows.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowsetLocateGetRowsByBkm()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex = 0; // max 3
|
|
DBCOUNTITEM cGotRows = 0;
|
|
DBCOUNTITEM iRowNum[3] = {2,4,5}; //Row numbers of rows to get.
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
DBORDINAL cColumns = 0;
|
|
BYTE* pData = NULL;
|
|
DBBKMARK rgcbBookmarks[3];
|
|
BYTE *rgpBookmarks[3]={NULL,NULL,NULL};
|
|
DBROWSTATUS rgRowStatus[3]; //Not required to initialize.
|
|
HROW rghRows[3] ; //Not required to initialize.
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
DBBINDING* rgBindings = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowsetLocate* pIRowsetLocate = NULL;
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IRowsetLocate,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRowsetLocate))
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create an accessor.
|
|
TESTC_(hr=GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF,
|
|
NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
BLOB_LONG, NULL),S_OK)
|
|
|
|
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cColumns,
|
|
&rgColumnsOrd, NULL,NULL,NULL,NULL))
|
|
|
|
//get the bookmark for the 2nd row
|
|
TESTC(GetBookmark(2,cbRowSize,hAccessor,cBindings, rgBindings,
|
|
(IUnknown*)m_pIRowset, &rgcbBookmarks[0],&rgpBookmarks[0]))
|
|
|
|
//get the bookmark for the 4th row
|
|
TESTC(GetBookmark(4,cbRowSize,hAccessor,cBindings, rgBindings,
|
|
(IUnknown*)m_pIRowset, &rgcbBookmarks[1],&rgpBookmarks[1]))
|
|
|
|
//get the bookmark for the 5th row
|
|
TESTC(GetBookmark(5,cbRowSize,hAccessor,cBindings, rgBindings,
|
|
(IUnknown*)m_pIRowset, &rgcbBookmarks[2],&rgpBookmarks[2]))
|
|
|
|
TESTC_(hr=pIRowsetLocate->GetRowsByBookmark(NULL, 3, rgcbBookmarks,
|
|
(const BYTE**)rgpBookmarks, rghRows, rgRowStatus), S_OK)
|
|
|
|
for(ulIndex=0; ulIndex<3; ulIndex++)
|
|
{
|
|
TESTC(rghRows[ulIndex] != DB_NULL_HROW)
|
|
cGotRows++;
|
|
COMPARE(rgRowStatus[ulIndex] , DBROWSTATUS_S_OK);
|
|
}
|
|
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize);
|
|
|
|
for(ulIndex=0; ulIndex<3; ulIndex++)
|
|
{
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
|
|
TESTC_(hr=m_pIRowset->GetData(rghRows[ulIndex], hAccessor,
|
|
pData), S_OK)
|
|
|
|
COMPARE(CompareData(cColumns, rgColumnsOrd, iRowNum[ulIndex],
|
|
pData, cBindings, rgBindings, m_pTable, m_pIMalloc,
|
|
PRIMARY), TRUE);
|
|
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData);
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(pData);
|
|
CHECK(m_pIRowset->ReleaseRows(3, rghRows, NULL,NULL,NULL), S_OK);
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
PROVIDER_FREE(rgpBookmarks[0]);
|
|
PROVIDER_FREE(rgpBookmarks[1]);
|
|
PROVIDER_FREE(rgpBookmarks[2]);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowsetLocate);
|
|
return tTestResult;
|
|
} //testIRowsetLocateGetRowsByBkm
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Get hash values for certain bookmarks.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowsetLocateHash()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex = 0; //max 3
|
|
DBBKMARK rgcbBookmarks[3];
|
|
BYTE *rgpBookmarks[3]={NULL,NULL,NULL};
|
|
DBHASHVALUE rgHashedValues[3]; //Not required to initialize.
|
|
DBROWSTATUS rgBookmarkStatus[3]; //Not required to initialize.
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
DBBINDING* rgBindings = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowsetLocate* pIRowsetLocate = NULL;
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IRowsetLocate,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRowsetLocate))
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create an accessor.
|
|
TESTC_(hr=GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF,
|
|
NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
BLOB_LONG, NULL),S_OK)
|
|
|
|
//get the bookmark for the 1st row
|
|
TESTC(GetBookmark(1,cbRowSize,hAccessor,cBindings, rgBindings,
|
|
(IUnknown*)m_pIRowset, &rgcbBookmarks[0],&rgpBookmarks[0]))
|
|
|
|
//get the bookmark for 1st row again
|
|
TESTC(GetBookmark(1,cbRowSize,hAccessor,cBindings, rgBindings,
|
|
(IUnknown*)m_pIRowset, &rgcbBookmarks[1],&rgpBookmarks[1]))
|
|
|
|
//get the bookmark for the 4th row
|
|
TESTC(GetBookmark(4,cbRowSize,hAccessor,cBindings, rgBindings,
|
|
(IUnknown*)m_pIRowset, &rgcbBookmarks[2],&rgpBookmarks[2]))
|
|
|
|
//Hash returns different values
|
|
TESTC_(hr = pIRowsetLocate->Hash(NULL,3,rgcbBookmarks,
|
|
(const BYTE **)rgpBookmarks, rgHashedValues,rgBookmarkStatus),
|
|
S_OK)
|
|
|
|
for(ulIndex=0; ulIndex<3; ulIndex++)
|
|
{
|
|
COMPARE(rgBookmarkStatus[ulIndex] , DBROWSTATUS_S_OK);
|
|
}
|
|
|
|
//The first 2 hash values are for the first row, hence they
|
|
//should be equal. The third one should be different.
|
|
COMPARE(rgHashedValues[0] == rgHashedValues[1], TRUE);
|
|
COMPARE(rgHashedValues[1] != rgHashedValues[2], TRUE);
|
|
COMPARE(rgHashedValues[0] != rgHashedValues[2], TRUE);
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(rgpBookmarks[0]);
|
|
PROVIDER_FREE(rgpBookmarks[1]);
|
|
PROVIDER_FREE(rgpBookmarks[2]);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowsetLocate);
|
|
return tTestResult;
|
|
} //testIRowsetLocateHash
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Make data corresponding to a certain row and column (choosing a
|
|
//fixed length column). Use this as the search criterion for FindNextRow.
|
|
//Verify the obtained rows.
|
|
//
|
|
TESTRESULT CQuickTest::testFindNextRow()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBORDINAL ulIndex = 0;
|
|
DBORDINAL cRowsetCols = 0;
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
DBORDINAL cColumns = 0;
|
|
DBCOUNTITEM ulRowNum = 0;
|
|
DB_LORDINAL ulColNum = 0;
|
|
DBLENGTH cbDataLength = 0;
|
|
DBCOLUMNINFO* rgInfo = NULL;
|
|
WCHAR* pStrBuf = NULL;
|
|
WCHAR wszData[2000];
|
|
BYTE* pMakeData = NULL;
|
|
void* pvData = NULL;
|
|
BYTE* pFindValue = NULL;
|
|
BYTE* pData = NULL;
|
|
DBTYPE wColType = DBTYPE_EMPTY;
|
|
DBTYPE wVariantType = DBTYPE_EMPTY;
|
|
DBBKMARK rgcbBookmarks[1];
|
|
BYTE *rgpBookmarks[1]={NULL};
|
|
HROW* rghRows = NULL ;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
DBBINDING* rgBindings = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
IAccessor* pIAccessor = NULL;
|
|
IColumnsInfo* pIColumnsInfo = NULL;
|
|
IRowsetFind* pIRowsetFind = NULL;
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IRowsetFind,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRowsetFind))
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create an accessor.
|
|
TESTC_(hr=GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF,
|
|
NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
BLOB_LONG, NULL),S_OK)
|
|
|
|
//Bookmark will be got for the following row num.
|
|
ulRowNum = 2;
|
|
|
|
//get the bookmark for the 'ulRowNum' row
|
|
TESTC(GetBookmark(ulRowNum,cbRowSize,hAccessor,cBindings, rgBindings,
|
|
(IUnknown*)m_pIRowset, &rgcbBookmarks[0],&rgpBookmarks[0]))
|
|
|
|
//Release hAccessor and free bindings. But don't release IAccessor.
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings,
|
|
FALSE);
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IColumnsInfo,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIColumnsInfo))
|
|
|
|
TESTC_(hr = pIColumnsInfo->GetColumnInfo(&cColumns, &rgInfo,
|
|
&pStrBuf), S_OK)
|
|
|
|
//Get a fixed-length column whose data we will use for the FindRow.
|
|
for(ulIndex=1; ulIndex<cColumns; ulIndex++)
|
|
{
|
|
if(IsFixedLength(rgInfo[ulIndex].wType))
|
|
break;
|
|
}
|
|
if(ulIndex==cColumns)
|
|
{
|
|
odtLog<<L"Could not find a fixed length column to bind to for the findValue.\n";
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
wColType = rgInfo[ulIndex].wType ;
|
|
ulColNum = rgInfo[ulIndex].iOrdinal;
|
|
|
|
//MakeData will generate data for the following row num.
|
|
ulRowNum = 3;
|
|
|
|
//MakeData to be used for FindNextRow.
|
|
TESTC_(hr=m_pTable->MakeData(wszData, ulRowNum, ulColNum, PRIMARY,
|
|
wColType, TRUE, &wVariantType), S_OK)
|
|
|
|
//If it is a variant, then use correct variant type.
|
|
pMakeData = (BYTE *)WSTR2DBTYPE(wszData, ( wColType ==
|
|
DBTYPE_VARIANT ? wVariantType : wColType) ,NULL );
|
|
|
|
cbDataLength = GetDBTypeSize(wColType) ;
|
|
|
|
SAFE_ALLOC(pFindValue, BYTE, cbDataLength+offsetof(DATA, bValue))
|
|
|
|
//If the find value is to be a variant then convert the data to
|
|
//a variant.
|
|
if ( wColType == DBTYPE_VARIANT )
|
|
pvData = DBTYPE2VARIANT(pMakeData, wVariantType);
|
|
else
|
|
pvData = pMakeData;
|
|
|
|
//Create the binding for the find value.
|
|
memcpy(pFindValue+offsetof(DATA, bValue), pvData, (size_t) cbDataLength);
|
|
|
|
*(DBSTATUS *)(pFindValue+offsetof(DATA, sStatus)) = DBSTATUS_S_OK;
|
|
|
|
*(DBLENGTH *)(pFindValue+offsetof(DATA, ulLength)) = cbDataLength;
|
|
|
|
//Create an accessor and binding for one column (ulColNum).
|
|
TESTC_(hr = GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA, &hAccessor, &rgBindings, &cBindings,
|
|
&cbRowSize, DBPART_VALUE | DBPART_STATUS | DBPART_LENGTH,
|
|
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, 1,
|
|
&ulColNum, NULL,
|
|
NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_LONG ), S_OK)
|
|
|
|
//Call the method (FindNextRow) to be tested.
|
|
hr = pIRowsetFind->FindNextRow(NULL, hAccessor, pFindValue,
|
|
DBCOMPAREOPS_EQ, rgcbBookmarks[0], rgpBookmarks[0], 0, 2,
|
|
&cRowsObtained, &rghRows) ;
|
|
|
|
//Make sure we got back 2 rows.
|
|
TESTC_(hr, S_OK)
|
|
TESTC(cRowsObtained == 2)
|
|
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize);
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
|
|
//Get data for the first of the 2 rows. The data in this should
|
|
//match our search data.
|
|
TESTC_(hr = m_pIRowset->GetData(rghRows[0], hAccessor, pData), S_OK)
|
|
|
|
TESTC(CompareBuffer((void*)pData, (void*)pFindValue, 1, rgBindings,
|
|
m_pIMalloc, FALSE, FALSE, COMPARE_ONLY))
|
|
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData);
|
|
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
|
|
//Get the data for the second of the 2 rows. This should be the
|
|
//row which comes right after the row which matched the search
|
|
//data.
|
|
TESTC_(hr = m_pIRowset->GetData(rghRows[1], hAccessor, pData),
|
|
S_OK)
|
|
|
|
//Get list of ordinals.
|
|
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols,
|
|
&rgColumnsOrd, NULL, NULL, NULL, NULL))
|
|
|
|
TESTC(CompareData(cRowsetCols,rgColumnsOrd,ulRowNum+1,pData,1,
|
|
rgBindings, m_pTable, m_pIMalloc, PRIMARY))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData);
|
|
SAFE_FREE(pData);
|
|
CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
PROVIDER_FREE(rgpBookmarks[0]);
|
|
PROVIDER_FREE(pStrBuf);
|
|
PROVIDER_FREE(pvData);
|
|
PROVIDER_FREE(rgInfo);
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
SAFE_FREE(pFindValue);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIColumnsInfo);
|
|
SAFE_RELEASE(pIRowsetFind);
|
|
return tTestResult;
|
|
} //testFindNextRow
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Get the bookmarks for some rows and obtain their approximate
|
|
//position by calling the method GetApproximatePosition. Verify that
|
|
//the positions returned have reasonable approximations.
|
|
//
|
|
TESTRESULT CQuickTest::testGetApproxPos()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBBKMARK rgcbBookmarks[3];
|
|
BYTE *rgpBookmarks[3]={NULL,NULL,NULL};
|
|
DBCOUNTITEM cRowsOnTable = 0;
|
|
DBCOUNTITEM cRows = 0;
|
|
DBCOUNTITEM ulPosition = 0;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
DBBINDING* rgBindings = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowsetScroll* pIRS = NULL;
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IRowsetScroll,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRS))
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create an accessor.
|
|
TESTC_(hr=GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF,
|
|
NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
BLOB_LONG, NULL),S_OK)
|
|
|
|
//get the bookmark for the 1st row
|
|
TESTC(GetBookmark(1,cbRowSize,hAccessor,cBindings, rgBindings,
|
|
(IUnknown*)m_pIRowset, &rgcbBookmarks[0],&rgpBookmarks[0]))
|
|
|
|
//get the bookmark for the 3rd row
|
|
TESTC(GetBookmark(3,cbRowSize,hAccessor,cBindings, rgBindings,
|
|
(IUnknown*)m_pIRowset, &rgcbBookmarks[1],&rgpBookmarks[1]))
|
|
|
|
//get the bookmark for the 5th row
|
|
TESTC(GetBookmark(5,cbRowSize,hAccessor,cBindings, rgBindings,
|
|
(IUnknown*)m_pIRowset, &rgcbBookmarks[2],&rgpBookmarks[2]))
|
|
|
|
cRowsOnTable = m_pTable->CountRowsOnTable();
|
|
|
|
//Bookmark for row 1.
|
|
TESTC_(hr = pIRS->GetApproximatePosition(NULL, rgcbBookmarks[0],
|
|
rgpBookmarks[0], &ulPosition, &cRows), S_OK)
|
|
TESTC(cRows >= ulPosition)
|
|
odtLog<<L"INFO: Position returned for row 1 = "<<ulPosition<<L".\n";
|
|
|
|
//Bookmark for row 3.
|
|
TESTC_(hr = pIRS->GetApproximatePosition(NULL, rgcbBookmarks[1],
|
|
rgpBookmarks[1], &ulPosition, &cRows), S_OK)
|
|
TESTC(cRows >= ulPosition)
|
|
odtLog<<L"INFO: Position returned for row 3 = "<<ulPosition<<L".\n";
|
|
|
|
//Bookmark for row 5.
|
|
TESTC_(hr = pIRS->GetApproximatePosition(NULL, rgcbBookmarks[2],
|
|
rgpBookmarks[2], &ulPosition, &cRows), S_OK)
|
|
TESTC(cRows >= ulPosition)
|
|
odtLog<<L"INFO: Position returned for row 5 = "<<ulPosition<<L".\n";
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(rgpBookmarks[0]);
|
|
PROVIDER_FREE(rgpBookmarks[1]);
|
|
PROVIDER_FREE(rgpBookmarks[2]);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRS);
|
|
return tTestResult;
|
|
} //testGetApproxPos
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Call the method GetRowsAtRatio using 0 for numerator and the
|
|
//total number of rows for the denominator. This should fetch rows
|
|
//starting with the first row in the rowset. Verify the obtained rows.
|
|
//
|
|
TESTRESULT CQuickTest::testGetRowsAtRatio()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex = 0; //small no.
|
|
DBCOUNTITEM cRowsOnTable = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DBCOUNTITEM cRowsObtained2 = 0;
|
|
HROW* rghRows = NULL;
|
|
HROW* rghRows2 = NULL;
|
|
IRowsetScroll* pIRS = NULL;
|
|
IRowsetIdentity* pIRI = NULL;
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IRowsetScroll,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRS))
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IRowsetIdentity,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRI))
|
|
|
|
cRowsOnTable = m_pTable->CountRowsOnTable();
|
|
|
|
//Pass in 0 for numerator and cRowsOnTable for denominator. This
|
|
//is guaranteed to fetch the first 3 rows.
|
|
TESTC_(hr = pIRS->GetRowsAtRatio(NULL, NULL, 0, cRowsOnTable, 3,
|
|
&cRowsObtained, &rghRows), S_OK)
|
|
|
|
TESTC(cRowsObtained == 3)
|
|
TESTC(rghRows != NULL)
|
|
|
|
//Position cursor to beginning of rowset.
|
|
TESTC_(RestartPosition(m_pIRowset), S_OK)
|
|
|
|
//Fetch the first 3 rows using GetNextRows.
|
|
TESTC_(hr = GetNextRows(m_pIRowset, NULL, 0, 3, &cRowsObtained2,
|
|
&rghRows2), S_OK)
|
|
|
|
//Verify that the rows returned by GetRowsAtRatio are the same as
|
|
//that fetched by GetNextRows.
|
|
for(ulIndex=0; ulIndex<cRowsObtained; ulIndex++)
|
|
TESTC_(hr = pIRI->IsSameRow(rghRows[ulIndex], rghRows2[ulIndex]),
|
|
S_OK)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained2, &rghRows2), S_OK);
|
|
SAFE_RELEASE(pIRI);
|
|
SAFE_RELEASE(pIRS);
|
|
return tTestResult;
|
|
} //testGetRowsAtRatio
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Initialize IRowPosition with m_pIRowset. Then call the various
|
|
//methods of IRowPosition and verify their functionality.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowPosition()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
HROW* rghRows = NULL;
|
|
HROW hRows2 = DB_NULL_HROW;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
VARIANT_BOOL bValue = VARIANT_FALSE;
|
|
IRowsetInfo* pIRI = NULL;
|
|
IRowPosition* pIRowPosition = NULL;
|
|
|
|
hr = CoCreateInstance(CLSID_OLEDB_ROWPOSITIONLIBRARY, NULL,
|
|
CLSCTX_INPROC_SERVER, IID_IRowPosition,
|
|
(LPVOID *)&pIRowPosition);
|
|
|
|
if(hr != S_OK)
|
|
{
|
|
odtLog<<L"Could not create an instance of the row position library.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
TESTC(pIRowPosition != NULL)
|
|
|
|
//The positioning will be done on the m_pIRowset rowset.
|
|
TESTC_(hr = pIRowPosition->Initialize((IUnknown*)m_pIRowset), S_OK)
|
|
|
|
//Call GetRowset to obtain IRowsetInfo.
|
|
TESTC_(hr = pIRowPosition->GetRowset(IID_IRowsetInfo, (IUnknown**)
|
|
&pIRI), S_OK)
|
|
|
|
TESTC(pIRI != NULL)
|
|
|
|
//Use the obtained IRowsetInfo interface.
|
|
TESTC(GetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, (IUnknown*)
|
|
pIRI, &bValue))
|
|
|
|
//Clear any existing row position.
|
|
TESTC_(hr = pIRowPosition->ClearRowPosition(), S_OK)
|
|
|
|
//Position cursor to beginning of rowset.
|
|
TESTC_(RestartPosition(m_pIRowset), S_OK)
|
|
|
|
//Get the handle to the 2nd row.
|
|
TESTC_(hr = GetNextRows(m_pIRowset, NULL, 1, 1, &cRowsObtained,
|
|
&rghRows), S_OK)
|
|
|
|
//Set the row position to the 2nd row.
|
|
TESTC_(hr = pIRowPosition->SetRowPosition(NULL, rghRows[0],
|
|
DBPOSITION_OK), S_OK)
|
|
|
|
TESTC_(hr = m_pIRowset->ReleaseRows(1,rghRows, NULL, NULL,
|
|
NULL),S_OK);
|
|
|
|
//Get the current row position.
|
|
TESTC_(hr = pIRowPosition->GetRowPosition(NULL, &hRows2,
|
|
NULL), S_OK)
|
|
|
|
//Make sure it is same as the one we had set.
|
|
TESTC(rghRows[0] == hRows2)
|
|
|
|
TESTC_(hr = m_pIRowset->ReleaseRows(1,rghRows, NULL, NULL,
|
|
NULL),S_OK);
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
SAFE_RELEASE(pIRI);
|
|
SAFE_RELEASE(pIRowPosition);
|
|
return tTestResult;
|
|
} //testIRowPosition
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Aggregate the rowset and test it.
|
|
//
|
|
TESTRESULT CQuickTest::testAggregateRowset()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr;
|
|
IUnknown* pIUnkInner = NULL;
|
|
|
|
CAggregate Aggregate(m_pIOpenRowset);
|
|
|
|
TESTC(m_pTable && m_pIOpenRowset)
|
|
|
|
//Aggregation
|
|
hr = CreateOpenRowset(m_pTable, IID_IUnknown, (IUnknown**)&pIUnkInner, &Aggregate);
|
|
Aggregate.SetUnkInner(pIUnkInner);
|
|
|
|
//Check if aggregation is supported.
|
|
if(hr==DB_E_NOAGGREGATION)
|
|
{
|
|
odtLog<<"Aggregation is not supported.\n";
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Verify Aggregation for this rowset...
|
|
TESTC(Aggregate.VerifyAggregationQI(hr, IID_IRowset))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIUnkInner);
|
|
return tTestResult;
|
|
} //testAggregateRowset
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Use the IRowset interface to obtain the IRowsetIdentity
|
|
//interface. Fetch the first 2 rows. If we can fetch backwards, then
|
|
//fetch the second row again. Use the method IsSameRow to compare the
|
|
//row handles. Verify the results.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowsetIdentity()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
HROW* rghRows1 = NULL;
|
|
HROW* rghRows2 = NULL;
|
|
DBCOUNTITEM cRowsObtained1 = 0;
|
|
DBCOUNTITEM cRowsObtained2 = 0;
|
|
IRowsetIdentity* pIRId = NULL;
|
|
|
|
if(m_ulMaxOpenRows == 0)
|
|
m_ulMaxOpenRows = m_pTable->CountRowsOnTable();
|
|
|
|
//Obtain IRowsetIdentity interface.
|
|
if(!VerifyInterface(m_pIRowset,IID_IRowsetIdentity,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRId))
|
|
return TEST_FAIL;
|
|
|
|
//Position cursor at beginning of rowset.
|
|
TESTC_(RestartPosition(m_pIRowset), S_OK)
|
|
|
|
//Fetch the first 2 rows.
|
|
TEST2C_(hr = GetNextRows(m_pIRowset, NULL, 0, 2, &cRowsObtained1,
|
|
(HROW **)&rghRows1), S_OK, DB_S_ROWLIMITEXCEEDED)
|
|
|
|
if(hr==S_OK)
|
|
{
|
|
TESTC(cRowsObtained1==2 && rghRows1)
|
|
}
|
|
else
|
|
{
|
|
//hr is DB_S_ROWLIMITEXCEEDED.
|
|
COMPARE(m_ulMaxOpenRows<2, TRUE);
|
|
COMPARE(cRowsObtained1, 1);
|
|
}
|
|
|
|
//If we can fetch backwards, get the 2nd row again.
|
|
if(m_fFetchBackwards &&(m_ulMaxOpenRows>2))
|
|
{
|
|
//Use IRowset to get 2nd row again.
|
|
TESTC_(hr = GetNextRows(m_pIRowset, NULL, 0, -1,
|
|
&cRowsObtained2, (HROW **)&rghRows2), S_OK)
|
|
|
|
//The 2nd row fetched first time is compared to the
|
|
//2nd row fetched second time.
|
|
CHECK(pIRId->IsSameRow(rghRows1[1], *rghRows2), S_OK);
|
|
|
|
//The 1st row is compared to the 2nd row fetched second time.
|
|
CHECK(pIRId->IsSameRow(rghRows1[0], *rghRows2), S_FALSE);
|
|
}
|
|
|
|
//Compare the 1st row with the 2nd row.
|
|
if(cRowsObtained1 == 2)
|
|
CHECK(pIRId->IsSameRow(rghRows1[0], rghRows1[1]), S_FALSE);
|
|
|
|
//Compare the 1st row with itself.
|
|
CHECK(pIRId->IsSameRow(rghRows1[0], rghRows1[0]), S_OK);
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained1, &rghRows1), S_OK);
|
|
CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained2, &rghRows2), S_OK);
|
|
SAFE_RELEASE(pIRId);
|
|
return tTestResult;
|
|
} //testIRowsetIdentity
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Call the method RestartPosition. Then fetch all the rows in
|
|
//the table (sequentially) one at a time (in the forward direction).
|
|
//Compare data for that row and release it. Determine the MAXOPENROWS.
|
|
//Restart position and open the maximum number of rows all at once.
|
|
//Compare their data. Release them all. Call RestartPosition again. If
|
|
//fetching backwards is supported, then skip 4 rows forward and fetch
|
|
//backwards 3 rows. So we should get the 4th, 3rd and 2nd rows. Compare
|
|
//their data and release them.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowset()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBCOUNTITEM ulIndex = 0;
|
|
DBCOUNTITEM cRows = 0, cMultRows = 0;
|
|
DBORDINAL cRowsetCols = 0;
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
DBBINDING* rgBindings = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
IAccessor* pIAccessor = NULL;
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create Accessor with a binding using length,
|
|
//status and value. This accessor binds the Index
|
|
//column also.
|
|
TESTC_(GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF,
|
|
NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Get list of ordinals.
|
|
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols,
|
|
&rgColumnsOrd, NULL, NULL, NULL, NULL))
|
|
|
|
//Get number of rows on table.
|
|
cRows = m_pTable->CountRowsOnTable();
|
|
|
|
//Position cursor on first row.
|
|
TESTC_(RestartPosition(m_pIRowset), S_OK)
|
|
|
|
//Get one row at a time, compare and release.
|
|
for(ulIndex=0; ulIndex<cRows; ulIndex++)
|
|
TESTC(GetDataAndCompare(0, 1, ulIndex+1, cRowsetCols,
|
|
rgColumnsOrd, m_pIRowset, hAccessor, cBindings,
|
|
rgBindings, cbRowSize))
|
|
|
|
//Determine how many rows we can open at a time.
|
|
if(cRows >= m_ulMaxOpenRows)
|
|
cMultRows = m_ulMaxOpenRows;
|
|
if(cRows < m_ulMaxOpenRows)
|
|
cMultRows = cRows;
|
|
if(m_ulMaxOpenRows == 0)
|
|
cMultRows = cRows;
|
|
|
|
//Restart position.
|
|
TESTC_(RestartPosition(m_pIRowset), S_OK)
|
|
|
|
//Now get multiple rows, compare and then release all.
|
|
TESTC(GetDataAndCompare(0, cMultRows, 1, cRowsetCols,
|
|
rgColumnsOrd, m_pIRowset, hAccessor, cBindings,
|
|
rgBindings, cbRowSize))
|
|
|
|
//Restart position.
|
|
TESTC_(RestartPosition(m_pIRowset), S_OK)
|
|
|
|
//If fetch backwards is supported, then skip 2 rows and fetch
|
|
//backwards 2 rows. We will get rows 2 and 1. Verify their data.
|
|
if((cMultRows>4) && (m_fFetchBackwards))
|
|
TESTC(GetDataAndCompare(2, -2, 2, cRowsetCols,
|
|
rgColumnsOrd, m_pIRowset, hAccessor, cBindings,
|
|
rgBindings, cbRowSize))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
return tTestResult;
|
|
} //testIRowset
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Check if Updateability and DBPROPVAL_UP_CHANGE are supported.
|
|
//Create an accessor binds all updateable, non-index columns. Fetch the
|
|
//first row. Set it's data. Call GetData on the first row. Verify the
|
|
//data obtained is same as the one we had set.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowsetChangeSet()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG_PTR updtFlag = 0;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBORDINAL cRowsetCols = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
HROW* rghRows = NULL;
|
|
BYTE* pData = NULL;
|
|
BYTE* pData2 = NULL;
|
|
DBCOUNTITEM cBindings = 0;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBBINDING* rgBindings = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowsetChange* pIRC = NULL;
|
|
|
|
if(!IsUsableInterface(ROWSET_INTERFACE, IID_IRowsetChange))
|
|
{
|
|
odtLog<<L"IID_IRowsetChange is not required.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
//Get value of the DBPROP_UPDATABILITY property.
|
|
if(!GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, (IUnknown*)
|
|
m_pIRowset, &updtFlag))
|
|
{
|
|
odtLog<<L"INFO: Could not get the value of DBPROP_UPDATABILITY.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
if(!(updtFlag & DBPROPVAL_UP_CHANGE))
|
|
{
|
|
odtLog<<L"CHANGE is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IRowsetChange,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRC))
|
|
|
|
//Get list of ordinals.
|
|
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols,
|
|
&rgColumnsOrd, NULL, NULL, NULL, NULL))
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create Accessor with a binding using length, status and value.
|
|
//This accessor binds all updateable non-index columns.
|
|
TESTC_(GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
UPDATEABLE_NONINDEX_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Restart position.
|
|
TESTC_(RestartPosition(m_pIRowset), S_OK)
|
|
|
|
//Allocate 2 new data buffers
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
SAFE_ALLOC(pData2, BYTE, cbRowSize)
|
|
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
memset(pData2, 0, (size_t) cbRowSize);
|
|
|
|
//Get the first row.
|
|
TESTC_(GetNextRows(m_pIRowset, NULL,0,1,&cRowsObtained,
|
|
&rghRows),S_OK)
|
|
|
|
//Make data corresponding to row (g_ulNextRow+1).
|
|
TESTC_(FillInputBindings(m_pTable, DBACCESSOR_ROWDATA,
|
|
cBindings, rgBindings, &pData, ++g_ulNextRow, cRowsetCols,
|
|
rgColumnsOrd, PRIMARY),S_OK)
|
|
|
|
//Set data of first row.
|
|
TESTC_(hr=pIRC->SetData(rghRows[0],hAccessor,pData),S_OK)
|
|
|
|
//Get the data for the first row
|
|
TESTC_(m_pIRowset->GetData(rghRows[0],hAccessor,pData2),S_OK)
|
|
|
|
//make sure GetData should be able to see the change
|
|
TESTC(CompareBuffer(pData2,pData,cBindings,rgBindings,
|
|
m_pIMalloc,TRUE, FALSE, COMPARE_ONLY))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData, TRUE);
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData2, TRUE);
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRC);
|
|
return tTestResult;
|
|
} //testIRowsetChangeSet
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc @mfunc Check if Updateability and DBPROPVAL_UP_DELETE are
|
|
//supported. Delete the first row. Make sure it was deleted.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowsetChangeDelete()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG_PTR updtFlag = 0;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW* rghRows = NULL;
|
|
DBROWSTATUS rgRowStatus[1];
|
|
BYTE* pData = NULL;
|
|
DBCOUNTITEM cBindings = 0;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBBINDING* rgBindings = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowsetChange* pIRC = NULL;
|
|
|
|
if(!IsUsableInterface(ROWSET_INTERFACE, IID_IRowsetChange))
|
|
{
|
|
odtLog<<L"IID_IRowsetChange is not required.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
//Get value of the DBPROP_UPDATABILITY property.
|
|
if(!GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, (IUnknown*)
|
|
m_pIRowset, &updtFlag))
|
|
{
|
|
odtLog<<L"INFO: Could not get the value of DBPROP_UPDATABILITY.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
if(!(updtFlag & DBPROPVAL_UP_DELETE))
|
|
{
|
|
odtLog<<L"DELETE is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IRowsetChange,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRC))
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create Accessor with a binding using length, status and value.
|
|
//This accessor binds all updateable non-index columns.
|
|
TESTC_(GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
UPDATEABLE_NONINDEX_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Restart position.
|
|
TESTC_(RestartPosition(m_pIRowset), S_OK)
|
|
|
|
//Get the first row.
|
|
TESTC_(GetNextRows(m_pIRowset, NULL,0,1,&cRowsObtained,
|
|
&rghRows),S_OK)
|
|
|
|
//Delete the first row.
|
|
TESTC_(pIRC->DeleteRows(NULL,1,rghRows,rgRowStatus), S_OK)
|
|
m_pTable->SubtractRow();
|
|
|
|
TESTC(rgRowStatus[0] == DBROWSTATUS_S_OK)
|
|
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
|
|
//Call GetData on the deleted row. This should fail.
|
|
hr = m_pIRowset->GetData(rghRows[0], hAccessor, pData);
|
|
CHECKW(hr, DB_E_DELETEDROW);
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(pData);
|
|
CHECK(ReleaseRows(&m_pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRC);
|
|
return tTestResult;
|
|
} //testIRowsetChangeDelete
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Check if Updateability and DBPROPVAL_UP_INSERT are supported.
|
|
//Create an accessor binds all updateable, non-index columns. Create
|
|
//data for a new row and insert it. Verify that the new row was inserted
|
|
//into the rowset.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowsetChangeInsert()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG_PTR updtFlag = 0;
|
|
DBORDINAL cRowsetCols = 0;
|
|
ULONG cRowsInserted = 0; //small no.
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
HROW hNewRow = DB_NULL_HROW;
|
|
BYTE* pData = NULL;
|
|
BYTE* pData2 = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBBINDING* rgBindings = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowsetChange* pIRC = NULL;
|
|
|
|
if(!IsUsableInterface(ROWSET_INTERFACE, IID_IRowsetChange))
|
|
{
|
|
odtLog<<L"IID_IRowsetChange is not required.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
//Get value of the DBPROP_UPDATABILITY property.
|
|
if(!GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, (IUnknown*)
|
|
m_pIRowset, &updtFlag))
|
|
{
|
|
odtLog<<L"INFO: Could not get the value of DBPROP_UPDATABILITY.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
if(!(updtFlag & DBPROPVAL_UP_INSERT))
|
|
{
|
|
odtLog<<L"INSERT is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IRowsetChange,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRC))
|
|
|
|
//Get list of ordinals.
|
|
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols,
|
|
&rgColumnsOrd, NULL, NULL, NULL, NULL))
|
|
|
|
TESTC(VerifyInterface(m_pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create Accessor with a binding using length, status and value.
|
|
//This accessor binds all updateable non-index columns.
|
|
TESTC_(GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
UPDATEABLE_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Restart position.
|
|
TESTC_(RestartPosition(m_pIRowset), S_OK)
|
|
|
|
//Allocate 2 new data buffers
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
SAFE_ALLOC(pData2, BYTE, cbRowSize)
|
|
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
memset(pData2, 0, (size_t) cbRowSize);
|
|
|
|
//Make data corresponding to row (g_ulNextRow+1).
|
|
TESTC_(FillInputBindings(m_pTable, DBACCESSOR_ROWDATA,
|
|
cBindings, rgBindings, &pData,++g_ulNextRow, cRowsetCols,
|
|
rgColumnsOrd, PRIMARY),S_OK)
|
|
|
|
//Insert the row.
|
|
TESTC_(pIRC->InsertRow(NULL,hAccessor,pData,&hNewRow),S_OK)
|
|
TESTC(hNewRow != DB_NULL_HROW)
|
|
m_pTable->AddRow();
|
|
cRowsInserted++;
|
|
|
|
//get the data for the new row
|
|
TESTC_(m_pIRowset->GetData(hNewRow,hAccessor,pData2),S_OK)
|
|
|
|
//Compare the data.
|
|
TESTC(CompareBuffer(pData2,pData,cBindings,rgBindings,
|
|
m_pIMalloc,TRUE, FALSE, COMPARE_ONLY))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData, TRUE);
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData2, TRUE);
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
CHECK(m_pIRowset->ReleaseRows(cRowsInserted, &hNewRow, NULL,NULL,
|
|
NULL), S_OK);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRC);
|
|
return tTestResult;
|
|
} //testIRowsetChangeInsert
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Create a rowset with IRowsetUpdate. Modify the rowset. Use the
|
|
//methods of IRowsetUpdate to Undo and Update changes. Verify results
|
|
//of the various methods of this interface.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowsetUpdate()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG_PTR updtFlag = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DBORDINAL cRowsetCols = 0;
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
HROW* rghRows = NULL;
|
|
BYTE* pData = NULL;
|
|
BYTE* pData2 = NULL;
|
|
BYTE* pOrgData = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBBINDING* rgBindings = NULL;
|
|
DBCOUNTITEM cRowsOut = 0;
|
|
DBCOUNTITEM cPendingRows = 0;
|
|
HROW* rghRowsOut = NULL;
|
|
HROW* rgPendingRows = NULL;
|
|
DBROWSTATUS* rgRowStatus = NULL;
|
|
DBPENDINGSTATUS pendingStatus = DBPENDINGSTATUS_NEW |
|
|
DBPENDINGSTATUS_CHANGED |
|
|
DBPENDINGSTATUS_DELETED ;
|
|
DBPENDINGSTATUS* rgPendingStatus = NULL;
|
|
IRowset* pIRowset = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowsetUpdate* pIRowsetUpdate = NULL;
|
|
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
|
|
LONG ulUpdateFlags = DBPROPVAL_UP_CHANGE|
|
|
DBPROPVAL_UP_DELETE|
|
|
DBPROPVAL_UP_INSERT ;
|
|
|
|
//Set the following properties (ALL REQUIRED).
|
|
SetProperty(DBPROP_IRowsetUpdate, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets);
|
|
|
|
SetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets,
|
|
(void*)(LONG_PTR)ulUpdateFlags, DBTYPE_I4, //cast modified
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetProperty(DBPROP_CANHOLDROWS,
|
|
DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ;
|
|
|
|
//Open a rowset with above properties set.
|
|
hr=CreateOpenRowset(m_pTable, IID_IRowset,
|
|
(IUnknown**)&pIRowset);
|
|
|
|
if(hr==DB_E_ERRORSOCCURRED)
|
|
{
|
|
DumpPropertyErrors(m_cPropSets, m_rgPropSets);
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
TESTC(!pIRowset)
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
TEST2C_(hr, S_OK, DB_S_ERRORSOCCURRED)
|
|
|
|
//Get value of the DBPROP_UPDATABILITY property.
|
|
if(!GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, (IUnknown*)
|
|
pIRowset, &updtFlag))
|
|
{
|
|
odtLog<<L"INFO: Could not get the value of DBPROP_UPDATABILITY.\n";
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//We need DBPROPVAL_UP_CHANGE and DBPROPVAL_UP_DELETE to be supported
|
|
//for this test.
|
|
if(!(updtFlag & DBPROPVAL_UP_CHANGE) || !(updtFlag & DBPROPVAL_UP_DELETE))
|
|
{
|
|
odtLog<<L"DBPROPVAL_UP_CHANGE and/or DBPROPVAL_UP_DELETE is not supported.\n";
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Get list of ordinals.
|
|
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols,
|
|
&rgColumnsOrd, NULL, NULL, NULL, NULL))
|
|
|
|
TESTC(VerifyInterface(pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
TESTC(VerifyInterface(pIRowset,IID_IRowsetUpdate,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRowsetUpdate))
|
|
|
|
//Create Accessor with a binding using length, status and value.
|
|
//This accessor binds all updateable non-index columns.
|
|
TESTC_(GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
UPDATEABLE_NONINDEX_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Donot call RestartPosition. We should be at the beginning of
|
|
//the rowset.
|
|
|
|
//Allocate 2 new data buffers
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
SAFE_ALLOC(pData2, BYTE, cbRowSize)
|
|
SAFE_ALLOC(pOrgData, BYTE, cbRowSize)
|
|
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
memset(pData2, 0, (size_t) cbRowSize);
|
|
memset(pOrgData, 0, (size_t) cbRowSize);
|
|
|
|
//Fetch the 2nd row.
|
|
TESTC_(hr = GetNextRows(pIRowset, NULL,1,1,&cRowsObtained,
|
|
&rghRows),S_OK)
|
|
|
|
TESTC_(hr = pIRowset->GetData(rghRows[0],hAccessor,pOrgData),S_OK)
|
|
|
|
//Make data corresponding to row (g_ulNextRow+1).
|
|
TESTC_(FillInputBindings(m_pTable, DBACCESSOR_ROWDATA,
|
|
cBindings, rgBindings, &pData, ++g_ulNextRow, cRowsetCols,
|
|
rgColumnsOrd, PRIMARY),S_OK)
|
|
|
|
//Set data of 2nd row.
|
|
TESTC_(hr = pIRowsetUpdate->SetData(rghRows[0],hAccessor,pData),S_OK)
|
|
|
|
//GetPendingRows should return the 2nd row.
|
|
TESTC_(hr = pIRowsetUpdate->GetPendingRows(NULL, pendingStatus,
|
|
&cPendingRows, &rgPendingRows, &rgPendingStatus), S_OK)
|
|
|
|
//Check return values. Pending status should be _CHANGED.
|
|
TESTC(cPendingRows==1 && rgPendingRows && rgPendingStatus)
|
|
TESTC(rgPendingRows[0] != DB_NULL_HROW)
|
|
TESTC(rgPendingStatus[0] == DBPENDINGSTATUS_CHANGED)
|
|
|
|
rgPendingStatus[0] = DBPENDINGSTATUS_INVALIDROW;
|
|
|
|
//Call GetRowsStatus on rgPendingRows obtained from the call
|
|
//to GetPendingRows. Pending status should be _CHANGED.
|
|
TESTC_(hr = pIRowsetUpdate->GetRowStatus(NULL, 1, rgPendingRows,
|
|
rgPendingStatus), S_OK)
|
|
TESTC(rgPendingStatus[0] == DBPENDINGSTATUS_CHANGED)
|
|
|
|
PROVIDER_FREE(rgPendingRows);
|
|
PROVIDER_FREE(rgPendingStatus);
|
|
|
|
//Get data for the 2nd row.
|
|
TESTC_(hr = pIRowset->GetData(rghRows[0],hAccessor,pData2),S_OK)
|
|
|
|
//The data should be the new one we had set it to.
|
|
TESTC(CompareData(cRowsetCols, rgColumnsOrd, g_ulNextRow, pData2, cBindings,
|
|
rgBindings, m_pTable, m_pIMalloc, PRIMARY, COMPARE_ONLY))
|
|
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData);
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData2);
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
memset(pData2, 0, (size_t) cbRowSize);
|
|
|
|
//This should return the original data for the 2nd row.
|
|
TESTC_(hr = pIRowsetUpdate->GetOriginalData(rghRows[0], hAccessor,
|
|
pData2), S_OK)
|
|
|
|
//Make sure it is the orginal data.
|
|
TESTC(CompareBuffer(pOrgData,pData2,cBindings,rgBindings,
|
|
m_pIMalloc,TRUE, FALSE, COMPARE_ONLY))
|
|
|
|
//Undo the change made to the 2nd row.
|
|
TESTC_(hr = pIRowsetUpdate->Undo(NULL, 1, rghRows, &cRowsOut,
|
|
&rghRowsOut, &rgRowStatus), S_OK)
|
|
|
|
TESTC(cRowsOut==1 && rghRowsOut && rgRowStatus &&
|
|
rgRowStatus[0]==DBROWSTATUS_S_OK)
|
|
|
|
TESTC(rghRowsOut[0] != DB_NULL_HROW)
|
|
|
|
//Get the data after undoing the change.
|
|
TESTC_(hr = pIRowset->GetData(rghRowsOut[0],hAccessor,pData),S_OK)
|
|
|
|
//This should be the same as the original data for 2nd row.
|
|
TESTC(CompareBuffer(pData2,pData,cBindings,rgBindings,
|
|
m_pIMalloc,TRUE, FALSE, COMPARE_ONLY))
|
|
|
|
PROVIDER_FREE(rghRowsOut);
|
|
PROVIDER_FREE(rgRowStatus);
|
|
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData);
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData2);
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
memset(pData2, 0, (size_t) cbRowSize);
|
|
|
|
//Release the row handle.
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
|
|
//Get the 3rd row.
|
|
TESTC_(hr = GetNextRows(pIRowset, NULL,0,1,&cRowsObtained,
|
|
&rghRows),S_OK)
|
|
|
|
//Delete the 3rd row.
|
|
TESTC_(pIRowsetUpdate->DeleteRows(NULL,1,rghRows,rgRowStatus), S_OK)
|
|
|
|
//GetPendingRows should give 1 row with status _DELETED.
|
|
TESTC_(hr = pIRowsetUpdate->GetPendingRows(NULL, pendingStatus,
|
|
&cPendingRows, &rgPendingRows, &rgPendingStatus), S_OK)
|
|
|
|
TESTC(cPendingRows==1 && rgPendingRows && rgPendingStatus)
|
|
TESTC(rgPendingStatus[0] == DBPENDINGSTATUS_DELETED)
|
|
|
|
//Update the change.
|
|
TESTC_(hr = pIRowsetUpdate->Update(NULL, 1, rghRows, &cRowsOut,
|
|
&rghRowsOut,&rgRowStatus), S_OK)
|
|
|
|
TESTC(cRowsOut==1 && rghRowsOut && rgRowStatus)
|
|
TESTC(rghRowsOut[0] != DB_NULL_HROW)
|
|
TESTC(rgRowStatus[0] == DBROWSTATUS_S_OK)
|
|
|
|
//Try to call GetData on the row which was deleted and updated.
|
|
//This should fail. The expected return code is DB_E_DELETEDROW,
|
|
//although this is provider specific.
|
|
hr = pIRowset->GetData(rghRows[0],hAccessor,pData) ;
|
|
CHECKW(hr, DB_E_DELETEDROW) ;
|
|
|
|
cRowsObtained = 0;
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pOrgData);
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
SAFE_FREE(pData);
|
|
SAFE_FREE(pData2);
|
|
SAFE_FREE(pOrgData);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
PROVIDER_FREE(rgRowStatus);
|
|
PROVIDER_FREE(rghRowsOut);
|
|
PROVIDER_FREE(rgPendingRows);
|
|
PROVIDER_FREE(rgPendingStatus);
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
SAFE_RELEASE(pIAccessor);
|
|
SAFE_RELEASE(pIRowsetUpdate);
|
|
SAFE_RELEASE(pIRowset);
|
|
return tTestResult;
|
|
} //testIRowsetUpdate
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Open 2 rowsets on the same table. Fetch the first rows of each
|
|
//rowset and keep the row handles. Call SetData to modify the data of
|
|
//the first row of rowset1. Then call IRowsetResynch::ResynchRows on
|
|
//rowset2. Now the data of rowset2 should reflect the change made in
|
|
//rowset1. Verify this.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowsetResynch()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBCOUNTITEM cRowsObtained1 = 0;
|
|
DBCOUNTITEM cRowsObtained2 = 0;
|
|
DBCOUNTITEM cRowsOut = 0;
|
|
ULONG_PTR updtFlag = 0;
|
|
HROW* rghRows1 = NULL;
|
|
HROW* rghRows2 = NULL;
|
|
HROW* rghRowsOut = NULL;
|
|
DBORDINAL cRowsetCols = 0;
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
BYTE* pData = NULL;
|
|
BYTE* pData2 = NULL;
|
|
DBROWSTATUS* rgRowStatus = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBBINDING* rgBindings = NULL;
|
|
IRowset* pIRowset1 = NULL;
|
|
IRowset* pIRowset2 = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowsetUpdate* pIRowsetUpdate = NULL;
|
|
IRowsetChange* pIRowsetChange = NULL;
|
|
IRowsetResynch* pIRowsetResynch = NULL;
|
|
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
|
|
LONG ulUpdateFlags = DBPROPVAL_UP_CHANGE|
|
|
DBPROPVAL_UP_DELETE|
|
|
DBPROPVAL_UP_INSERT ;
|
|
|
|
//Set the following properties.
|
|
SetProperty(DBPROP_IRowsetResynch, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets) ;
|
|
SetProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets) ;
|
|
|
|
SetSettableProperty(DBPROP_OTHERUPDATEDELETE, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets) ;
|
|
|
|
SetSettableProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets,
|
|
(void*)(LONG_PTR)ulUpdateFlags, DBTYPE_I4, //cast modified
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetProperty(DBPROP_CANHOLDROWS,
|
|
DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ;
|
|
|
|
//Open a rowset with above properties set.
|
|
hr=CreateOpenRowset(m_pTable, IID_IRowset,(IUnknown**)
|
|
&pIRowset1);
|
|
|
|
if(hr==DB_E_ERRORSOCCURRED)
|
|
{
|
|
DumpPropertyErrors(m_cPropSets, m_rgPropSets);
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
TESTC(!pIRowset1)
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
TEST2C_(hr, S_OK, DB_S_ERRORSOCCURRED)
|
|
|
|
//Get value of the DBPROP_UPDATABILITY property.
|
|
if(!GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, (IUnknown*)
|
|
pIRowset1, &updtFlag))
|
|
{
|
|
odtLog<<L"Could not get the value of DBPROP_UPDATABILITY.\n";
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
if(!(updtFlag & DBPROPVAL_UP_CHANGE))
|
|
{
|
|
odtLog<<L"CHANGE is not supported.\n";
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//If IRowsetUpdate exists then fail the test.
|
|
if(VerifyInterface(pIRowset1,IID_IRowsetUpdate,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRowsetUpdate))
|
|
{
|
|
odtLog<<L"Requested to be in immediate-update mode, but currently in buffered mode.\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Open another rowset with above properties set.
|
|
TEST2C_(hr = CreateOpenRowset(m_pTable, IID_IRowset,
|
|
(IUnknown**)&pIRowset2), S_OK, DB_S_ERRORSOCCURRED)
|
|
|
|
TESTC(VerifyInterface(pIRowset1,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
TESTC(VerifyInterface(pIRowset1,IID_IRowsetChange,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRowsetChange))
|
|
|
|
TESTC(VerifyInterface(pIRowset2,IID_IRowsetResynch,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRowsetResynch))
|
|
|
|
//Create Accessor with a binding using length, status and value.
|
|
//This accessor binds updateable non-index columns.
|
|
TESTC_(GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
UPDATEABLE_NONINDEX_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Get list of ordinals.
|
|
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols,
|
|
&rgColumnsOrd, NULL, NULL, NULL, NULL))
|
|
|
|
//Allocate 2 new data buffers
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
SAFE_ALLOC(pData2, BYTE, cbRowSize)
|
|
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
memset(pData2, 0, (size_t) cbRowSize);
|
|
|
|
//Restart position for rowset1.
|
|
TESTC_(RestartPosition(pIRowset1), S_OK)
|
|
|
|
//Fetch first row of rowset1.
|
|
TESTC_(hr = GetNextRows(pIRowset1, NULL,0,1,&cRowsObtained1,
|
|
&rghRows1),S_OK)
|
|
|
|
//Restart position for rowset2.
|
|
TESTC_(RestartPosition(pIRowset2), S_OK)
|
|
|
|
//Fetch first row of rowset2.
|
|
TESTC_(hr = GetNextRows(pIRowset2, NULL,0,1,&cRowsObtained2,
|
|
&rghRows2),S_OK)
|
|
|
|
//Make data corresponding to row (g_ulNextRow+1).
|
|
TESTC_(FillInputBindings(m_pTable, DBACCESSOR_ROWDATA,
|
|
cBindings, rgBindings, &pData, ++g_ulNextRow, cRowsetCols,
|
|
rgColumnsOrd, PRIMARY),S_OK)
|
|
|
|
//Set data of 1st row of rowset1 to that of row (cTotalRows+1).
|
|
TESTC_(hr = pIRowsetChange->SetData(rghRows1[0],hAccessor,pData),S_OK)
|
|
|
|
//Release accessor and bindings.
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
|
|
TESTC(VerifyInterface(pIRowset2,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create Accessor with a binding using length, status and value.
|
|
//This accessor binds the updateable non-index columns.
|
|
TESTC_(GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
UPDATEABLE_NONINDEX_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Get the backend data for first row of rowset2.
|
|
TESTC_(hr = pIRowsetResynch->GetVisibleData(rghRows2[0], hAccessor,
|
|
pData2), S_OK)
|
|
|
|
//This should be same as the new data that the first row of rowset1
|
|
//was set to.
|
|
TESTC(CompareBuffer(pData2,pData,cBindings,rgBindings,
|
|
m_pIMalloc,TRUE, FALSE, COMPARE_ONLY))
|
|
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData2);
|
|
memset(pData2, 0, (size_t) cbRowSize);
|
|
|
|
//Resynch the rows of rowset2.
|
|
TESTC_(hr = pIRowsetResynch->ResynchRows(1, rghRows2, &cRowsOut,
|
|
&rghRowsOut, &rgRowStatus), S_OK)
|
|
|
|
TESTC(cRowsOut==1 && rghRowsOut && rgRowStatus)
|
|
TESTC(rgRowStatus[0] == DBROWSTATUS_S_OK)
|
|
|
|
//Get the data for the first row of rowset2.
|
|
TESTC_(hr = pIRowset2->GetData(rghRowsOut[0], hAccessor, pData2),
|
|
S_OK)
|
|
|
|
//It should be the same as the data which was set in rowset1.
|
|
TESTC(CompareBuffer(pData2,pData,cBindings,rgBindings,
|
|
m_pIMalloc,TRUE, FALSE, COMPARE_ONLY))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData, TRUE);
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData2, TRUE);
|
|
CHECK(ReleaseRows(&pIRowset1, &cRowsObtained1, &rghRows1), S_OK);
|
|
CHECK(ReleaseRows(&pIRowset2, &cRowsObtained2, &rghRows2), S_OK);
|
|
PROVIDER_FREE(rghRowsOut);
|
|
PROVIDER_FREE(rgRowStatus);
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowsetUpdate);
|
|
SAFE_RELEASE(pIRowsetChange);
|
|
SAFE_RELEASE(pIRowset1);
|
|
SAFE_RELEASE(pIRowset2);
|
|
SAFE_RELEASE(pIRowsetResynch);
|
|
return tTestResult;
|
|
} //testIRowsetResynch
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Open a rowset with IRowsetRefresh (in the buffered update mode).
|
|
//Fetch the first row of the rowset and keep the row handle. Call
|
|
//SetData to modify the data of the first row. Then, without calling
|
|
//IRowsetUpdate::Update, call IRowsetRefresh::RefreshVisibleData. Then
|
|
//call GetData on the first row. This should give the original data
|
|
//corresponding to the first row.
|
|
//
|
|
TESTRESULT CQuickTest::testIRowsetRefresh()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DBCOUNTITEM cRowsOut = 0;
|
|
ULONG_PTR updtFlag = 0;
|
|
HROW* rghRows = NULL;
|
|
HROW* rghRowsOut = NULL;
|
|
DBORDINAL cRowsetCols = 0;
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
BYTE* pData = NULL;
|
|
BYTE* pOrgData = NULL;
|
|
BYTE* pData2 = NULL;
|
|
DBROWSTATUS* rgRowStatus = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBBINDING* rgBindings = NULL;
|
|
IRowset* pIRowset = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowsetUpdate* pIRowsetUpdate = NULL;
|
|
IRowsetRefresh* pIRowsetRefresh = NULL;
|
|
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
|
|
LONG ulUpdateFlags = DBPROPVAL_UP_CHANGE|
|
|
DBPROPVAL_UP_DELETE|
|
|
DBPROPVAL_UP_INSERT ;
|
|
|
|
//Set the following properties.
|
|
SetProperty(DBPROP_IRowsetRefresh, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets) ;
|
|
|
|
SetProperty(DBPROP_IRowsetUpdate, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets,
|
|
(void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_REQUIRED) ;
|
|
|
|
SetSettableProperty(DBPROP_OTHERUPDATEDELETE, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets) ;
|
|
|
|
SetSettableProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets,
|
|
(void*)(LONG_PTR)ulUpdateFlags, DBTYPE_I4, //cast modified
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetProperty(DBPROP_CANHOLDROWS,
|
|
DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ;
|
|
|
|
//Open a rowset with above properties set.
|
|
hr=CreateOpenRowset(m_pTable, IID_IRowset,(IUnknown**)&pIRowset);
|
|
|
|
if(hr==DB_E_ERRORSOCCURRED)
|
|
{
|
|
DumpPropertyErrors(m_cPropSets, m_rgPropSets);
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
TESTC(!pIRowset);
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
|
|
}
|
|
|
|
TEST2C_(hr, S_OK, DB_S_ERRORSOCCURRED)
|
|
|
|
//Get value of the DBPROP_UPDATABILITY property.
|
|
if(!GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, (IUnknown*)
|
|
pIRowset, &updtFlag))
|
|
{
|
|
odtLog<<L"INFO: Could not get the value of DBPROP_UPDATABILITY.\n";
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Make sure CHANGE is supported.
|
|
if(!(updtFlag & DBPROPVAL_UP_CHANGE))
|
|
{
|
|
odtLog<<L"CHANGE is not supported.\n";
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(VerifyInterface(pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
TESTC(VerifyInterface(pIRowset,IID_IRowsetUpdate,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRowsetUpdate))
|
|
|
|
TESTC(VerifyInterface(pIRowset,IID_IRowsetRefresh,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRowsetRefresh))
|
|
|
|
//Create Accessor with a binding using length, status and value.
|
|
//This accessor binds updateable non-index columns.
|
|
TESTC_(GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
UPDATEABLE_NONINDEX_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Get list of ordinals.
|
|
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols,
|
|
&rgColumnsOrd, NULL, NULL, NULL, NULL))
|
|
|
|
//Allocate 2 new data buffers
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
SAFE_ALLOC(pData2, BYTE, cbRowSize)
|
|
SAFE_ALLOC(pOrgData, BYTE, cbRowSize)
|
|
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
memset(pData2, 0, (size_t) cbRowSize);
|
|
memset(pOrgData, 0, (size_t) cbRowSize);
|
|
|
|
//Restart position.
|
|
TESTC_(RestartPosition(pIRowset), S_OK)
|
|
|
|
//Fetch first row.
|
|
TESTC_(hr = GetNextRows(pIRowset, NULL,0,1,&cRowsObtained,
|
|
&rghRows),S_OK)
|
|
|
|
//Get data of the first row.
|
|
TESTC_(hr = pIRowset->GetData(rghRows[0], hAccessor, pOrgData),
|
|
S_OK)
|
|
|
|
//Make data corresponding to row (g_ulNextRow+1).
|
|
TESTC_(FillInputBindings(m_pTable, DBACCESSOR_ROWDATA,
|
|
cBindings, rgBindings, &pData, ++g_ulNextRow, cRowsetCols,
|
|
rgColumnsOrd, PRIMARY),S_OK)
|
|
|
|
//Set data of 1st row.
|
|
TESTC_(hr = pIRowsetUpdate->SetData(rghRows[0],hAccessor,pData),S_OK)
|
|
|
|
//Get the backend data for first row.
|
|
TESTC_(hr = pIRowsetRefresh->GetLastVisibleData(rghRows[0], hAccessor,
|
|
pData2), S_OK)
|
|
|
|
//This should be same as the original data of first row.
|
|
TESTC(CompareBuffer(pData2,pOrgData,cBindings,rgBindings,
|
|
m_pIMalloc,TRUE, FALSE, COMPARE_ONLY))
|
|
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData2);
|
|
memset(pData2, 0, (size_t) cbRowSize);
|
|
|
|
//Resynch the first row.
|
|
TESTC_(hr = pIRowsetRefresh->RefreshVisibleData(NULL, 1, rghRows,
|
|
TRUE, &cRowsOut, &rghRowsOut, &rgRowStatus), S_OK)
|
|
|
|
TESTC(cRowsOut==1 && rghRowsOut && rgRowStatus)
|
|
TESTC(rgRowStatus[0] == DBROWSTATUS_S_OK)
|
|
|
|
//Get the data for the first row.
|
|
TESTC_(hr = pIRowset->GetData(rghRowsOut[0], hAccessor, pData2),
|
|
S_OK)
|
|
|
|
//It should be the same as the original data of first row.
|
|
TESTC(CompareBuffer(pData2,pOrgData,cBindings,rgBindings,
|
|
m_pIMalloc,TRUE, FALSE, COMPARE_ONLY))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData, TRUE);
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pData2, TRUE);
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings, pOrgData, TRUE);
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
PROVIDER_FREE(rghRowsOut);
|
|
PROVIDER_FREE(rgRowStatus);
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowsetUpdate);
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIRowsetRefresh);
|
|
return tTestResult;
|
|
} //testIRowsetRefresh
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
//@mfunc Obtain the IAccesssor interface through the ICommand interface.
|
|
//Create bindings and then create an accessor with this binding. The
|
|
//length, status and value fields are bound. All columns are bound
|
|
//including BLOB_LONG. Verify the status of the bindings after creating
|
|
//the accessor. Then call the method GetBindings and verify that
|
|
//they are the same as the ones used to create the accessor. Use the
|
|
//accessor to fetch rows and verify them. Call ReleaseAccessor.
|
|
//
|
|
TESTRESULT CQuickTest::testCmdIAccessor()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBCOUNTITEM ulIndex = 0;
|
|
DBCOUNTITEM cRows = 0;
|
|
DBROWCOUNT cRowsAffected = 0;
|
|
DBORDINAL cRowsetCols = 0;
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
DBBINDSTATUS* rgStatus = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
ULONG cPropSets = 0;
|
|
DBPROPSET* rgPropSets = NULL;
|
|
DBCOUNTITEM cBindings = 0;
|
|
DBBINDING* rgBindings = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowset* pIRowset = NULL;
|
|
ICommand* pICommand = NULL;
|
|
|
|
//Set this property.
|
|
SetSettableProperty(DBPROP_IRowsetLocate,
|
|
DBPROPSET_ROWSET, &cPropSets, &rgPropSets) ;
|
|
|
|
//Create SQL stmt and set command text.
|
|
TEST2C_(hr = m_pTable->ExecuteCommand(SELECT_ALLFROMTBL,
|
|
IID_ICommand, NULL, NULL, &cRowsetCols, &rgColumnsOrd,
|
|
EXECUTE_NEVER, cPropSets, rgPropSets, NULL,
|
|
NULL, &pICommand), S_OK, DB_S_ERRORSOCCURRED)
|
|
|
|
TESTC(pICommand != NULL)
|
|
|
|
//Obtain the IAccessor (command) interface.
|
|
if(!VerifyInterface(pICommand,IID_IAccessor,
|
|
COMMAND_INTERFACE,(IUnknown**)&pIAccessor))
|
|
return TEST_FAIL;
|
|
|
|
//Create Accessor with a binding using length, status and value.
|
|
//All columns are bound including BLOB_LONG.
|
|
TESTC_(hr = GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,
|
|
&hAccessor, &rgBindings, &cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,
|
|
NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_LONG,
|
|
&rgStatus),S_OK)
|
|
|
|
//Verify status of bindings.
|
|
for(ulIndex=0; ulIndex<cBindings; ulIndex++)
|
|
TESTC(rgStatus[ulIndex] == DBBINDSTATUS_OK)
|
|
|
|
//Call the IAccessor::GetBindings method and verify.
|
|
TESTC(VerifyBindings(pIAccessor, hAccessor, cBindings, rgBindings,
|
|
DBACCESSOR_ROWDATA))
|
|
|
|
//cRowsAffected is undefined on output.
|
|
TESTC_(hr = pICommand->Execute(NULL, IID_IRowset, NULL, &cRowsAffected,
|
|
(IUnknown**)&pIRowset), S_OK)
|
|
|
|
TESTC(pIRowset != NULL)
|
|
|
|
//Get number of rows.
|
|
cRows = m_pTable->CountRowsOnTable();
|
|
|
|
//Make sure we are on the first row.
|
|
TESTC_(RestartPosition(pIRowset), S_OK)
|
|
|
|
//For each row in the table, fetch the row, compare the data in the
|
|
//row and release the row.
|
|
for(ulIndex=0; ulIndex<cRows; ulIndex++)
|
|
TESTC(GetDataAndCompare(0, 1, ulIndex+1, cRowsetCols,
|
|
rgColumnsOrd, pIRowset, hAccessor, cBindings,
|
|
rgBindings, cbRowSize))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
FreeProperties(&cPropSets, &rgPropSets);
|
|
PROVIDER_FREE(rgStatus);
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pICommand);
|
|
return tTestResult;
|
|
} //testCmdIAccessor
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Obtain the ICommandProperties interface. Attempt to set three
|
|
//properties. If the method call returns S_OK then verify that all the
|
|
//three properties were correctly set. If method returns DB_S_ERRORSOCCURRED
|
|
//then verify that the relevant property is not supported or not settable.
|
|
//
|
|
TESTRESULT CQuickTest::testSetCmdProp()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
USHORT usSupported = 0;
|
|
ULONG ulIndex = 0;
|
|
ICommandProperties* pICommProp = NULL;
|
|
|
|
//Obtain the ICommandProperties interface.
|
|
if(!VerifyInterface(m_pICommand,IID_ICommandProperties,
|
|
COMMAND_INTERFACE,(IUnknown**)&pICommProp))
|
|
return TEST_FAIL;
|
|
|
|
//Set the following four properties.
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
SetProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET, &m_cPropSets,
|
|
&m_rgPropSets);
|
|
SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &m_cPropSets,
|
|
&m_rgPropSets);
|
|
SetProperty(DBPROP_CANSCROLLBACKWARDS, DBPROPSET_ROWSET, &m_cPropSets,
|
|
&m_rgPropSets);
|
|
|
|
//Call the SetProperties method for the above properties.
|
|
TEST2C_(hr = pICommProp->SetProperties(m_cPropSets, m_rgPropSets),
|
|
S_OK, DB_S_ERRORSOCCURRED)
|
|
|
|
//Loop through all the properties.
|
|
for(ulIndex=0; ulIndex < m_rgPropSets[0].cProperties; ulIndex++)
|
|
{
|
|
//If status shows DBPROPSTATUS_OK then make sure the value
|
|
//of that property was set to VARIANT_TRUE. the hr in this
|
|
//case has to be either S_OK or DB_S_ERRORSOCCURRED.
|
|
if(m_rgPropSets[0].rgProperties[ulIndex].dwStatus ==
|
|
DBPROPSTATUS_OK)
|
|
{
|
|
COMPARE(GetProperty(m_rgPropSets[0].rgProperties[ulIndex].dwPropertyID,
|
|
m_rgPropSets[0].guidPropertySet, pICommProp), TRUE);
|
|
|
|
if(hr==DB_S_ERRORSOCCURRED)
|
|
usSupported++;
|
|
else
|
|
TESTC_(hr, S_OK)
|
|
}
|
|
|
|
//If return value was DB_S_ERRORSOCCURRED then.....
|
|
if(hr==DB_S_ERRORSOCCURRED)
|
|
{
|
|
//If status shows DBPROPSTATUS_NOTSUPPORTED then make sure
|
|
//that the property is not supported.
|
|
if(m_rgPropSets[0].rgProperties[ulIndex].dwStatus ==
|
|
DBPROPSTATUS_NOTSUPPORTED)
|
|
{
|
|
COMPARE(SupportedProperty(m_rgPropSets[0].rgProperties[ulIndex].dwPropertyID,
|
|
m_rgPropSets[0].guidPropertySet), FALSE);
|
|
}
|
|
//If the status shows DBPROPSTATUS_NOTSETTABLE then make sure
|
|
//that the property is not settable.
|
|
else if(m_rgPropSets[0].rgProperties[ulIndex].dwStatus ==
|
|
DBPROPSTATUS_NOTSETTABLE)
|
|
{
|
|
COMPARE(SettableProperty(m_rgPropSets[0].rgProperties[ulIndex].dwPropertyID,
|
|
m_rgPropSets[0].guidPropertySet), FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
//If DB_S_ERRORSOCCURRED was returned, then the number of properties
|
|
//set successfully should be >0 and <cProperties.
|
|
if(hr==DB_S_ERRORSOCCURRED)
|
|
TESTC(usSupported>0 && usSupported<m_rgPropSets[0].cProperties)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
SAFE_RELEASE(pICommProp);
|
|
return tTestResult;
|
|
} //testSetCmdProp
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
//@mfunc Obtain the ICommandText interface. Create an SQL stmt and set
|
|
//the command text. Then get the command text. Verify that the stmt got
|
|
//is the same that was used to set the command text. Create another SQL
|
|
//stmt. Set the command text, prepare it and execute it. Then get the
|
|
//command text and verify.
|
|
//
|
|
TESTRESULT CQuickTest::testICmdText()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
WCHAR* pSQLSet = NULL;
|
|
WCHAR* pSQLGet = NULL;
|
|
DBROWCOUNT cRowsAffected=0;
|
|
GUID guidDialect = DB_NULLGUID;
|
|
ICommandText* pICT = NULL;
|
|
ICommandPrepare* pICommandPrepare = NULL;
|
|
|
|
//Create a command object and get the ICommand interface.
|
|
TESTC_(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommandText,
|
|
(IUnknown**)&pICT), S_OK)
|
|
|
|
//Create the following SQL Stmt.
|
|
TESTC(SUCCEEDED(m_pTable->CreateSQLStmt(SELECT_UPDATEABLE,
|
|
NULL, &pSQLSet, NULL, NULL)))
|
|
|
|
//Set the command text to the above SQL stmt.
|
|
TESTC_(pICT->SetCommandText(DBGUID_DEFAULT, pSQLSet), S_OK)
|
|
|
|
//Get the command text.
|
|
TEST2C_(hr = pICT->GetCommandText(&guidDialect, &pSQLGet), S_OK,
|
|
DB_S_DIALECTIGNORED)
|
|
|
|
//Verify that SQL stmt got is the same that was used to set the
|
|
//command text.
|
|
TESTC(wcscmp(pSQLSet, pSQLGet) == 0)
|
|
|
|
//Free command text
|
|
PROVIDER_FREE(pSQLSet);
|
|
PROVIDER_FREE(pSQLGet);
|
|
|
|
//Create another SQL Stmt.
|
|
TESTC(SUCCEEDED(m_pTable->CreateSQLStmt(SELECT_ALLFROMTBL,NULL,
|
|
&pSQLSet,NULL,NULL)))
|
|
|
|
//Set the command text to the above SQL stmt.
|
|
TESTC_(pICT->SetCommandText(DBGUID_DEFAULT, pSQLSet), S_OK)
|
|
|
|
//If ICommandPrepare is supported, prepare the command.
|
|
//It is not required to prepare the command for Execute.
|
|
if(VerifyInterface(pICT,IID_ICommandPrepare,
|
|
COMMAND_INTERFACE,(IUnknown**)&pICommandPrepare))
|
|
{
|
|
TESTC(pICommandPrepare->Prepare(1) == S_OK)
|
|
}
|
|
|
|
//Execute the command. cRowsAffected is undefined on output.
|
|
TESTC_(pICT->Execute(NULL, IID_NULL, NULL, &cRowsAffected,
|
|
NULL),S_OK)
|
|
|
|
//Get the command text after command execution.
|
|
TEST2C_(hr = pICT->GetCommandText(&guidDialect, &pSQLGet), S_OK,
|
|
DB_S_DIALECTIGNORED)
|
|
|
|
//Verify that SQL stmt got is the same that was used to set the
|
|
//command text before execution.
|
|
TESTC(wcscmp(pSQLSet, pSQLGet) == 0)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pSQLSet);
|
|
PROVIDER_FREE(pSQLGet);
|
|
SAFE_RELEASE(pICommandPrepare);
|
|
SAFE_RELEASE(pICT);
|
|
return tTestResult;
|
|
} //testICmdText
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Create a command on the session. Call the GetDBSession method
|
|
//to obtain the IOpenRowset interface. S_FALSE may be returned by this
|
|
//method if the provider did not have an object that created the command.
|
|
//If S_OK is returned, verify the interface obtained. Set the command
|
|
//text and execute it asking for the IRowsetInfo interface. Call the
|
|
//GetSpecification method on it to obtain the ICommand interface. Verify
|
|
//that it should be the same as the first command interface. Call
|
|
//GetDBSession again, this time to get IDBCreateCommand. Verify this
|
|
//interface.
|
|
//
|
|
TESTRESULT CQuickTest::testICmdGetDBSession()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ICommand* pICmd1 = NULL;
|
|
ICommand* pICmd2 = NULL;
|
|
IOpenRowset* pIOR = NULL;
|
|
IRowsetInfo* pIRowsetInfo = NULL;
|
|
IDBCreateCommand* pIDBCC = NULL;
|
|
|
|
//Create a command object and get the ICommand interface.
|
|
TESTC_(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand,
|
|
(IUnknown**)&pICmd1), S_OK)
|
|
|
|
//Call the GetDBSession method.
|
|
TEST2C_(hr = pICmd1->GetDBSession(IID_IOpenRowset, (IUnknown**)&pIOR),
|
|
S_OK, S_FALSE)
|
|
|
|
if(hr==S_FALSE)
|
|
{
|
|
COMPARE(pIOR, NULL);
|
|
//Issue a warning.
|
|
odtLog<<L"WARNING: S_FALSE was returned for ICommand::GetDBSession.\n";
|
|
CHECKW(hr, S_OK);
|
|
}
|
|
|
|
//Verify the obtained interface.
|
|
if(hr == S_OK)
|
|
TESTC(VerifyEqualInterface(pIOR, m_pIOpenRowset))
|
|
|
|
//Set the command text for execution.
|
|
TESTC_(SetCommandText(m_pIMalloc, pICmd1, m_pTable, NULL, eSELECT,
|
|
SELECT_ALLFROMTBL, NULL), S_OK)
|
|
|
|
//Execute the command and request IRowsetInfo.
|
|
TESTC_(hr=pICmd1->Execute(NULL,IID_IRowsetInfo, NULL, NULL,
|
|
(IUnknown**)&pIRowsetInfo), S_OK)
|
|
|
|
//Call GetSpecification method of IRowsetInfo.
|
|
TEST2C_(hr = pIRowsetInfo->GetSpecification(IID_ICommand, (IUnknown**)
|
|
&pICmd2), S_OK, S_FALSE)
|
|
|
|
if(hr==S_FALSE)
|
|
{
|
|
COMPARE(pICmd2, NULL);
|
|
//Issue a warning.
|
|
odtLog<<L"WARNING: S_FALSE was returned for IRowsetInfo::GetSpecification.\n";
|
|
CHECKW(hr, S_OK);
|
|
}
|
|
|
|
if(hr==S_OK)
|
|
{
|
|
//Verify obtained interface.
|
|
TESTC(VerifyEqualInterface(pICmd1, pICmd2))
|
|
|
|
//Call GetDBSession on the obtained ICommand interface, this time
|
|
//requesting IDBCreateCommand.
|
|
m_hr = pICmd2->GetDBSession(IID_IDBCreateCommand, (IUnknown**)
|
|
&pIDBCC) ;
|
|
|
|
if(m_hr==S_FALSE)
|
|
{
|
|
//Issue a warning.
|
|
odtLog<<L"WARNING: GetDBSession returned S_FALSE.\n";
|
|
CHECKW(m_hr, S_OK);
|
|
}
|
|
else
|
|
TESTC_(m_hr, S_OK)
|
|
|
|
//Verify obtained interface.
|
|
TESTC(VerifyEqualInterface(pIDBCC, m_pIDBCreateCommand))
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pICmd1);
|
|
SAFE_RELEASE(pICmd2);
|
|
SAFE_RELEASE(pIOR);
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
SAFE_RELEASE(pIDBCC);
|
|
return tTestResult;
|
|
} //testICmdGetDBSession
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Check if the provider is Read-only. Create a command object and
|
|
//obtain the ICommand interface. Set the command text to insert and
|
|
//execute the command. Again set the command text to insert and execute
|
|
//the command. The set the command text to select all from table and
|
|
//execute this command, asking for IRowset. The previous 2 calls to
|
|
//execute did not request any interface (passed in IID_NULL).
|
|
//
|
|
TESTRESULT CQuickTest::testICmdExec1()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
BOOL fIsProvReadOnly = FALSE;
|
|
WCHAR* pwszCmdText = NULL;
|
|
HRESULT hr = E_FAIL;
|
|
DBCOUNTITEM ulIndex = 0;
|
|
DBCOUNTITEM cTotalRows = 0;
|
|
DBROWCOUNT cRowsAffected=0;
|
|
DBORDINAL cRowsetCols = 0;
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
DBBINDING* rgBindings = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
IAccessor* pIAccessor = NULL;
|
|
ICommandText* pICmd1 = NULL;
|
|
IRowset* pIRowset = NULL;
|
|
|
|
//Check if provider is Read-only.
|
|
if(IsProviderReadOnly((IUnknown*)m_pIOpenRowset))
|
|
fIsProvReadOnly = TRUE;
|
|
|
|
//Create a command object.
|
|
TESTC_(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommandText,
|
|
(IUnknown**)&pICmd1), S_OK)
|
|
|
|
if(!fIsProvReadOnly)
|
|
{
|
|
//Set the command text to insert.
|
|
TESTC_(SetCommandText(m_pIMalloc, pICmd1, m_pTable, NULL,eINSERT,
|
|
NO_QUERY, NULL,NULL,NULL,NULL,&pwszCmdText), S_OK)
|
|
|
|
//Execute the command.
|
|
TEST2C_(hr=pICmd1->Execute(NULL, IID_NULL, NULL, &cRowsAffected,
|
|
NULL),S_OK, DB_E_NOCOMMAND)
|
|
|
|
if(pwszCmdText)
|
|
{
|
|
TESTC_(hr, S_OK)
|
|
//Check affected rows.
|
|
TESTC(cRowsAffected==1 || cRowsAffected==DB_COUNTUNAVAILABLE)
|
|
//Insert adds a row.
|
|
m_pTable->AddRow();
|
|
}
|
|
else
|
|
TESTC_(hr, DB_E_NOCOMMAND)
|
|
|
|
SAFE_FREE(pwszCmdText);
|
|
|
|
//Set the command text to insert again. The command text has to
|
|
//be set again to insert a unique row.
|
|
TESTC_(SetCommandText(m_pIMalloc, pICmd1, m_pTable, NULL,eINSERT,
|
|
NO_QUERY, NULL,NULL,NULL,NULL,&pwszCmdText), S_OK)
|
|
|
|
//Execute the command.
|
|
TEST2C_(hr=pICmd1->Execute(NULL, IID_NULL, NULL, &cRowsAffected,
|
|
NULL),S_OK, DB_E_NOCOMMAND)
|
|
|
|
if(pwszCmdText)
|
|
{
|
|
TESTC_(hr, S_OK)
|
|
//Check affected rows.
|
|
TESTC(cRowsAffected==1 || cRowsAffected==DB_COUNTUNAVAILABLE)
|
|
//Insert adds a row.
|
|
m_pTable->AddRow();
|
|
}
|
|
else
|
|
TESTC_(hr, DB_E_NOCOMMAND)
|
|
}
|
|
|
|
//Set command text to select all from table.
|
|
TESTC_(SetCommandText(m_pIMalloc, pICmd1, m_pTable, NULL, eSELECT,
|
|
SELECT_ALLFROMTBL, NULL), S_OK)
|
|
|
|
//Execute this command.
|
|
TESTC_(hr=pICmd1->Execute(NULL, IID_IRowset, NULL,NULL, (IUnknown**)
|
|
&pIRowset),S_OK)
|
|
|
|
//Verify that pIRowset is not NULL.
|
|
TESTC(pIRowset != NULL)
|
|
|
|
//Obtain the ICommandProperties interface.
|
|
TESTC(VerifyInterface(pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
cTotalRows = m_pTable->CountRowsOnTable();
|
|
|
|
//Create Accessor with a binding using length, status and value.
|
|
TESTC_(GetAccessorAndBindings(pIAccessor, DBACCESSOR_ROWDATA,
|
|
&hAccessor, &rgBindings, &cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL,
|
|
NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, NO_BLOB_COLS),
|
|
S_OK)
|
|
|
|
//Get list of ordinals.
|
|
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols,
|
|
&rgColumnsOrd, NULL, NULL, NULL, NULL))
|
|
|
|
//Get data from the rowset and verify.
|
|
for(ulIndex=0; ulIndex<cTotalRows; ulIndex++)
|
|
{
|
|
TESTC(GetDataAndCompare(0,1,ulIndex+1, cRowsetCols,
|
|
rgColumnsOrd, pIRowset, hAccessor, cBindings, rgBindings,
|
|
cbRowSize))
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(pwszCmdText);
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pICmd1);
|
|
return tTestResult;
|
|
} //testICmdExec1
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Create a command object. Set the command text to select all
|
|
//from table. Prepare the command (if supported). Execute this command
|
|
//thrice. The first time no interface is requested (IID_NULL). The second
|
|
//time an IRowset interface is requested. The third time an IRowsetInfo
|
|
//is requested. Verify that the 2 interfaces returned belong to different
|
|
//rowset objects.
|
|
//
|
|
TESTRESULT CQuickTest::testICmdExec2()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBCOUNTITEM cTotalRows = 0;
|
|
DBROWCOUNT cRowsAffected=0;
|
|
ICommand* pICmd1 = NULL;
|
|
IRowset* pIRowset = NULL;
|
|
IRowsetInfo* pIRowsetInfo = NULL;
|
|
ICommandPrepare* pICommandPrepare = NULL;
|
|
|
|
//Create a command object.
|
|
TESTC_(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand,
|
|
(IUnknown**)&pICmd1), S_OK)
|
|
|
|
//Set the command text to select all from table.
|
|
TESTC_(SetCommandText(m_pIMalloc, pICmd1, m_pTable, NULL, eSELECT,
|
|
SELECT_ALLFROMTBL, NULL), S_OK)
|
|
|
|
//If ICommandPrepare is supported, prepare the command (Not required)
|
|
if(VerifyInterface(pICmd1,IID_ICommandPrepare,
|
|
COMMAND_INTERFACE,(IUnknown**)&pICommandPrepare))
|
|
{
|
|
TESTC(pICommandPrepare->Prepare(3) == S_OK)
|
|
}
|
|
|
|
cTotalRows = m_pTable->CountRowsOnTable();
|
|
|
|
//Execute the command, not requesting any interface. cRowsAffected
|
|
//is undefined on output.
|
|
CHECK(hr=pICmd1->Execute(NULL, IID_NULL, NULL, &cRowsAffected,
|
|
NULL),S_OK);
|
|
|
|
//Execute command again, requesting an IRowset interface.
|
|
CHECK(hr=pICmd1->Execute(NULL, IID_IRowset, NULL,NULL, (IUnknown**)
|
|
&pIRowset),S_OK);
|
|
|
|
//Execute command again, requesting an IRowsetInfo interface.
|
|
CHECK(hr=pICmd1->Execute(NULL, IID_IRowsetInfo, NULL,NULL, (IUnknown**)
|
|
&pIRowsetInfo),S_OK);
|
|
|
|
//Verify that the 2 interfaces returned are not for the same rowset
|
|
//object.
|
|
COMPARE(VerifyEqualInterface(pIRowset, pIRowsetInfo), FALSE);
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
SAFE_RELEASE(pICommandPrepare);
|
|
SAFE_RELEASE(pICmd1);
|
|
return tTestResult;
|
|
} //testICmdExec2
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Call prepare without having set the command text. This should
|
|
//fail. Set the command text to select all from table. Call
|
|
//GetColumnInfo before preparing the command. Check for expected return
|
|
//code. Then execute the command to open a rowset. Calling Prepare now
|
|
//should fail again as the rowset object is open. Now release the rowset,
|
|
//prepare the command and then call GetColumnInfo. It should succeed
|
|
//this time.
|
|
//
|
|
TESTRESULT CQuickTest::testCmdPrep()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBORDINAL cColumns = 0;
|
|
WCHAR* pStringsBuffer = NULL;
|
|
DBCOLUMNINFO* rgInfo = NULL;
|
|
IRowset* pIRowset = NULL;
|
|
IColumnsInfo* pIColumnsInfo = NULL;
|
|
ICommand* pICmd1 = NULL;
|
|
ICommandPrepare* pICommandPrepare = NULL;
|
|
|
|
//Create a command object.
|
|
TESTC_(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand,
|
|
(IUnknown**)&pICmd1), S_OK)
|
|
|
|
if(!VerifyInterface(pICmd1,IID_ICommandPrepare,
|
|
COMMAND_INTERFACE,(IUnknown**)&pICommandPrepare))
|
|
{
|
|
odtLog<<L"ICommandPrepare is not supported.\n";
|
|
SAFE_RELEASE(pICmd1);
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
//Call prepare without having set the command text.
|
|
TESTC_(hr=pICommandPrepare->Prepare(1), DB_E_NOCOMMAND)
|
|
|
|
//Set the command text to select all from table.
|
|
TESTC_(SetCommandText(m_pIMalloc, pICmd1, m_pTable, NULL, eSELECT,
|
|
SELECT_ALLFROMTBL, NULL), S_OK)
|
|
|
|
TESTC(VerifyInterface(pICmd1,IID_IColumnsInfo,
|
|
COMMAND_INTERFACE,(IUnknown**)&pIColumnsInfo))
|
|
|
|
//Call GetColumnInfo without preparing the command.
|
|
TESTC_(pIColumnsInfo->GetColumnInfo(&cColumns,&rgInfo,&pStringsBuffer)
|
|
,DB_E_NOTPREPARED)
|
|
|
|
//Execute the command to open a rowset.
|
|
TESTC_(hr=pICmd1->Execute(NULL, IID_IRowset, NULL,NULL, (IUnknown**)
|
|
&pIRowset),S_OK)
|
|
|
|
//Call Prepare with the rowset open.
|
|
TESTC_(hr=pICommandPrepare->Prepare(1), DB_E_OBJECTOPEN)
|
|
|
|
//Release the rowset.
|
|
SAFE_RELEASE(pIRowset);
|
|
|
|
//Prepare the command.
|
|
TESTC_(hr=pICommandPrepare->Prepare(1), S_OK)
|
|
|
|
//Call GetColumnInfo. This should succeed.
|
|
TESTC_(pIColumnsInfo->GetColumnInfo(&cColumns,&rgInfo,&pStringsBuffer)
|
|
,S_OK)
|
|
|
|
TESTC(cColumns>0 && rgInfo && pStringsBuffer)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(rgInfo);
|
|
PROVIDER_FREE(pStringsBuffer);
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIColumnsInfo);
|
|
SAFE_RELEASE(pICommandPrepare);
|
|
SAFE_RELEASE(pICmd1);
|
|
return tTestResult;
|
|
} //testCmdPrep
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Set the command text to select all from table. Call Unprepare.
|
|
//This should succeed. Now prepare the command and execute it to open
|
|
//a rowset. Calling Unprepare now would fail due to the rowset being
|
|
//open. Now release the rowset and then call Unprepare.
|
|
//
|
|
TESTRESULT CQuickTest::testCmdUnprep()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
IRowset* pIRowset = NULL;
|
|
ICommand* pICmd1 = NULL;
|
|
ICommandPrepare* pICommandPrepare = NULL;
|
|
|
|
//Create a command object.
|
|
TESTC_(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand,
|
|
(IUnknown**)&pICmd1), S_OK)
|
|
|
|
if(!VerifyInterface(pICmd1,IID_ICommandPrepare,
|
|
COMMAND_INTERFACE,(IUnknown**)&pICommandPrepare))
|
|
{
|
|
odtLog<<L"ICommandPrepare is not supported.\n";
|
|
SAFE_RELEASE(pICmd1);
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
//Set the command text to select all from table.
|
|
TESTC_(SetCommandText(m_pIMalloc, pICmd1, m_pTable, NULL, eSELECT,
|
|
SELECT_ALLFROMTBL, NULL), S_OK)
|
|
|
|
//Calling Unprepare without preparing should succeed.
|
|
TESTC_(hr=pICommandPrepare->Unprepare(), S_OK)
|
|
|
|
//Prepare the command.
|
|
TESTC_(hr=pICommandPrepare->Prepare(1), S_OK)
|
|
|
|
//Execute the command
|
|
TESTC_(hr=pICmd1->Execute(NULL, IID_IRowset, NULL,NULL, (IUnknown**)
|
|
&pIRowset),S_OK)
|
|
|
|
//Unprepare should fail as the rowset is open.
|
|
TESTC_(hr=pICommandPrepare->Unprepare(), DB_E_OBJECTOPEN)
|
|
|
|
//Release the rowset.
|
|
SAFE_RELEASE(pIRowset);
|
|
|
|
//Now Unprepare should succeed.
|
|
TESTC_(hr=pICommandPrepare->Unprepare(), S_OK)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pICommandPrepare);
|
|
SAFE_RELEASE(pICmd1);
|
|
return tTestResult;
|
|
} //testCmdUnprep
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Make the parameter bindings to be used in testICmdWParam.
|
|
//
|
|
BOOL CQuickTest::MakeParamBindings(
|
|
CTable* pTable,
|
|
DBORDINAL cColumnsOnTable,
|
|
DBORDINAL* pcParamColMap,
|
|
LONG_PTR* rgParamColMap,
|
|
DB_UPARAMS* pcDbParamBindInfo,
|
|
DBPARAMBINDINFO* rgDbParamBindInfo,
|
|
DB_UPARAMS* rgParamOrdinals,
|
|
DBCOLUMNINFO* rgTableInfo
|
|
)
|
|
{
|
|
DBORDINAL ulIndex;
|
|
BOOL bSuccess = FALSE;
|
|
DBORDINAL ulSearchable;
|
|
CCol TempCol;
|
|
|
|
TESTC(pTable && pcParamColMap && rgParamColMap && pcDbParamBindInfo
|
|
&& rgDbParamBindInfo && rgParamOrdinals && rgTableInfo)
|
|
|
|
//Make the parameter bindings for all searchable columns in
|
|
//the table.
|
|
for (ulIndex = 0; ulIndex < cColumnsOnTable; ulIndex++)
|
|
{
|
|
TESTC_(pTable->GetColInfo(ulIndex+1, TempCol), S_OK)
|
|
|
|
ulSearchable = TempCol.GetSearchable() ;
|
|
|
|
//SELECT_ALL_WITH_SEARCHABLE_AND_UPDATEABLE includes only
|
|
//those columns in the command text which agree with the
|
|
//following condition.
|
|
if((ulSearchable == DB_LIKE_ONLY ||
|
|
ulSearchable == DB_ALL_EXCEPT_LIKE ||
|
|
ulSearchable == DB_SEARCHABLE ) &&
|
|
(TempCol.GetUpdateable()) &&
|
|
(!TempCol.GetIsLong())
|
|
)
|
|
{
|
|
//Record the column number in the array if it is
|
|
//searchable & updateable.
|
|
rgParamColMap[*pcParamColMap] = (LONG_PTR) TempCol.GetColNum();
|
|
(*pcParamColMap)++;
|
|
|
|
//Build Information for SetParameterInfo.
|
|
rgParamOrdinals[*pcDbParamBindInfo] = *pcDbParamBindInfo + 1;
|
|
rgDbParamBindInfo[*pcDbParamBindInfo].pwszDataSourceType =
|
|
wcsDuplicate(TempCol.GetProviderTypeName());
|
|
|
|
rgDbParamBindInfo[*pcDbParamBindInfo].pwszName = NULL;
|
|
|
|
rgDbParamBindInfo[*pcDbParamBindInfo].dwFlags =
|
|
DBPARAMFLAGS_ISINPUT;
|
|
if (TempCol.GetNullable())
|
|
rgDbParamBindInfo[*pcDbParamBindInfo].dwFlags |=
|
|
DBPARAMFLAGS_ISNULLABLE;
|
|
|
|
rgDbParamBindInfo[*pcDbParamBindInfo].ulParamSize =
|
|
rgTableInfo[ulIndex].ulColumnSize;
|
|
rgDbParamBindInfo[*pcDbParamBindInfo].bScale =
|
|
(BYTE)rgTableInfo[ulIndex].bScale;
|
|
rgDbParamBindInfo[*pcDbParamBindInfo].bPrecision =
|
|
(BYTE)rgTableInfo[ulIndex].bPrecision;
|
|
(*pcDbParamBindInfo)++;
|
|
}
|
|
}
|
|
|
|
bSuccess = TRUE;
|
|
|
|
CLEANUP:
|
|
return bSuccess;
|
|
} //MakeParamBindings
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Test GetParameterInfo for ICommandWithParameters.
|
|
//
|
|
TESTRESULT CQuickTest::testGetParamInfo(
|
|
ICommandWithParameters* pICWP,
|
|
CTable* pTable,
|
|
DB_UPARAMS cDbParamBindInfo,
|
|
DBPARAMBINDINFO* rgDbParamBindInfo,
|
|
LONG_PTR* rgParamColMap
|
|
)
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr;
|
|
DB_UPARAMS ulIndex;
|
|
DB_UPARAMS cParams = 0;
|
|
DBPARAMINFO* rgLocalParamInfo = NULL;
|
|
WCHAR* pwszNamesBuffer = NULL;
|
|
CCol TempCol;
|
|
|
|
TESTC(pICWP && pTable && rgDbParamBindInfo && rgParamColMap)
|
|
|
|
//Call GetParameterInfo.
|
|
TESTC_(hr = pICWP->GetParameterInfo(&cParams, &rgLocalParamInfo,
|
|
&pwszNamesBuffer), S_OK)
|
|
|
|
TESTC(cParams == cDbParamBindInfo)
|
|
TESTC(rgLocalParamInfo != NULL)
|
|
|
|
//We did not give any names to the parameters when we called
|
|
//SetParameterInfo. Hence, the names buffer should be NULL.
|
|
if(pwszNamesBuffer != NULL)
|
|
odtLog<<L"INFO: All parameter names were NULL. Hence, the names buffer should be NULL. Instead of NULL, the names buffer contains "<<pwszNamesBuffer<<L".\n";
|
|
|
|
//Check the parameter info obtained by calling GetParameterInfo
|
|
//above, with the paramBindInfo which we had set earlier (before
|
|
//execution).
|
|
for(ulIndex=0; ulIndex<cParams; ulIndex++)
|
|
{
|
|
TESTC((rgLocalParamInfo[ulIndex].dwFlags & DBPARAMFLAGS_ISINPUT)
|
|
== DBPARAMFLAGS_ISINPUT)
|
|
|
|
TESTC(rgLocalParamInfo[ulIndex].iOrdinal == ulIndex+1)
|
|
TESTC(!rgLocalParamInfo[ulIndex].pwszName)
|
|
|
|
TESTC_(pTable->GetColInfo(rgParamColMap[ulIndex], TempCol),
|
|
S_OK)
|
|
|
|
COMPAREW(rgLocalParamInfo[ulIndex].pTypeInfo, TempCol.GetTypeInfo());
|
|
|
|
if(rgLocalParamInfo[ulIndex].wType != TempCol.GetProviderType())
|
|
{
|
|
odtLog<<L"INFO: wType returned from GetParamInfo was "<<GetDBTypeName(rgLocalParamInfo[ulIndex].wType)<<" instead of "<<GetDBTypeName(TempCol.GetProviderType())<<".\n";
|
|
}
|
|
else
|
|
{
|
|
if(rgLocalParamInfo[ulIndex].ulParamSize != rgDbParamBindInfo[ulIndex].ulParamSize)
|
|
odtLog<<L"INFO: For "<<GetDBTypeName(rgLocalParamInfo[ulIndex].wType)<<" ParamSize returned from GetParamInfo was "<<rgLocalParamInfo[ulIndex].ulParamSize<<" instead of "<<rgDbParamBindInfo[ulIndex].ulParamSize<<".\n";
|
|
|
|
if(rgLocalParamInfo[ulIndex].bPrecision != rgDbParamBindInfo[ulIndex].bPrecision)
|
|
odtLog<<L"INFO: For "<<GetDBTypeName(rgLocalParamInfo[ulIndex].wType)<<" Precision returned from GetParamInfo was "<<rgLocalParamInfo[ulIndex].bPrecision<<" instead of "<<rgDbParamBindInfo[ulIndex].bPrecision<<".\n";
|
|
|
|
if(rgLocalParamInfo[ulIndex].bScale != rgDbParamBindInfo[ulIndex].bScale)
|
|
odtLog<<L"INFO: For "<<GetDBTypeName(rgLocalParamInfo[ulIndex].wType)<<" Scale returned from GetParamInfo was "<<rgLocalParamInfo[ulIndex].bScale<<" instead of "<<rgDbParamBindInfo[ulIndex].bScale<<".\n";
|
|
}
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pwszNamesBuffer);
|
|
PROVIDER_FREE(rgLocalParamInfo);
|
|
return tTestResult;
|
|
} //testGetParamInfo
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Make the parameter bindings for all searchable columns in
|
|
//the table. Get the bindings for the Searchable & Updateable columns.
|
|
//Set the command text for searching with parameters. Prepare the command
|
|
//and call GetParameterInfo. Verify. Then call SetParameterInfo with
|
|
//the parameter bindings we made. Make parameter data and execute the
|
|
//command with these parameters. Verify the obtained rowset. Now call
|
|
//GetParameterInfo again. Compare this with the paramBindInfo which we
|
|
//had used for SetParameterInfo.
|
|
//
|
|
TESTRESULT CQuickTest::testICmdWParam()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
HRESULT hrGetParam = S_OK;
|
|
ULONG_PTR ulIndex = 0;
|
|
DBORDINAL cColumnsOnTable = 0;
|
|
LONG_PTR* rgParamColMap = NULL;
|
|
DB_UPARAMS* rgParamOrdinals = NULL;
|
|
DBPARAMBINDINFO* rgDbParamBindInfo = NULL;
|
|
DB_UPARAMS cParams = 0;
|
|
DBPARAMINFO* rgLocalParamInfo = NULL;
|
|
DBORDINAL cParamColMap = 0;
|
|
DB_UPARAMS cDbParamBindInfo = 0;
|
|
DBORDINAL cTableInfo = 0;
|
|
DBCOLUMNINFO* rgTableInfo = NULL;
|
|
LPWSTR pTableStringsBuffer = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
DBBINDING* rgBindings = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBPARAMS dbParams;
|
|
BYTE* pData = NULL;
|
|
DBROWCOUNT cRowsAffected = 0;
|
|
WCHAR* pwszSqlStmt = NULL;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW* rghRows = NULL;
|
|
CTable* pTable = NULL;
|
|
ICommandPrepare* pICommandPrepare = NULL;
|
|
ICommandWithParameters* pICWP = NULL;
|
|
ICommand* pICommand = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowset* pIRowset = NULL;
|
|
IColumnsInfo* pIColumnsInfo = NULL;
|
|
|
|
//Create a new command object.
|
|
TESTC_(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand,
|
|
(IUnknown**)&pICommand), S_OK)
|
|
|
|
//Obtain pointer to ICommandWithParameters, if it is supported.
|
|
if(!VerifyInterface(pICommand,IID_ICommandWithParameters,
|
|
COMMAND_INTERFACE,(IUnknown**)&pICWP))
|
|
{
|
|
odtLog<<L"ICommandWithParameters is not supported.\n";
|
|
SAFE_RELEASE(pICommand);
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
//Get pointer to IAccessor (command accessor).
|
|
TESTC(VerifyInterface(pICommand,IID_IAccessor,
|
|
COMMAND_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Get pointer to ICommandPrepare, if it is supported.
|
|
if(!VerifyInterface(pICommand,IID_ICommandPrepare,
|
|
COMMAND_INTERFACE,(IUnknown**)&pICommandPrepare))
|
|
pICommandPrepare = NULL;
|
|
|
|
//Create a new table.
|
|
pTable = new CTable(m_pIOpenRowset, (LPWSTR)gwszModuleName, NONULLS);
|
|
TESTC(pTable != NULL)
|
|
TESTC_(pTable->CreateTable(MIN_ROWS), S_OK)
|
|
|
|
//Set command text to "select * from [table]"
|
|
TESTC_(pTable->ExecuteCommand(SELECT_ALLFROMTBL, IID_IUnknown,
|
|
NULL, NULL, NULL, NULL, EXECUTE_NEVER, 0, NULL, NULL, NULL,
|
|
&pICommand), S_OK)
|
|
|
|
//Prepare the command, if ICommandPrepare is supported. Preparing
|
|
//the command is required for calling GetColumnInfo.
|
|
if(pICommandPrepare)
|
|
{
|
|
TESTC_(pICommandPrepare->Prepare(1), S_OK)
|
|
}
|
|
|
|
//Get pointer to IColumnInfo.
|
|
TESTC(VerifyInterface(pICommand,IID_IColumnsInfo,
|
|
COMMAND_INTERFACE,(IUnknown**)&pIColumnsInfo))
|
|
|
|
//Get the column info (cmd text set to select all from table).
|
|
TESTC_(pIColumnsInfo->GetColumnInfo(&cTableInfo,
|
|
&rgTableInfo, &pTableStringsBuffer), S_OK);
|
|
|
|
SAFE_RELEASE(pIColumnsInfo);
|
|
|
|
cColumnsOnTable = pTable->CountColumnsOnTable();
|
|
|
|
SAFE_ALLOC(rgParamColMap, LONG_PTR, cColumnsOnTable)
|
|
SAFE_ALLOC(rgParamOrdinals, DB_UPARAMS, cColumnsOnTable)
|
|
SAFE_ALLOC(rgDbParamBindInfo, DBPARAMBINDINFO, cColumnsOnTable)
|
|
|
|
memset(rgDbParamBindInfo, 0, (size_t) (cColumnsOnTable*sizeof(DBPARAMBINDINFO)));
|
|
memset(rgParamColMap, 0, (size_t) (cColumnsOnTable*sizeof(LONG_PTR)));
|
|
memset(rgParamOrdinals, 0, (size_t) (cColumnsOnTable*sizeof(DB_UPARAMS)));
|
|
|
|
//Make the parameter bindings.
|
|
TESTC(MakeParamBindings(pTable, cColumnsOnTable, &cParamColMap,
|
|
rgParamColMap, &cDbParamBindInfo, rgDbParamBindInfo,
|
|
rgParamOrdinals, rgTableInfo))
|
|
|
|
//Get the Bindings for the Searchable & Updateable columns by
|
|
//passing an array containing the column ordinals for searchable
|
|
//& updateable columns only. This is a command acessor.
|
|
TESTC_(hr = GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_PARAMETERDATA, &hAccessor, &rgBindings, &cBindings,
|
|
&cbRowSize, DBPART_VALUE | DBPART_STATUS | DBPART_LENGTH,
|
|
USE_COLS_TO_BIND_ARRAY, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, cParamColMap,
|
|
rgParamColMap, rgParamOrdinals,
|
|
NO_COLS_OWNED_BY_PROV, DBPARAMIO_INPUT, BLOB_LONG ), S_OK)
|
|
|
|
// Set the command text to a statement like "select col2,col5,...
|
|
// from [table] where col2=?,col5=?,...".
|
|
TESTC_(hr = pTable->ExecuteCommand(
|
|
SELECT_ALL_WITH_SEARCHABLE_AND_UPDATEABLE, IID_IUnknown, NULL,
|
|
&pwszSqlStmt, NULL, NULL, EXECUTE_NEVER, 0, NULL, NULL, NULL,
|
|
&pICommand), S_OK)
|
|
|
|
//Make sure the command text was built.
|
|
TESTC(pwszSqlStmt != NULL)
|
|
|
|
//Prepare the command. Required for GetParameterInfo.
|
|
if(pICommandPrepare)
|
|
{
|
|
TESTC_(pICommandPrepare->Prepare(2), S_OK)
|
|
}
|
|
|
|
//GetParameterInfo will return DB_E_PARAMUNAVAILABLE if provider
|
|
//cannot derive parameter information from the command. Otherwise,
|
|
//it returns S_OK.
|
|
TEST2C_(hrGetParam = pICWP->GetParameterInfo(&cParams, &rgLocalParamInfo,
|
|
NULL), S_OK, DB_E_PARAMUNAVAILABLE)
|
|
|
|
if (hrGetParam == DB_E_PARAMUNAVAILABLE)
|
|
{
|
|
TESTC(cParams==0 && rgLocalParamInfo==NULL)
|
|
odtLog<<L"INFO: Provider cannot derive parameter information from the command (SetParameterInfo has not been called).\n";
|
|
}
|
|
else
|
|
{
|
|
TESTC(cParams==cParamColMap && rgLocalParamInfo)
|
|
PROVIDER_FREE(rgLocalParamInfo);
|
|
}
|
|
|
|
//Set the parameter info. If the Provider can derive parameter
|
|
//information from the command (i.e., if the above call to
|
|
//GetParameterInfo returned S_OK), then SetParameterInfo will
|
|
//return DB_S_TYPEINFOOVERRIDDEN.
|
|
TEST2C_(hr = pICWP->SetParameterInfo(cDbParamBindInfo, rgParamOrdinals,
|
|
rgDbParamBindInfo), S_OK, DB_S_TYPEINFOOVERRIDDEN)
|
|
|
|
if(hrGetParam == DB_E_PARAMUNAVAILABLE)
|
|
CHECK(hr, S_OK);
|
|
if(hrGetParam == S_OK)
|
|
CHECK(hr, DB_S_TYPEINFOOVERRIDDEN);
|
|
|
|
//Make the parameter data (corresponding to row 1).
|
|
TESTC_(hr = FillInputBindings(pTable, DBACCESSOR_PARAMETERDATA,
|
|
cBindings, rgBindings, &pData, 1, cParamColMap, rgParamColMap),
|
|
S_OK)
|
|
|
|
//Set the DBPARAMS structure to contain the parameter data "pData".
|
|
dbParams.pData = pData;
|
|
dbParams.cParamSets = 1;
|
|
dbParams.hAccessor = hAccessor;
|
|
|
|
//Execute command with parameters.
|
|
hr = pICommand->Execute(NULL, IID_IRowset, &dbParams, &cRowsAffected,
|
|
(IUnknown**)&pIRowset) ;
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
odtLog<<L"WARNING: Failure in executing command with parameters. The syntax used may not supported by the provider.\n";
|
|
CHECKW(hr, S_OK);
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC_(hr, S_OK)
|
|
|
|
TESTC(pIRowset != NULL)
|
|
|
|
//Release pData, accessor and bindings. These will be reused.
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings,pData, TRUE) ;
|
|
pData = NULL;
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
|
|
//Obtain IAccessor on the rowset.
|
|
TESTC(VerifyInterface(pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create an accessor and bindings, with all columns of the rowset
|
|
//bound. This is a rowset accessor.
|
|
TESTC_(hr = GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA, &hAccessor, &rgBindings, &cBindings,
|
|
&cbRowSize, DBPART_VALUE | DBPART_STATUS | DBPART_LENGTH,
|
|
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, 0, NULL, NULL ,
|
|
NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM, BLOB_LONG ), S_OK)
|
|
|
|
//Allocate pData.
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
memset(pData,0, (size_t) cbRowSize);
|
|
|
|
//Position cursor at beginning of rowset.
|
|
TESTC_(RestartPosition(pIRowset), S_OK)
|
|
|
|
//Fetch 3 rows. The rowset, however, should have only 1 row,
|
|
//because the parameter data was built to match the data for
|
|
//1 row only (the first row of the base table).
|
|
TEST2C_(hr = GetNextRows(pIRowset, NULL, 0,3, &cRowsObtained,
|
|
&rghRows), DB_S_ENDOFROWSET, DB_S_ROWLIMITEXCEEDED)
|
|
|
|
TESTC(cRowsObtained == 1)
|
|
|
|
//Get data of the first row.
|
|
TESTC_(hr = pIRowset->GetData(rghRows[0], hAccessor, pData), S_OK)
|
|
|
|
//The data has to match the data of the first row of base table.
|
|
TESTC(CompareData(cParamColMap, rgParamColMap, 1, pData,
|
|
cBindings, rgBindings, pTable, m_pIMalloc))
|
|
|
|
//Now test GetParameterInfo.
|
|
TESTC(testGetParamInfo(pICWP, pTable, cDbParamBindInfo,
|
|
rgDbParamBindInfo, rgParamColMap) == TEST_PASS)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings,pData, TRUE) ;
|
|
for(ulIndex=0; ulIndex<cDbParamBindInfo; ulIndex++)
|
|
{
|
|
PROVIDER_FREE(rgDbParamBindInfo[ulIndex].pwszName);
|
|
PROVIDER_FREE(rgDbParamBindInfo[ulIndex].pwszDataSourceType);
|
|
}
|
|
PROVIDER_FREE(rgTableInfo);
|
|
PROVIDER_FREE(pTableStringsBuffer);
|
|
PROVIDER_FREE(rgParamColMap);
|
|
PROVIDER_FREE(rgParamOrdinals);
|
|
PROVIDER_FREE(rgDbParamBindInfo) ;
|
|
PROVIDER_FREE(pwszSqlStmt);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pICommandPrepare);
|
|
SAFE_RELEASE(pICWP);
|
|
SAFE_RELEASE(pICommand);
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIColumnsInfo);
|
|
if(pTable)
|
|
pTable->DropTable();
|
|
SAFE_DELETE(pTable);
|
|
return tTestResult;
|
|
} //testICmdWParam
|
|
|
|
|
|
//---------------------------------------------------------------------
|
|
//@mfunc Make a sql select stmt with list of updateable columns.
|
|
//Set the command text to this statement.
|
|
//Execute command and request IMultipleResults. Get the first
|
|
//rowset and verify. Release this rowset. Make sure there was only 1
|
|
//rowset in the results.
|
|
//
|
|
TESTRESULT CQuickTest::testIMultipleResults()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBCOUNTITEM ulIndex = 0;
|
|
DBCOUNTITEM cRows = 0;
|
|
DBORDINAL cColumns = 0;
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
DBROWCOUNT cRowsAffected = 0;
|
|
WCHAR* pwszTableName = NULL;
|
|
WCHAR* pwszSelectUpdt = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
DBBINDING* rgBindings = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowset* pIRowset1 = NULL;
|
|
IRowset* pIRowset2 = NULL;
|
|
ICommandText* pICmdText = NULL;
|
|
IMultipleResults* pIMR = NULL;
|
|
|
|
//Create a command object.
|
|
TESTC_(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommandText,
|
|
(IUnknown**)&pICmdText), S_OK)
|
|
|
|
TESTC(m_pTable != NULL)
|
|
|
|
pwszTableName = m_pTable->GetTableName();
|
|
|
|
//Get number of rows.
|
|
cRows = m_pTable->CountRowsOnTable();
|
|
|
|
//Make a sql select stmt with list of updateable columns.
|
|
TESTC_(hr = m_pTable->CreateSQLStmt(SELECT_UPDATEABLE, pwszTableName,
|
|
&pwszSelectUpdt, &cColumns, &rgColumnsOrd), S_OK)
|
|
|
|
TESTC(pwszSelectUpdt != NULL)
|
|
|
|
//Set the command text to the multiple stmt.
|
|
TESTC_(hr = pICmdText->SetCommandText(DBGUID_DEFAULT, pwszSelectUpdt),
|
|
S_OK)
|
|
|
|
//Execute command and request IMultipltResults.
|
|
TESTC_(hr = pICmdText->Execute(NULL, IID_IMultipleResults, NULL,
|
|
&cRowsAffected, (IUnknown**)&pIMR), S_OK)
|
|
|
|
//Get the first rowset and verify. cRowsAffected is undefined
|
|
//on output.
|
|
TESTC_(hr = pIMR->GetResult(NULL, 0, IID_IRowset, &cRowsAffected,
|
|
(IUnknown**)&pIRowset1), S_OK)
|
|
|
|
TESTC(VerifyInterface(pIRowset1,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
TESTC_(hr=GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF,
|
|
NULL, NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Make sure we are on the first row.
|
|
TESTC_(RestartPosition(pIRowset1), S_OK)
|
|
|
|
//For each row in the table, fetch the row, compare the data in the
|
|
//row and release the row.
|
|
for(ulIndex=0; ulIndex<cRows; ulIndex++)
|
|
TESTC(GetDataAndCompare(0, 1, ulIndex+1, cColumns,
|
|
rgColumnsOrd, pIRowset1, hAccessor, cBindings,
|
|
rgBindings, cbRowSize, m_pTable))
|
|
|
|
if(pIAccessor && hAccessor)
|
|
CHECK(pIAccessor->ReleaseAccessor(hAccessor, NULL), S_OK);
|
|
hAccessor = DB_NULL_HACCESSOR;
|
|
SAFE_RELEASE(pIAccessor);
|
|
SAFE_RELEASE(pIRowset1);
|
|
|
|
//Calling GetResult a second time should return DB_S_NORESULT,
|
|
//as there was only 1 sql stmt in the command text.
|
|
TESTC_(hr = pIMR->GetResult(NULL, 0, IID_IRowset, &cRowsAffected,
|
|
(IUnknown**)&pIRowset2), DB_S_NORESULT)
|
|
|
|
TESTC(pIRowset2 == NULL)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(pwszSelectUpdt);
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowset1);
|
|
SAFE_RELEASE(pIRowset2);
|
|
SAFE_RELEASE(pIMR);
|
|
SAFE_RELEASE(pICmdText);
|
|
return tTestResult;
|
|
} //testIMultipleResults
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Check if IDBCreateSession has error support. Call CreateSession
|
|
//with an invalid argument. Get the error records and get an IErrorInfo
|
|
//for every record. Loop through each record and verify the various
|
|
//information returned by the methods of IErrorInfo.
|
|
//
|
|
TESTRESULT CQuickTest::testIError()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndex = 0;
|
|
LCID lcid ;
|
|
GUID guid ;
|
|
DWORD dwHelpContext = 0;
|
|
ULONG cRecords = 0;
|
|
BSTR bstrDescription;
|
|
BSTR bstrHelpFile;
|
|
BSTR bstrSource ;
|
|
WCHAR* wszString = NULL ;
|
|
IErrorInfo** rgIErrorInfo = NULL;
|
|
IErrorInfo* pIEI = NULL;
|
|
IErrorRecords* pIER = NULL;
|
|
IErrorLookup* pIEL = NULL;
|
|
ISupportErrorInfo* pISEI = NULL;
|
|
IDBCreateSession* pIDBCS = NULL;
|
|
|
|
//Get ISupportErrorInfo.
|
|
if (!VerifyInterface(m_pIDBInitialize, IID_ISupportErrorInfo,
|
|
DATASOURCE_INTERFACE, (IUnknown **)&pISEI))
|
|
{
|
|
odtLog << L"Interface ISupportErrorInfo is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
//Check if IDBCreateSession has error support.
|
|
hr = pISEI->InterfaceSupportsErrorInfo(IID_IDBCreateSession);
|
|
|
|
if (hr == S_FALSE)
|
|
{
|
|
SAFE_RELEASE(pISEI);
|
|
odtLog<<L"IDBCreateSession does not have error support.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
TESTC_(hr, S_OK)
|
|
|
|
TESTC(VerifyInterface(m_pIDBInitialize, IID_IDBCreateSession,
|
|
DATASOURCE_INTERFACE, (IUnknown **)&pIDBCS))
|
|
|
|
//Call CreateSession with an invalid argument.
|
|
hr = pIDBCS->CreateSession(NULL, IID_IOpenRowset, NULL);
|
|
|
|
TESTC_(hr, E_INVALIDARG)
|
|
|
|
//Validate the correct behavior for the given error situation.
|
|
TESTC(XCHECK((IUnknown*)pIDBCS, IID_IDBCreateSession, hr))
|
|
|
|
hr = pIDBCS->CreateSession(NULL, IID_IOpenRowset, NULL);
|
|
|
|
TESTC_(hr, E_INVALIDARG)
|
|
|
|
//Get the IErrorInfo interface.
|
|
hr = GetErrorInfo(0, &pIEI) ;
|
|
if(hr == S_FALSE)
|
|
{
|
|
odtLog<<L"ErrorInfo is not supported.\n";
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(hr==S_OK && (pIEI))
|
|
|
|
//Get IErrorRecords interface.
|
|
TESTC(VerifyInterface(pIEI, IID_IErrorRecords, ERROR_INTERFACE,
|
|
(IUnknown **)&pIER))
|
|
|
|
//get the number of error records.
|
|
if(!CHECK(pIER->GetRecordCount(&cRecords), S_OK))
|
|
goto CLEANUP;
|
|
|
|
//There has to be at least one error record.
|
|
if (cRecords == 0)
|
|
{
|
|
odtLog << L"No error records were found in the error object.\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Now get an IErrorInfo for every record
|
|
rgIErrorInfo = (IErrorInfo **)PROVIDER_ALLOC(sizeof(IErrorInfo *) * cRecords);
|
|
TESTC(rgIErrorInfo != NULL)
|
|
|
|
lcid = GetSystemDefaultLCID();
|
|
|
|
//For each record...
|
|
for (ulIndex=0; ulIndex<cRecords; ulIndex++)
|
|
{
|
|
//Place each interface in an element of our array
|
|
TESTC_(pIER->GetErrorInfo(ulIndex, lcid,
|
|
(IErrorInfo**)&rgIErrorInfo[ulIndex]), S_OK)
|
|
}
|
|
|
|
//Loop through each error record.
|
|
for (ulIndex = cRecords; ulIndex > 0; ulIndex--)
|
|
{
|
|
//GetDescription.
|
|
if(CHECK(hr = ((IErrorInfo *)rgIErrorInfo[ulIndex-1])->GetDescription(
|
|
&bstrDescription), S_OK))
|
|
{
|
|
if (wszString = BSTR2WSTR(bstrDescription, TRUE))
|
|
{
|
|
TESTC(wcslen(wszString) > 0)
|
|
odtLog << L"INFO: Description for record " << ulIndex-1 << L":"
|
|
<< wszString << L"\n" ;
|
|
PROVIDER_FREE(wszString);
|
|
}
|
|
}
|
|
|
|
//GetGUID.
|
|
if(CHECK(hr = ((IErrorInfo *)rgIErrorInfo[ulIndex-1])->GetGUID(
|
|
&guid), S_OK))
|
|
{
|
|
//Make sure the right interface was returned
|
|
TESTC(guid == IID_IDBCreateSession)
|
|
}
|
|
|
|
//GetHelpContext
|
|
CHECK(hr = ((IErrorInfo *)rgIErrorInfo[ulIndex-1])->GetHelpContext(
|
|
&dwHelpContext), S_OK) ;
|
|
|
|
//GetHelpFile
|
|
if(CHECK(hr = ((IErrorInfo *)rgIErrorInfo[ulIndex-1])->GetHelpFile(
|
|
&bstrHelpFile), S_OK))
|
|
{
|
|
if (wszString = BSTR2WSTR(bstrHelpFile, TRUE))
|
|
{
|
|
odtLog << L"INFO: Help File for record " << ulIndex-1 << L":"
|
|
<< wszString << L"\n";
|
|
odtLog << L"INFO: Help Context = "<<dwHelpContext<<L".\n";
|
|
PROVIDER_FREE(wszString);
|
|
}
|
|
}
|
|
|
|
//GetSource
|
|
if (CHECK(hr = ((IErrorInfo *)rgIErrorInfo[ulIndex-1])->GetSource(
|
|
&bstrSource), S_OK))
|
|
{
|
|
if (wszString = BSTR2WSTR(bstrSource, TRUE))
|
|
{
|
|
TESTC(wcslen(wszString) > 0)
|
|
odtLog << L"INFO: Source for record " << ulIndex-1 << L":"
|
|
<< wszString << L"\n";
|
|
PROVIDER_FREE(wszString);
|
|
}
|
|
}
|
|
|
|
} //For-Loop Ends.
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
if (rgIErrorInfo)
|
|
{
|
|
//Release each records IErrorInfo interface
|
|
for (ulIndex=0; ulIndex<cRecords; ulIndex++)
|
|
SAFE_RELEASE((IErrorInfo*)rgIErrorInfo[ulIndex]);
|
|
|
|
//Delete array of interface pointers
|
|
PROVIDER_FREE(rgIErrorInfo);
|
|
}
|
|
PROVIDER_FREE(wszString);
|
|
SAFE_RELEASE(pIDBCS);
|
|
SAFE_RELEASE(pISEI);
|
|
SAFE_RELEASE(pIEL);
|
|
SAFE_RELEASE(pIER);
|
|
SAFE_RELEASE(pIEI);
|
|
return tTestResult;
|
|
} //testIError
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Start a transaction. Open a rowset with updateable properties.
|
|
//Get the third row and set its data to some new data. Now commit the
|
|
//transaction (fPreserve=FALSE). If DBPROP_COMMITPRESERVE is FALSE, then
|
|
//release the rowset and open another rowset. Verify that the third row
|
|
//has the new data.
|
|
//
|
|
TESTRESULT CQuickTest::testTransactionCommit()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG_PTR updtFlag = 0;
|
|
BOOL bProvUpdateable = TRUE;
|
|
BOOL bCommitPreserve = FALSE;
|
|
ULONG ulTransLevel = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DBORDINAL cRowsetCols = 0;
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
HROW* rghRows = NULL;
|
|
BYTE* pData = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBBINDING* rgBindings = NULL;
|
|
IRowset* pIRowset = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowsetChange* pIRowsetChange = NULL;
|
|
ITransactionLocal* pITL = NULL;
|
|
|
|
//Get ITransactionLocal.
|
|
if(!VerifyInterface(m_pIOpenRowset, IID_ITransactionLocal,
|
|
SESSION_INTERFACE, (IUnknown **)&pITL))
|
|
{
|
|
odtLog << L"ITransactionLocal is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
|
|
LONG ulUpdateFlags = DBPROPVAL_UP_CHANGE|
|
|
DBPROPVAL_UP_DELETE|
|
|
DBPROPVAL_UP_INSERT ;
|
|
|
|
//Set the following properties.
|
|
SetProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets,
|
|
(void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetSettableProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets,
|
|
(void*)(LONG_PTR)ulUpdateFlags, DBTYPE_I4, //cast modified
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetProperty(DBPROP_CANHOLDROWS,
|
|
DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ;
|
|
|
|
//Start a transaction.
|
|
TESTC_(hr = pITL->StartTransaction(ISOLATIONLEVEL_READCOMMITTED,
|
|
0, NULL, &ulTransLevel), S_OK)
|
|
|
|
//Open a rowset with above properties set.
|
|
TEST2C_(hr=CreateOpenRowset(m_pTable, IID_IRowset,(IUnknown**)
|
|
&pIRowset), S_OK, DB_S_ERRORSOCCURRED)
|
|
|
|
//Get value of the DBPROP_UPDATABILITY property.
|
|
if(!GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, (IUnknown*)
|
|
pIRowset, &updtFlag))
|
|
{
|
|
odtLog<<L"INFO: Could not get the value of DBPROP_UPDATABILITY.\n";
|
|
bProvUpdateable = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if(!(updtFlag & DBPROPVAL_UP_CHANGE))
|
|
{
|
|
odtLog<<L"CHANGE is not supported.\n";
|
|
bProvUpdateable = FALSE;
|
|
}
|
|
}
|
|
|
|
if(!GetProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET, (IUnknown*)
|
|
pIRowset))
|
|
{
|
|
odtLog<<L"IRowsetChange is not supported.\n";
|
|
bProvUpdateable = FALSE;
|
|
}
|
|
|
|
//Get list of ordinals.
|
|
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols,
|
|
&rgColumnsOrd, NULL, NULL, NULL, NULL))
|
|
|
|
TESTC(VerifyInterface(pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
if(bProvUpdateable)
|
|
{
|
|
TESTC(VerifyInterface(pIRowset,IID_IRowsetChange,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRowsetChange))
|
|
}
|
|
|
|
//Create Accessor with a binding using length, status and value.
|
|
//This accessor binds the updateable non-index columns.
|
|
TESTC_(GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
UPDATEABLE_NONINDEX_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Get the value of the property DBPROP_COMMITPRESERVE.
|
|
if(GetProperty(DBPROP_COMMITPRESERVE, DBPROPSET_ROWSET, (IUnknown*)
|
|
pIRowset))
|
|
bCommitPreserve = TRUE;
|
|
|
|
//Allocate a new data buffer
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
|
|
//Restart position.
|
|
TESTC_(RestartPosition(pIRowset), S_OK)
|
|
|
|
//Get third row.
|
|
TESTC_(hr = GetNextRows(pIRowset, NULL,2,1,&cRowsObtained,
|
|
&rghRows),S_OK)
|
|
|
|
//Make data corresponding to row (g_ulNextRow+1).
|
|
TESTC_(FillInputBindings(m_pTable, DBACCESSOR_ROWDATA,
|
|
cBindings, rgBindings, &pData, ++g_ulNextRow, cRowsetCols,
|
|
rgColumnsOrd, PRIMARY),S_OK)
|
|
|
|
if(bProvUpdateable)
|
|
{
|
|
//Set data corresponding to row (g_ulNextRow+1).
|
|
TESTC_(hr = pIRowsetChange->SetData(rghRows[0],hAccessor,
|
|
pData),S_OK)
|
|
}
|
|
|
|
//Release...cleanup...
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings,pData, TRUE) ;
|
|
pData = NULL;
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowsetChange);
|
|
|
|
//pIRowset has not been freed.
|
|
|
|
//Commit the transaction with fRetaining=FALSE.
|
|
//FUTURE ATTENTION required here.
|
|
if((hr=pITL->Commit(FALSE, XACTTC_SYNC, 0)) == XACT_E_NOTSUPPORTED)
|
|
if((hr=pITL->Commit(FALSE, XACTTC_SYNC_PHASETWO, 0)) == XACT_E_NOTSUPPORTED)
|
|
if((hr=pITL->Commit(FALSE, XACTTC_ASYNC_PHASEONE, 0)) == XACT_E_NOTSUPPORTED)
|
|
if((hr=pITL->Commit(FALSE, XACTTC_SYNC_PHASEONE, 0)) == XACT_E_NOTSUPPORTED)
|
|
if((hr=pITL->Commit(FALSE, 0, 0)) == XACT_E_NOTSUPPORTED)
|
|
{
|
|
odtLog<<L"None of the XACTTC commit flag values were supported.\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//The Commit should have succeeded.
|
|
TESTC_(hr, S_OK)
|
|
|
|
//If DBPROP_COMMITPRESERVE was FALSE, then release pIRowset and
|
|
//open a rowset again. Otherwise, the current rowset is valid, so
|
|
//proceed.
|
|
if(!bCommitPreserve)
|
|
{
|
|
//Verify the rowset is in zombie state.
|
|
TESTC_(RestartPosition(pIRowset), E_UNEXPECTED)
|
|
|
|
SAFE_RELEASE(pIRowset);
|
|
TEST2C_(hr=CreateOpenRowset(m_pTable, IID_IRowset,(IUnknown**)
|
|
&pIRowset), S_OK, DB_S_ERRORSOCCURRED)
|
|
}
|
|
|
|
TESTC(VerifyInterface(pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create Accessor with a binding using length, status and value.
|
|
//This accessor binds the updateable non-index columns.
|
|
TESTC_(GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
UPDATEABLE_NONINDEX_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Allocate a new data buffer
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
|
|
//Restart position.
|
|
TESTC_(RestartPosition(pIRowset), S_OK)
|
|
|
|
//Get third row.
|
|
TESTC_(hr = GetNextRows(pIRowset, NULL,2,1,&cRowsObtained,
|
|
&rghRows),S_OK)
|
|
|
|
TESTC_(hr = pIRowset->GetData(rghRows[0], hAccessor, pData), S_OK)
|
|
|
|
if(bProvUpdateable)
|
|
{
|
|
//The first row should contain the new data which was set in
|
|
//the transaction before committing.
|
|
TESTC(CompareData(cRowsetCols, rgColumnsOrd, g_ulNextRow,
|
|
pData, cBindings, rgBindings, m_pTable, m_pIMalloc, PRIMARY,
|
|
COMPARE_ONLY))
|
|
}
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings,pData, TRUE) ;
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowsetChange);
|
|
SAFE_RELEASE(pIRowset);
|
|
if((hr=pITL->Abort(NULL, FALSE, FALSE)) == XACT_E_NOTSUPPORTED)
|
|
hr=pITL->Abort(NULL, FALSE, TRUE) ;
|
|
SAFE_RELEASE(pITL);
|
|
return tTestResult;
|
|
} //testTransactionCommit
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Start a transaction. Open a rowset with updateable properties.
|
|
//Get the third row and set its data to some new data. Now abort the
|
|
//transaction (fPreserve=FALSE). If DBPROP_ABORTPRESERVE is FALSE, then
|
|
//release the rowset and open another rowset. Verify that the third row
|
|
//has the old data.
|
|
//
|
|
TESTRESULT CQuickTest::testTransactionAbort()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
ULONG_PTR updtFlag = 0;
|
|
BOOL bProvUpdateable = TRUE;
|
|
BOOL bAbortPreserve = FALSE;
|
|
ULONG ulTransLevel = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DBORDINAL cRowsetCols = 0;
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
HROW* rghRows = NULL;
|
|
BYTE* pData = NULL;
|
|
BYTE* pOrgData = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBBINDING* rgBindings = NULL;
|
|
IRowset* pIRowset = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
IRowsetChange* pIRowsetChange = NULL;
|
|
ITransactionLocal* pITL = NULL;
|
|
|
|
//Get ITransactionLocal.
|
|
if(!VerifyInterface(m_pIOpenRowset, IID_ITransactionLocal,
|
|
SESSION_INTERFACE, (IUnknown **)&pITL))
|
|
{
|
|
odtLog << L"ITransactionLocal is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
|
|
LONG ulUpdateFlags = DBPROPVAL_UP_CHANGE|
|
|
DBPROPVAL_UP_DELETE|
|
|
DBPROPVAL_UP_INSERT ;
|
|
|
|
//Set the following properties.
|
|
SetProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets,
|
|
(void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetSettableProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets,
|
|
(void*)(LONG_PTR)ulUpdateFlags, DBTYPE_I4, //cast modified
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetProperty(DBPROP_CANHOLDROWS,
|
|
DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ;
|
|
|
|
//Start a transaction.
|
|
TESTC_(hr = pITL->StartTransaction(ISOLATIONLEVEL_READCOMMITTED,
|
|
0, NULL, &ulTransLevel), S_OK)
|
|
|
|
//Open a rowset with above properties set.
|
|
TEST2C_(hr=CreateOpenRowset(m_pTable, IID_IRowset,(IUnknown**)
|
|
&pIRowset), S_OK, DB_S_ERRORSOCCURRED)
|
|
|
|
//Get value of the DBPROP_UPDATABILITY property.
|
|
if(!GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET, (IUnknown*)
|
|
pIRowset, &updtFlag))
|
|
{
|
|
odtLog<<L"INFO: Could not get the value of DBPROP_UPDATABILITY.\n";
|
|
bProvUpdateable = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if(!(updtFlag & DBPROPVAL_UP_CHANGE))
|
|
{
|
|
odtLog<<L"CHANGE is not supported.\n";
|
|
bProvUpdateable = FALSE;
|
|
}
|
|
}
|
|
|
|
if(!GetProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET, (IUnknown*)
|
|
pIRowset))
|
|
{
|
|
odtLog<<L"IRowsetChange is not supported.\n";
|
|
bProvUpdateable = FALSE;
|
|
}
|
|
|
|
//Get list of ordinals.
|
|
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols,
|
|
&rgColumnsOrd, NULL, NULL, NULL, NULL))
|
|
|
|
TESTC(VerifyInterface(pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
if(bProvUpdateable)
|
|
{
|
|
TESTC(VerifyInterface(pIRowset,IID_IRowsetChange,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRowsetChange))
|
|
}
|
|
|
|
//Create Accessor with a binding using length, status and value.
|
|
//This accessor binds the updateable non-index columns.
|
|
TESTC_(GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
UPDATEABLE_NONINDEX_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Get the value of the property DBPROP_ABORTPRESERVE.
|
|
if(GetProperty(DBPROP_ABORTPRESERVE, DBPROPSET_ROWSET, (IUnknown*)
|
|
pIRowset))
|
|
bAbortPreserve = TRUE;
|
|
|
|
//Allocate a new data buffer
|
|
SAFE_ALLOC(pOrgData, BYTE, cbRowSize)
|
|
memset(pOrgData, 0, (size_t) cbRowSize);
|
|
|
|
//Restart position.
|
|
TESTC_(RestartPosition(pIRowset), S_OK)
|
|
|
|
//Get third row.
|
|
TESTC_(hr = GetNextRows(pIRowset, NULL,2,1,&cRowsObtained,
|
|
&rghRows),S_OK)
|
|
|
|
TESTC_(hr = pIRowset->GetData(rghRows[0], hAccessor, pOrgData), S_OK)
|
|
|
|
//Make data corresponding to row (g_ulNextRow+1).
|
|
TESTC_(FillInputBindings(m_pTable, DBACCESSOR_ROWDATA,
|
|
cBindings, rgBindings, &pData, ++g_ulNextRow, cRowsetCols,
|
|
rgColumnsOrd, PRIMARY),S_OK)
|
|
|
|
if(bProvUpdateable)
|
|
{
|
|
//Set data corresponding to row (g_ulNextRow+1).
|
|
TESTC_(hr = pIRowsetChange->SetData(rghRows[0],hAccessor,
|
|
pData),S_OK)
|
|
}
|
|
|
|
//Release...cleanup...
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings,pData, TRUE) ;
|
|
pData = NULL;
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowsetChange);
|
|
|
|
//Abort the transaction with fRetaining=FALSE.
|
|
if((hr=pITL->Abort(NULL, FALSE, FALSE)) == XACT_E_NOTSUPPORTED)
|
|
if((hr=pITL->Abort(NULL, FALSE, TRUE)) == XACT_E_NOTSUPPORTED)
|
|
{
|
|
odtLog<<L"INFO: Failure when calling Abort.\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//The transaction should have aborted successfully.
|
|
TESTC_(hr, S_OK)
|
|
|
|
//If DBPROP_ABORTPRESERVE was FALSE, then release pIRowset and
|
|
//open a rowset again. Otherwise, the current rowset is valid, so
|
|
//proceed.
|
|
if(!bAbortPreserve)
|
|
{
|
|
//Verify the rowset is in zombie state.
|
|
TESTC_(RestartPosition(pIRowset), E_UNEXPECTED)
|
|
|
|
SAFE_RELEASE(pIRowset);
|
|
TEST2C_(hr=CreateOpenRowset(m_pTable, IID_IRowset,(IUnknown**)
|
|
&pIRowset), S_OK, DB_S_ERRORSOCCURRED)
|
|
}
|
|
|
|
TESTC(VerifyInterface(pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create Accessor with a binding using length, status and value.
|
|
//This accessor binds the updateable non-index columns.
|
|
TESTC_(hr = GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
UPDATEABLE_NONINDEX_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
NO_BLOB_COLS, NULL),S_OK)
|
|
|
|
//Allocate a new data buffer
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
|
|
//Restart position.
|
|
TESTC_(RestartPosition(pIRowset), S_OK)
|
|
|
|
//Get third row.
|
|
TESTC_(hr = GetNextRows(pIRowset, NULL,2,1,&cRowsObtained,
|
|
&rghRows),S_OK)
|
|
|
|
TESTC_(hr = pIRowset->GetData(rghRows[0], hAccessor, pData), S_OK)
|
|
|
|
//The data should correspond to the original data of first row.
|
|
TESTC(CompareBuffer(pOrgData,pData,cBindings,rgBindings,
|
|
m_pIMalloc,TRUE, FALSE, COMPARE_ONLY))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings,pData, TRUE) ;
|
|
if(pOrgData)
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings,pOrgData, TRUE);
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pIRowsetChange);
|
|
SAFE_RELEASE(pIRowset);
|
|
if((hr=pITL->Abort(NULL, FALSE, FALSE)) == XACT_E_NOTSUPPORTED)
|
|
hr=pITL->Abort(NULL, FALSE, TRUE) ;
|
|
SAFE_RELEASE(pITL);
|
|
return tTestResult;
|
|
} //testTransactionAbort
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Create an accessor binding all columns. Look for a binding of
|
|
//type DBTYPE_IUNKNOWN. Fetch the first row and get its data. Compare
|
|
//the data for the DBTYPE_IUNKNOWN binding. CompareData gets the
|
|
//ISequentialStream interface and calls read. It then verifies the data
|
|
//read through ISequentialStream.
|
|
//
|
|
TESTRESULT CQuickTest::testStorageObj()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBCOUNTITEM ulBinding = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DBORDINAL cRowsetCols = 0;
|
|
DB_LORDINAL* rgColumnsOrd = NULL;
|
|
HROW* rghRows = NULL;
|
|
BYTE* pData = NULL;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBCOUNTITEM cBindings = 0;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBBINDING* rgBindings = NULL;
|
|
IRowset* pIRowset = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
ISequentialStream* pISS = NULL;
|
|
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
|
|
//Set the following properties. IRowsetLocate is required if
|
|
//we have bound BLOB columns and are going to fetch the data.
|
|
SetSupportedProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets) ;
|
|
|
|
SetProperty(DBPROP_CANHOLDROWS,
|
|
DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ;
|
|
|
|
//Open a rowset with above properties set.
|
|
hr=CreateOpenRowset(m_pTable, IID_IRowset,(IUnknown**)&pIRowset);
|
|
|
|
if(hr == DB_E_ERRORSOCCURRED)
|
|
{
|
|
TESTC(!pIRowset)
|
|
DumpPropertyErrors(m_cPropSets, m_rgPropSets);
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
TESTC(!pIRowset)
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
TESTC_(hr, S_OK)
|
|
|
|
//Get list of ordinals.
|
|
TESTC(m_pTable->GetQueryInfo(SELECT_ALLFROMTBL, &cRowsetCols,
|
|
&rgColumnsOrd, NULL, NULL, NULL, NULL))
|
|
|
|
TESTC(VerifyInterface(pIRowset,IID_IAccessor,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIAccessor))
|
|
|
|
//Create Accessor with a binding using length, status and value.
|
|
//This accessor binds all columns. Include BLOB_IID_ISEQSTREAM
|
|
//and BLOB_BIND_STR.
|
|
TESTC_(GetAccessorAndBindings(pIAccessor,
|
|
DBACCESSOR_ROWDATA,&hAccessor, &rgBindings,
|
|
&cBindings, &cbRowSize,
|
|
DBPART_LENGTH | DBPART_STATUS | DBPART_VALUE,
|
|
ALL_COLS_BOUND, FORWARD, NO_COLS_BY_REF, NULL,
|
|
NULL, NULL, DBTYPE_EMPTY, 0, NULL,
|
|
NULL,NO_COLS_OWNED_BY_PROV, DBPARAMIO_NOTPARAM,
|
|
BLOB_IID_ISEQSTREAM|BLOB_BIND_STR, NULL),S_OK)
|
|
|
|
//There should be a binding of type DBTYPE_IUNKNOWN for this test.
|
|
if(!FindBinding(cBindings, rgBindings, DBTYPE_IUNKNOWN, &ulBinding))
|
|
{
|
|
odtLog<<L"No column of type DBTYPE_IUNKNOWN in the rowset.\n";
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Allocate a new data buffer
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize)
|
|
memset(pData, 0, (size_t) cbRowSize);
|
|
|
|
//Restart position.
|
|
TESTC_(RestartPosition(pIRowset), S_OK)
|
|
|
|
//Get first row.
|
|
TESTC_(hr = GetNextRows(pIRowset, NULL,0,1,&cRowsObtained,
|
|
&rghRows),S_OK)
|
|
|
|
//Get data for first row.
|
|
TESTC_(hr = pIRowset->GetData(rghRows[0], hAccessor, pData), S_OK)
|
|
|
|
TESTC_(hr = GetStorageData(cBindings, rgBindings, pData, NULL,
|
|
NULL, IID_ISequentialStream, (IUnknown**)&pISS), S_OK)
|
|
|
|
TESTC(pISS != NULL)
|
|
|
|
//Compare the data for the DBTYPE_IUNKNOWN binding. This function
|
|
//gets the ISequentialStream interface and calls read. It then
|
|
//verifies the data read through ISequentialStream.
|
|
TESTC(CompareData(cRowsetCols, rgColumnsOrd, 1, pData, 1,
|
|
&rgBindings[ulBinding], m_pTable, m_pIMalloc, PRIMARY,
|
|
COMPARE_ONLY))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
CHECK(ReleaseRows(&pIRowset, &cRowsObtained, &rghRows), S_OK);
|
|
if(pData)
|
|
ReleaseInputBindingsMemory(cBindings, rgBindings,pData, TRUE) ;
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
PROVIDER_FREE(rgColumnsOrd);
|
|
FreeAccessorAndBindings(&pIAccessor,&hAccessor,&cBindings,&rgBindings);
|
|
SAFE_RELEASE(pISS);
|
|
SAFE_RELEASE(pIRowset);
|
|
return tTestResult;
|
|
} //testStorageObj
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// Test the IRow interface of the row object.
|
|
//
|
|
BOOL CQuickTest::testIRow(IRow* pIRow, DBCOUNTITEM ulRowNum)
|
|
{
|
|
TBEGIN
|
|
HRESULT hr = E_FAIL;
|
|
CRowObject CRow;
|
|
IRowset* pIRowset = NULL;
|
|
IAccessor* pIAccessor = NULL;
|
|
|
|
if(!pIRow || !m_pTable)
|
|
return FALSE;
|
|
|
|
//Try to get the source rowset of this row object.
|
|
TEST2C_(hr=pIRow->GetSourceRowset(IID_IRowset, (IUnknown**)&pIRowset,
|
|
NULL), S_OK, DB_E_NOSOURCEOBJECT)
|
|
|
|
//Try to get the source rowset again, with a different iid.
|
|
if(hr==S_OK)
|
|
TESTC_(hr=pIRow->GetSourceRowset(IID_IAccessor, (IUnknown**)&pIAccessor,
|
|
NULL), S_OK)
|
|
else
|
|
TESTC_(hr=pIRow->GetSourceRowset(IID_IAccessor, (IUnknown**)&pIAccessor,
|
|
NULL), DB_E_NOSOURCEOBJECT)
|
|
|
|
if(hr==S_OK)
|
|
TESTC((pIAccessor != NULL) && (pIRowset!= NULL))
|
|
else
|
|
odtLog<<L"INFO: There is no rowset object as source for the row.\n";
|
|
|
|
//If a row number (of this row in parent rowset) was passed in,
|
|
//use that to verify data.
|
|
if(ulRowNum)
|
|
{
|
|
TESTC_(CRow.SetRowObject(pIRow), S_OK)
|
|
|
|
TESTC(CRow.VerifyGetColumns(ulRowNum, m_pTable, ALL_COLS_BOUND,
|
|
NO_BLOB_COLS, FORWARD, NO_COLS_BY_REF, DBTYPE_EMPTY, 0,
|
|
NULL))
|
|
}
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIAccessor);
|
|
SAFE_RELEASE(pIRowset);
|
|
TRETURN
|
|
} //testIRow
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
//@mfunc Test the IColumnsInfo2 interface of a row object.
|
|
//
|
|
BOOL CQuickTest::testColInfo2(
|
|
CRowObject* pCRowObj,
|
|
BOOL bTestResColInfo)
|
|
{
|
|
TBEGIN
|
|
HRESULT hr;
|
|
DBORDINAL ulIndex = 0;
|
|
BOOL fColIDWarning = FALSE;
|
|
DBID rgColIDMasks[4];
|
|
DBORDINAL ulCols=0, ulCols2=0;
|
|
DBORDINAL cColsInBaseTable = 0;
|
|
DBID* rgColIDs = NULL;
|
|
DBCOLUMNINFO* rgColInfo = NULL;
|
|
DBCOLUMNINFO* rgColInfo2 = NULL;
|
|
WCHAR* pStrBuf = NULL;
|
|
WCHAR* pStrBuf2 = NULL;
|
|
CCol rgCol;
|
|
IColumnsInfo* pICI = NULL;
|
|
IColumnsInfo2* pICI2 = NULL;
|
|
|
|
TESTC((pCRowObj!=NULL) && (m_pTable!=NULL))
|
|
|
|
//Test MapColumnIDs.
|
|
TESTC(testMapColumnIDs(pCRowObj->pIRow()))
|
|
|
|
if(bTestResColInfo)
|
|
TESTC(VerifyInterface(pCRowObj->pIRow(), IID_IColumnsInfo2,
|
|
ROW_INTERFACE, (IUnknown**)&pICI2))
|
|
else
|
|
TESTC(VerifyInterface(pCRowObj->pIRow(), IID_IColumnsInfo,
|
|
ROW_INTERFACE, (IUnknown**)&pICI))
|
|
|
|
//Test GetColumnInfo method.
|
|
|
|
if(pICI2)
|
|
TESTC_(pICI2->GetColumnInfo(&ulCols, &rgColInfo, &pStrBuf), S_OK)
|
|
else
|
|
TESTC_(pICI->GetColumnInfo(&ulCols, &rgColInfo, &pStrBuf), S_OK)
|
|
|
|
TESTC(ulCols!=0 && rgColInfo!=NULL && pStrBuf!=NULL)
|
|
|
|
//Verify the number of columns.
|
|
if(rgColInfo[0].iOrdinal==0)
|
|
TESTC(ulCols-1 >= m_pTable->CountColumnsOnTable())
|
|
else
|
|
TESTC(ulCols >= m_pTable->CountColumnsOnTable())
|
|
|
|
//Verify the DBCOLUMNINFO values.
|
|
for(ulIndex=0; ulIndex<ulCols; ulIndex++)
|
|
{
|
|
//Ignore the bookmarks column if it exists.
|
|
if((ulIndex==0)&&(rgColInfo[ulIndex].iOrdinal==0))
|
|
{
|
|
// Check for the Bookmark FLAG.
|
|
TESTC(rgColInfo[ulIndex].dwFlags & DBCOLUMNFLAGS_ISBOOKMARK)
|
|
continue;
|
|
}
|
|
|
|
//Verify the ordinal value.
|
|
TESTC(rgColInfo[ulIndex].iOrdinal == ulIndex+rgColInfo[0].iOrdinal)
|
|
|
|
//Get the CCol structure for this column.
|
|
if(m_pTable->GetColInfo(rgColInfo[ulIndex].iOrdinal, rgCol) != S_OK)
|
|
continue;
|
|
|
|
cColsInBaseTable++;
|
|
|
|
//Verify the column name.
|
|
if((rgColInfo[ulIndex].pwszName)&&(rgCol.GetColName()))
|
|
TESTC(wcscmp(rgColInfo[ulIndex].pwszName,
|
|
rgCol.GetColName()) == 0)
|
|
else
|
|
TESTC((rgColInfo[ulIndex].pwszName == NULL)&&
|
|
(rgCol.GetColName() == NULL))
|
|
|
|
//ITypeInfo is reserved for future use.
|
|
TESTC(rgColInfo[ulIndex].pTypeInfo == rgCol.GetTypeInfo())
|
|
|
|
//Verify the DBTYPE.
|
|
TESTC(rgColInfo[ulIndex].wType == rgCol.GetProviderType())
|
|
|
|
//Compare the column IDs.
|
|
if(!CompareDBID(rgColInfo[ulIndex].columnid, *(rgCol.GetColID())))
|
|
{
|
|
if(ulIndex>1)
|
|
TESTC(fColIDWarning)
|
|
TESTC(rgColInfo[ulIndex].columnid.eKind != (*(rgCol.GetColID())).eKind)
|
|
fColIDWarning = TRUE;
|
|
}
|
|
}
|
|
|
|
TESTC(cColsInBaseTable == m_pTable->CountColumnsOnTable())
|
|
|
|
if(fColIDWarning)
|
|
{
|
|
//Issue a warning.
|
|
odtLog<<L"WARNING: ColID returned is of different DBKIND.\n";
|
|
COMPAREW(fColIDWarning, FALSE);
|
|
}
|
|
|
|
//If we do not have to test IColumnsInfo2::GetRestrictedColumnInfo,
|
|
//then skip the following portion.
|
|
|
|
if(!bTestResColInfo)
|
|
goto CLEANUP;
|
|
|
|
//rgColumnIDMasks should be ignoed when cColumnIDMasks=0.
|
|
TESTC_(pICI2->GetRestrictedColumnInfo(0, INVALID(DBID*), 0, &ulCols2,
|
|
&rgColIDs, &rgColInfo2, &pStrBuf2), S_OK)
|
|
|
|
//The columns obtained from GetRestrictedColumnInfo with zero
|
|
//restrictions has to be same as that obtained from GetColumnInfo method.
|
|
|
|
TESTC(ulCols2 == ulCols)
|
|
TESTC(rgColIDs!=NULL && rgColInfo2!=NULL && pStrBuf2!=NULL)
|
|
|
|
for(ulIndex=0; ulIndex<ulCols; ulIndex++)
|
|
{
|
|
TESTC(rgColInfo2[ulIndex].iOrdinal == ulIndex+rgColInfo2[0].iOrdinal)
|
|
TESTC(CompareDBID(rgColInfo2[ulIndex].columnid, rgColInfo[ulIndex].columnid))
|
|
TESTC(CompareDBID(rgColInfo2[ulIndex].columnid, rgColIDs[ulIndex]))
|
|
}
|
|
|
|
SAFE_FREE(rgColInfo2);
|
|
SAFE_FREE(pStrBuf2);
|
|
SAFE_FREE(rgColIDs);
|
|
ulCols2 = 0;
|
|
|
|
//Build restrictions for GetRestrictedColumnInfo.
|
|
|
|
for(ulIndex=0; ulIndex<4; ulIndex++)
|
|
rgColIDMasks[ulIndex].eKind = DBKIND_NAME;
|
|
|
|
rgColIDMasks[0].uName.pwszName = L"C";
|
|
rgColIDMasks[1].uName.pwszName = L"c";
|
|
rgColIDMasks[2].uName.pwszName = L"N";
|
|
rgColIDMasks[3].uName.pwszName = L"n";
|
|
|
|
//Call GetRestrictedColumnInfo with above restrictions
|
|
//and verify.
|
|
|
|
TEST2C_(hr=pICI2->GetRestrictedColumnInfo(4, rgColIDMasks, 0, &ulCols2,
|
|
&rgColIDs, &rgColInfo2, &pStrBuf2), S_OK, DB_E_NOCOLUMN)
|
|
|
|
if(hr==S_OK)
|
|
TESTC(ulCols2>0 && rgColIDs!=NULL && rgColInfo2!=NULL && pStrBuf2!=NULL)
|
|
else
|
|
TESTC(ulCols2==0 && rgColIDs==NULL && rgColInfo2==NULL && pStrBuf2==NULL)
|
|
|
|
for(ulIndex=0; ulIndex<ulCols2; ulIndex++)
|
|
{
|
|
TESTC(rgColInfo2[ulIndex].columnid.uName.pwszName != NULL)
|
|
TESTC((_wcsnicmp(rgColInfo2[ulIndex].columnid.uName.pwszName,
|
|
L"c",1)==0) ||
|
|
(_wcsnicmp(rgColInfo2[ulIndex].columnid.uName.pwszName,
|
|
L"n",1)==0) )
|
|
}
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(rgColIDs);
|
|
SAFE_FREE(rgColInfo);
|
|
SAFE_FREE(rgColInfo2);
|
|
SAFE_FREE(pStrBuf);
|
|
SAFE_FREE(pStrBuf2);
|
|
SAFE_RELEASE(pICI);
|
|
SAFE_RELEASE(pICI2);
|
|
TRETURN
|
|
} //testColInfo2
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// @mfunc Test IRowChange interface.
|
|
//
|
|
BOOL CQuickTest::testIRowChange(CRowObject* pCRowObj)
|
|
{
|
|
TBEGIN
|
|
DBLENGTH cbRowSize = 0;
|
|
DBORDINAL cColAccess = 0;
|
|
DBCOLUMNACCESS* rgColAccess = NULL;
|
|
void* pData = NULL;
|
|
|
|
TESTC((pCRowObj!=NULL) && (m_pTable!=NULL))
|
|
|
|
//Create the DBCOLUMNACCESS struct and fill in data to be set on the row.
|
|
|
|
TESTC_(pCRowObj->CreateColAccess(&cColAccess, &rgColAccess, &pData,
|
|
&cbRowSize, UPDATEABLE_NONINDEX_COLS_BOUND), S_OK)
|
|
|
|
TESTC_(pCRowObj->FillColAccess(m_pTable, cColAccess, rgColAccess,
|
|
2, PRIMARY), S_OK)
|
|
|
|
//Call SetColumns to change the data in the row object.
|
|
TESTC_(pCRowObj->SetColumns(cColAccess, rgColAccess), S_OK)
|
|
|
|
//Verify new data in row object.
|
|
TESTC(pCRowObj->VerifyGetColumns(2, m_pTable, UPDATEABLE_NONINDEX_COLS_BOUND))
|
|
|
|
//Replace the original data by calling SetColumns again.
|
|
|
|
TESTC_(pCRowObj->FillColAccess(m_pTable, cColAccess, rgColAccess,
|
|
1, PRIMARY), S_OK)
|
|
|
|
TESTC_(pCRowObj->SetColumns(cColAccess, rgColAccess), S_OK)
|
|
|
|
TESTC(pCRowObj->VerifyGetColumns(1, m_pTable, UPDATEABLE_NONINDEX_COLS_BOUND))
|
|
|
|
CLEANUP:
|
|
FreeColAccess(cColAccess, rgColAccess);
|
|
SAFE_FREE(pData);
|
|
TRETURN
|
|
} //testIRowChange
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// @mfunc Test the IRowSchemaChange interface.
|
|
//
|
|
BOOL CQuickTest::testIRowSchemaChange(CRowObject* pCRowObj)
|
|
{
|
|
TBEGIN
|
|
DBORDINAL ulIndex = 0;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBORDINAL cColAccess = 0;
|
|
DBCOLUMNACCESS* rgColAccess = NULL;
|
|
DBCOLUMNINFO* rgNewColInfo = NULL;
|
|
void* pData = NULL;
|
|
DBORDINAL cColInfo2 = 0;
|
|
DBORDINAL cColInfo = 0;
|
|
DBCOLUMNINFO* rgColInfo = NULL;
|
|
WCHAR* pwszBuff = NULL;
|
|
DBSTATUS dwStatus = 0;
|
|
IColumnsInfo* pICI = NULL;
|
|
IRowSchemaChange* pIRSC = NULL;
|
|
|
|
TESTC((pCRowObj!=NULL) && (m_pTable!=NULL))
|
|
|
|
//Create the DBCOLUMNACCESS struct and fill in data. One
|
|
//column from this will be modified and used for AddColumn.
|
|
|
|
TESTC_(pCRowObj->CreateColAccess(&cColAccess, &rgColAccess, &pData,
|
|
&cbRowSize, UPDATEABLE_NONINDEX_COLS_BOUND), S_OK)
|
|
|
|
TESTC_(pCRowObj->FillColAccess(m_pTable, cColAccess, rgColAccess,
|
|
2, PRIMARY), S_OK)
|
|
|
|
//Allocate a new DBCOLUMNINFO struct to pass in to AddColumns.
|
|
SAFE_ALLOC(rgNewColInfo, DBCOLUMNINFO, 1);
|
|
memset(rgNewColInfo, 0, sizeof(DBCOLUMNINFO));
|
|
|
|
TESTC(VerifyInterface(pCRowObj->pIRow(), IID_IColumnsInfo,
|
|
ROW_INTERFACE, (IUnknown**)&pICI))
|
|
|
|
TESTC_(pICI->GetColumnInfo(&cColInfo, &rgColInfo, &pwszBuff), S_OK)
|
|
|
|
//Get the column info for same column as in rgColAccess[0].
|
|
for(ulIndex=0; ulIndex<cColInfo; ulIndex++)
|
|
{
|
|
if(CompareDBID(rgColInfo[ulIndex].columnid, rgColAccess[0].columnid))
|
|
break;
|
|
}
|
|
|
|
//Make sure we did find it before hitting end of the FOR loop.
|
|
TESTC(ulIndex<cColInfo);
|
|
|
|
//copy.
|
|
rgNewColInfo[0] = rgColInfo[ulIndex];
|
|
|
|
//Free and null string pointers.
|
|
SAFE_FREE(pwszBuff);
|
|
rgNewColInfo[0].pwszName = NULL;
|
|
if(rgNewColInfo[0].columnid.eKind == DBKIND_GUID_NAME ||
|
|
rgNewColInfo[0].columnid.eKind == DBKIND_NAME)
|
|
rgNewColInfo[0].columnid.uName.pwszName = NULL;
|
|
|
|
//Create a unique name for the columnid.
|
|
switch(rgNewColInfo[0].columnid.eKind)
|
|
{
|
|
case DBKIND_GUID_PROPID:
|
|
case DBKIND_GUID:
|
|
//Create a new guid (fairly unique!)
|
|
TESTC_(CoCreateGuid(&rgNewColInfo[0].columnid.uGuid.guid),S_OK);
|
|
break;
|
|
|
|
case DBKIND_PROPID:
|
|
rgNewColInfo[0].columnid.uName.ulPropid++;
|
|
break;
|
|
|
|
case DBKIND_GUID_NAME:
|
|
case DBKIND_NAME:
|
|
{
|
|
GUID guid;
|
|
CoCreateGuid(&guid);
|
|
TESTC_(StringFromCLSID(guid, &rgNewColInfo[0].columnid.uName.pwszName),S_OK)
|
|
rgNewColInfo[0].pwszName = rgNewColInfo[0].columnid.uName.pwszName;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
TESTC(FALSE);
|
|
break;
|
|
};
|
|
|
|
//NOTE: No need to modify rgColAccess[0].columnid.
|
|
// This should be ignored. We will let it remain
|
|
// different from rgNewColInfo[0].columnid just to
|
|
// make sure it is ignored.
|
|
|
|
TESTC(VerifyInterface(pCRowObj->pIRow(), IID_IRowSchemaChange,
|
|
ROW_INTERFACE, (IUnknown**)&pIRSC))
|
|
|
|
//Add the new column.
|
|
TESTC_(pIRSC->AddColumns(1, rgNewColInfo, rgColAccess), S_OK)
|
|
TESTC(rgColAccess[0].dwStatus == DBSTATUS_S_OK)
|
|
|
|
SAFE_FREE(rgColInfo);
|
|
|
|
//Verify the new column was added.
|
|
TESTC_(pICI->GetColumnInfo(&cColInfo2, &rgColInfo, &pwszBuff), S_OK)
|
|
TESTC(cColInfo2 = cColInfo+1)
|
|
|
|
for(ulIndex=0; ulIndex<cColInfo2; ulIndex++)
|
|
if(CompareDBID(rgColInfo[ulIndex].columnid, rgNewColInfo[0].columnid))
|
|
break;
|
|
|
|
TESTC(ulIndex<cColInfo2)
|
|
SAFE_FREE(rgColInfo);
|
|
SAFE_FREE(pwszBuff);
|
|
|
|
//Delete the new column.
|
|
TESTC_(pIRSC->DeleteColumns(1, &rgNewColInfo[0].columnid, &dwStatus), S_OK)
|
|
TESTC(dwStatus == DBSTATUS_S_OK)
|
|
|
|
//Verify the new column is deleted.
|
|
|
|
TESTC_(pICI->GetColumnInfo(&cColInfo2, &rgColInfo, &pwszBuff), S_OK)
|
|
TESTC(cColInfo2 = cColInfo)
|
|
|
|
for(ulIndex=0; ulIndex<cColInfo2; ulIndex++)
|
|
if(CompareDBID(rgColInfo[ulIndex].columnid, rgNewColInfo[0].columnid))
|
|
break;
|
|
|
|
TESTC(ulIndex == cColInfo2)
|
|
|
|
CLEANUP:
|
|
if(rgNewColInfo)
|
|
SAFE_FREE(rgNewColInfo[0].pwszName);
|
|
SAFE_FREE(rgColInfo);
|
|
SAFE_FREE(pwszBuff);
|
|
SAFE_FREE(rgNewColInfo);
|
|
FreeColAccess(cColAccess, rgColAccess);
|
|
SAFE_FREE(pData);
|
|
SAFE_RELEASE(pICI);
|
|
SAFE_RELEASE(pIRSC);
|
|
TRETURN
|
|
} //testIRowSchemaChange
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// Test Case Section
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(TCDataSource)
|
|
//---------------------------------------------------------------------
|
|
// @class DataSource Interfaces
|
|
//
|
|
class TCDataSource : public CQuickTest {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(TCDataSource,CQuickTest);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember IDBInitialize::Initialize
|
|
int Variation_1();
|
|
// @cmember IDBInitialize::Uninitialize
|
|
int Variation_2();
|
|
// @cmember IDBCreateSession
|
|
int Variation_3();
|
|
// @cmember IDBProperties::GetProperties
|
|
int Variation_4();
|
|
// @cmember IDBProperties::GetProperties(ALL)
|
|
int Variation_5();
|
|
// @cmember IDBProperties::GetPropertyInfo
|
|
int Variation_6();
|
|
// @cmember IDBProperties::GetPropertyInfo(ALL)
|
|
int Variation_7();
|
|
// @cmember IDBProperties::SetProperties
|
|
int Variation_8();
|
|
// @cmember Get properties before initialization
|
|
int Variation_9();
|
|
// @cmember IDBInfo::GetKeywords
|
|
int Variation_10();
|
|
// @cmember IDBInfo::GetLiteralInfo
|
|
int Variation_11();
|
|
// @cmember ISourcesRowset
|
|
int Variation_12();
|
|
// @cmember IDataInitialize::CreateDBInstance
|
|
int Variation_13();
|
|
// @cmember IDataInitialize::GetDataSource
|
|
int Variation_14();
|
|
// @cmember IPersist::GetClassID
|
|
int Variation_15();
|
|
// @cmember IPersistFile::GetClassID
|
|
int Variation_16();
|
|
// @cmember IPersistFile::IsDirty
|
|
int Variation_17();
|
|
// @cmember IPersistFile::Save
|
|
int Variation_18();
|
|
// @cmember IPersistFile::SaveCompleted
|
|
int Variation_19();
|
|
// @cmember IPersistFile::Load
|
|
int Variation_20();
|
|
// @cmember IPersistFile::GetCurFile
|
|
int Variation_21();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(TCDataSource)
|
|
#define THE_CLASS TCDataSource
|
|
BEG_TEST_CASE(TCDataSource, CQuickTest, L"DataSource Interfaces")
|
|
TEST_VARIATION(1, L"IDBInitialize::Initialize")
|
|
TEST_VARIATION(2, L"IDBInitialize::Uninitialize")
|
|
TEST_VARIATION(3, L"IDBCreateSession")
|
|
TEST_VARIATION(4, L"IDBProperties::GetProperties")
|
|
TEST_VARIATION(5, L"IDBProperties::GetProperties(ALL)")
|
|
TEST_VARIATION(6, L"IDBProperties::GetPropertyInfo")
|
|
TEST_VARIATION(7, L"IDBProperties::GetPropertyInfo(ALL)")
|
|
TEST_VARIATION(8, L"IDBProperties::SetProperties")
|
|
TEST_VARIATION(9, L"Get properties before initialization")
|
|
TEST_VARIATION(10, L"IDBInfo::GetKeywords")
|
|
TEST_VARIATION(11, L"IDBInfo::GetLiteralInfo")
|
|
TEST_VARIATION(12, L"ISourcesRowset")
|
|
TEST_VARIATION(13, L"IDataInitialize::CreateDBInstance")
|
|
TEST_VARIATION(14, L"IDataInitialize::GetDataSource")
|
|
TEST_VARIATION(15, L"IPersist::GetClassID")
|
|
TEST_VARIATION(16, L"IPersistFile::GetClassID")
|
|
TEST_VARIATION(17, L"IPersistFile::IsDirty")
|
|
TEST_VARIATION(18, L"IPersistFile::Save")
|
|
TEST_VARIATION(19, L"IPersistFile::SaveCompleted")
|
|
TEST_VARIATION(20, L"IPersistFile::Load")
|
|
TEST_VARIATION(21, L"IPersistFile::GetCurFile")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(TCSession)
|
|
//*---------------------------------------------------------------------
|
|
// @class Session Interfaces
|
|
//
|
|
class TCSession : public CQuickTest {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(TCSession,CQuickTest);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember IGetDataSource
|
|
int Variation_1();
|
|
// @cmember IOpenRowset
|
|
int Variation_2();
|
|
// @cmember ISessionProperties::GetProperties
|
|
int Variation_3();
|
|
// @cmember ISessionProperties::SetProperties
|
|
int Variation_4();
|
|
// @cmember IDBCreateCommand
|
|
int Variation_5();
|
|
// @cmember IDBSchemaRowset::GetSchemas
|
|
int Variation_6();
|
|
// @cmember IDBSchemaRowset::GetRowset(DBSCHEMA_COLUMNS)
|
|
int Variation_7();
|
|
// @cmember IDBSchemaRowset::GetRowset(DBSCHEMA_TABLES)
|
|
int Variation_8();
|
|
// @cmember IDBSchemaRowset::GetRowset(DBSCHEMA_PROVIDER_TYPES)
|
|
int Variation_9();
|
|
// @cmember ITableDefinition::AddColumn
|
|
int Variation_10();
|
|
// @cmember ITableDefinition::CreateTable
|
|
int Variation_11();
|
|
// @cmember ITableDefinition::DropColumn
|
|
int Variation_12();
|
|
// @cmember ITableDefinition::DropTable
|
|
int Variation_13();
|
|
// @cmember IIndexDefinition
|
|
int Variation_14();
|
|
// @cmember IAlterIndex
|
|
int Variation_15();
|
|
// @cmember IAlterTable::AlterColumn
|
|
int Variation_16();
|
|
// @cmember IAlterTable::AlterTable
|
|
int Variation_17();
|
|
// @cmember ITableDefinitionWithConstraints - AddConstraint & DropConstraint
|
|
int Variation_18();
|
|
// @cmember ITableDefinitionWithConstraints::CreateTableWithConstraints
|
|
int Variation_19();
|
|
// @cmember AggregateSession
|
|
int Variation_20();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(TCSession)
|
|
#define THE_CLASS TCSession
|
|
BEG_TEST_CASE(TCSession, CQuickTest, L"Session Interfaces")
|
|
TEST_VARIATION(1, L"IGetDataSource")
|
|
TEST_VARIATION(2, L"IOpenRowset")
|
|
TEST_VARIATION(3, L"ISessionProperties::GetProperties")
|
|
TEST_VARIATION(4, L"ISessionProperties::SetProperties")
|
|
TEST_VARIATION(5, L"IDBCreateCommand")
|
|
TEST_VARIATION(6, L"IDBSchemaRowset::GetSchemas")
|
|
TEST_VARIATION(7, L"IDBSchemaRowset::GetRowset(DBSCHEMA_COLUMNS)")
|
|
TEST_VARIATION(8, L"IDBSchemaRowset::GetRowset(DBSCHEMA_TABLES)")
|
|
TEST_VARIATION(9, L"IDBSchemaRowset::GetRowset(DBSCHEMA_PROVIDER_TYPES)")
|
|
TEST_VARIATION(10, L"ITableDefinition::AddColumn")
|
|
TEST_VARIATION(11, L"ITableDefinition::CreateTable")
|
|
TEST_VARIATION(12, L"ITableDefinition::DropColumn")
|
|
TEST_VARIATION(13, L"ITableDefinition::DropTable")
|
|
TEST_VARIATION(14, L"IIndexDefinition")
|
|
TEST_VARIATION(15, L"IAlterIndex")
|
|
TEST_VARIATION(16, L"IAlterTable::AlterColumn")
|
|
TEST_VARIATION(17, L"IAlterTable::AlterTable")
|
|
TEST_VARIATION(18, L"ITableDefinitionWithConstraints - AddConstraint & DropConstraint")
|
|
TEST_VARIATION(19, L"ITableDefinitionWithConstraints::CreateTableWithConstraints")
|
|
TEST_VARIATION(20, L"AggregateSession")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(TCRowsetNotUpdateable)
|
|
//*---------------------------------------------------------------------
|
|
// @class Rowset Interfaces (Non-Updateable Rowset)
|
|
//
|
|
class TCRowsetNotUpdateable : public CQuickTest {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(TCRowsetNotUpdateable,CQuickTest);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember IConvertType
|
|
int Variation_1();
|
|
// @cmember IColumnsInfo::GetColumnInfo
|
|
int Variation_2();
|
|
// @cmember IColumnsInfo::MapColumnIDs
|
|
int Variation_3();
|
|
// @cmember IAccessor
|
|
int Variation_4();
|
|
// @cmember IRowsetInfo::GetProperties
|
|
int Variation_5();
|
|
// @cmember IRowsetInfo::GetReferencedRowset
|
|
int Variation_6();
|
|
// @cmember IRowsetInfo::GetSpecification (Session)
|
|
int Variation_7();
|
|
// @cmember IRowsetInfo::GetSpecification (Command)
|
|
int Variation_8();
|
|
// @cmember IRowset (No Properties)
|
|
int Variation_9();
|
|
// @cmember IRowset (Scroll_Back & Canholdrows)
|
|
int Variation_10();
|
|
// @cmember IColumnsRowset::GetAvailableColumns
|
|
int Variation_11();
|
|
// @cmember IColumnsRowset::GetColumnsRowset
|
|
int Variation_12();
|
|
// @cmember IRowsetLocate::Compare
|
|
int Variation_13();
|
|
// @cmember IRowsetLocate::GetRowsAt
|
|
int Variation_14();
|
|
// @cmember IRowsetLocate::GetRowsByBookmark
|
|
int Variation_15();
|
|
// @cmember IRowsetLocate::Hash
|
|
int Variation_16();
|
|
// @cmember IRowsetFind
|
|
int Variation_17();
|
|
// @cmember IRowsetScroll::GetApproximatePosition
|
|
int Variation_18();
|
|
// @cmember IRowsetScroll::GetRowsAtRatio
|
|
int Variation_19();
|
|
// @cmember IRowPosition
|
|
int Variation_20();
|
|
// @cmember AggregateRowset
|
|
int Variation_21();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(TCRowsetNotUpdateable)
|
|
#define THE_CLASS TCRowsetNotUpdateable
|
|
BEG_TEST_CASE(TCRowsetNotUpdateable, CQuickTest, L"Rowset Interfaces (Non-Updateable Rowset)")
|
|
TEST_VARIATION(1, L"IConvertType")
|
|
TEST_VARIATION(2, L"IColumnsInfo::GetColumnInfo")
|
|
TEST_VARIATION(3, L"IColumnsInfo::MapColumnIDs")
|
|
TEST_VARIATION(4, L"IAccessor")
|
|
TEST_VARIATION(5, L"IRowsetInfo::GetProperties")
|
|
TEST_VARIATION(6, L"IRowsetInfo::GetReferencedRowset")
|
|
TEST_VARIATION(7, L"IRowsetInfo::GetSpecification (Session)")
|
|
TEST_VARIATION(8, L"IRowsetInfo::GetSpecification (Command)")
|
|
TEST_VARIATION(9, L"IRowset (No Properties)")
|
|
TEST_VARIATION(10, L"IRowset (Scroll_Back & Canholdrows)")
|
|
TEST_VARIATION(11, L"IColumnsRowset::GetAvailableColumns")
|
|
TEST_VARIATION(12, L"IColumnsRowset::GetColumnsRowset")
|
|
TEST_VARIATION(13, L"IRowsetLocate::Compare")
|
|
TEST_VARIATION(14, L"IRowsetLocate::GetRowsAt")
|
|
TEST_VARIATION(15, L"IRowsetLocate::GetRowsByBookmark")
|
|
TEST_VARIATION(16, L"IRowsetLocate::Hash")
|
|
TEST_VARIATION(17, L"IRowsetFind")
|
|
TEST_VARIATION(18, L"IRowsetScroll::GetApproximatePosition")
|
|
TEST_VARIATION(19, L"IRowsetScroll::GetRowsAtRatio")
|
|
TEST_VARIATION(20, L"IRowPosition")
|
|
TEST_VARIATION(21, L"AggregateRowset")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(TCRowsetUpdateable)
|
|
//*---------------------------------------------------------------------
|
|
// @class Rowset Interfaces (Updateable Rowset)
|
|
//
|
|
class TCRowsetUpdateable : public CQuickTest {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(TCRowsetUpdateable,CQuickTest);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember IRowsetIdentity
|
|
int Variation_1();
|
|
// @cmember IRowset (various properties set)
|
|
int Variation_2();
|
|
// @cmember IRowsetChange::SetData
|
|
int Variation_3();
|
|
// @cmember IRowsetChange::DeleteRows
|
|
int Variation_4();
|
|
// @cmember IRowsetChange::InsertRow
|
|
int Variation_5();
|
|
// @cmember IRowsetUpdate
|
|
int Variation_6();
|
|
// @cmember IRowsetResynch
|
|
int Variation_7();
|
|
// @cmember IRowsetRefresh
|
|
int Variation_8();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(TCRowsetUpdateable)
|
|
#define THE_CLASS TCRowsetUpdateable
|
|
BEG_TEST_CASE(TCRowsetUpdateable, CQuickTest, L"Rowset Interfaces (Updateable Rowset)")
|
|
TEST_VARIATION(1, L"IRowsetIdentity")
|
|
TEST_VARIATION(2, L"IRowset (various properties set)")
|
|
TEST_VARIATION(3, L"IRowsetChange::SetData")
|
|
TEST_VARIATION(4, L"IRowsetChange::DeleteRows")
|
|
TEST_VARIATION(5, L"IRowsetChange::InsertRow")
|
|
TEST_VARIATION(6, L"IRowsetUpdate")
|
|
TEST_VARIATION(7, L"IRowsetResynch")
|
|
TEST_VARIATION(8, L"IRowsetRefresh")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(TCCommand)
|
|
//*-----------------------------------------------------------------------
|
|
// @class Command Interfaces
|
|
//
|
|
class TCCommand : public CQuickTest {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(TCCommand,CQuickTest);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember IAccessor
|
|
int Variation_1();
|
|
// @cmember IColumnsInfo::GetColumnInfo
|
|
int Variation_2();
|
|
// @cmember IColumnsInfo::MapColumnIDs
|
|
int Variation_3();
|
|
// @cmember ICommandProperties::GetProperties
|
|
int Variation_4();
|
|
// @cmember ICommandProperties::SetProperties
|
|
int Variation_5();
|
|
// @cmember IConvertType
|
|
int Variation_6();
|
|
// @cmember ICommandText
|
|
int Variation_7();
|
|
// @cmember ICommand::GetDBSession
|
|
int Variation_8();
|
|
// @cmember ICommand::Execute (set,exe,set,exe,set,exe)
|
|
int Variation_9();
|
|
// @cmember ICommand::Execute (set,exe,exe,exe)
|
|
int Variation_10();
|
|
// @cmember IColumnsRowset::GetAvailableColumns
|
|
int Variation_11();
|
|
// @cmember IColumnsRowset::GetColumnsRowset
|
|
int Variation_12();
|
|
// @cmember ICommandPrepare::Prepare
|
|
int Variation_13();
|
|
// @cmember ICommandPrepare::Unprepare
|
|
int Variation_14();
|
|
// @cmember ICommandWithParameters
|
|
int Variation_15();
|
|
// @cmember IMultipleResults
|
|
int Variation_16();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(TCCommand)
|
|
#define THE_CLASS TCCommand
|
|
BEG_TEST_CASE(TCCommand, CQuickTest, L"Command Interfaces")
|
|
TEST_VARIATION(1, L"IAccessor")
|
|
TEST_VARIATION(2, L"IColumnsInfo::GetColumnInfo")
|
|
TEST_VARIATION(3, L"IColumnsInfo::MapColumnIDs")
|
|
TEST_VARIATION(4, L"ICommandProperties::GetProperties")
|
|
TEST_VARIATION(5, L"ICommandProperties::SetProperties")
|
|
TEST_VARIATION(6, L"IConvertType")
|
|
TEST_VARIATION(7, L"ICommandText")
|
|
TEST_VARIATION(8, L"ICommand::GetDBSession")
|
|
TEST_VARIATION(9, L"ICommand::Execute (set,exe,set,exe,set,exe)")
|
|
TEST_VARIATION(10, L"ICommand::Execute (set,exe,exe,exe)")
|
|
TEST_VARIATION(11, L"IColumnsRowset::GetAvailableColumns")
|
|
TEST_VARIATION(12, L"IColumnsRowset::GetColumnsRowset")
|
|
TEST_VARIATION(13, L"ICommandPrepare::Prepare")
|
|
TEST_VARIATION(14, L"ICommandPrepare::Unprepare")
|
|
TEST_VARIATION(15, L"ICommandWithParameters")
|
|
TEST_VARIATION(16, L"IMultipleResults")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(TCOtherObjects)
|
|
//*-----------------------------------------------------------------------
|
|
// @class Other Objects
|
|
//
|
|
class TCOtherObjects : public CQuickTest {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(TCOtherObjects,CQuickTest);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember ErrorInterfaces
|
|
int Variation_1();
|
|
// @cmember Transaction(Commit)
|
|
int Variation_2();
|
|
// @cmember Transaction(Abort)
|
|
int Variation_3();
|
|
// @cmember StorageInterface
|
|
int Variation_4();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(TCOtherObjects)
|
|
#define THE_CLASS TCOtherObjects
|
|
BEG_TEST_CASE(TCOtherObjects, CQuickTest, L"Other Objects")
|
|
TEST_VARIATION(1, L"ErrorInterfaces")
|
|
TEST_VARIATION(2, L"Transaction(Commit)")
|
|
TEST_VARIATION(3, L"Transaction(Abort)")
|
|
TEST_VARIATION(4, L"StorageInterface")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(TCBinder)
|
|
//*-----------------------------------------------------------------------
|
|
// @class Binder Interfaces
|
|
//
|
|
class TCBinder : public CQuickTest {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(TCBinder,CQuickTest);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember IBindResource
|
|
int Variation_1();
|
|
// @cmember ICreateRow
|
|
int Variation_2();
|
|
// @cmember IDBBinderProperties - Set rowset props
|
|
int Variation_3();
|
|
// @cmember IDBBinderProperties - Reset
|
|
int Variation_4();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(TCBinder)
|
|
#define THE_CLASS TCBinder
|
|
BEG_TEST_CASE(TCBinder, CQuickTest, L"Binder Interfaces")
|
|
TEST_VARIATION(1, L"IBindResource")
|
|
TEST_VARIATION(2, L"ICreateRow")
|
|
TEST_VARIATION(3, L"IDBBinderProperties - Set rowset props")
|
|
TEST_VARIATION(4, L"IDBBinderProperties - Reset")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(TCRow)
|
|
//*-----------------------------------------------------------------------
|
|
// @class Row Interfaces
|
|
//
|
|
class TCRow : public CQuickTest {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(TCRow,CQuickTest);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember IRow
|
|
int Variation_1();
|
|
// @cmember IGetSession
|
|
int Variation_2();
|
|
// @cmember IConvertType
|
|
int Variation_3();
|
|
// @cmember IColumnsInfo
|
|
int Variation_4();
|
|
// @cmember IColumnsInfo2
|
|
int Variation_5();
|
|
// @cmember IGetRow
|
|
int Variation_6();
|
|
// @cmember IGetSourceRow
|
|
int Variation_7();
|
|
// @cmember IRowChange
|
|
int Variation_8();
|
|
// @cmember IRowSchemaChange
|
|
int Variation_9();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(TCRow)
|
|
#define THE_CLASS TCRow
|
|
BEG_TEST_CASE(TCRow, CQuickTest, L"Row Interfaces")
|
|
TEST_VARIATION(1, L"IRow")
|
|
TEST_VARIATION(2, L"IGetSession")
|
|
TEST_VARIATION(3, L"IConvertType")
|
|
TEST_VARIATION(4, L"IColumnsInfo")
|
|
TEST_VARIATION(5, L"IColumnsInfo2")
|
|
TEST_VARIATION(6, L"IGetRow")
|
|
TEST_VARIATION(7, L"IGetSourceRow")
|
|
TEST_VARIATION(8, L"IRowChange")
|
|
TEST_VARIATION(9, L"IRowSchemaChange")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
|
|
// }} END_DECLARE_TEST_CASES()
|
|
|
|
// {{ TCW_TESTMODULE(ThisModule)
|
|
TEST_MODULE(8, ThisModule, gwszModuleDescrip)
|
|
TEST_CASE(1, TCDataSource)
|
|
TEST_CASE(2, TCSession)
|
|
TEST_CASE(3, TCRowsetNotUpdateable)
|
|
TEST_CASE(4, TCRowsetUpdateable)
|
|
TEST_CASE(5, TCCommand)
|
|
TEST_CASE(6, TCOtherObjects)
|
|
TEST_CASE(7, TCBinder)
|
|
TEST_CASE(8, TCRow)
|
|
END_TEST_MODULE()
|
|
// }} TCW_TESTMODULE_END
|
|
|
|
// {{ TCW_TC_PROTOTYPE(TCDataSource)
|
|
//*---------------------------------------------------------------------
|
|
//| Test Case: TCDataSource - DataSource Interfaces
|
|
//| Created: 08/24/95
|
|
//*---------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine. Gets the pointers to
|
|
//IPersistFile and IDBProperties interfaces. Also initializes m_rgPropIDSets
|
|
//m_rgPropInfoSets with the selected properties.
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL TCDataSource::Init()
|
|
{
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
if(CQuickTest::Init())
|
|
// }}
|
|
{
|
|
if(CHECK(m_hr = CreateDataSourceObject(),S_OK))
|
|
{
|
|
VerifyInterface(m_pIDBInitialize,IID_IPersistFile,
|
|
DATASOURCE_INTERFACE,(IUnknown **)&m_pIPersistFile) ;
|
|
VerifyInterface(m_pIDBInitialize, IID_IDBProperties,
|
|
DATASOURCE_INTERFACE, (IUnknown**)&m_pIDBProperties) ;
|
|
|
|
if(m_pIDBProperties == NULL)
|
|
{
|
|
odtLog<<L"INFO: Could not get IDBProperties (level-0) interface.\n";
|
|
return FALSE;
|
|
}
|
|
|
|
InitPropIDStructs();
|
|
|
|
if(CHECK(InitializeDSO(), S_OK))
|
|
{
|
|
InitSupInfo();
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IDBInitialize::Initialize
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
//Create another DSO. Get the initialization properties and initialize
|
|
//it. To make sure that it was actually initialized call CreateSession.
|
|
//
|
|
int TCDataSource::Variation_1()
|
|
{
|
|
IDBInitialize* pIDBInitialize = NULL;
|
|
IDBCreateSession* pIDBCreateSession = NULL;
|
|
IOpenRowset* pIOpenRowset = NULL;
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr;
|
|
|
|
//Create a new Data Source Object and initialize it.
|
|
TESTC_(CreateNewDSO(NULL, IID_IDBInitialize,
|
|
(IUnknown**)&pIDBInitialize), S_OK)
|
|
|
|
//Obtain the IDBCreateSession interface.
|
|
if(!VerifyInterface(pIDBInitialize, IID_IDBCreateSession,
|
|
DATASOURCE_INTERFACE, (IUnknown**)&pIDBCreateSession))
|
|
goto CLEANUP;
|
|
|
|
//CreateSession should succeed if the DSO was properly initialized.
|
|
if(!CHECK(hr = pIDBCreateSession->CreateSession(NULL, IID_IOpenRowset,
|
|
(IUnknown**)&pIOpenRowset), S_OK))
|
|
goto CLEANUP;
|
|
|
|
if(hr == S_OK)
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
//Release Session.
|
|
SAFE_RELEASE(pIOpenRowset);
|
|
SAFE_RELEASE(pIDBCreateSession);
|
|
//Release the DSO.
|
|
SAFE_RELEASE(pIDBInitialize);
|
|
return tTestResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IDBInitialize::Uninitialize
|
|
//and then calls Uninitialize on it.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_2()
|
|
{
|
|
IDBInitialize* pIDBInitialize = NULL;
|
|
IDBProperties* pIDBProperties = NULL;
|
|
ULONG cPropSets =0;
|
|
DBPROPSET* rgPropSets = NULL;
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr;
|
|
|
|
//Create a new DSO.
|
|
CHECK(hr = GetModInfo()->CreateProvider(NULL, IID_IDBInitialize,
|
|
(IUnknown**)&pIDBInitialize), S_OK);
|
|
if(pIDBInitialize==NULL)
|
|
{
|
|
odtLog<<L"INFO: Could not create another DSO.\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Obtain the IDBProperties interface.
|
|
if(!VerifyInterface(pIDBInitialize, IID_IDBProperties,
|
|
DATASOURCE_INTERFACE, (IUnknown**)&pIDBProperties))
|
|
goto CLEANUP;
|
|
|
|
//Get the initialization properties and set them.
|
|
GetInitProps(&cPropSets, &rgPropSets);
|
|
CHECK(hr = pIDBProperties->SetProperties(cPropSets, rgPropSets),
|
|
S_OK);
|
|
|
|
//Calling Uninitialize before Initialize should succeed.
|
|
CHECK(hr = pIDBInitialize->Uninitialize(), S_OK);
|
|
if(hr != S_OK)
|
|
{
|
|
odtLog<<L"INFO: Failure on Uninitialize (before Initialize).\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Initialize DSO.
|
|
CHECK(hr = pIDBInitialize->Initialize(), S_OK);
|
|
if(hr != S_OK)
|
|
{
|
|
odtLog<<L"INFO: Failure on Initialize.\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Call Uninitialize on the DSO. This should succeed.
|
|
CHECK(hr = pIDBInitialize->Uninitialize(), S_OK);
|
|
if(hr == S_OK)
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
FreeProperties(&cPropSets, &rgPropSets);
|
|
//Release the DSO.
|
|
SAFE_RELEASE(pIDBProperties);
|
|
SAFE_RELEASE(pIDBInitialize);
|
|
return tTestResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IDBCreateSession
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_3()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
IDBCreateSession* pIDBCreateSession = NULL;
|
|
IOpenRowset* pIOpenRowset = NULL;
|
|
|
|
//Make sure that DSO is initialized before creating session.
|
|
if(!m_fInitialized)
|
|
CHECK(InitializeDSO(REINITIALIZE_NO), S_OK) ;
|
|
|
|
if(!VerifyInterface(m_pIDBInitialize, IID_IDBCreateSession,
|
|
DATASOURCE_INTERFACE,(IUnknown**) &pIDBCreateSession))
|
|
{
|
|
odtLog<<L"Error getting IDBCreateSession Interface.\n";
|
|
return TEST_FAIL;
|
|
}
|
|
|
|
TESTC_(pIDBCreateSession->CreateSession(NULL, IID_IOpenRowset,
|
|
(IUnknown**)&pIOpenRowset), S_OK)
|
|
|
|
TESTC(pIOpenRowset != NULL)
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIOpenRowset) ;
|
|
SAFE_RELEASE(pIDBCreateSession) ;
|
|
return tTestResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IDBProperties::GetProperties
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_4()
|
|
{
|
|
return testGetProperties() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IDBProperties::GetProperties(ALL)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_5()
|
|
{
|
|
return testGetAllProperties(m_pIDBProperties) ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(6)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IDBProperties::GetPropertyInfo
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_6()
|
|
{
|
|
return testGetPropInfo() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(7)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IDBProperties::GetPropertyInfo(ALL)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_7()
|
|
{
|
|
return testGetAllPropInfo(m_pIDBProperties) ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(8)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IDBProperties::SetProperties
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_8()
|
|
{
|
|
return ((testSetProperties1() == TEST_PASS) && (testSetProperties2() == TEST_PASS)) ? TEST_PASS : TEST_FAIL;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(9)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc Get properties before initialization
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_9()
|
|
{
|
|
return testGetPropBeforeInit() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(10)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IDBInfo::GetKeywords
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_10()
|
|
{
|
|
return testGetKeywords();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(11)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IDBInfo::GetLiteralInfo
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_11()
|
|
{
|
|
return testGetLiteralInfo();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(12)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc ISourcesRowset
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_12()
|
|
{
|
|
return testISrcRowset();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(13)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IDataInitialize::CreateDBInstance
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_13()
|
|
{
|
|
return testIDataIzCreateDBIns();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(14)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IDataInitialize::GetDataSource
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_14()
|
|
{
|
|
return testIDataIzGetDS();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(15)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IPersist::GetClassID
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_15()
|
|
{
|
|
CLSID clsid;
|
|
IPersist * pIPersist;
|
|
|
|
//Return if this interface is not supported
|
|
if (!VerifyInterface(m_pIDBInitialize,IID_IPersist,
|
|
DATASOURCE_INTERFACE,(IUnknown **)&pIPersist))
|
|
return TEST_FAIL;
|
|
|
|
//Verify that CLSID returned is identical to the Provider CLSID
|
|
CHECK(pIPersist->GetClassID(&clsid), S_OK);
|
|
|
|
SAFE_RELEASE(pIPersist);
|
|
|
|
return (clsid == GetModInfo()->GetThisTestModule()->m_ProviderClsid) ? TEST_PASS : TEST_FAIL;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(16)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IPersistFile::GetClassID
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_16()
|
|
{
|
|
CLSID clsid;
|
|
|
|
//Return if this interface is not supported
|
|
if(m_pIPersistFile == NULL)
|
|
return TEST_SKIPPED;
|
|
|
|
//Verify that CLSID returned is identical to the Provider CLSID
|
|
CHECK(m_pIPersistFile->GetClassID(&clsid), S_OK);
|
|
|
|
return (clsid == GetModInfo()->GetThisTestModule()->m_ProviderClsid) ? TEST_PASS : TEST_FAIL;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(17)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IPersistFile::IsDirty
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_17()
|
|
{
|
|
if(m_pIPersistFile == NULL)
|
|
return TEST_SKIPPED;
|
|
|
|
//We haven't called Save yet, so we should be in a dirty state.
|
|
//S_FALSE is only returned when the object had been saved and has
|
|
//maintained the same state since.
|
|
CHECK(m_hr = m_pIPersistFile->IsDirty(),S_OK);
|
|
|
|
return (m_hr == S_OK) ? TEST_PASS : TEST_FAIL;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(18)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IPersistFile::Save
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_18()
|
|
{
|
|
if(m_pIPersistFile == NULL)
|
|
return TEST_SKIPPED;
|
|
|
|
//Test if the save to file succeeds.
|
|
m_hr = PersistToFile();
|
|
|
|
if (m_hr ==S_OK)
|
|
{
|
|
//If SAVE was successful, then the IsDirty should be FALSE.
|
|
CHECK(m_pIPersistFile->IsDirty(),S_FALSE);
|
|
return TEST_PASS;
|
|
}
|
|
else if (m_hr == E_NOTIMPL)
|
|
{
|
|
COMPARE((GetModInfo()->UseServiceComponents() & SERVICECOMP_INVOKE), SERVICECOMP_INVOKE);
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
return TEST_FAIL;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(19)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IPersistFile::SaveCompleted
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_19()
|
|
{
|
|
BOOL fResults = FALSE;
|
|
|
|
if(m_pIPersistFile == NULL)
|
|
return TEST_SKIPPED;
|
|
|
|
//Do the save
|
|
m_hr = PersistToFile();
|
|
|
|
if (m_hr == S_OK)
|
|
{
|
|
//Save completed should now return S_OK
|
|
if (CHECK(m_pIPersistFile->SaveCompleted(m_wszFile),S_OK))
|
|
fResults = TRUE;
|
|
return (fResults) ? TEST_PASS : TEST_FAIL;
|
|
}
|
|
else if (m_hr == E_NOTIMPL)
|
|
{
|
|
COMPARE((GetModInfo()->UseServiceComponents() & SERVICECOMP_INVOKE), SERVICECOMP_INVOKE);
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
return TEST_FAIL;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(20)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IPersistFile::Load
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_20()
|
|
{
|
|
BOOL fResults = FALSE;
|
|
|
|
if(m_pIPersistFile == NULL)
|
|
return TEST_SKIPPED;
|
|
|
|
//Do the save
|
|
m_hr = PersistToFile();
|
|
|
|
if (m_hr == S_OK)
|
|
{
|
|
//We must release the current session for uninitialize to work
|
|
if(m_pIOpenRowset != NULL || m_pIDBCreateCommand != NULL)
|
|
ReleaseDBSession();
|
|
|
|
//Uninitialize.
|
|
if (CHECK(UninitializeDSO(), S_OK))
|
|
{
|
|
//Now Load should succeed
|
|
if (CHECK(m_pIPersistFile->Load((LPOLESTR)m_wszFile,
|
|
STGM_READWRITE),S_OK))
|
|
{
|
|
// Initialize the Provider with Loaded Properties
|
|
if (CHECK(InitializeDSO(), S_OK))
|
|
fResults = TRUE;
|
|
}
|
|
}
|
|
return (fResults) ? TEST_PASS : TEST_FAIL;
|
|
}
|
|
else if (m_hr == E_NOTIMPL)
|
|
{
|
|
COMPARE((GetModInfo()->UseServiceComponents() & SERVICECOMP_INVOKE), SERVICECOMP_INVOKE);
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
return TEST_FAIL;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(21)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IPersistFile::GetCurFile
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCDataSource::Variation_21()
|
|
{
|
|
LPOLESTR pwszCurFile = NULL;
|
|
BOOL fResults = FALSE;
|
|
|
|
if(m_pIPersistFile == NULL)
|
|
return TEST_SKIPPED;
|
|
|
|
//Do the save
|
|
m_hr = PersistToFile();
|
|
|
|
if (m_hr == S_OK)
|
|
{
|
|
if(!CHECK(m_pIPersistFile->GetCurFile(&pwszCurFile),S_OK))
|
|
return TEST_FAIL;
|
|
|
|
//If any of these is NULL, fail test.
|
|
if(pwszCurFile && m_wszFile)
|
|
{
|
|
//Returns 0 when identical
|
|
fResults = COMPARE(wcscmp(pwszCurFile,m_wszFile),0);
|
|
}
|
|
|
|
PROVIDER_FREE(pwszCurFile);
|
|
return (fResults) ? TEST_PASS : TEST_FAIL;
|
|
}
|
|
else if (m_hr == E_NOTIMPL)
|
|
{
|
|
COMPARE((GetModInfo()->UseServiceComponents() & SERVICECOMP_INVOKE), SERVICECOMP_INVOKE);
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
return TEST_FAIL;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//----------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL TCDataSource::Terminate()
|
|
{
|
|
CHAR* pszFile = NULL;
|
|
|
|
//Delete file we used for persistence
|
|
if (m_wszFile[0] != L'\0')
|
|
{
|
|
pszFile = ConvertToMBCS(m_wszFile);
|
|
remove(pszFile);
|
|
}
|
|
|
|
PROVIDER_FREE(pszFile);
|
|
|
|
FreeProperties(&m_cPropInfoSets, &m_rgPropInfoSets);
|
|
FreeProperties(&m_cPropIDSets, &m_rgPropIDSets);
|
|
SAFE_RELEASE(m_pIPersistFile);
|
|
SAFE_RELEASE(m_pIDBProperties);
|
|
ReleaseDBSession();
|
|
ReleaseDataSourceObject();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(CQuickTest::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(TCSession)
|
|
//*---------------------------------------------------------------------
|
|
//| Test Case: TCSession - Session Interfaces
|
|
//| Created: 3/18/98
|
|
//*---------------------------------------------------------------------
|
|
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL TCSession::Init()
|
|
{
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
if(CQuickTest::Init())
|
|
// }}
|
|
{
|
|
if(CHECK(m_hr = CreateDBSession(),S_OK))
|
|
{
|
|
CTable* pTable = NULL;
|
|
|
|
//Required for using some ExtraLib functions.
|
|
g_pIDBInitialize = m_pIDBInitialize;
|
|
g_pIOpenRowset = m_pIOpenRowset;
|
|
|
|
//Create a table with MIN_ROWS rows.
|
|
if(CreateTable(&pTable, MIN_ROWS))
|
|
{
|
|
SetTable(pTable, DELETETABLE_NO);
|
|
if(m_pTable)
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IGetDataSource
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_1()
|
|
{
|
|
return testGetDataSource() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IOpenRowset
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_2()
|
|
{
|
|
return testOpenRowset() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc ISessionProperties::GetProperties
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_3()
|
|
{
|
|
return testSessGetProp() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc ISessionProperties::SetProperties
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_4()
|
|
{
|
|
return testSessSetProp() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IDBCreateCommand
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_5()
|
|
{
|
|
if(!m_pIDBCreateCommand)
|
|
{
|
|
odtLog<<L"Commands are not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
return testCreateCommand() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(6)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IDBSchemaRowset::GetSchemas
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_6()
|
|
{
|
|
return testGetSchemas() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(7)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IDBSchemaRowset::GetRowset(DBSCHEMA_COLUMNS)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_7()
|
|
{
|
|
return testColumnsSchemaRowset() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(8)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IDBSchemaRowset::GetRowset(DBSCHEMA_TABLES)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_8()
|
|
{
|
|
return testTablesSchemaRowset() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(9)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IDBSchemaRowset::GetRowset(DBSCHEMA_PROVIDER_TYPES)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_9()
|
|
{
|
|
return testProvTypesSchemaRowset() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(10)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc ITableDefinition::AddColumn
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_10()
|
|
{
|
|
return testAddColumn() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(11)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc ITableDefinition::CreateTable
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_11()
|
|
{
|
|
return testCreateTable() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(12)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc ITableDefinition::DropColumn
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_12()
|
|
{
|
|
return testDropColumn() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(13)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc ITableDefinition::DropTable
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_13()
|
|
{
|
|
return testDropTable() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(14)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IIndexDefinition
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_14()
|
|
{
|
|
return testIIndexDef() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(15)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IAlterIndex
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_15()
|
|
{
|
|
return testAlterIndex() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(16)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IAlterTable::AlterColumn
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_16()
|
|
{
|
|
return testAlterColumn() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(17)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IAlterTable::AlterTable
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_17()
|
|
{
|
|
return testAlterTable() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(18)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc ITableDefinitionWithConstraints - AddConstraint & DropConstraint
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_18()
|
|
{
|
|
return testAddAndDropConstraint() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(19)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc ITableDefinitionWithConstraints::CreateTableWithConstraints
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_19()
|
|
{
|
|
return testCreateTableWithConstraints() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(20)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc AggregateSession
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCSession::Variation_20()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
IDBInitialize* pIDBI = NULL;
|
|
IDBCreateSession* pIDBCreateSession = NULL;
|
|
|
|
TESTC_(CreateNewDSO(NULL, IID_IDBInitialize, (IUnknown**)
|
|
&pIDBI), S_OK)
|
|
|
|
TESTC(VerifyInterface(pIDBI,IID_IDBCreateSession,
|
|
DATASOURCE_INTERFACE,(IUnknown**)&pIDBCreateSession))
|
|
|
|
tTestResult = testAggregateSession(pIDBCreateSession);
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIDBCreateSession);
|
|
SAFE_RELEASE(pIDBI);
|
|
return tTestResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL TCSession::Terminate()
|
|
{
|
|
if(m_pTable)
|
|
m_pTable->DropTable();
|
|
SAFE_DELETE(m_pTable);
|
|
ReleaseDBSession();
|
|
ReleaseDataSourceObject();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(CQuickTest::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(TCRowsetNotUpdateable)
|
|
//*---------------------------------------------------------------------
|
|
//| Test Case: TCRowsetNotUpdateable - Rowset Interfaces (Non-Updateable Rowset)
|
|
//| Created: 3/24/98
|
|
//*---------------------------------------------------------------------
|
|
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL TCRowsetNotUpdateable::Init()
|
|
{
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
if(CQuickTest::Init())
|
|
// }}
|
|
{
|
|
if(CHECK(m_hr = CreateDBSession(),S_OK))
|
|
{
|
|
CTable* pTable = NULL;
|
|
|
|
//Required for using some ExtraLib functions without using
|
|
//the ExtraLib classes.
|
|
g_pIDBInitialize = m_pIDBInitialize;
|
|
g_pIOpenRowset = m_pIOpenRowset;
|
|
|
|
//Create a table with MIN_ROWS rows.
|
|
if(CreateTable(&pTable, MIN_ROWS))
|
|
{
|
|
SetTable(pTable, DELETETABLE_NO);
|
|
|
|
//Set the following properties.
|
|
SetProperty(DBPROP_IRowsetScroll,
|
|
DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets,
|
|
(void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
SetProperty(DBPROP_IRowsetFind,
|
|
DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets,
|
|
(void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
SetProperty(DBPROP_IColumnsRowset,
|
|
DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets,
|
|
(void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
SetProperty(DBPROP_ORDEREDBOOKMARKS,
|
|
DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets,
|
|
(void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
SetProperty(DBPROP_CANSCROLLBACKWARDS,
|
|
DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets,
|
|
(void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
SetProperty(DBPROP_IRowsetLocate,
|
|
DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets,
|
|
(void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
SetProperty(DBPROP_BOOKMARKS,
|
|
DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets,
|
|
(void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
SetProperty(DBPROP_IRowsetIdentity,
|
|
DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ;
|
|
SetProperty(DBPROP_CANHOLDROWS,
|
|
DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ;
|
|
|
|
//Open a rowset with above properties set.
|
|
m_hr=CreateOpenRowset(m_pTable, IID_IRowset,
|
|
(IUnknown**)&m_pIRowset);
|
|
|
|
if(FAILED(m_hr))
|
|
DumpPropertyErrors(m_cPropSets, m_rgPropSets);
|
|
|
|
if(m_hr==S_OK || m_hr==DB_S_ERRORSOCCURRED)
|
|
{
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets) ;
|
|
|
|
VARIANT vVar;
|
|
VariantInit(&vVar);
|
|
|
|
//Get the values of following properties.
|
|
if(GetProperty(DBPROP_MAXOPENROWS, DBPROPSET_ROWSET,
|
|
m_pIRowset, &vVar))
|
|
m_ulMaxOpenRows = V_I4(&vVar);
|
|
else
|
|
m_ulMaxOpenRows = 0;
|
|
|
|
VariantClear(&vVar);
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IConvertType
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_1()
|
|
{
|
|
return testIConvertType() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IColumnsInfo::GetColumnInfo
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_2()
|
|
{
|
|
return testGetColumnInfo((IUnknown*)m_pIRowset) ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IColumnsInfo::MapColumnIDs
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_3()
|
|
{
|
|
return testMapColumnIDs((IUnknown*)m_pIRowset) ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IAccessor
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_4()
|
|
{
|
|
return testIAccessor() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IRowsetInfo::GetProperties
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_5()
|
|
{
|
|
return testRowsetGetProp((IUnknown*)m_pIRowset) ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(6)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IRowsetInfo::GetReferencedRowset
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_6()
|
|
{
|
|
return testIRowsetInfoGetRefRowset() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(7)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IRowsetInfo::GetSpecification (Session)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_7()
|
|
{
|
|
return testIRowsetInfoGetSpec() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(8)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRowsetInfo::GetSpecification (Command)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_8()
|
|
{
|
|
return testIRowsetInfoGetSpecCmd() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(9)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IRowset (No Properties)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_9()
|
|
{
|
|
return testIRowset2() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(10)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IRowset (Scroll_Back & Canholdrows)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_10()
|
|
{
|
|
BOOL fPropSup = TRUE;
|
|
|
|
if(!GetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET,
|
|
(IUnknown*)m_pIRowset))
|
|
{
|
|
odtLog<<L"CANHOLDROWS (level-0 prop) is not supported.\n";
|
|
return TEST_FAIL;
|
|
}
|
|
|
|
if(!GetProperty(DBPROP_CANSCROLLBACKWARDS, DBPROPSET_ROWSET,
|
|
(IUnknown*)m_pIRowset))
|
|
fPropSup = FALSE;
|
|
|
|
if(!fPropSup)
|
|
{
|
|
odtLog<<L"CANSCROLLBACKWARDS is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
return testIRowset3() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(11)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IColumnsRowset::GetAvailableColumns
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_11()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBORDINAL cOptCols = 0;
|
|
DBID* rgOptCols = NULL;
|
|
|
|
hr=GetAvailableColumns((IUnknown*)m_pIRowset, &cOptCols,
|
|
&rgOptCols) ;
|
|
|
|
if(hr==E_NOINTERFACE)
|
|
return TEST_SKIPPED;
|
|
else
|
|
TESTC_(hr, S_OK)
|
|
|
|
TESTC(CheckOptColumns(cOptCols, rgOptCols))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(rgOptCols);
|
|
return tTestResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(12)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IColumnsRowset::GetColumnsRowset
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_12()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
BOOL bBookmark = FALSE;
|
|
DBORDINAL cOptCols = 0;
|
|
DBID* rgOptCols = NULL;
|
|
IColumnsRowset* pIColumnsRowset = NULL;
|
|
IRowset* pIRowset = NULL;
|
|
|
|
if(GetProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET,
|
|
(IUnknown*)m_pIRowset))
|
|
bBookmark = TRUE;
|
|
|
|
if(!VerifyInterface(m_pIRowset,IID_IColumnsRowset,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIColumnsRowset))
|
|
{
|
|
odtLog<<L"IColumnsRowset is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
TESTC(pIColumnsRowset != NULL)
|
|
|
|
TESTC_(hr=GetAvailableColumns((IUnknown*)m_pIRowset, &cOptCols,
|
|
&rgOptCols), S_OK)
|
|
|
|
TESTC_(pIColumnsRowset->GetColumnsRowset(NULL, cOptCols, rgOptCols,
|
|
IID_IRowset, 0, NULL, (IUnknown**)&pIRowset), S_OK)
|
|
|
|
TESTC(CheckColumnsRowset((IUnknown*) pIRowset, cOptCols, bBookmark))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(rgOptCols);
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIColumnsRowset);
|
|
return tTestResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(13)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRowsetLocate::Compare
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_13()
|
|
{
|
|
//Check if the provider supports IRowsetLocate interface.
|
|
if(!GetProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET,
|
|
(IUnknown*)m_pIRowset))
|
|
{
|
|
odtLog<<L"IRowsetLocate is not supported\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
return testIRowsetLocateCompare();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(14)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRowsetLocate::GetRowsAt
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_14()
|
|
{
|
|
//Check if the provider supports IRowsetLocate interface.
|
|
if(!GetProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET,
|
|
(IUnknown*)m_pIRowset))
|
|
{
|
|
odtLog<<L"IRowsetLocate is not supported\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
return testIRowsetLocateGetRowsAt();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(15)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRowsetLocate::GetRowsByBookmark
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_15()
|
|
{
|
|
//Check if the provider supports IRowsetLocate interface.
|
|
if(!GetProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET,
|
|
(IUnknown*)m_pIRowset))
|
|
{
|
|
odtLog<<L"IRowsetLocate is not supported\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
return testIRowsetLocateGetRowsByBkm();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(16)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRowsetLocate::Hash
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_16()
|
|
{
|
|
//Check if the provider supports IRowsetLocate interface.
|
|
if(!GetProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET,
|
|
(IUnknown*)m_pIRowset))
|
|
{
|
|
odtLog<<L"IRowsetLocate is not supported\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
return testIRowsetLocateHash();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(17)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRowsetFind
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_17()
|
|
{
|
|
//Check if the provider supports IRowsetLocate interface.
|
|
if(!GetProperty(DBPROP_IRowsetFind, DBPROPSET_ROWSET,
|
|
(IUnknown*)m_pIRowset))
|
|
{
|
|
odtLog<<L"IRowsetFind is not supported\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
return testFindNextRow();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(18)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRowsetScroll::GetApproximatePosition
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_18()
|
|
{
|
|
//Check if the provider supports IRowsetScroll interface.
|
|
if(!GetProperty(DBPROP_IRowsetScroll, DBPROPSET_ROWSET,
|
|
(IUnknown*)m_pIRowset))
|
|
{
|
|
odtLog<<L"IRowsetScroll is not supported\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
return testGetApproxPos();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(19)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRowsetScroll::GetRowsAtRatio
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_19()
|
|
{
|
|
//Check if the provider supports IRowsetScroll interface.
|
|
if(!GetProperty(DBPROP_IRowsetScroll, DBPROPSET_ROWSET,
|
|
(IUnknown*)m_pIRowset))
|
|
{
|
|
odtLog<<L"IRowsetScroll is not supported\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
return testGetRowsAtRatio();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(20)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRowPosition
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_20()
|
|
{
|
|
return testIRowPosition();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(21)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc AggregateRowset
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetNotUpdateable::Variation_21()
|
|
{
|
|
return testAggregateRowset();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL TCRowsetNotUpdateable::Terminate()
|
|
{
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
SAFE_RELEASE(m_pIRowset);
|
|
if(m_pTable)
|
|
m_pTable->DropTable();
|
|
SAFE_DELETE(m_pTable);
|
|
ReleaseDBSession();
|
|
ReleaseDataSourceObject();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(CQuickTest::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(TCRowsetUpdateable)
|
|
//*---------------------------------------------------------------------
|
|
//| Test Case: TCRowsetUpdateable - Rowset Interfaces (Updateable Rowset)
|
|
//| Created: 4/1/98
|
|
//*---------------------------------------------------------------------
|
|
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL TCRowsetUpdateable::Init()
|
|
{
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
if(CQuickTest::Init())
|
|
// }}
|
|
{
|
|
if(CHECK(m_hr = CreateDBSession(),S_OK))
|
|
{
|
|
CTable* pTable = NULL;
|
|
|
|
//Required for using some ExtraLib functions without using
|
|
//the ExtraLib classes.
|
|
g_pIDBInitialize = m_pIDBInitialize;
|
|
g_pIOpenRowset = m_pIOpenRowset;
|
|
|
|
//Create table with MIN_ROWS rows.
|
|
if(CreateTable(&pTable, MIN_ROWS))
|
|
{
|
|
SetTable(pTable, DELETETABLE_NO);
|
|
|
|
LONG ulUpdateFlags = DBPROPVAL_UP_CHANGE|
|
|
DBPROPVAL_UP_DELETE|
|
|
DBPROPVAL_UP_INSERT ;
|
|
|
|
//Set the following properties.
|
|
SetProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets,
|
|
(void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets,
|
|
(void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetProperty(DBPROP_IRowsetIdentity, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets,
|
|
(void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetSettableProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets) ;
|
|
|
|
SetProperty(DBPROP_CANFETCHBACKWARDS,DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets,
|
|
(void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET,
|
|
&m_cPropSets, &m_rgPropSets,
|
|
(void*)(LONG_PTR)ulUpdateFlags, DBTYPE_I4, //cast modified
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetProperty(DBPROP_CANHOLDROWS,
|
|
DBPROPSET_ROWSET, &m_cPropSets, &m_rgPropSets) ;
|
|
|
|
//Open a rowset with above properties set.
|
|
m_hr=CreateOpenRowset(m_pTable, IID_IRowset,
|
|
(IUnknown**)&m_pIRowset);
|
|
|
|
if(FAILED(m_hr))
|
|
DumpPropertyErrors(m_cPropSets, m_rgPropSets);
|
|
|
|
if(m_hr==S_OK || m_hr==DB_S_ERRORSOCCURRED)
|
|
{
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
|
|
//ExtraLib global.
|
|
g_ulNextRow = m_pTable->CountRowsOnTable() + 10;
|
|
|
|
//Get the values of following properties.
|
|
if(!GetProperty(DBPROP_MAXOPENROWS, DBPROPSET_ROWSET,
|
|
m_pIRowset, &m_ulMaxOpenRows))
|
|
m_ulMaxOpenRows = 0;
|
|
|
|
if(GetProperty(DBPROP_CANFETCHBACKWARDS,
|
|
DBPROPSET_ROWSET, m_pIRowset))
|
|
m_fFetchBackwards = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IRowsetIdentity
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetUpdateable::Variation_1()
|
|
{
|
|
return testIRowsetIdentity() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IRowset (various properties set)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetUpdateable::Variation_2()
|
|
{
|
|
return testIRowset() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IRowsetChange::SetData
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetUpdateable::Variation_3()
|
|
{
|
|
//Check if the provider supports IRowsetChange interface.
|
|
if(GetProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET,
|
|
(IUnknown*)m_pIRowset))
|
|
return testIRowsetChangeSet() ;
|
|
|
|
odtLog<<L"IRowsetChange is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRowsetChange::DeleteRows
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetUpdateable::Variation_4()
|
|
{
|
|
//Check if the provider supports IRowsetChange interface.
|
|
if(GetProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET,
|
|
(IUnknown*)m_pIRowset))
|
|
return testIRowsetChangeDelete() ;
|
|
|
|
odtLog<<L"IRowsetChange is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRowsetChange::InsertRow
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetUpdateable::Variation_5()
|
|
{
|
|
//Check if the provider supports IRowsetChange interface.
|
|
if(GetProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET,
|
|
(IUnknown*)m_pIRowset))
|
|
return testIRowsetChangeInsert() ;
|
|
|
|
odtLog<<L"IRowsetChange is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(6)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRowsetUpdate
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetUpdateable::Variation_6()
|
|
{
|
|
return testIRowsetUpdate();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(7)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRowsetResynch
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetUpdateable::Variation_7()
|
|
{
|
|
return testIRowsetResynch();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(8)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRowsetRefresh
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRowsetUpdateable::Variation_8()
|
|
{
|
|
return testIRowsetRefresh();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL TCRowsetUpdateable::Terminate()
|
|
{
|
|
BOOL bUseInsertWithParams = FALSE;
|
|
ICommandWithParameters* pICommandWithParameters=NULL;
|
|
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
SAFE_RELEASE(m_pIRowset);
|
|
DBCOUNTITEM ulRows = 0;
|
|
|
|
//Determine if we are going to use insert with literals
|
|
//or insert with parameters.
|
|
if((!GetModInfo()->IsUsingITableDefinition() ||
|
|
(GetModInfo()->IsUsingITableDefinition() && !SupportedProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET, m_pIDBInitialize,ROWSET_INTERFACE)) ||
|
|
GetModInfo()->GetInsert()==INSERT_WITHPARAMS) &&
|
|
GetModInfo()->GetInsert()!=INSERT_COMMAND &&
|
|
m_pIDBCreateCommand &&
|
|
(m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommandWithParameters,(IUnknown**)&pICommandWithParameters)==S_OK))
|
|
bUseInsertWithParams = TRUE;
|
|
|
|
SAFE_RELEASE(pICommandWithParameters);
|
|
|
|
//Cleanup and refresh the table. Delete all the rows and
|
|
//insert original rows again, hence restoring table to
|
|
//a fresh state.
|
|
if(m_pTable)
|
|
{
|
|
ulRows = m_pTable->GetRowsOnCTable();
|
|
m_hr = m_pTable->DeleteRows(ALLROWS);
|
|
if(m_hr == S_OK)
|
|
for(DBCOUNTITEM i=0; i<ulRows; i++)
|
|
{
|
|
if(bUseInsertWithParams)
|
|
CHECK(m_pTable->InsertWithParams(i+1, PRIMARY), S_OK);
|
|
else
|
|
CHECK(m_pTable->Insert(i+1, PRIMARY), S_OK);
|
|
}
|
|
m_pTable->DropTable();
|
|
}
|
|
SAFE_DELETE(m_pTable);
|
|
ReleaseDBSession();
|
|
ReleaseDataSourceObject();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(CQuickTest::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(TCCommand)
|
|
//*---------------------------------------------------------------------
|
|
//| Test Case: TCCommand - Command Interfaces
|
|
//| Created: 4/13/98
|
|
//*---------------------------------------------------------------------
|
|
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL TCCommand::Init()
|
|
{
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
if(CQuickTest::Init())
|
|
// }}
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IDBCreateCommand* pIDBCreateCommand = NULL;
|
|
|
|
// Get DB Session
|
|
if(CHECK(hr = CreateDBSession(), S_OK))
|
|
{
|
|
if(m_pIDBCreateCommand)
|
|
{
|
|
if(CHECK(hr = m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand,(IUnknown **)&m_pICommand),S_OK))
|
|
{
|
|
// Make sure DB Session returned is correct
|
|
COMPARE(SUCCEEDED(hr=m_pICommand->GetDBSession(IID_IDBCreateCommand, (IUnknown **)&pIDBCreateCommand)),TRUE);
|
|
if(hr==S_OK)
|
|
COMPARE(VerifyEqualInterface(m_pIDBCreateCommand, pIDBCreateCommand), TRUE);
|
|
SAFE_RELEASE(pIDBCreateCommand);
|
|
|
|
//For ExtraLib functions.
|
|
g_pIDBInitialize = m_pIDBInitialize;
|
|
g_pIOpenRowset = m_pIOpenRowset;
|
|
|
|
CTable* pTable = NULL;
|
|
|
|
//Create table with MIN_ROWS rows.
|
|
if(CreateTable(&pTable, MIN_ROWS))
|
|
{
|
|
GetProperty(DBPROP_SQLSUPPORT, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &m_ulSQLSup);
|
|
|
|
SetTable(pTable, DELETETABLE_NO);
|
|
if(!m_pTable)
|
|
return FALSE;
|
|
|
|
//Create SQL stmt and set command text.
|
|
if(!CHECK(m_pTable->ExecuteCommand(SELECT_ALLFROMTBL,
|
|
IID_ICommand, NULL, NULL, NULL, NULL,
|
|
EXECUTE_NEVER, 0, NULL, NULL, NULL,
|
|
&m_pICommand), S_OK))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
odtLog<<L"INFO: Failure in CreateTable(...).\n";
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
COMPARE(m_pIDBInitialize != NULL, TRUE);
|
|
COMPARE(m_pIOpenRowset != NULL, TRUE);
|
|
odtLog<<L"WARNING: Commands not supported. SKIP all variations\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IAccessor
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCommand::Variation_1()
|
|
{
|
|
return testCmdIAccessor() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IColumnsInfo::GetColumnInfo
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCommand::Variation_2()
|
|
{
|
|
ICommandPrepare* pICommandPrepare = NULL;
|
|
|
|
if(VerifyInterface(m_pICommand,IID_ICommandPrepare,
|
|
COMMAND_INTERFACE,(IUnknown**)&pICommandPrepare))
|
|
{
|
|
if(!CHECK(pICommandPrepare->Prepare(1), S_OK))
|
|
{
|
|
SAFE_RELEASE(pICommandPrepare);
|
|
return TEST_FAIL;
|
|
}
|
|
SAFE_RELEASE(pICommandPrepare);
|
|
}
|
|
|
|
return testGetColumnInfo((IUnknown*)m_pICommand) ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IColumnsInfo::MapColumnIDs
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCommand::Variation_3()
|
|
{
|
|
ICommandPrepare* pICommandPrepare = NULL;
|
|
|
|
if(VerifyInterface(m_pICommand,IID_ICommandPrepare,
|
|
COMMAND_INTERFACE,(IUnknown**)&pICommandPrepare))
|
|
{
|
|
if(!CHECK(pICommandPrepare->Prepare(1), S_OK))
|
|
{
|
|
SAFE_RELEASE(pICommandPrepare);
|
|
return TEST_FAIL;
|
|
}
|
|
SAFE_RELEASE(pICommandPrepare);
|
|
}
|
|
|
|
return testMapColumnIDs((IUnknown*)m_pICommand) ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc ICommandProperties::GetProperties
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCommand::Variation_4()
|
|
{
|
|
return testRowsetGetProp((IUnknown*)m_pICommand) ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc ICommandProperties::SetProperties
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCommand::Variation_5()
|
|
{
|
|
return testSetCmdProp() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(6)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc IConvertType
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCommand::Variation_6()
|
|
{
|
|
return testIConvertType() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(7)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc ICommandText
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCommand::Variation_7()
|
|
{
|
|
return testICmdText() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(8)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc ICommand::GetDBSession
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCommand::Variation_8()
|
|
{
|
|
return testICmdGetDBSession() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(9)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc ICommand::Execute (set,exe,set,exe,set,exe)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCommand::Variation_9()
|
|
{
|
|
return testICmdExec1() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(10)
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc ICommand::Execute (set,exe,exe,exe)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCommand::Variation_10()
|
|
{
|
|
return testICmdExec2() ;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(11)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IColumnsRowset::GetAvailableColumns
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCommand::Variation_11()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
DBORDINAL cOptCols = 0;
|
|
DBID* rgOptCols = NULL;
|
|
ICommand* pICommand = NULL;
|
|
ICommandPrepare* pICommandPrepare = NULL;
|
|
|
|
//Create a command object.
|
|
TESTC_(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand,
|
|
(IUnknown**)&pICommand), S_OK)
|
|
|
|
//Set the command text to select all from table.
|
|
TESTC_(SetCommandText(m_pIMalloc, pICommand, m_pTable, NULL, eSELECT,
|
|
SELECT_ALLFROMTBL, NULL), S_OK)
|
|
|
|
//If ICommandPrepare is supported, prepare the command.
|
|
if(VerifyInterface(pICommand,IID_ICommandPrepare,
|
|
COMMAND_INTERFACE,(IUnknown**)&pICommandPrepare))
|
|
{
|
|
TESTC_(pICommandPrepare->Prepare(1), S_OK)
|
|
}
|
|
|
|
hr=GetAvailableColumns((IUnknown*)pICommand, &cOptCols,
|
|
&rgOptCols) ;
|
|
|
|
if(hr==E_NOINTERFACE)
|
|
{
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
else
|
|
TESTC_(hr, S_OK)
|
|
|
|
TESTC(CheckOptColumns(cOptCols, rgOptCols))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(rgOptCols);
|
|
SAFE_RELEASE(pICommandPrepare);
|
|
SAFE_RELEASE(pICommand);
|
|
return tTestResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(12)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IColumnsRowset::GetColumnsRowset
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCommand::Variation_12()
|
|
{
|
|
TESTRESULT tTestResult = TEST_FAIL;
|
|
HRESULT hr = S_OK;
|
|
BOOL bBookmark = FALSE;
|
|
DBORDINAL cOptCols = 0;
|
|
DBID* rgOptCols = NULL;
|
|
ICommand* pICommand = NULL;
|
|
ICommandPrepare* pICommandPrepare = NULL;
|
|
IColumnsRowset* pIColumnsRowset = NULL;
|
|
IRowset* pIRowset = NULL;
|
|
|
|
//Create a command object.
|
|
TESTC_(hr=m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand,
|
|
(IUnknown**)&pICommand), S_OK)
|
|
|
|
//Set the command text to select all from table.
|
|
TESTC_(SetCommandText(m_pIMalloc, pICommand, m_pTable, NULL, eSELECT,
|
|
SELECT_ALLFROMTBL, NULL), S_OK)
|
|
|
|
//If ICommandPrepare is supported, prepare the command.
|
|
if(VerifyInterface(pICommand,IID_ICommandPrepare,
|
|
COMMAND_INTERFACE,(IUnknown**)&pICommandPrepare))
|
|
{
|
|
TESTC_(pICommandPrepare->Prepare(1), S_OK)
|
|
}
|
|
|
|
if(!VerifyInterface(pICommand,IID_IColumnsRowset,
|
|
COMMAND_INTERFACE,(IUnknown**)&pIColumnsRowset))
|
|
{
|
|
odtLog<<L"IColumnsRowset is not supported.\n";
|
|
tTestResult = TEST_SKIPPED;
|
|
goto CLEANUP;
|
|
}
|
|
TESTC(pIColumnsRowset != NULL)
|
|
|
|
//Check for property DBPROP_BOOKMARKS on this command object.
|
|
if(GetProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET,
|
|
(IUnknown*)pICommand))
|
|
bBookmark = TRUE;
|
|
|
|
TESTC_(hr=GetAvailableColumns((IUnknown*)pICommand, &cOptCols,
|
|
&rgOptCols), S_OK)
|
|
|
|
TESTC_(pIColumnsRowset->GetColumnsRowset(NULL, cOptCols, rgOptCols,
|
|
IID_IRowset, 0, NULL, (IUnknown**)&pIRowset), S_OK)
|
|
|
|
TESTC(CheckColumnsRowset((IUnknown*) pIRowset, cOptCols, bBookmark))
|
|
|
|
tTestResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
PROVIDER_FREE(rgOptCols);
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIColumnsRowset);
|
|
SAFE_RELEASE(pICommandPrepare);
|
|
SAFE_RELEASE(pICommand);
|
|
return tTestResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(13)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc ICommandPrepare::Prepare
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCommand::Variation_13()
|
|
{
|
|
return testCmdPrep();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(14)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc ICommandPrepare::Unprepare
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCommand::Variation_14()
|
|
{
|
|
return testCmdUnprep();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(15)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc ICommandWithParameters
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCommand::Variation_15()
|
|
{
|
|
return testICmdWParam();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(16)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IMultipleResults
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCCommand::Variation_16()
|
|
{
|
|
VARIANT vVar;
|
|
VariantInit(&vVar);
|
|
|
|
if(!GetProperty(DBPROP_MULTIPLERESULTS, DBPROPSET_DATASOURCEINFO,
|
|
m_pIDBInitialize, &vVar))
|
|
{
|
|
odtLog<<L"Multiple Results are not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
if(!(V_I4(&vVar) & DBPROPVAL_MR_SUPPORTED))
|
|
{
|
|
odtLog<<L"Multiple Results Objects are not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
return testIMultipleResults();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*---------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL TCCommand::Terminate()
|
|
{
|
|
FreeProperties(&m_cPropSets, &m_rgPropSets);
|
|
SAFE_RELEASE(m_pICommand);
|
|
if(m_pTable)
|
|
m_pTable->DropTable();
|
|
SAFE_DELETE(m_pTable);
|
|
ReleaseDBSession();
|
|
ReleaseDataSourceObject();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(CQuickTest::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(TCOtherObjects)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: TCOtherObjects - Other Objects
|
|
//| Created: 6/8/98
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL TCOtherObjects::Init()
|
|
{
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
if(CQuickTest::Init())
|
|
// }}
|
|
{
|
|
if(CHECK(m_hr = CreateDBSession(), S_OK))
|
|
{
|
|
CTable* pTable = NULL;
|
|
|
|
g_pIDBInitialize = m_pIDBInitialize;
|
|
g_pIOpenRowset = m_pIOpenRowset;
|
|
|
|
//Create table with MIN_ROWS rows.
|
|
if(CreateTable(&pTable, MIN_ROWS))
|
|
{
|
|
SetTable(pTable, DELETETABLE_NO);
|
|
if(m_pTable)
|
|
{
|
|
g_ulNextRow = m_pTable->CountRowsOnTable() + 10;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc ErrorInterfaces
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCOtherObjects::Variation_1()
|
|
{
|
|
return testIError();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Transaction(Commit)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCOtherObjects::Variation_2()
|
|
{
|
|
return testTransactionCommit();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Transaction(Abort)
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCOtherObjects::Variation_3()
|
|
{
|
|
return testTransactionAbort();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc StorageInterface
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCOtherObjects::Variation_4()
|
|
{
|
|
return testStorageObj();
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL TCOtherObjects::Terminate()
|
|
{
|
|
if(m_pTable)
|
|
m_pTable->DropTable();
|
|
SAFE_DELETE(m_pTable);
|
|
ReleaseDBSession();
|
|
ReleaseDataSourceObject();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(CQuickTest::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(TCBinder)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: TCBinder - Binder Interfaces
|
|
//| Created: 9/22/98
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL TCBinder::Init()
|
|
{
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
if(CQuickTest::Init())
|
|
// }}
|
|
{
|
|
TBEGIN
|
|
BOOL bTest;
|
|
CTable* pTable = NULL;
|
|
IGetDataSource* pIGetDataSource = NULL;
|
|
|
|
//Get the root binder.
|
|
bTest = CreateRootBinder();
|
|
if(bTest != TEST_PASS)
|
|
return bTest;
|
|
|
|
TESTC(DefaultObjectTesting(m_pIBindResource, BINDER_INTERFACE))
|
|
|
|
//bind to a session.
|
|
TEST2C_(m_pIBindResource->Bind(NULL, m_pwszRowsetURL,
|
|
DBBINDURLFLAG_READ, DBGUID_SESSION, IID_IOpenRowset,
|
|
NULL, NULL, NULL, (IUnknown**)&m_pIOpenRowset), S_OK,
|
|
DB_S_ERRORSOCCURRED)
|
|
|
|
TESTC(VerifyInterface(m_pIOpenRowset,IID_IGetDataSource,
|
|
SESSION_INTERFACE,(IUnknown**)&pIGetDataSource))
|
|
|
|
//get a dso.
|
|
TESTC_(pIGetDataSource->GetDataSource(IID_IDBInitialize,
|
|
(IUnknown**)&m_pIDBInitialize), S_OK)
|
|
|
|
g_pIDBInitialize = m_pIDBInitialize;
|
|
g_pIOpenRowset = m_pIOpenRowset;
|
|
|
|
TESTC(CreateTable(&pTable, 5))
|
|
|
|
SetTable(pTable, DELETETABLE_NO);
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIGetDataSource);
|
|
TRETURN
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IBindResource
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCBinder::Variation_1()
|
|
{
|
|
TBEGIN
|
|
|
|
SAFE_RELEASE(m_pIRowset); //Should be NULL anyway.
|
|
|
|
//bind to a rowset.
|
|
TEST2C_(m_pIBindResource->Bind(NULL, m_pwszRowsetURL,
|
|
DBBINDURLFLAG_READ, DBGUID_ROWSET, IID_IRowset,
|
|
NULL, NULL, NULL, (IUnknown**)&m_pIRowset), S_OK,
|
|
DB_S_ERRORSOCCURRED)
|
|
TESTC(m_pIRowset != NULL)
|
|
|
|
TESTC(DefaultObjectTesting(m_pIRowset, ROWSET_INTERFACE))
|
|
|
|
//Get the values of following properties.
|
|
if(!GetProperty(DBPROP_MAXOPENROWS, DBPROPSET_ROWSET,
|
|
m_pIRowset, &m_ulMaxOpenRows))
|
|
m_ulMaxOpenRows = 0;
|
|
|
|
if(GetProperty(DBPROP_CANFETCHBACKWARDS, DBPROPSET_ROWSET,
|
|
m_pIRowset))
|
|
m_fFetchBackwards = TRUE;
|
|
|
|
TESTC(testIRowset())
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(m_pIRowset);
|
|
TRETURN
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc ICreateRow
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCBinder::Variation_2()
|
|
{
|
|
TBEGIN
|
|
HRESULT hr;
|
|
ULONG_PTR ulVal = 0;
|
|
WCHAR* pwszNewURL = NULL;
|
|
IRow* pIRow = NULL;
|
|
ICreateRow* pICreateRow = NULL;
|
|
|
|
TESTC(VerifyInterface(m_pIBindResource,IID_ICreateRow,
|
|
BINDER_INTERFACE,(IUnknown**)&pICreateRow))
|
|
|
|
hr=pICreateRow->CreateRow(NULL, m_pwszRowsetURL,
|
|
DBBINDURLFLAG_READWRITE|DBBINDURLFLAG_OPENIFEXISTS,
|
|
DBGUID_ROW, IID_IRow, NULL, NULL, NULL, &pwszNewURL,
|
|
(IUnknown**)&pIRow);
|
|
|
|
if(hr==S_OK || hr==DB_S_ERRORSOCCURRED)
|
|
{
|
|
TESTC(DefaultObjectTesting(pIRow, ROW_INTERFACE))
|
|
TESTC(testIRow(pIRow))
|
|
TESTC(pwszNewURL != NULL)
|
|
COMPARE(wcscmp(pwszNewURL, m_pwszRowsetURL), 0);
|
|
}
|
|
else if(hr==DB_E_RESOURCEEXISTS)
|
|
odtLog<<L"INFO: The provider does not support OPENIFEXISTS behaviour on ICreateRow.\n";
|
|
else if(hr==DB_E_NOTSUPPORTED)
|
|
odtLog<<L"INFO: The provider does not support ROW objects.\n";
|
|
else if(hr==E_NOINTERFACE)
|
|
odtLog<<L"INFO: ICreateRow is not supported.\n";
|
|
else
|
|
CHECK(hr, S_OK);
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(pwszNewURL);
|
|
SAFE_RELEASE(pIRow);
|
|
SAFE_RELEASE(pICreateRow);
|
|
TRETURN
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IDBBinderProperties - Set rowset props
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCBinder::Variation_3()
|
|
{
|
|
TBEGIN
|
|
HRESULT hr, hr2;
|
|
ULONG cPropSets = 0;
|
|
DBPROPSET* rgPropSets = NULL;
|
|
BSTR pbstrCC = L"QuikTest - DBPROP_CURRENTCATALOG";
|
|
IRowset* pIRowset = NULL;
|
|
IRowsetInfo* pIRInfo = NULL;
|
|
IGetDataSource* pIGDS = NULL;
|
|
IDBProperties* pIDBProp = NULL;
|
|
IRowsetIdentity* pIRIdentity = NULL;
|
|
IRowsetLocate* pIRLocate = NULL;
|
|
IDBBinderProperties* pIDBBProp = NULL;
|
|
|
|
VARIANT vVar;
|
|
VariantInit(&vVar);
|
|
|
|
TESTC(VerifyInterface(m_pIBindResource,IID_IDBBinderProperties,
|
|
BINDER_INTERFACE,(IUnknown**)&pIDBBProp))
|
|
|
|
//Reset binder props.
|
|
TESTC_(pIDBBProp->Reset(), S_OK)
|
|
|
|
//Set the init props on binder.
|
|
TESTC(GetInitProps(&cPropSets, &rgPropSets))
|
|
|
|
//set a bunch of datasource and rowset props on the root
|
|
//binder.
|
|
|
|
SetProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE,
|
|
&cPropSets, &rgPropSets, (void*)pbstrCC, DBTYPE_BSTR,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetProperty(DBPROP_MULTIPLECONNECTIONS, DBPROPSET_DATASOURCE,
|
|
&cPropSets, &rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET,
|
|
&cPropSets, &rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetProperty(DBPROP_CANFETCHBACKWARDS, DBPROPSET_ROWSET,
|
|
&cPropSets, &rgPropSets, (void*)VARIANT_TRUE, DBTYPE_BOOL,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetProperty(DBPROP_IRowsetIdentity, DBPROPSET_ROWSET,
|
|
&cPropSets, &rgPropSets) ;
|
|
|
|
SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &cPropSets,
|
|
&rgPropSets) ;
|
|
|
|
TESTC_(hr=pIDBBProp->SetProperties(cPropSets, rgPropSets), S_OK)
|
|
|
|
//bind to a rowset and verify props.
|
|
TEST3C_(hr = m_pIBindResource->Bind(NULL, m_pwszRowsetURL,
|
|
DBBINDURLFLAG_READ, DBGUID_ROWSET, IID_IRowset,
|
|
NULL, NULL, NULL, (IUnknown**)&pIRowset), S_OK,
|
|
DB_S_ERRORSOCCURRED, DB_E_ERRORSOCCURRED)
|
|
|
|
if(hr == DB_E_ERRORSOCCURRED)
|
|
{
|
|
odtLog<<L"WARNING: Bind returned DB_E_ERRORSOCCURRED. This could be because setting rowset props is not supported through the Binder.\n";
|
|
CHECKW(hr, S_OK);
|
|
goto CLEANUP;
|
|
}
|
|
|
|
TESTC(pIRowset != NULL)
|
|
|
|
TESTC(VerifyInterface(pIRowset,IID_IRowsetInfo,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRInfo))
|
|
|
|
//get the dso in order to verify the DATASOURCE props.
|
|
TEST2C_(hr2=pIRInfo->GetSpecification(IID_IGetDataSource, (IUnknown**)&pIGDS), S_OK, S_FALSE)
|
|
if(hr2 == S_OK)
|
|
TESTC_(pIGDS->GetDataSource(IID_IDBProperties, (IUnknown**)&pIDBProp), S_OK)
|
|
|
|
COMPARE(GetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET,
|
|
pIRowset), TRUE);
|
|
|
|
COMPARE(GetProperty(DBPROP_IRowsetIdentity, DBPROPSET_ROWSET,
|
|
pIRowset), TRUE);
|
|
|
|
COMPARE(VerifyInterface(pIRowset,IID_IRowsetIdentity,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRIdentity), TRUE);
|
|
|
|
if(S_OK == hr)
|
|
{
|
|
COMPARE(GetProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET,
|
|
pIRowset), TRUE);
|
|
COMPARE(VerifyInterface(pIRowset,IID_IRowsetLocate,
|
|
ROWSET_INTERFACE,(IUnknown**)&pIRLocate), TRUE);
|
|
COMPARE(GetProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET,
|
|
pIRowset), TRUE);
|
|
COMPARE(GetProperty(DBPROP_CANFETCHBACKWARDS, DBPROPSET_ROWSET,
|
|
pIRowset), TRUE);
|
|
|
|
if(pIDBProp)
|
|
{
|
|
COMPARE(GetProperty(DBPROP_MULTIPLECONNECTIONS, DBPROPSET_DATASOURCE,
|
|
pIDBProp), TRUE);
|
|
COMPARE(GetProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE,
|
|
pIDBProp, &vVar), TRUE);
|
|
COMPARE(wcscmp(V_BSTR(&vVar), pbstrCC), 0);
|
|
}
|
|
}
|
|
else // hr==DB_S_ERRORSOCCURRED
|
|
{
|
|
if(GetProperty(DBPROP_IRowsetLocate, DBPROPSET_ROWSET,
|
|
pIRowset))
|
|
COMPARE(GetProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET,
|
|
pIRowset), TRUE);
|
|
if(GetProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE,
|
|
pIDBProp, &vVar))
|
|
COMPARE(wcscmp(V_BSTR(&vVar), pbstrCC), 0);
|
|
}
|
|
|
|
CLEANUP:
|
|
VariantClear(&vVar);
|
|
FreeProperties(&cPropSets, &rgPropSets);
|
|
SAFE_RELEASE(pIRIdentity);
|
|
SAFE_RELEASE(pIRLocate);
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIRInfo);
|
|
SAFE_RELEASE(pIGDS);
|
|
SAFE_RELEASE(pIDBProp);
|
|
SAFE_RELEASE(pIDBBProp);
|
|
TRETURN
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IDBBinderProperties - Reset
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCBinder::Variation_4()
|
|
{
|
|
TBEGIN
|
|
HRESULT hr;
|
|
ULONG ulIndex; //small no.
|
|
ULONG_PTR ulMaxRows = 0;
|
|
ULONG_PTR ulUpdt = 0;
|
|
ULONG cPropSets = 0;
|
|
DBPROPSET* rgPropSets = NULL;
|
|
VARIANT vrgDefault[4];
|
|
IRowset* pIRowset = NULL;
|
|
IDBBinderProperties* pIDBBProp = NULL;
|
|
|
|
for(ulIndex=0; ulIndex<4; ulIndex++)
|
|
VariantInit(&vrgDefault[ulIndex]);
|
|
|
|
TESTC(VerifyInterface(m_pIBindResource,IID_IDBBinderProperties,
|
|
BINDER_INTERFACE,(IUnknown**)&pIDBBProp))
|
|
|
|
//
|
|
//STEP-1 : Obtain the default values of 4 rowset properties and
|
|
//store them in vrgDefault.
|
|
//
|
|
|
|
TESTC_(pIDBBProp->Reset(), S_OK)
|
|
|
|
TESTC(GetInitProps(&cPropSets, &rgPropSets))
|
|
|
|
TESTC_(hr=pIDBBProp->SetProperties(cPropSets, rgPropSets), S_OK)
|
|
|
|
TEST2C_(m_pIBindResource->Bind(NULL, m_pwszRowsetURL,
|
|
DBBINDURLFLAG_READ, DBGUID_ROWSET, IID_IRowset,
|
|
NULL, NULL, NULL, (IUnknown**)&pIRowset), S_OK,
|
|
DB_S_ERRORSOCCURRED)
|
|
TESTC(pIRowset != NULL)
|
|
|
|
TESTC(GetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET,
|
|
pIRowset, &vrgDefault[0]))
|
|
|
|
TESTC(GetProperty(DBPROP_IRowsetIdentity, DBPROPSET_ROWSET,
|
|
pIRowset, &vrgDefault[1]))
|
|
|
|
if(!GetProperty(DBPROP_MAXROWS, DBPROPSET_ROWSET,
|
|
pIRowset, &vrgDefault[2]))
|
|
VariantInit(&vrgDefault[2]);
|
|
|
|
if(!GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET,
|
|
pIRowset, &vrgDefault[3]))
|
|
VariantInit(&vrgDefault[3]);
|
|
|
|
SAFE_RELEASE(pIRowset);
|
|
|
|
//
|
|
//STEP-2 : Set the values of the 4 rowset properties. Then call
|
|
//Reset(). After calling Reset(), Bind to a Rowset.
|
|
//
|
|
|
|
SetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET, &cPropSets,
|
|
&rgPropSets) ;
|
|
|
|
SetProperty(DBPROP_IRowsetIdentity, DBPROPSET_ROWSET,
|
|
&cPropSets, &rgPropSets) ;
|
|
|
|
SetProperty(DBPROP_MAXROWS, DBPROPSET_ROWSET,
|
|
&cPropSets, &rgPropSets, (void*)25, DBTYPE_I4,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
SetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET,
|
|
&cPropSets, &rgPropSets, (void*)7, DBTYPE_I4,
|
|
DBPROPOPTIONS_OPTIONAL) ;
|
|
|
|
TEST2C_(hr=pIDBBProp->SetProperties(cPropSets, rgPropSets), S_OK,
|
|
DB_S_ERRORSOCCURRED)
|
|
|
|
TESTC_(pIDBBProp->Reset(), S_OK)
|
|
|
|
FreeProperties(&cPropSets, &rgPropSets);
|
|
|
|
TESTC(GetInitProps(&cPropSets, &rgPropSets))
|
|
|
|
TESTC_(hr=pIDBBProp->SetProperties(cPropSets, rgPropSets), S_OK)
|
|
|
|
TEST2C_(m_pIBindResource->Bind(NULL, m_pwszRowsetURL,
|
|
DBBINDURLFLAG_READ, DBGUID_ROWSET, IID_IRowset,
|
|
NULL, NULL, NULL, (IUnknown**)&pIRowset), S_OK,
|
|
DB_S_ERRORSOCCURRED)
|
|
TESTC(pIRowset != NULL)
|
|
|
|
//
|
|
//STEP-3 : Obtain the 4 rowset properties from the rowset. Verify
|
|
//that their values match the default ones stored in vrgDefault.
|
|
//
|
|
|
|
if(GetProperty(DBPROP_CANHOLDROWS, DBPROPSET_ROWSET,
|
|
pIRowset))
|
|
TESTC(V_BOOL(&vrgDefault[0]) == VARIANT_TRUE)
|
|
else
|
|
TESTC(V_BOOL(&vrgDefault[0]) == VARIANT_FALSE)
|
|
|
|
if(GetProperty(DBPROP_IRowsetIdentity, DBPROPSET_ROWSET,
|
|
pIRowset))
|
|
TESTC(V_BOOL(&vrgDefault[1]) == VARIANT_TRUE)
|
|
else
|
|
TESTC(V_BOOL(&vrgDefault[1]) == VARIANT_FALSE)
|
|
|
|
if(GetProperty(DBPROP_MAXROWS, DBPROPSET_ROWSET,
|
|
pIRowset, &ulMaxRows))
|
|
TESTC(((ULONG_PTR)V_I4(&vrgDefault[2])) == ulMaxRows)
|
|
else
|
|
TESTC(V_VT(&vrgDefault[2]) == VT_EMPTY)
|
|
|
|
if(GetProperty(DBPROP_UPDATABILITY, DBPROPSET_ROWSET,
|
|
pIRowset, &ulUpdt))
|
|
TESTC(((ULONG_PTR)V_I4(&vrgDefault[3])) == ulUpdt)
|
|
else
|
|
TESTC(V_VT(&vrgDefault[3]) == VT_EMPTY)
|
|
|
|
CLEANUP:
|
|
for(ulIndex=0; ulIndex<4; ulIndex++)
|
|
VariantClear(&vrgDefault[ulIndex]);
|
|
FreeProperties(&cPropSets, &rgPropSets);
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIDBBProp);
|
|
TRETURN
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL TCBinder::Terminate()
|
|
{
|
|
if(m_pTable)
|
|
m_pTable->DropTable();
|
|
SAFE_DELETE(m_pTable);
|
|
SAFE_RELEASE(m_pIOpenRowset);
|
|
SAFE_RELEASE(m_pIDBInitialize);
|
|
SAFE_RELEASE(m_pIBindResource);
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(CQuickTest::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(TCRow)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: TCRow - Row Interfaces
|
|
//| Created: 9/22/98
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL TCRow::Init()
|
|
{
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
if(CQuickTest::Init())
|
|
// }}
|
|
{
|
|
TBEGIN
|
|
ULONG_PTR ulOleObj = 0;
|
|
CTable* pTable = NULL;
|
|
|
|
TESTC_(m_hr = CreateDBSession(),S_OK)
|
|
|
|
//Required for using some ExtraLib functions.
|
|
g_pIDBInitialize = m_pIDBInitialize;
|
|
g_pIOpenRowset = m_pIOpenRowset;
|
|
|
|
//Check if provider supports ROW Objects. If not, then SKIP
|
|
//this test case.
|
|
TESTC_PROVIDER(GetProperty(DBPROP_OLEOBJECTS, DBPROPSET_DATASOURCEINFO,
|
|
m_pIDBInitialize, &ulOleObj))
|
|
TESTC_PROVIDER((ulOleObj & DBPROPVAL_OO_ROWOBJECT) ==
|
|
DBPROPVAL_OO_ROWOBJECT)
|
|
|
|
//Create a table with MIN_ROWS rows.
|
|
TESTC(CreateTable(&pTable, MIN_ROWS))
|
|
|
|
SetTable(pTable, DELETETABLE_NO);
|
|
TESTC(m_pTable != NULL)
|
|
|
|
//Create the parent Rowset of the row objects used for testing
|
|
//in the variations.
|
|
m_pCRowset = new CRowset();
|
|
m_pCRowset->SetProperty(DBPROP_CANHOLDROWS);
|
|
m_pCRowset->SetProperty(DBPROP_IRowsetIdentity);
|
|
m_pCRowset->SetSettableProperty(DBPROP_IRowsetLocate);
|
|
TESTC_(m_pCRowset->CreateRowset(USE_SUPPORTED_SELECT_ALLFROMTBL,
|
|
IID_IRowset, m_pTable),S_OK);
|
|
|
|
CLEANUP:
|
|
TRETURN
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRow
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRow::Variation_1()
|
|
{
|
|
TBEGIN
|
|
HRESULT hr;
|
|
DBCOUNTITEM ulIndex = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW hRow = DB_NULL_HROW;
|
|
HROW* rghRows = NULL;
|
|
IRowsetInfo* pIRowsetInfo = NULL;
|
|
IRowsetIdentity* pIRIdentity = NULL;
|
|
|
|
TESTC_(m_pCRowset->RestartPosition(),S_OK)
|
|
|
|
for(ulIndex=1; ulIndex<=m_pCRowset->m_ulTableRows; ulIndex++)
|
|
{
|
|
CRowObject RowObj;
|
|
|
|
//Get first row and create a row object on it.
|
|
TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK)
|
|
|
|
TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(),
|
|
rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS)
|
|
|
|
TESTC(DefaultObjectTesting(RowObj.pIRow(), ROW_INTERFACE))
|
|
|
|
//Veify the GetColumns method.
|
|
TESTC(RowObj.VerifyGetColumns(ulIndex, m_pTable))
|
|
|
|
//Call GetSourceRowset and verify that the correct parent
|
|
//is returned.
|
|
TEST2C_(hr = RowObj.GetSourceRowset(IID_IRowsetInfo, (IUnknown**)&pIRowsetInfo,
|
|
&hRow), S_OK, DB_E_NOSOURCEOBJECT)
|
|
|
|
if(S_OK == hr)
|
|
{
|
|
TESTC(hRow != DB_NULL_HROW)
|
|
TESTC(VerifyEqualInterface(pIRowsetInfo, m_pCRowset->pIRowset()))
|
|
|
|
TESTC(VerifyInterface(pIRowsetInfo, IID_IRowsetIdentity,
|
|
ROWSET_INTERFACE, (IUnknown**)&pIRIdentity))
|
|
|
|
TESTC_(pIRIdentity->IsSameRow(hRow, rghRows[0]), S_OK)
|
|
|
|
CHECK(m_pCRowset->ReleaseRows(1, &hRow),S_OK);
|
|
hRow = DB_NULL_HROW;
|
|
}
|
|
|
|
CHECK(m_pCRowset->ReleaseRows(cRowsObtained, rghRows),S_OK);
|
|
cRowsObtained = 0;
|
|
PROVIDER_FREE(rghRows);
|
|
SAFE_RELEASE(pIRIdentity);
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
}
|
|
|
|
CLEANUP:
|
|
m_pCRowset->ReleaseRows(cRowsObtained, rghRows);
|
|
PROVIDER_FREE(rghRows);
|
|
SAFE_RELEASE(pIRIdentity);
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
TRETURN
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IGetSession
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRow::Variation_2()
|
|
{
|
|
TBEGIN
|
|
DBCOUNTITEM ulIndex = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW* rghRows = NULL;
|
|
IOpenRowset* pIOR = NULL;
|
|
|
|
TESTC_(m_pCRowset->RestartPosition(),S_OK)
|
|
|
|
for(ulIndex=1; ulIndex<=m_pCRowset->m_ulTableRows; ulIndex++)
|
|
{
|
|
CRowObject RowObj;
|
|
|
|
TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK)
|
|
|
|
TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(),
|
|
rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS)
|
|
|
|
TESTC_(RowObj.GetSession(IID_IOpenRowset, (IUnknown**)&pIOR), S_OK)
|
|
|
|
TESTC(VerifyEqualInterface(pIOR, m_pIOpenRowset))
|
|
|
|
TESTC_(m_pCRowset->ReleaseRows(cRowsObtained, rghRows),S_OK)
|
|
cRowsObtained = 0;
|
|
PROVIDER_FREE(rghRows);
|
|
SAFE_RELEASE(pIOR);
|
|
}
|
|
|
|
CLEANUP:
|
|
m_pCRowset->ReleaseRows(cRowsObtained, rghRows);
|
|
PROVIDER_FREE(rghRows);
|
|
SAFE_RELEASE(pIOR);
|
|
TRETURN
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IConvertType
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRow::Variation_3()
|
|
{
|
|
TBEGIN
|
|
DBCOUNTITEM ulIndex = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW* rghRows = NULL;
|
|
|
|
//Make sure these are NULL, although hey should be.
|
|
SAFE_RELEASE(m_pICommand);
|
|
SAFE_RELEASE(m_pIRowset);
|
|
SAFE_RELEASE(m_pIRow);
|
|
|
|
TESTC_(m_pCRowset->RestartPosition(),S_OK)
|
|
|
|
for(ulIndex=1; ulIndex<=m_pCRowset->m_ulTableRows; ulIndex++)
|
|
{
|
|
CRowObject RowObj;
|
|
|
|
TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK)
|
|
|
|
TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(),
|
|
rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS)
|
|
|
|
m_pIRow = RowObj.pIRow();
|
|
TESTC(testIConvertType())
|
|
m_pIRow = NULL;
|
|
|
|
TESTC_(m_pCRowset->ReleaseRows(cRowsObtained, rghRows),S_OK)
|
|
cRowsObtained = 0;
|
|
PROVIDER_FREE(rghRows);
|
|
}
|
|
|
|
CLEANUP:
|
|
m_pIRow = NULL;
|
|
m_pCRowset->ReleaseRows(cRowsObtained, rghRows);
|
|
PROVIDER_FREE(rghRows);
|
|
TRETURN
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IColumnsInfo
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRow::Variation_4()
|
|
{
|
|
TBEGIN
|
|
DBCOUNTITEM ulIndex = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW* rghRows = NULL;
|
|
|
|
TESTC_(m_pCRowset->RestartPosition(),S_OK)
|
|
|
|
for(ulIndex=1; ulIndex<=m_pCRowset->m_ulTableRows; ulIndex++)
|
|
{
|
|
CRowObject RowObj;
|
|
|
|
TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK)
|
|
|
|
TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(),
|
|
rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS)
|
|
|
|
TESTC(testColInfo2(&RowObj))
|
|
|
|
TESTC_(m_pCRowset->ReleaseRows(cRowsObtained, rghRows),S_OK)
|
|
cRowsObtained = 0;
|
|
PROVIDER_FREE(rghRows);
|
|
}
|
|
|
|
CLEANUP:
|
|
m_pCRowset->ReleaseRows(cRowsObtained, rghRows);
|
|
PROVIDER_FREE(rghRows);
|
|
TRETURN
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IColumnsInfo2
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRow::Variation_5()
|
|
{
|
|
TBEGIN
|
|
DBCOUNTITEM ulIndex = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW* rghRows = NULL;
|
|
IColumnsInfo2* pICI2 = NULL;
|
|
|
|
TESTC_(m_pCRowset->RestartPosition(),S_OK)
|
|
|
|
for(ulIndex=1; ulIndex<=m_pCRowset->m_ulTableRows; ulIndex++)
|
|
{
|
|
CRowObject RowObj;
|
|
|
|
TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK)
|
|
|
|
TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(),
|
|
rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS)
|
|
|
|
if(ulIndex==1)
|
|
TESTC_PROVIDER(VerifyInterface(RowObj.pIRow(), IID_IColumnsInfo2,
|
|
ROW_INTERFACE, (IUnknown**)&pICI2))
|
|
else
|
|
TESTC(VerifyInterface(RowObj.pIRow(), IID_IColumnsInfo2,
|
|
ROW_INTERFACE, (IUnknown**)&pICI2))
|
|
|
|
TESTC(testColInfo2(&RowObj, TRUE))
|
|
|
|
TESTC_(m_pCRowset->ReleaseRows(cRowsObtained, rghRows),S_OK)
|
|
cRowsObtained = 0;
|
|
PROVIDER_FREE(rghRows);
|
|
SAFE_RELEASE(pICI2);
|
|
}
|
|
|
|
CLEANUP:
|
|
m_pCRowset->ReleaseRows(cRowsObtained, rghRows);
|
|
PROVIDER_FREE(rghRows);
|
|
SAFE_RELEASE(pICI2);
|
|
TRETURN
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(6)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IGetRow
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRow::Variation_6()
|
|
{
|
|
TBEGIN
|
|
DBCOUNTITEM ulIndex = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW* rghRows = NULL;
|
|
WCHAR* pwszURL = NULL;
|
|
IGetRow* pIGetRow = NULL;
|
|
|
|
TESTC_(m_pCRowset->RestartPosition(),S_OK)
|
|
|
|
TESTC(VerifyInterface(m_pCRowset->pIRowset(), IID_IGetRow,
|
|
ROWSET_INTERFACE, (IUnknown**)&pIGetRow))
|
|
|
|
for(ulIndex=1; ulIndex<=m_pCRowset->m_ulTableRows; ulIndex++)
|
|
{
|
|
CRowObject RowObj;
|
|
|
|
TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK)
|
|
|
|
//The following tests the GetRowFromHROW method.
|
|
|
|
TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(),
|
|
rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS)
|
|
|
|
TESTC(RowObj.VerifyGetColumns(ulIndex, m_pTable))
|
|
|
|
//Now test the GetURLFromHROW method.
|
|
|
|
TESTC_(pIGetRow->GetURLFromHROW(rghRows[0], &pwszURL), S_OK)
|
|
TESTC((pwszURL != NULL) && (wcslen(pwszURL)>2))
|
|
TESTC(wcsstr(pwszURL, L":") != NULL)
|
|
|
|
TESTC_(m_pCRowset->ReleaseRows(cRowsObtained, rghRows),S_OK)
|
|
cRowsObtained = 0;
|
|
PROVIDER_FREE(rghRows);
|
|
SAFE_FREE(pwszURL);
|
|
}
|
|
|
|
CLEANUP:
|
|
m_pCRowset->ReleaseRows(cRowsObtained, rghRows);
|
|
PROVIDER_FREE(rghRows);
|
|
SAFE_FREE(pwszURL);
|
|
SAFE_RELEASE(pIGetRow);
|
|
TRETURN
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(7)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IGetSourceRow
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRow::Variation_7()
|
|
{
|
|
TBEGIN
|
|
HRESULT hr;
|
|
DBCOUNTITEM ulIndex = 0;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW* rghRows = NULL;
|
|
DBID dbid = DBROWCOL_DEFAULTSTREAM;
|
|
IGetSession* pIGS = NULL;
|
|
IGetSourceRow* pIGetSourceRow = NULL;
|
|
|
|
TESTC_(m_pCRowset->RestartPosition(),S_OK)
|
|
|
|
for(ulIndex=1; ulIndex<=m_pCRowset->m_ulTableRows; ulIndex++)
|
|
{
|
|
CRowObject RowObj;
|
|
|
|
TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK)
|
|
|
|
TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(),
|
|
rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS)
|
|
|
|
TEST2C_(hr=RowObj.Open(NULL, &dbid, DBGUID_STREAM, IID_IGetSourceRow,
|
|
(IUnknown**)&pIGetSourceRow), S_OK, DB_E_BADCOLUMNID)
|
|
|
|
if(hr==S_OK)
|
|
{
|
|
TEST2C_(hr=pIGetSourceRow->GetSourceRow(IID_IGetSession, (IUnknown**)
|
|
&pIGS), S_OK, DB_E_NOSOURCEOBJECT)
|
|
|
|
if(hr==S_OK)
|
|
TESTC(VerifyEqualInterface(pIGS, RowObj.pIRow()))
|
|
else
|
|
TESTC(!pIGS)
|
|
}
|
|
|
|
TESTC_(m_pCRowset->ReleaseRows(cRowsObtained, rghRows),S_OK)
|
|
cRowsObtained = 0;
|
|
PROVIDER_FREE(rghRows);
|
|
SAFE_RELEASE(pIGS);
|
|
SAFE_RELEASE(pIGetSourceRow);
|
|
}
|
|
|
|
CLEANUP:
|
|
m_pCRowset->ReleaseRows(cRowsObtained, rghRows);
|
|
PROVIDER_FREE(rghRows);
|
|
SAFE_RELEASE(pIGS);
|
|
SAFE_RELEASE(pIGetSourceRow);
|
|
TRETURN
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(8)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRowChange
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRow::Variation_8()
|
|
{
|
|
TBEGIN
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW* rghRows = NULL;
|
|
IRowChange* pIRowChange = NULL;
|
|
|
|
CRowObject RowObj;
|
|
|
|
TESTC_(m_pCRowset->RestartPosition(),S_OK)
|
|
|
|
TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK)
|
|
|
|
TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(),
|
|
rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS)
|
|
|
|
TESTC_PROVIDER(VerifyInterface(RowObj.pIRow(), IID_IRowChange,
|
|
ROW_INTERFACE, (IUnknown**)&pIRowChange))
|
|
|
|
TESTC(testIRowChange(&RowObj))
|
|
|
|
CLEANUP:
|
|
m_pCRowset->ReleaseRows(cRowsObtained, rghRows);
|
|
PROVIDER_FREE(rghRows);
|
|
SAFE_RELEASE(pIRowChange);
|
|
TRETURN
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(9)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc IRowSchemaChange
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int TCRow::Variation_9()
|
|
{
|
|
TBEGIN
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW* rghRows = NULL;
|
|
IRowSchemaChange* pIRowSchemaChange = NULL;
|
|
|
|
CRowObject RowObj;
|
|
|
|
TESTC_(m_pCRowset->RestartPosition(),S_OK)
|
|
|
|
TESTC_(m_pCRowset->GetNextRows(0, 1, &cRowsObtained, &rghRows),S_OK)
|
|
|
|
TEST2C_(RowObj.CreateRowObject(m_pCRowset->pIRowset(),
|
|
rghRows[0]), S_OK, DB_S_NOROWSPECIFICCOLUMNS)
|
|
|
|
TESTC_PROVIDER(VerifyInterface(RowObj.pIRow(), IID_IRowSchemaChange,
|
|
ROW_INTERFACE, (IUnknown**)&pIRowSchemaChange))
|
|
|
|
TESTC(testIRowSchemaChange(&RowObj))
|
|
|
|
CLEANUP:
|
|
m_pCRowset->ReleaseRows(cRowsObtained, rghRows);
|
|
PROVIDER_FREE(rghRows);
|
|
SAFE_RELEASE(pIRowSchemaChange);
|
|
TRETURN
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL TCRow::Terminate()
|
|
{
|
|
if(m_pTable)
|
|
m_pTable->DropTable();
|
|
SAFE_DELETE(m_pTable);
|
|
SAFE_DELETE(m_pCRowset);
|
|
ReleaseDBSession();
|
|
ReleaseDataSourceObject();
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(CQuickTest::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// Test Driver
|
|
//
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// The test driver (main) function. This runs all the tests (and all
|
|
// variations in them) when QuikTest is run as a stand-alone executable.
|
|
//
|
|
void __cdecl main(int argc, char* argv[])
|
|
{
|
|
HRESULT hr = S_OK ;
|
|
CHAR* pszCmdLine = NULL ;
|
|
CHAR* pszTemp = NULL;
|
|
WCHAR* pwszCmdLine = NULL ;
|
|
WCHAR* pwszProvName = NULL ;
|
|
CLSID clsidProvider ;
|
|
ITestCases* pTC = NULL ;
|
|
IError* pIError = NULL;
|
|
CBaseError* pCBError = NULL;
|
|
TESTRESULT tResult = eVariationStatusNonExistent ; // VARIATION_STATUS
|
|
|
|
VARIANT_BOOL fResult=VARIANT_FALSE;
|
|
LONG dwResult=0;
|
|
LONG cTotalVars=0;
|
|
LONG cCaseCount=0;
|
|
LONG cVarCount=0;
|
|
LONG iTestNum=0;
|
|
LONG iVarNum=0;
|
|
ULONG cVarPassed=0;
|
|
ULONG cVarFailed=0; //Total number of failures; not variations failed.
|
|
ULONG cVarSkipped=0;
|
|
ULONG cVarNonExistent=0;
|
|
|
|
LONG cVarErrors = 0;
|
|
LONG cVarWarnings = 0;
|
|
LONG cModErrors = 0;
|
|
LONG cModWarnings = 0;
|
|
|
|
BSTR bstrModuleName = NULL;
|
|
BSTR bstrModuleDesc = NULL;
|
|
BSTR bstrCaseName = NULL;
|
|
BSTR bstrCaseDesc = NULL;
|
|
BSTR bstrVarDesc = NULL;
|
|
|
|
if(hr != OleInitialize(NULL)) goto CLEANUP ;
|
|
SetUseIMallocSpy(FALSE) ;
|
|
|
|
//Get the command line.
|
|
pszCmdLine = GetCommandLineA() ;
|
|
|
|
//Remove the first arg, which is the executable name.
|
|
//What's left is the Init string.
|
|
if(argc>=2 && argv && argv[0] && argv[1])
|
|
{
|
|
pszTemp = strstr(pszCmdLine, argv[0]);
|
|
if(pszTemp)
|
|
pszCmdLine = pszTemp + strlen(argv[0]) + 1 ;
|
|
}
|
|
else
|
|
{
|
|
OutputText(L"Expected at least 2 args on command line.\n");
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Now the command line consists of only the Init string.
|
|
pwszCmdLine = ConvertToWCHAR(pszCmdLine) ;
|
|
if(pwszCmdLine==NULL)
|
|
{
|
|
OutputText(L"Failed to convert Command Line.\n");
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Create a temporary CModInfo to use it's member function
|
|
//GetInitStringValue to get the provider name from the
|
|
//init string. Donot check for its return value. It will return
|
|
//false since we passed in a NULL.
|
|
CreateModInfo(NULL);
|
|
GetModInfo()->SetInitString(pwszCmdLine) ;
|
|
if(!GetModInfo()->GetInitStringValue(L"PROVIDER", &pwszProvName))
|
|
{
|
|
OutputText(L"Failed to get the Provider Name.\n");
|
|
OutputText(L"Include PROVIDER=... in the Init String.\n");
|
|
goto CLEANUP;
|
|
}
|
|
ReleaseModInfo(NULL);
|
|
//Destroyed the temporary CModInfo.
|
|
|
|
//From provider name get class ID.
|
|
if(FAILED(hr = CLSIDFromProgID(pwszProvName , &clsidProvider)))
|
|
hr = CLSIDFromString(pwszProvName , &clsidProvider) ;
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
OutputText(L"Failed to get CLSID from Provider Name.\n");
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Initialize the Global Module Data.
|
|
SetGlobalModuleData() ;
|
|
g_pThisTestModule->m_pwszInitString = SYSSTRING_ALLOC(pwszCmdLine) ;
|
|
g_pThisTestModule->m_ProviderClsid = clsidProvider ;
|
|
|
|
//This stmt is not required. It gets set to this by default.
|
|
g_pThisTestModule->m_clsctxProvider = CLSCTX_INPROC_SERVER;
|
|
|
|
//Create and initialize the CModInfo which will be used throughout
|
|
//the test.
|
|
if(!ModuleInit(g_pThisTestModule))
|
|
{
|
|
OutputText(L"ModuleInit failed.\n");
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Create an error class to be used when run as a stand-alone
|
|
//executable.
|
|
pCBError = new CBaseError;
|
|
if(pCBError == NULL)
|
|
{
|
|
OutputText(L"Failed to create an Error Object.\n");
|
|
goto CLEANUP;
|
|
}
|
|
//Get the IError interface from our error object.
|
|
pCBError->QueryInterface(IID_IError, (void**)&pIError);
|
|
if(pIError == NULL)
|
|
{
|
|
OutputText(L"Failed to get the IError interface.\n");
|
|
goto CLEANUP;
|
|
}
|
|
//Set the obtained IError as our Error interface to use.
|
|
GetModInfo()->GetErrorObject()->SetErrorInterface(pIError);
|
|
|
|
//Get name and description of the module and print it alongwith
|
|
//the initialization string.
|
|
g_pThisTestModule->GetName(&bstrModuleName);
|
|
g_pThisTestModule->GetDescription(&bstrModuleDesc);
|
|
OutputText(L" \n") ;
|
|
OutputText(L"-------------------------------------------------------------------------------\n") ;
|
|
OutputText(L"ModuleName: %s\n",bstrModuleName) ;
|
|
OutputText(L"ModuleDesc: %s\n",bstrModuleDesc) ;
|
|
OutputText(L"Initialization: %s\n",pwszCmdLine) ;
|
|
OutputText(L"-------------------------------------------------------------------------------\n") ;
|
|
|
|
//Get number of test cases.
|
|
g_pThisTestModule->GetCaseCount(&cCaseCount);
|
|
|
|
//Initialize error and warning counters.
|
|
pCBError->ResetModErrors();
|
|
pCBError->ResetModWarnings();
|
|
|
|
//Loop through the Test Cases.
|
|
for( iTestNum=0; iTestNum<cCaseCount; iTestNum++)
|
|
{
|
|
//Initialize error and warning counters.
|
|
pCBError->ResetCaseErrors();
|
|
pCBError->ResetCaseWarnings();
|
|
|
|
//Get the test case.
|
|
if(!CHECK(g_pThisTestModule->GetCase(iTestNum,&pTC), S_OK))
|
|
goto CLEANUP;
|
|
if(pTC==NULL)
|
|
{
|
|
OutputText(L"Failed to get test case (%d).\n", iTestNum+1);
|
|
continue;
|
|
}
|
|
pTC->GetVariationCount(&cVarCount) ;
|
|
pTC->GetName(&bstrCaseName);
|
|
pTC->GetDescription(&bstrCaseDesc);
|
|
OutputText(L" \n");
|
|
OutputText(L"%s: %s.\n",bstrCaseName,bstrCaseDesc);
|
|
|
|
//Increment total variation count by number of vars in this
|
|
//test case.
|
|
cTotalVars += cVarCount;
|
|
|
|
//Call the Init() function of this test case. If fails, goto
|
|
//terminate().
|
|
pTC->Init(&dwResult);
|
|
if(dwResult == (LONG)TEST_FAIL)
|
|
{
|
|
//If Init fails, then all variations within that TestCase
|
|
//are counted as failed.
|
|
cVarFailed += cVarCount;
|
|
OutputText(L"Init failed.\n");
|
|
goto TERMINATE;
|
|
}
|
|
else if(dwResult == (LONG)TEST_SKIPPED)
|
|
{
|
|
//If Init is skipped, then all variations within that
|
|
//TestCase are counted as skipped.
|
|
cVarSkipped += cVarCount;
|
|
//Skip all variations in this test case.
|
|
goto TERMINATE;
|
|
}
|
|
|
|
//Loop through the variations.
|
|
for( iVarNum=0; iVarNum<cVarCount; iVarNum++)
|
|
{
|
|
//Initialize error and warning counters.
|
|
pCBError->ResetVarErrors();
|
|
pCBError->ResetVarWarnings();
|
|
|
|
pTC->GetVariationDesc(iVarNum, &bstrVarDesc);
|
|
OutputText(L"\tVariation (%d) %s.\n",iVarNum+1, bstrVarDesc);
|
|
tResult = eVariationStatusNonExistent;
|
|
|
|
//Execute the variation.
|
|
try
|
|
{
|
|
pTC->ExecuteVariation(iVarNum, &tResult) ;
|
|
}
|
|
catch(...)
|
|
{
|
|
OutputText(L"\tEXCEPTION thrown.\n");
|
|
tResult = TEST_FAIL;
|
|
}
|
|
|
|
//Get error and warning count of this variation.
|
|
pCBError->GetVarErrors(&cVarErrors);
|
|
pCBError->GetVarWarnings(&cVarWarnings);
|
|
|
|
if(cVarErrors > 0)
|
|
tResult = TEST_FAIL;
|
|
|
|
//Display Result of the variation.
|
|
switch(tResult)
|
|
{
|
|
case TEST_PASS:
|
|
if(cVarWarnings > 0)
|
|
OutputText(L"\tWARNING\n");
|
|
else
|
|
OutputText(L"\tPASS\n");
|
|
cVarPassed++;
|
|
break;
|
|
case TEST_FAIL:
|
|
OutputText(L"\tFAIL ******** FAIL\n");
|
|
if(cVarErrors==0)
|
|
cVarFailed++;
|
|
else
|
|
cVarFailed += cVarErrors;
|
|
break;
|
|
case TEST_SKIPPED:
|
|
OutputText(L"\tSKIPPED\n");
|
|
cVarSkipped++;
|
|
break;
|
|
default:
|
|
OutputText(L"\tNON-EXISTENT\n");
|
|
cVarNonExistent++;
|
|
break;
|
|
}//switch
|
|
OutputText(L"\n");
|
|
SAFE_SYSFREE(bstrVarDesc);
|
|
}
|
|
|
|
TERMINATE:
|
|
//Call the terminate() function of this test case.
|
|
pTC->Terminate(&fResult) ;
|
|
SAFE_SYSFREE(bstrCaseName);
|
|
SAFE_SYSFREE(bstrCaseDesc);
|
|
SAFE_RELEASE(pTC);
|
|
cVarCount = 0;
|
|
}
|
|
|
|
//Get error and warning count of entire module.
|
|
pCBError->GetModErrors(&cModErrors);
|
|
pCBError->GetModWarnings(&cModWarnings);
|
|
|
|
OutputText(L" \n");
|
|
OutputText(L"-------------------------------------------------------------------------------\n") ;
|
|
OutputText(L"FAILURES = %d\t(Total number of errors in entire test)\n", cVarFailed);
|
|
OutputText(L"Warnings = %d\t(Total number of warnings in entire test)\n", cModWarnings);
|
|
OutputText(L"Skipped = %d\t(Number of variations skipped)\n", cVarSkipped);
|
|
OutputText(L"Passed = %d/%d\t(Number of variations passed and skipped / Number of variations run)\n", cVarPassed+cVarSkipped, cTotalVars);
|
|
OutputText(L"Pass Percent = %d\t(percentage of above ratio)\n", (cVarPassed+cVarSkipped)*100/cTotalVars);
|
|
OutputText(L"-------------------------------------------------------------------------------\n") ;
|
|
|
|
//Terminate module. Releases CModInfo.
|
|
if(!ModuleTerminate(g_pThisTestModule))
|
|
OutputText(L"ModuleTerminate Failed.\n");
|
|
|
|
CLEANUP:
|
|
SAFE_RELEASE(pIError);
|
|
SAFE_FREE(pwszCmdLine);
|
|
SAFE_FREE(pwszProvName);
|
|
SAFE_SYSFREE(bstrModuleName);
|
|
SAFE_SYSFREE(bstrModuleDesc);
|
|
OleUninitialize() ;
|
|
}
|