21543 lines
613 KiB
C++
21543 lines
613 KiB
C++
//--------------------------------------------------------------------
|
|
// Microsoft OLE DB Test
|
|
//
|
|
// Copyright 1995-2000 Microsoft Corporation.
|
|
//
|
|
// @doc
|
|
//
|
|
// @module IDBSCHMR.CPP | Source file for IDBSchemaRowset test
|
|
//
|
|
//--------------------------------------------------------------------
|
|
|
|
#include "modstandard.hpp"
|
|
#include "IDBSchmR.h"
|
|
#include "extralib.h"
|
|
|
|
#define CLEANUP(x) if(x) goto CLEANUP;
|
|
#define TERMINATE(x) if(x) return FALSE;
|
|
#define CONTINUE(x) if (x) return TRUE;
|
|
|
|
#define PI (IUnknown *)
|
|
#define PPI (IUnknown **)
|
|
#define PPPI (IUnknown ***)
|
|
#define WC (WCHAR *)
|
|
|
|
#define INIT Init_Stuff();
|
|
#define FREE Free_Stuff();
|
|
|
|
// free other pointer
|
|
#define RESTRICTNOTSUPPORTED(x) if(!(m_currentBitMask & x))m_fAtLeast1UnsupportedRestrictionIsSet=TRUE;
|
|
|
|
|
|
IDBSchemaRowset * g_pIDBSchemaRowset=NULL;
|
|
|
|
BOOL g_fKagera; // Track whether running against Kagera
|
|
BOOL g_fSQLServer; // Track whether the backend is SQL Server
|
|
|
|
// Initially use Sql Server provider specific guid and prop value
|
|
GUID g_guidHistogramRowset = DBGUID_HISTOGRAM_ROWSET;
|
|
DBPROPID g_propTableStatistics = DBPROP_TABLESTATISTICS;
|
|
|
|
ULONG cSchemas;
|
|
GUID * rgSchemas;
|
|
ULONG * rgRestrictions=NULL;
|
|
|
|
// Global strings for primary and foreign keys.
|
|
WCHAR *g_pwszAddPrimaryKeyOnTable1=NULL;
|
|
WCHAR *g_pwszAddPrimaryKeyOnTable2=NULL;
|
|
WCHAR *g_pwszAddForeignKeyOnTable1=NULL;
|
|
WCHAR *g_pwszDropPrimaryKeyConstraint1=NULL;
|
|
WCHAR *g_pwszDropForeignKeyConstraint1=NULL;
|
|
WCHAR *g_pwszDropPrimaryKeyConstraint2=NULL;
|
|
CTable *g_pKeyTable1=NULL;
|
|
CTable *g_pKeyTable2=NULL;
|
|
BOOL g_fKeysOnTable=FALSE;
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CErrorCache
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
#define CCHECK(ErrObj, hrAct, hrExp, ulErr, pwszMsg, fWarn) (ErrObj.CCheck((hrAct), \
|
|
(hrExp), (ulErr), (pwszMsg), (fWarn), LONGSTRING(__FILE__), (__LINE__)))
|
|
#define CCOMPARE(ErrObj, fResult, ulErr, pwszMsg, fWarn) (ErrObj.CCompare((fResult), \
|
|
(ulErr), (pwszMsg), (fWarn), LONGSTRING(__FILE__), (__LINE__)))
|
|
|
|
enum ERROR_CACHE_ENUM
|
|
{
|
|
// DBSCHEMA_TABLE_STATISTICS cached errors
|
|
EC_EXTRA_COLUMN = 1,
|
|
EC_BAD_COL_OR_TUPLE_CARD,
|
|
EC_BAD_TABLE_CARDINALITY,
|
|
EC_BAD_HR_OPENHISTOGRAM,
|
|
EC_NULL_RANGE_COUNT,
|
|
EC_BAD_RANGE_ROWS,
|
|
EC_BAD_EQ_ROWS,
|
|
EC_BAD_DISTINCT_RANGE_ROWS,
|
|
// DBSCHEMA_COLUMNS cached errors
|
|
EC_BAD_COLUMN_FLAGS,
|
|
EC_BAD_CHARACTER_MAXIMUM_LENGTH,
|
|
EC_BAD_CHARACTER_OCTET_LENGTH,
|
|
EC_BAD_DATETIME_PRECISION,
|
|
EC_COLUMNS_NULL_NUMERIC_SCALE,
|
|
EC_COLUMNS_BAD_NUMERIC_PRECISION,
|
|
// DBSCHEMA_INDEXES cached errors
|
|
EC_INDEXES_NULLS_ISNULL,
|
|
EC_INDEXES_INDEX_NAME_ISNULL,
|
|
EC_INDEXES_UNIQUE_ISNULL,
|
|
EC_INDEXES_AUTO_UPDATE_ISNULL,
|
|
// DBSCHEMA_PROCEDURES cached errors
|
|
EC_PROCEDURES_PROC_DEF_ISNULL,
|
|
// DBSCHEMA_PROCEDURE_COLUMNS cached errors
|
|
EC_PROC_COLS_IS_NULLABLE_ISNULL,
|
|
EC_INVALID_IS_NULLABLE,
|
|
// DBSCHEMA_PROVIDER_TYPES cached errors
|
|
EC_INCORRECT_SORT,
|
|
EC_MAX_ERROR_NUMBER // Must always be last enum
|
|
};
|
|
|
|
LPWSTR g_ppwszErrorStrings[] =
|
|
{
|
|
// DBSCHEMA_TABLE_STATISTICS cached errors
|
|
L"EC_EXTRA_COLUMN",
|
|
L"EC_BAD_COL_OR_TUPLE_CARD",
|
|
L"EC_BAD_TABLE_CARDINALITY",
|
|
L"EC_BAD_HR_OPENHISTOGRAM",
|
|
L"EC_NULL_RANGE_COUNT",
|
|
L"EC_BAD_RANGE_ROWS",
|
|
L"EC_BAD_EQ_ROWS",
|
|
L"EC_BAD_DISTINCT_RANGE_ROWS",
|
|
// DBSCHEMA_COLUMNS cached errors
|
|
L"EC_BAD_COLUMN_FLAGS",
|
|
L"EC_BAD_CHARACTER_MAXIMUM_LENGTH",
|
|
L"EC_BAD_CHARACTER_OCTET_LENGTH",
|
|
L"EC_BAD_DATETIME_PRECISION",
|
|
L"EC_COLUMNS_NULL_NUMERIC_SCALE",
|
|
L"EC_COLUMNS_BAD_NUMERIC_PRECISION",
|
|
// DBSCHEMA_INDEXES cached errors
|
|
L"EC_INDEXES_NULLS_ISNULL",
|
|
L"EC_INDEXES_INDEX_NAME_ISNULL",
|
|
L"EC_INDEXES_UNIQUE_ISNULL",
|
|
L"EC_INDEXES_AUTO_UPDATE_ISNULL",
|
|
// DBSCHEMA_PROCEDURES cached errors
|
|
L"EC_PROCEDURES_PROC_DEF_ISNULL",
|
|
// DBSCHEMA_PROCEDURE_COLUMNS cached errors
|
|
L"EC_PROC_COLS_IS_NULLABLE_ISNULL",
|
|
L"EC_INVALID_IS_NULLABLE",
|
|
// DBSCHEMA_PROVIDER_TYPES cached errors
|
|
L"EC_INCORRECT_SORT",
|
|
};
|
|
|
|
|
|
class CErrorCache
|
|
{
|
|
|
|
private:
|
|
|
|
ULONG m_ulDebugMode;
|
|
ULONG m_ulMaxCachedErrors;
|
|
ULONG * m_pulErrorCache;
|
|
ULONG m_cErrorsCached;
|
|
|
|
BOOL IsErrorCached(ULONG ulError);
|
|
|
|
public:
|
|
|
|
CErrorCache(void);
|
|
|
|
~CErrorCache(void);
|
|
|
|
BOOL Init(ULONG ulDebugMode);
|
|
|
|
BOOL CCheck(HRESULT hrActual, HRESULT hrExpected, ULONG ulError = 0,
|
|
LPWSTR pwszMessage = NULL, BOOL fWarning = FALSE, LPWSTR pwszFile = NULL,
|
|
ULONG ulLine = 0);
|
|
|
|
BOOL CCompare(BOOL fResult, ULONG ulError = 0, LPWSTR pwszMessage = NULL,
|
|
BOOL fWarning = FALSE, LPWSTR pwszFile = NULL, ULONG ulLine = 0);
|
|
};
|
|
|
|
CErrorCache::CErrorCache(void)
|
|
{
|
|
m_ulDebugMode = 0;
|
|
m_ulMaxCachedErrors = EC_MAX_ERROR_NUMBER-1;
|
|
m_pulErrorCache = NULL;
|
|
m_cErrorsCached = 0;
|
|
}
|
|
|
|
CErrorCache::~CErrorCache(void)
|
|
{
|
|
// Print summary of errors cached if there is at least one
|
|
// error cached.
|
|
if (m_cErrorsCached)
|
|
{
|
|
odtLog << L"\n\nThe following errors were cached:\n\n";
|
|
|
|
for (ULONG iErr = 0; iErr < m_ulMaxCachedErrors; iErr++)
|
|
if (m_pulErrorCache[iErr])
|
|
odtLog << L"\t" << g_ppwszErrorStrings[iErr] <<
|
|
L"\t\t" << m_pulErrorCache[iErr] << L"\n";
|
|
|
|
odtLog << L"\n\n";
|
|
odtLog << L"To see error details instead of this summary please add 'DEBUGMODE=FULL;' to the init string.\n\n";
|
|
|
|
}
|
|
|
|
SAFE_FREE(m_pulErrorCache);
|
|
}
|
|
|
|
BOOL CErrorCache::Init(ULONG ulDebugMode)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
|
|
m_ulDebugMode = ulDebugMode;
|
|
|
|
// Allocate memory for error cache. Since we don't expect this to be more than
|
|
// a few 10's of items just use a static array.
|
|
SAFE_ALLOC(m_pulErrorCache, ULONG, m_ulMaxCachedErrors);
|
|
|
|
// Init all cache locations to 0, no error cached
|
|
memset(m_pulErrorCache, 0, m_ulMaxCachedErrors*sizeof(ULONG));
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
return fResult;
|
|
}
|
|
|
|
BOOL CErrorCache::IsErrorCached(ULONG ulError)
|
|
{
|
|
ASSERT(ulError <= m_ulMaxCachedErrors);
|
|
|
|
// In case this gets called before init.
|
|
if (!m_pulErrorCache)
|
|
return FALSE;
|
|
|
|
// If the cache has a value other than 0 then it's been cached
|
|
return m_pulErrorCache[ulError-1];
|
|
}
|
|
|
|
BOOL CErrorCache::CCheck(HRESULT hrActual, HRESULT hrExpected, ULONG ulError,
|
|
LPWSTR pwszMessage, BOOL fWarning, LPWSTR pwszFile,
|
|
ULONG ulLine)
|
|
{
|
|
BOOL fReturn = hrActual == hrExpected;
|
|
|
|
// Check for valid error number
|
|
if (ulError == 0 || ulError > m_ulMaxCachedErrors)
|
|
return FALSE;
|
|
|
|
// If this error is already cached then we allow it to pass unless debugmode is full.
|
|
if (IsErrorCached(ulError) && !(m_ulDebugMode & DEBUGMODE_FULL))
|
|
{
|
|
if (!fReturn)
|
|
// Update the cache
|
|
m_pulErrorCache[ulError-1]++;
|
|
return fReturn;
|
|
}
|
|
|
|
// Otherwise we have to perform the comparison. Note we can't just return the
|
|
// value from PrivLibValidate because on warning it always returns TRUE even on
|
|
// a miscompare
|
|
PrivlibValidate(hrActual, hrExpected, fWarning, pwszFile, ulLine);
|
|
|
|
// If the comparison failed, then print failure message
|
|
if (!fReturn)
|
|
{
|
|
// Update the cache
|
|
if (!(m_ulDebugMode & DEBUGMODE_FULL))
|
|
{
|
|
m_pulErrorCache[ulError-1]++;
|
|
m_cErrorsCached++;
|
|
}
|
|
|
|
if (pwszMessage)
|
|
odtLog << pwszMessage << L"\n";
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
BOOL CErrorCache::CCompare(BOOL fResult, ULONG ulError, LPWSTR pwszMessage,
|
|
BOOL fWarning, LPWSTR pwszFile, ULONG ulLine)
|
|
{
|
|
|
|
// Check for valid error number
|
|
if (ulError == 0 || ulError > m_ulMaxCachedErrors)
|
|
return FALSE;
|
|
|
|
// If this error is already cached then we allow it to pass unless debugmode is full.
|
|
if (IsErrorCached(ulError) && !(m_ulDebugMode & DEBUGMODE_FULL))
|
|
{
|
|
if (!fResult)
|
|
// Update the cache
|
|
m_pulErrorCache[ulError-1]++;
|
|
return fResult;
|
|
}
|
|
|
|
// Otherwise we have to perform the comparison. Note we can't just return the
|
|
// value from PrivLibValidate because on warning it always returns TRUE even on
|
|
// a miscompare
|
|
PrivlibCompare(fResult, fWarning, pwszFile, ulLine);
|
|
|
|
// If the comparison failed, then print failure message
|
|
if (!fResult)
|
|
{
|
|
if (!(m_ulDebugMode & DEBUGMODE_FULL))
|
|
{
|
|
m_pulErrorCache[ulError-1]++;
|
|
m_cErrorsCached++;
|
|
}
|
|
|
|
if (pwszMessage)
|
|
odtLog << pwszMessage << L"\n";
|
|
}
|
|
|
|
return fResult;
|
|
}
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// TraceSchemaName
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
ULONG TraceSchemaName
|
|
(
|
|
GUID guid,
|
|
BOOL fToScreen,
|
|
BOOL fAddNewLine
|
|
)
|
|
{
|
|
LPWSTR pwszSchemaName = L"";
|
|
|
|
// Find the schema
|
|
if(IsEqualGUID(DBSCHEMA_ASSERTIONS,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_ASSERTIONS;
|
|
else if(IsEqualGUID(DBSCHEMA_CATALOGS,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_CATALOGS;
|
|
else if(IsEqualGUID(DBSCHEMA_CHARACTER_SETS,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_CHARACTER_SETS;
|
|
else if(IsEqualGUID(DBSCHEMA_CHECK_CONSTRAINTS,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_CHECK_CONSTRAINTS;
|
|
else if(IsEqualGUID(DBSCHEMA_COLLATIONS,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_COLLATIONS;
|
|
else if(IsEqualGUID(DBSCHEMA_COLUMN_DOMAIN_USAGE,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_COLUMN_DOMAIN_USAGE;
|
|
else if(IsEqualGUID(DBSCHEMA_COLUMN_PRIVILEGES,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_COLUMN_PRIVILEGES;
|
|
else if(IsEqualGUID(DBSCHEMA_COLUMNS,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_COLUMNS;
|
|
else if(IsEqualGUID(DBSCHEMA_CONSTRAINT_COLUMN_USAGE,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_CONSTRAINT_COLUMN_USAGE;
|
|
else if(IsEqualGUID(DBSCHEMA_CONSTRAINT_TABLE_USAGE,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_CONSTRAINT_TABLE_USAGE;
|
|
else if(IsEqualGUID(DBSCHEMA_FOREIGN_KEYS,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_FOREIGN_KEYS;
|
|
else if(IsEqualGUID(DBSCHEMA_INDEXES,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_INDEXES;
|
|
else if(IsEqualGUID(DBSCHEMA_KEY_COLUMN_USAGE,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_KEY_COLUMN_USAGE;
|
|
else if(IsEqualGUID(DBSCHEMA_PRIMARY_KEYS,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_PRIMARY_KEYS;
|
|
else if(IsEqualGUID(DBSCHEMA_PROCEDURE_COLUMNS,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_PROCEDURE_COLUMNS;
|
|
else if(IsEqualGUID(DBSCHEMA_PROCEDURE_PARAMETERS, guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_PROCEDURE_PARAMETERS;
|
|
else if(IsEqualGUID(DBSCHEMA_PROCEDURES,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_PROCEDURES;
|
|
else if(IsEqualGUID(DBSCHEMA_PROVIDER_TYPES,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_PROVIDER_TYPES;
|
|
else if(IsEqualGUID(DBSCHEMA_REFERENTIAL_CONSTRAINTS,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_REFERENTIAL_CONSTRAINTS;
|
|
else if(IsEqualGUID(DBSCHEMA_SCHEMATA,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_SCHEMATA;
|
|
else if(IsEqualGUID(DBSCHEMA_SQL_LANGUAGES,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_SQL_LANGUAGES;
|
|
else if(IsEqualGUID(DBSCHEMA_STATISTICS,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_STATISTICS;
|
|
else if(IsEqualGUID(DBSCHEMA_TABLES,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_TABLES;
|
|
else if(IsEqualGUID(DBSCHEMA_TABLES_INFO,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_TABLES_INFO;
|
|
else if(IsEqualGUID(DBSCHEMA_TABLE_CONSTRAINTS,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_TABLE_CONSTRAINTS;
|
|
else if(IsEqualGUID(DBSCHEMA_TABLE_PRIVILEGES,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_TABLE_PRIVILEGES;
|
|
else if(IsEqualGUID(DBSCHEMA_TABLE_STATISTICS,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_TABLE_STATISTICS;
|
|
else if(IsEqualGUID(DBSCHEMA_TRANSLATIONS,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_TRANSLATIONS;
|
|
else if(IsEqualGUID(DBSCHEMA_TRUSTEE,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_TRUSTEE;
|
|
else if(IsEqualGUID(DBSCHEMA_USAGE_PRIVILEGES,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_USAGE_PRIVILEGES;
|
|
else if(IsEqualGUID(DBSCHEMA_VIEW_COLUMN_USAGE,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_VIEW_COLUMN_USAGE;
|
|
else if(IsEqualGUID(DBSCHEMA_VIEW_TABLE_USAGE,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_VIEW_TABLE_USAGE;
|
|
else if(IsEqualGUID(DBSCHEMA_VIEWS,guid))
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_VIEWS;
|
|
else
|
|
pwszSchemaName = (LPWSTR)wszDBSCHEMA_GUID;
|
|
|
|
PRVTRACE(L"%s",pwszSchemaName);
|
|
if(fAddNewLine)
|
|
PRVTRACE(L"\n");
|
|
|
|
if(fToScreen)
|
|
{
|
|
odtLog << pwszSchemaName;
|
|
if(fAddNewLine)
|
|
odtLog <<ENDL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void TracePropertyName
|
|
(
|
|
DBPROPID prop,
|
|
BOOL fToScreen,
|
|
BOOL fAddNewLine
|
|
)
|
|
{
|
|
LPWSTR pwszProp = L"PROPERTY unknown";
|
|
|
|
|
|
if(prop==DBPROP_ABORTPRESERVE)
|
|
pwszProp = (LPWSTR)wszABORTPRESERVE;
|
|
if(prop==DBPROP_ACCESSORDER)
|
|
pwszProp = (LPWSTR)wszACCESSORDER;
|
|
if(prop==DBPROP_APPENDONLY)
|
|
pwszProp = (LPWSTR)wszAPPENDONLY;
|
|
else if(prop==DBPROP_BLOCKINGSTORAGEOBJECTS)
|
|
pwszProp = (LPWSTR)wszBLOCKINGSTORAGEOBJECTS;
|
|
else if(prop==DBPROP_BOOKMARKINFO)
|
|
pwszProp = (LPWSTR)wszBOOKMARKINFO;
|
|
else if(prop==DBPROP_BOOKMARKS)
|
|
pwszProp = (LPWSTR)wszBOOKMARKS;
|
|
else if(prop==DBPROP_BOOKMARKSKIPPED)
|
|
pwszProp = (LPWSTR)wszBOOKMARKSKIPPED;
|
|
else if(prop==DBPROP_BOOKMARKTYPE)
|
|
pwszProp = (LPWSTR)wszBOOKMARKTYPE;
|
|
else if(prop==DBPROP_CACHEDEFERRED)
|
|
pwszProp = (LPWSTR)wszCACHEDEFERRED;
|
|
else if(prop==DBPROP_CANFETCHBACKWARDS)
|
|
pwszProp = (LPWSTR)wszCANFETCHBACKWARDS;
|
|
else if(prop==DBPROP_CANHOLDROWS)
|
|
pwszProp = (LPWSTR)wszCANHOLDROWS;
|
|
else if(prop==DBPROP_CANSCROLLBACKWARDS)
|
|
pwszProp = (LPWSTR)wszCANSCROLLBACKWARDS;
|
|
else if(prop==DBPROP_CHANGEINSERTEDROWS)
|
|
pwszProp = (LPWSTR)wszCHANGEINSERTEDROWS;
|
|
else if(prop==DBPROP_COLUMNRESTRICT)
|
|
pwszProp = (LPWSTR)wszCOLUMNRESTRICT;
|
|
else if(prop==DBPROP_COMMANDTIMEOUT)
|
|
pwszProp = (LPWSTR)wszCOMMANDTIMEOUT;
|
|
else if(prop==DBPROP_COMMITPRESERVE)
|
|
pwszProp = (LPWSTR)wszCOMMITPRESERVE;
|
|
else if(prop==DBPROP_DEFERRED)
|
|
pwszProp = (LPWSTR)wszDEFERRED;
|
|
else if(prop==DBPROP_DELAYSTORAGEOBJECTS)
|
|
pwszProp = (LPWSTR)wszDELAYSTORAGEOBJECTS;
|
|
else if(prop==DBPROP_FILTERCOMPAREOPS)
|
|
pwszProp = (LPWSTR)wszFILTERCOMPAREOPS;
|
|
else if(prop==DBPROP_FINDCOMPAREOPS)
|
|
pwszProp = (LPWSTR)wszFINDCOMPAREOPS;
|
|
else if(prop==DBPROP_HIDDENCOLUMNS)
|
|
pwszProp = (LPWSTR)wszHIDDENCOLUMNS;
|
|
else if(prop==DBPROP_IMMOBILEROWS)
|
|
pwszProp = (LPWSTR)wszIMMOBILEROWS;
|
|
else if(prop==DBPROP_LITERALBOOKMARKS)
|
|
pwszProp = (LPWSTR)wszLITERALBOOKMARKS;
|
|
else if(prop==DBPROP_LITERALIDENTITY)
|
|
pwszProp = (LPWSTR)wszLITERALIDENTITY;
|
|
else if(prop==DBPROP_LOCKMODE)
|
|
pwszProp = (LPWSTR)wszLOCKMODE;
|
|
else if(prop==DBPROP_MAXOPENROWS)
|
|
pwszProp = (LPWSTR)wszMAXOPENROWS;
|
|
else if(prop==DBPROP_MAXPENDINGROWS)
|
|
pwszProp = (LPWSTR)wszMAXPENDINGROWS;
|
|
else if(prop==DBPROP_MAXROWS)
|
|
pwszProp = (LPWSTR)wszMAXROWS;
|
|
else if(prop==DBPROP_MAYWRITECOLUMN)
|
|
pwszProp = (LPWSTR)wszMAYWRITECOLUMN;
|
|
else if(prop==DBPROP_MEMORYUSAGE)
|
|
pwszProp = (LPWSTR)wszMEMORYUSAGE;
|
|
else if(prop==DBPROP_NOTIFICATIONGRANULARITY)
|
|
pwszProp = (LPWSTR)wszNOTIFICATIONGRANULARITY;
|
|
else if(prop==DBPROP_NOTIFICATIONPHASES)
|
|
pwszProp = (LPWSTR)wszNOTIFICATIONPHASES;
|
|
else if(prop==DBPROP_NOTIFYCOLUMNSET)
|
|
pwszProp = (LPWSTR)wszNOTIFYCOLUMNSET;
|
|
else if(prop==DBPROP_NOTIFYROWDELETE)
|
|
pwszProp = (LPWSTR)wszNOTIFYROWDELETE;
|
|
else if(prop==DBPROP_NOTIFYROWFIRSTCHANGE)
|
|
pwszProp = (LPWSTR)wszNOTIFYROWFIRSTCHANGE;
|
|
else if(prop==DBPROP_NOTIFYROWINSERT)
|
|
pwszProp = (LPWSTR)wszNOTIFYROWINSERT;
|
|
else if(prop==DBPROP_NOTIFYROWRESYNCH)
|
|
pwszProp = (LPWSTR)wszNOTIFYROWRESYNCH;
|
|
else if(prop==DBPROP_NOTIFYROWSETRELEASE)
|
|
pwszProp = (LPWSTR)wszNOTIFYROWSETRELEASE;
|
|
else if(prop==DBPROP_NOTIFYROWSETFETCHPOSITIONCHANGE)
|
|
pwszProp = (LPWSTR)wszNOTIFYROWSETFETCHPOSITIONCHANGE;
|
|
else if(prop==DBPROP_NOTIFYROWSETFETCHPOSITIONCHANGE)
|
|
pwszProp = (LPWSTR)wszNOTIFYROWSETFETCHPOSITIONCHANGE;
|
|
else if(prop==DBPROP_NOTIFYROWUNDOCHANGE)
|
|
pwszProp = (LPWSTR)wszNOTIFYROWUNDOCHANGE;
|
|
else if(prop==DBPROP_NOTIFYROWUNDOCHANGE)
|
|
pwszProp = (LPWSTR)wszNOTIFYROWUNDOCHANGE;
|
|
else if(prop==DBPROP_NOTIFYROWUNDODELETE)
|
|
pwszProp = (LPWSTR)wszNOTIFYROWUNDODELETE;
|
|
else if(prop==DBPROP_NOTIFYROWUNDOINSERT)
|
|
pwszProp = (LPWSTR)wszNOTIFYROWUNDOINSERT;
|
|
else if(prop==DBPROP_NOTIFYROWUPDATE)
|
|
pwszProp = (LPWSTR)wszNOTIFYROWUPDATE;
|
|
else if(prop==DBPROP_ORDEREDBOOKMARKS)
|
|
pwszProp = (LPWSTR)wszORDEREDBOOKMARKS;
|
|
else if(prop==DBPROP_OTHERINSERT)
|
|
pwszProp = (LPWSTR)wszOTHERINSERT;
|
|
else if(prop==DBPROP_OTHERUPDATEDELETE)
|
|
pwszProp = (LPWSTR)wszOTHERUPDATEDELETE;
|
|
else if(prop==DBPROP_OWNINSERT)
|
|
pwszProp = (LPWSTR)wszOWNINSERT;
|
|
else if(prop==DBPROP_OWNUPDATEDELETE)
|
|
pwszProp = (LPWSTR)wszOWNUPDATEDELETE;
|
|
else if(prop==DBPROP_QUICKRESTART)
|
|
pwszProp = (LPWSTR)wszQUICKRESTART;
|
|
else if(prop==DBPROP_REENTRANTEVENTS)
|
|
pwszProp = (LPWSTR)wszREENTRANTEVENTS;
|
|
else if(prop==DBPROP_REMOVEDELETED)
|
|
pwszProp = (LPWSTR)wszREMOVEDELETED;
|
|
else if(prop==DBPROP_REPORTMULTIPLECHANGES)
|
|
pwszProp = (LPWSTR)wszREPORTMULTIPLECHANGES;
|
|
else if(prop==DBPROP_RETURNPENDINGINSERTS)
|
|
pwszProp = (LPWSTR)wszRETURNPENDINGINSERTS;
|
|
else if(prop==DBPROP_ROWRESTRICT)
|
|
pwszProp = (LPWSTR)wszROWRESTRICT;
|
|
else if(prop==DBPROP_ROWSET_ASYNCH)
|
|
pwszProp = (LPWSTR)wszROWSET_ASYNCH;
|
|
else if(prop==DBPROP_ROWTHREADMODEL)
|
|
pwszProp = (LPWSTR)wszROWTHREADMODEL;
|
|
else if(prop==DBPROP_SERVERCURSOR)
|
|
pwszProp = (LPWSTR)wszSERVERCURSOR;
|
|
else if(prop==DBPROP_SERVERDATAONINSERT)
|
|
pwszProp = (LPWSTR)wszSERVERDATAONINSERT;
|
|
else if(prop==DBPROP_TRANSACTEDOBJECT)
|
|
pwszProp = (LPWSTR)wszTRANSACTEDOBJECT;
|
|
else if(prop==DBPROP_UNIQUEROWS)
|
|
pwszProp = (LPWSTR)wszUNIQUEROWS;
|
|
else if(prop==DBPROP_UPDATABILITY)
|
|
pwszProp = (LPWSTR)wszUPDATABILITY;
|
|
else if(prop==DBPROP_STRONGIDENTITY)
|
|
pwszProp = (LPWSTR)wszSTRONGIDENTITY;
|
|
else if(prop==DBPROP_IAccessor)
|
|
pwszProp = (LPWSTR)wszIAccessor;
|
|
else if(prop==DBPROP_IChapteredRowset)
|
|
pwszProp = (LPWSTR)wszIChapteredRowset;
|
|
else if(prop==DBPROP_IColumnsInfo)
|
|
pwszProp = (LPWSTR)wszIColumnsInfo;
|
|
else if(prop==DBPROP_IColumnsRowset)
|
|
pwszProp = (LPWSTR)wszIColumnsRowset;
|
|
else if(prop==DBPROP_IConnectionPointContainer)
|
|
pwszProp = (LPWSTR)wszIConnectionPointContainer;
|
|
else if(prop==DBPROP_IConvertType)
|
|
pwszProp = (LPWSTR)wszIConvertType;
|
|
else if(prop==DBPROP_IDBAsynchStatus)
|
|
pwszProp = (LPWSTR)wszIDBAsynchStatus;
|
|
else if(prop==DBPROP_ILockBytes)
|
|
pwszProp = (LPWSTR)wszILockBytes;
|
|
else if(prop==DBPROP_IMultipleResults)
|
|
pwszProp = (LPWSTR)wszIMultipleResults;
|
|
else if(prop==DBPROP_IParentRowset)
|
|
pwszProp = (LPWSTR)wszIParentRowset;
|
|
else if(prop==DBPROP_IRowset)
|
|
pwszProp = (LPWSTR)wszIRowset;
|
|
else if(prop==DBPROP_IRowsetChange)
|
|
pwszProp = (LPWSTR)wszIRowsetChange;
|
|
else if(prop==DBPROP_IRowsetCurrentIndex)
|
|
pwszProp = (LPWSTR)wszIRowsetCurrentIndex;
|
|
else if(prop==DBPROP_IRowsetFind)
|
|
pwszProp = (LPWSTR)wszIRowsetFind;
|
|
else if(prop==DBPROP_IRowsetIdentity)
|
|
pwszProp = (LPWSTR)wszIRowsetIdentity;
|
|
else if(prop==DBPROP_IRowsetInfo)
|
|
pwszProp = (LPWSTR)wszIRowsetInfo;
|
|
else if(prop==DBPROP_IRowsetIndex)
|
|
pwszProp = (LPWSTR)wszIRowsetIndex;
|
|
else if(prop==DBPROP_IRowsetInfo)
|
|
pwszProp = (LPWSTR)wszIRowsetInfo;
|
|
else if(prop==DBPROP_IRowsetLocate)
|
|
pwszProp = (LPWSTR)wszIRowsetLocate;
|
|
else if(prop==DBPROP_IRowsetRefresh)
|
|
pwszProp = (LPWSTR)wszIRowsetRefresh;
|
|
else if(prop==DBPROP_IRowsetResynch)
|
|
pwszProp = (LPWSTR)wszIRowsetResynch;
|
|
else if(prop==DBPROP_IRowsetScroll)
|
|
pwszProp = (LPWSTR)wszIRowsetScroll;
|
|
else if(prop==DBPROP_IRowsetUpdate)
|
|
pwszProp = (LPWSTR)wszIRowsetUpdate;
|
|
else if(prop==DBPROP_IRowsetView)
|
|
pwszProp = (LPWSTR)wszIRowsetView;
|
|
else if(prop==DBPROP_ISupportErrorInfo)
|
|
pwszProp = (LPWSTR)wszISupportErrorInfo;
|
|
else if(prop==DBPROP_ISequentialStream)
|
|
pwszProp = (LPWSTR)wszISequentialStream;
|
|
else if(prop==DBPROP_IStorage)
|
|
pwszProp = (LPWSTR)wszIStorage;
|
|
else if(prop==DBPROP_IStream)
|
|
pwszProp = (LPWSTR)wszIStream;
|
|
else if(prop==DBPROP_ISupportErrorInfo)
|
|
pwszProp = (LPWSTR)wszISupportErrorInfo;
|
|
|
|
PRVTRACE(L"%s",pwszProp);
|
|
if(fToScreen)
|
|
odtLog << L"\t" << pwszProp;
|
|
|
|
if(fAddNewLine)
|
|
{
|
|
PRVTRACE(L"\n");
|
|
if(fToScreen)
|
|
odtLog << L"\n";
|
|
}
|
|
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// GetRestrictionsFromSchema
|
|
//
|
|
// This returns the bitmask for the schema restrictions
|
|
// based on the schema.
|
|
//
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL TraceRestrictions
|
|
(
|
|
ULONG * restrictions,
|
|
ULONG schemaIndex,
|
|
ULONG * bitmask,
|
|
BOOL fOutLog
|
|
)
|
|
{
|
|
ULONG mask=0;
|
|
|
|
mask = restrictions[schemaIndex];
|
|
|
|
|
|
if(mask!=0)
|
|
{
|
|
if((mask) & FIRST)
|
|
{
|
|
PRVTRACE(L"1 ");
|
|
if(fOutLog)
|
|
odtLog << L"1 ";
|
|
}
|
|
if((mask) & SECOND)
|
|
{
|
|
PRVTRACE(L"2 ");
|
|
if(fOutLog)
|
|
odtLog << L"2 ";
|
|
}
|
|
if((mask) & THIRD)
|
|
{
|
|
PRVTRACE(L"3 ");
|
|
if(fOutLog)
|
|
odtLog << L"3 ";
|
|
}
|
|
if((mask) & FOURTH)
|
|
{
|
|
PRVTRACE(L"4 ");
|
|
if(fOutLog)
|
|
odtLog << L"4 ";
|
|
}
|
|
if((mask) & FIFTH)
|
|
{
|
|
PRVTRACE(L"5 ");
|
|
if(fOutLog)
|
|
odtLog << L"5 ";
|
|
}
|
|
if((mask) & SIXTH)
|
|
{
|
|
PRVTRACE(L"6 ");
|
|
if(fOutLog)
|
|
odtLog << L"6 ";
|
|
}
|
|
if((mask) & SEVENTH)
|
|
{
|
|
PRVTRACE(L"7 ");
|
|
if(fOutLog)
|
|
odtLog << L"7 ";
|
|
}
|
|
|
|
|
|
PRVTRACE(L"\n");
|
|
if(fOutLog)
|
|
odtLog << ENDL;
|
|
|
|
if(bitmask)
|
|
*bitmask = mask;
|
|
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
LPWSTR GetResourceString(UINT idsString)
|
|
{
|
|
CHAR szBuf[2*MAX_MSG_BUF];
|
|
LPWSTR pwszBuf = NULL;
|
|
ULONG ulStrLen;
|
|
HMODULE hMod = GetModuleHandle("idbschmr.dll");
|
|
|
|
TESTC(hMod != NULL);
|
|
|
|
// Load the string. LoadString truncates and null terminates if the string is too long for the buffer
|
|
// and returns the number of characters copied. So from that it is not possible to easily tell if
|
|
// truncation occurred. Calling GetLastError may work, but I think it is easier to just make sure we
|
|
// have an extra char in the buffer.
|
|
TESTC((ulStrLen = LoadString(hMod, idsString, szBuf, sizeof(szBuf)))>0);
|
|
TESTC(ulStrLen > 0);
|
|
TESTC(strlen(szBuf) < sizeof(szBuf)-1); // May have been truncation if this fails
|
|
|
|
// Convert to Unicode
|
|
pwszBuf = ConvertToWCHAR(szBuf);
|
|
|
|
CLEANUP:
|
|
|
|
return pwszBuf;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Base Class Section
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
class CSchemaTest : public CSessionObject
|
|
{
|
|
public:
|
|
|
|
// Static variables. (Set once but wont change values).
|
|
// @todo change them to real static variable.
|
|
|
|
ULONG m_cRowsetPropSet;
|
|
DBPROPSET * m_rgRowsetPropSet;
|
|
|
|
BOOL m_fAtLeast1UnsupportedRestrictionIsSet;
|
|
|
|
BOOL m_fPrintedSchemasAndRestrictions;
|
|
|
|
BOOL m_PrintSchemaName;
|
|
|
|
// Capture restrictions for this provider
|
|
BOOL m_fDontCaptureRestrictions;
|
|
|
|
// @cmember Pass all restrictions as init'd variants
|
|
BOOL m_fRestrictionsAsInitVariants;
|
|
|
|
// @cmember Do I want to pass in restriction when I know restriction is not supported?
|
|
BOOL m_fPassUnsupportedRestrictions;
|
|
|
|
// @cmember Global hresult
|
|
HRESULT m_HR;
|
|
|
|
// @cmember Variation level return
|
|
BOOL m_fResult;
|
|
|
|
// @cmember Was a bookmark requested for rowset
|
|
BOOL m_fBOOKMARK_REQUESTED;
|
|
|
|
// @cmember Was a bookmark found on rowset
|
|
BOOL m_fBOOKMARK_FOUND;
|
|
|
|
// @cmember Use first restriction
|
|
BOOL m_fRes1;
|
|
|
|
// @cmember Use second restriciton
|
|
BOOL m_fRes2;
|
|
|
|
// @cmember Use third restriciton
|
|
BOOL m_fRes3;
|
|
|
|
// @cmember Use fourth restriciton
|
|
BOOL m_fRes4;
|
|
|
|
// @cmember Use FIFTH restriction
|
|
BOOL m_fRes5;
|
|
|
|
// @cmember use sixth restriciton
|
|
BOOL m_fRes6;
|
|
|
|
// @cmember use seventh restriciton
|
|
BOOL m_fRes7;
|
|
|
|
// @cmember If catalog is found
|
|
BOOL m_fMyTableCatalogFound;
|
|
|
|
// @cmember If Schema is found
|
|
BOOL m_fMyTableSchemaFound;
|
|
|
|
// @cmember If first table name is found
|
|
BOOL m_MyTableName1Found;
|
|
|
|
// @cmember If second table name is found
|
|
BOOL m_MyTableName2Found;
|
|
|
|
// @cmember If column is found
|
|
BOOL m_MyColumnNameFound;
|
|
|
|
// @cmember If data type is found
|
|
BOOL m_MyTableTypeFound;
|
|
|
|
// @cmember Count of restrictions used
|
|
ULONG m_cErrors;
|
|
|
|
// @cmember Expect count of column in schema
|
|
ULONG m_cColumns;
|
|
|
|
// @cmember Expected count of restrictions in schema
|
|
ULONG m_cRestrictions;
|
|
|
|
// @cmember Count of restrictions being tested
|
|
ULONG m_cRestrictionsCurrent;
|
|
|
|
// @cmember Count of schemas provider supports
|
|
ULONG m_cSchemasSupported;
|
|
|
|
// @cmember Enum giving provider's OLEDB version
|
|
ULONG m_ulOLEDBVer;
|
|
|
|
// @cmember Count of Bindings
|
|
DBCOUNTITEM m_cDBBINDING;
|
|
|
|
// @cmember Count of Property Sets
|
|
ULONG m_cDBPROPSET;
|
|
|
|
// @cmember Count of DBPROPINFOSETs
|
|
ULONG m_cDBPROPINFOSET;
|
|
|
|
// @cmember Count of rowset DBPROPINFOSETs, including provider specific
|
|
ULONG m_cRowsetDBPROPINFOSET;
|
|
|
|
// @cmember Count of columns in rowset
|
|
DBORDINAL m_cDBCOLUMNINFO;
|
|
|
|
// @cmember Current schema being tested
|
|
GUID m_guid;
|
|
|
|
// @cmember Interface pointer I want returned
|
|
IID m_iid;
|
|
|
|
// Bitmask of which restrictions are requested
|
|
RESTRICTIONS m_restrict;
|
|
|
|
// Array of FIRST property
|
|
DBPROP m_rgDBPROP[MAXPROP];
|
|
|
|
// @cmember Array of Property Sets
|
|
DBPROPSET m_rgDBPROPSET[MAXPROP];
|
|
|
|
// @cmember CCol object
|
|
CCol m_col;
|
|
|
|
// @cmember First restriction
|
|
WCHAR * m_wszR1;
|
|
|
|
// @cmember Second restriction
|
|
WCHAR * m_wszR2;
|
|
|
|
// @cmember Third restriction
|
|
WCHAR * m_wszR3;
|
|
|
|
// @cmember Fourth restriction
|
|
WCHAR * m_wszR4;
|
|
|
|
// @cmember Fifth restriction
|
|
WCHAR * m_wszR5;
|
|
|
|
// @cmember Sixth restriction
|
|
WCHAR * m_wszR6;
|
|
|
|
// @cmember Seventh restriciton
|
|
WCHAR * m_wszR7;
|
|
|
|
// @cmember Non-string restriction (Currently only for Provider Type)
|
|
ULONG m_ulR;
|
|
|
|
// @cmember Bool restriction (Currently only for Best Match in Provider Types)
|
|
TYPE_BOOL m_fR;
|
|
|
|
// @cmember Rowset pointer should be NULL
|
|
BOOL m_fRowsetPointerNULL;
|
|
|
|
// @cmember Count of Restrictions should be 0
|
|
BOOL m_fCountRestrictionsNULL;
|
|
|
|
// @cmember Range of Restrictions shoulbd be NULL
|
|
BOOL m_fRangeRestrictionsNULL;
|
|
|
|
// @cmember Count of Property Sets should be 0
|
|
BOOL m_fCountPropSetNULL;
|
|
|
|
// @cmember Range of Property Sets should be NULL
|
|
BOOL m_fRangePropSetNULL;
|
|
|
|
// Array of restrictions, according to spec, no schema has more than 7
|
|
VARIANT m_rgvarRestrict[MAXRESTRICTION];
|
|
|
|
// Do I want to copy the restriction strings into my class members
|
|
BOOL m_fCaptureRestrictions;
|
|
|
|
// Print Supported Schemas prior to Testing
|
|
BOOL m_fPrintSupportedSchemas;
|
|
|
|
// DBTYPE
|
|
DBTYPE m_DataTypeRestriction;
|
|
|
|
// Object Type
|
|
SHORT m_ProcedureTypeRestriction;
|
|
|
|
// BEST MATCH
|
|
TYPE_BOOL m_BestMatchRestriction;
|
|
|
|
// Structure of guid and restrictions on guid
|
|
ULONG m_currentBitMask;
|
|
|
|
// if backend is sql server
|
|
BOOL m_bSqlServer;
|
|
|
|
///////////////
|
|
// Dynamic
|
|
//////////////
|
|
|
|
// @cmember Supported Property sets
|
|
DBPROP * m_rgSupportedProperties;
|
|
|
|
// @cmember Count of supported property sets
|
|
ULONG m_cSupportedProperties;
|
|
|
|
// @cmember Range of Restrictions that are supported
|
|
ULONG * m_rgRestrictionSupport;
|
|
|
|
// @cmember Expected column names
|
|
WCHAR ** m_rgColumnNames;
|
|
|
|
// @cmember Expected column types
|
|
DBTYPE * m_rgColumnTypes;
|
|
|
|
// @cmember Array of schemas provider supports
|
|
GUID * m_rgSchemas;
|
|
|
|
// @cmember Interface pointer
|
|
IDBSchemaRowset * m_pIDBSchemaRowset;
|
|
|
|
// @cmember Rowset pointer
|
|
IRowset * m_pIRowset;
|
|
|
|
// @cmember Count of DBPROPINFOSETs
|
|
DBPROPINFOSET * m_rgDBPROPINFOSET;
|
|
|
|
// @cmember Rowset property sets, including provider specific
|
|
DBPROPINFOSET * m_rgRowsetDBPROPINFOSET;
|
|
|
|
// @cmember Description Buffer
|
|
WCHAR * m_pDescBuffer;
|
|
LPWSTR m_pRowsetDescBuffer;
|
|
|
|
// @cmember Array of column information in rowset
|
|
DBCOLUMNINFO * m_rgDBCOLUMNINFO;
|
|
|
|
// @cmember Buffer of strings for column information
|
|
WCHAR * m_pStringsBuffer;
|
|
|
|
// @cmember Array of Bindings
|
|
DBBINDING * m_rgDBBINDING;
|
|
|
|
// @cmember Aggregation Pointer
|
|
IUnknown * m_punkOuter;
|
|
|
|
// @cmember IAccessor pointer
|
|
IAccessor * m_pIAccessor;
|
|
|
|
// @cmember IRowsetInfo pointer
|
|
IRowsetInfo * m_pIRowsetInfo;
|
|
|
|
// @cmember IColumnsInfo pointer
|
|
IColumnsInfo * m_pIColumnsInfo;
|
|
|
|
// @cmember IRowsetChange
|
|
IRowsetChange * m_pIRowsetChange;
|
|
|
|
// @cmember IUnknown
|
|
IUnknown * m_pIUnknown;
|
|
|
|
// @cmember m_pwszDropProc
|
|
WCHAR * m_pwszDropProc;
|
|
|
|
// @cmember m_eRowCount - how to interpret row count below
|
|
ROW_COUNT m_eRowCount;
|
|
|
|
// @cmember m_lRowCount - count of rows to expect from schema rowset
|
|
DBORDINAL m_ulRowCount;
|
|
|
|
// @cmember Restrictions
|
|
// If I can't find pubs for sql server or nwind for access,
|
|
// I'll take first catalog I find.
|
|
WCHAR * m_pwszCatalogRestriction;
|
|
WCHAR * m_pwszSchemaRestriction;
|
|
WCHAR * m_pwszTableRestriction;
|
|
WCHAR * m_pwszColumnRestriction;
|
|
|
|
WCHAR * m_pwszAssertion_ConstraintRestriction;
|
|
WCHAR * m_pwszCheck_ConstraintRestriction;
|
|
WCHAR * m_pwszKey_Column_Usage_ConstraintRestriction;
|
|
WCHAR * m_pwszReferential_ConstraintRestriction;
|
|
WCHAR * m_pwszTable_ConstraintRestriction;
|
|
|
|
WCHAR * m_pwszCharacter_SetRestriction;
|
|
WCHAR * m_pwszCollationRestriction;
|
|
WCHAR * m_pwszDomainRestriction;
|
|
WCHAR * m_pwszGrantorRestriction;
|
|
WCHAR * m_pwszGranteeRestriction;
|
|
WCHAR * m_pwszPK_TableRestriction;
|
|
WCHAR * m_pwszFK_TableRestriction;
|
|
WCHAR * m_pwszIndexRestriction;
|
|
WCHAR * m_pwszProcedureRestriction;
|
|
WCHAR * m_pwszProcedureColumnsRestriction;
|
|
WCHAR * m_pwszParameterRestriction;
|
|
TYPE_UI2 m_uiProcedureType;
|
|
WCHAR * m_pwszSchema_OwnerRestriction;
|
|
WCHAR * m_pwszTable_TypeRestriction;
|
|
WCHAR * m_pwszConstraint_TypeRestriction;
|
|
WCHAR * m_pwszTranslationReplace;
|
|
WCHAR * m_pwszObjectRestriction;
|
|
WCHAR * m_pwszObject_TypeRestriction;
|
|
WCHAR * m_pwszViewRestriction;
|
|
WCHAR * m_pwszStatisticsCatalogRestriction;
|
|
WCHAR * m_pwszStatisticsSchemaRestriction;
|
|
WCHAR * m_pwszStatisticsNameRestriction;
|
|
TYPE_UI2 m_uiStatisticsTypeRestriction;
|
|
LPWSTR m_pwszUpdateStatsFormat;
|
|
LPWSTR m_pwszSortSetting;
|
|
|
|
//--------------------
|
|
// Functions
|
|
//--------------------
|
|
|
|
// @cmember Constructor
|
|
CSchemaTest(const LPWSTR wszTestCaseName = NULL): CSessionObject(wszTestCaseName)
|
|
{
|
|
INIT
|
|
|
|
m_bSqlServer = FALSE;
|
|
m_rgDBPROPINFOSET=NULL;
|
|
m_pDescBuffer=NULL;
|
|
m_pRowsetDescBuffer = NULL;
|
|
m_cDBPROPINFOSET=0;
|
|
m_rgSupportedProperties=NULL;
|
|
m_cSupportedProperties=0;
|
|
m_fAtLeast1UnsupportedRestrictionIsSet=FALSE;
|
|
|
|
|
|
m_fPrintedSchemasAndRestrictions=FALSE;
|
|
m_currentBitMask = 0;
|
|
m_fDontCaptureRestrictions = FALSE;
|
|
|
|
m_rgColumnNames=NULL;
|
|
m_rgColumnTypes=NULL;
|
|
m_rgSchemas=NULL;
|
|
m_pDescBuffer=NULL;
|
|
m_pRowsetDescBuffer = NULL;
|
|
m_rgDBCOLUMNINFO=NULL;
|
|
m_pStringsBuffer=NULL;
|
|
m_rgDBBINDING=NULL;
|
|
m_punkOuter=NULL;
|
|
m_pIAccessor=NULL;
|
|
m_pIRowset=NULL;
|
|
m_pIRowsetInfo=NULL;
|
|
m_pIColumnsInfo=NULL;
|
|
m_pIRowsetChange=NULL;
|
|
m_pIOpenRowset = NULL;
|
|
m_pIDBSchemaRowset=NULL;
|
|
m_pIUnknown = NULL;
|
|
m_PrintSchemaName=TRUE;
|
|
|
|
m_pwszCatalogRestriction=NULL;
|
|
m_pwszSchemaRestriction=NULL;
|
|
m_pwszTableRestriction=NULL;
|
|
m_pwszColumnRestriction=NULL;
|
|
m_pwszAssertion_ConstraintRestriction=NULL;
|
|
m_pwszCheck_ConstraintRestriction=NULL;
|
|
m_pwszKey_Column_Usage_ConstraintRestriction=NULL;
|
|
m_pwszReferential_ConstraintRestriction=NULL;
|
|
m_pwszTable_ConstraintRestriction=NULL;
|
|
m_pwszCharacter_SetRestriction=NULL;
|
|
m_pwszCollationRestriction=NULL;
|
|
m_pwszDomainRestriction=NULL;
|
|
m_pwszGrantorRestriction=NULL;
|
|
m_pwszGranteeRestriction=NULL;
|
|
m_pwszPK_TableRestriction=NULL;
|
|
m_pwszFK_TableRestriction=NULL;
|
|
m_pwszIndexRestriction=NULL;
|
|
m_pwszProcedureRestriction=NULL;
|
|
m_pwszParameterRestriction=NULL;
|
|
m_pwszProcedureColumnsRestriction=NULL;
|
|
m_pwszStatisticsCatalogRestriction = NULL;
|
|
m_pwszStatisticsSchemaRestriction = NULL;
|
|
m_pwszStatisticsNameRestriction = NULL;
|
|
m_pwszUpdateStatsFormat = NULL;
|
|
m_pwszSortSetting = NULL;
|
|
|
|
m_uiProcedureType=0;
|
|
m_uiStatisticsTypeRestriction=0;
|
|
m_pwszSchema_OwnerRestriction=NULL;
|
|
m_pwszConstraint_TypeRestriction=NULL;
|
|
m_pwszTable_TypeRestriction=NULL;
|
|
m_pwszTranslationReplace=NULL;
|
|
m_pwszObjectRestriction=NULL;
|
|
m_pwszObject_TypeRestriction=NULL;
|
|
m_pwszViewRestriction=NULL;
|
|
m_rgRestrictionSupport=NULL;
|
|
|
|
m_rgRestrictionSupport=NULL;
|
|
m_pwszProcedureColumnsRestriction=NULL;
|
|
|
|
m_fPrintSupportedSchemas=TRUE;
|
|
m_fBOOKMARK_REQUESTED=FALSE;
|
|
m_fBOOKMARK_FOUND=FALSE;
|
|
m_fRes1=TRUE;
|
|
m_fRes2=TRUE;
|
|
m_fRes3=TRUE;
|
|
m_fRes4=TRUE;
|
|
m_fRes5=TRUE;
|
|
m_fRes6=TRUE;
|
|
m_fRes7=TRUE;
|
|
m_fMyTableCatalogFound=FALSE;
|
|
m_fMyTableSchemaFound=FALSE;
|
|
m_MyTableName1Found=FALSE;
|
|
m_MyTableName2Found=FALSE;
|
|
m_MyColumnNameFound=FALSE;
|
|
m_MyTableTypeFound=FALSE;
|
|
m_cErrors=0;
|
|
m_cColumns=0;
|
|
m_cRestrictions=0;
|
|
m_cRestrictionsCurrent=0;
|
|
m_cSchemasSupported=0;
|
|
m_cDBBINDING=0;
|
|
m_cDBPROPSET=0;
|
|
m_cDBCOLUMNINFO=0;
|
|
m_iid=IID_NULL;
|
|
m_guid=GUID_NULL;
|
|
m_restrict=0;
|
|
m_HR=E_FAIL;
|
|
m_fResult=FALSE;
|
|
m_fCaptureRestrictions=FALSE;
|
|
m_DataTypeRestriction=0;
|
|
m_ProcedureTypeRestriction=0;
|
|
|
|
|
|
m_fRowsetPointerNULL=FALSE;
|
|
m_fCountRestrictionsNULL=FALSE;
|
|
m_fRangeRestrictionsNULL=FALSE;
|
|
m_fCountPropSetNULL=FALSE;
|
|
m_fRangePropSetNULL=FALSE;
|
|
m_fPassUnsupportedRestrictions=FALSE;
|
|
m_fRestrictionsAsInitVariants=FALSE;
|
|
|
|
|
|
m_wszR1=NULL;
|
|
m_wszR2=NULL;
|
|
m_wszR3=NULL;
|
|
m_wszR4=NULL;
|
|
m_wszR5=NULL;
|
|
m_wszR6=NULL;
|
|
m_wszR7=NULL;
|
|
m_ulR=0;
|
|
m_fR = FALSE;
|
|
|
|
m_cRowsetDBPROPINFOSET = 0;
|
|
m_rgRowsetDBPROPINFOSET = NULL;
|
|
m_cRowsetPropSet=0;
|
|
m_rgRowsetPropSet=NULL;
|
|
m_eRowCount = MIN_VALUE;
|
|
m_ulRowCount = 1;
|
|
m_pwszTableName = NULL;
|
|
m_pwszStatName = NULL;
|
|
m_iOrdinalExpected = 0;
|
|
m_fDetailCheck = FALSE;
|
|
m_prgColInfo = NULL;
|
|
m_cColInfo = 0;
|
|
m_pwszStringsBuffer = NULL;
|
|
m_fPrimaryKey=FALSE;
|
|
m_fForeignKey=FALSE;
|
|
|
|
for(ULONG index=0;index<MAXRESTRICTION;index++)
|
|
VariantInit(&(m_rgvarRestrict[index]));
|
|
};
|
|
|
|
// @cmember Destructor
|
|
virtual ~CSchemaTest()
|
|
{
|
|
ULONG index;
|
|
FREE
|
|
|
|
ASSERT(!m_rgColumnNames);
|
|
ASSERT(!m_rgColumnTypes);
|
|
ASSERT(!m_rgSchemas);
|
|
ASSERT(!m_pIDBSchemaRowset);
|
|
ASSERT(!m_pIRowset);
|
|
ASSERT(!m_rgDBCOLUMNINFO);
|
|
ASSERT(!m_pStringsBuffer);
|
|
ASSERT(!m_rgDBBINDING);
|
|
ASSERT(!m_punkOuter);
|
|
ASSERT(!m_pIAccessor);
|
|
ASSERT(!m_pIRowsetInfo);
|
|
ASSERT(!m_pIColumnsInfo);
|
|
ASSERT(!m_pIRowsetChange);
|
|
ASSERT(!m_pIUnknown);
|
|
ASSERT(!m_pwszAssertion_ConstraintRestriction);
|
|
ASSERT(!m_pwszCheck_ConstraintRestriction);
|
|
ASSERT(!m_pwszKey_Column_Usage_ConstraintRestriction);
|
|
ASSERT(!m_pwszReferential_ConstraintRestriction);
|
|
ASSERT(!m_pwszTable_ConstraintRestriction);
|
|
ASSERT(!m_pwszCharacter_SetRestriction);
|
|
ASSERT(!m_pwszCollationRestriction);
|
|
ASSERT(!m_pwszDomainRestriction);
|
|
ASSERT(!m_pwszGrantorRestriction);
|
|
ASSERT(!m_pwszGranteeRestriction);
|
|
ASSERT(!m_pwszPK_TableRestriction);
|
|
ASSERT(!m_pwszFK_TableRestriction);
|
|
ASSERT(!m_pwszProcedureRestriction);
|
|
ASSERT(!m_pwszParameterRestriction);
|
|
ASSERT(!m_pwszProcedureColumnsRestriction);
|
|
ASSERT(!m_pwszSchema_OwnerRestriction);
|
|
ASSERT(!m_pwszConstraint_TypeRestriction);
|
|
ASSERT(!m_pwszTable_TypeRestriction);
|
|
ASSERT(!m_pwszTranslationReplace);
|
|
ASSERT(!m_pwszObjectRestriction);
|
|
ASSERT(!m_pwszObject_TypeRestriction);
|
|
ASSERT(!m_pwszViewRestriction);
|
|
ASSERT(!m_rgRestrictionSupport);
|
|
ASSERT(!m_rgRestrictionSupport);
|
|
ASSERT(!m_pwszProcedureColumnsRestriction);
|
|
|
|
for(index=0;index<MAXRESTRICTION;index++)
|
|
VariantClear(&(m_rgvarRestrict[index]));
|
|
for(index=0;index<MAXPROP;index++)
|
|
VariantClear(&(m_rgDBPROP[index].vValue));
|
|
|
|
SAFE_FREE(m_pwszTableName);
|
|
SAFE_FREE(m_pwszStatName);
|
|
SAFE_FREE(m_prgColInfo);
|
|
SAFE_FREE(m_pwszStringsBuffer);
|
|
};
|
|
|
|
// @cmember Init
|
|
BOOL Init(void);
|
|
|
|
// @cmember Terminate
|
|
BOOL Terminate(void);
|
|
|
|
// Check Results of Method
|
|
BOOL CheckResults(IUnknown * pIRowset, IID iid);
|
|
|
|
// Check Riid can be used
|
|
BOOL CheckRIID( IUnknown * pColRowset,IID iid);
|
|
|
|
// Verify Metadata of schema
|
|
BOOL CheckAgainstIColumnsInfo(void);
|
|
|
|
// GetRow
|
|
HRESULT GetRow(void);
|
|
|
|
// Set any interesting params and execute test method
|
|
HRESULT GetRowset(BOOL fFreeRowset=TRUE);
|
|
|
|
// Free Variation stuff
|
|
void Free_Stuff(void);
|
|
|
|
// Init Variation Stuff
|
|
void Init_Stuff(void);
|
|
|
|
// Get Next Schema Information, includes cRestrictions and rgRestrictions
|
|
BOOL GetSchemaInfo(
|
|
REQUESTED_SCHEMA schemaType, // [IN] if I want the schema supported, or not, or I have a specific schema in mind
|
|
ULONG ulIndexOfSchemaRequesting, // [IN] Index of Schema
|
|
GUID schema=GUID_NULL // [IN] index of schema (in header file)
|
|
);
|
|
|
|
// Verify Rowset for column names, column data types, and restrictions met.
|
|
// All TRACEable data will be put to debug window.
|
|
BOOL VerifyRowset(IUnknown * pIUnknown = NULL);
|
|
|
|
// @cmember VerifyRow, verifies restrictions only.
|
|
virtual BOOL VerifyRow(
|
|
GUID m_guid,
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pRow
|
|
);
|
|
|
|
// @cmember SetRestriction
|
|
void SetRestriction(ULONG bit);
|
|
|
|
// @cmember ClearRestriction
|
|
void ClearRestriction(ULONG bit);
|
|
|
|
// @cmember IsSchemaSupported
|
|
BOOL IsSchemaSupported(GUID schema);
|
|
|
|
// @cmember TestSchemaRestrictions
|
|
BOOL TestSchemaRestrictions(GUID schema,ULONG bit, ROW_COUNT eRowCount=DEFAULT, ULONG cExpRows=0);
|
|
|
|
// @cmember Test Data Returned from IDBSchema
|
|
BOOL TestReturnData(DBCOUNTITEM iRow,DATA * pColumn,ULONG bit,BOOL * fRes,WCHAR * wszRes, BOOL fNullable=TRUE);
|
|
|
|
// @cmember Test the Table Name Restriction
|
|
void SetRestriction(RESTRICTIONSENUM ebit,ULONG ulRestriction,WCHAR ** pwszR,WCHAR * wszRestriction);
|
|
|
|
BOOL PrepareParams_ASSERTIONS();
|
|
BOOL VerifyRow_ASSERTIONS(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_CATALOGS();
|
|
BOOL VerifyRow_CATALOGS(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_CHARACTER_SETS();
|
|
BOOL VerifyRow_CHARACTER_SETS(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_CHECK_CONSTRAINTS();
|
|
BOOL VerifyRow_CHECK_CONSTRAINTS(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_COLLATIONS();
|
|
BOOL VerifyRow_COLLATIONS(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_COLUMN_DOMAIN_USAGE();
|
|
BOOL VerifyRow_COLUMN_DOMAIN_USAGE(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_COLUMN_PRIVILEGES();
|
|
BOOL VerifyRow_COLUMN_PRIVILEGES(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_COLUMNS();
|
|
BOOL VerifyRow_COLUMNS(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_CONSTRAINT_COLUMN_USAGE();
|
|
BOOL VerifyRow_CONSTRAINT_COLUMN_USAGE(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_CONSTRAINT_TABLE_USAGE();
|
|
BOOL VerifyRow_CONSTRAINT_TABLE_USAGE(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_FOREIGN_KEYS();
|
|
BOOL VerifyRow_FOREIGN_KEYS(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_INDEXES();
|
|
BOOL VerifyRow_INDEXES(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_KEY_COLUMN_USAGE();
|
|
BOOL VerifyRow_KEY_COLUMN_USAGE(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_PRIMARY_KEYS();
|
|
BOOL VerifyRow_PRIMARY_KEYS(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_PROCEDURE_COLUMNS();
|
|
BOOL VerifyRow_PROCEDURE_COLUMNS(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_PROCEDURE_PARAMETERS();
|
|
BOOL VerifyRow_PROCEDURE_PARAMETERS(DBCOUNTITEM iRow, BYTE * pData);
|
|
|
|
BOOL PrepareParams_PROCEDURES();
|
|
BOOL VerifyRow_PROCEDURES(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_PROVIDER_TYPES();
|
|
BOOL VerifyRow_PROVIDER_TYPES(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_REFERENTIAL_CONSTRAINTS();
|
|
BOOL VerifyRow_REFERENTIAL_CONSTRAINTS(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_SCHEMATA();
|
|
BOOL VerifyRow_SCHEMATA(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_SQL_LANGUAGES();
|
|
BOOL VerifyRow_SQL_LANGUAGES(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_STATISTICS();
|
|
BOOL VerifyRow_STATISTICS(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_TABLE_CONSTRAINTS();
|
|
BOOL VerifyRow_TABLE_CONSTRAINTS(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_TABLE_PRIVILEGES();
|
|
BOOL VerifyRow_TABLE_PRIVILEGES(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_TABLE_STATISTICS();
|
|
BOOL VerifyRow_TABLE_STATISTICS(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_TABLES();
|
|
BOOL VerifyRow_TABLES(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_TABLES_INFO();
|
|
BOOL VerifyRow_TABLES_INFO(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_TRANSLATIONS();
|
|
BOOL VerifyRow_TRANSLATIONS(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_TRUSTEE();
|
|
BOOL VerifyRow_TRUSTEE(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_USAGE_PRIVILEGES();
|
|
BOOL VerifyRow_USAGE_PRIVILEGES(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_VIEW_COLUMN_USAGE();
|
|
BOOL VerifyRow_VIEW_COLUMN_USAGE(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_VIEW_TABLE_USAGE();
|
|
BOOL VerifyRow_VIEW_TABLE_USAGE(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
BOOL PrepareParams_VIEWS();
|
|
BOOL VerifyRow_VIEWS(DBCOUNTITEM iRow,BYTE * pData);
|
|
|
|
// Capture Restrictions
|
|
BOOL CaptureRestrictions();
|
|
void FreeRestrictions();
|
|
|
|
BOOL Find_Catalog_and_Schema();
|
|
BOOL Find_TableInfo();
|
|
BOOL Find_Assertion_Constraint();
|
|
BOOL Find_Character_Set();
|
|
BOOL Find_Collation();
|
|
BOOL Find_Domain();
|
|
BOOL Find_Grantor_and_Grantee();
|
|
BOOL Find_Key_Column_Usage_Constraint();
|
|
BOOL Find_Procedure();
|
|
BOOL Find_ProcedureColumn();
|
|
BOOL Find_Parameter();
|
|
BOOL Find_Referential_Constraint();
|
|
BOOL Find_Constraint_Type();
|
|
BOOL Find_Translation();
|
|
BOOL Find_View();
|
|
BOOL Find_Check_Constraint();
|
|
BOOL Find_BestMatch();
|
|
BOOL Find_PK_and_FK();
|
|
BOOL Find_Table_Statistics_Restrictions();
|
|
BOOL UpdateStatistics(void);
|
|
|
|
|
|
BOOL Release_Catalog_and_Schema();
|
|
BOOL Release_TableInfo();
|
|
BOOL Release_Assertion_Constraint();
|
|
BOOL Release_Character_Set();
|
|
BOOL Release_Collation();
|
|
BOOL Release_Domain();
|
|
BOOL Release_Grantor_and_Grantee();
|
|
BOOL Release_Key_Column_Usage_Constraint();
|
|
BOOL Release_Procedure();
|
|
BOOL Release_ProcedureColumn();
|
|
BOOL Release_Parameter();
|
|
BOOL Release_Referential_Constraint();
|
|
BOOL Release_Constraint_Type();
|
|
BOOL Release_Translation();
|
|
BOOL Release_View();
|
|
BOOL Release_Check_Constraint();
|
|
BOOL Release_Index_Type();
|
|
BOOL Release_PK_and_FK();
|
|
BOOL Release_Table_Statistics_Restrictions();
|
|
|
|
|
|
HRESULT GetAllPropertySets();
|
|
HRESULT FreeAllPropertySets();
|
|
|
|
HRESULT ShouldTestSchemaRestriction(GUID schema,ULONG restrictions);
|
|
HRESULT GetRowsetPropertySet();
|
|
ULONG NumberofRestrictions(GUID schema);
|
|
|
|
BOOL PropIsBool(DBPROPID prop);
|
|
BOOL IsRowsetPropertySupported(DBPROPID propid);
|
|
BOOL IsRowsetPropertySet(GUID guidPropset);
|
|
|
|
// Functions for creating tables with Primary and foreign keys.
|
|
BOOL InitKeysOnTable();
|
|
BOOL TerminateKeysOnTable();
|
|
|
|
// Returns restriction number if it is known the schema guid for index has a catalog restriction.
|
|
ULONG SchemaCatalogRestriction(GUID guidSchema);
|
|
ULONG SchemaCatalogRestriction(ULONG ulIndex);
|
|
|
|
// Returns restriction number if it is known the schema guid for index has a schema restriction.
|
|
ULONG SchemaSchemaRestriction(GUID guidSchema);
|
|
ULONG SchemaSchemaRestriction(ULONG ulIndex);
|
|
|
|
// Returns restriction number if it is known the schema guid for index has a table name restriction.
|
|
ULONG SchemaTableRestriction(GUID guidSchema);
|
|
ULONG SchemaTableRestriction(ULONG ulIndex);
|
|
|
|
// Sets catalog restriction for those schemas that support it to prevent excessive run times.
|
|
void LimitRestrictions(ULONG ulIndex);
|
|
|
|
protected:
|
|
ULONG m_ulTableOrdinal;
|
|
LPWSTR m_pwszStringsBuffer;
|
|
DBCOLUMNINFO * m_prgColInfo;
|
|
DBORDINAL m_cColInfo;
|
|
LPWSTR m_pwszTableName;
|
|
LPWSTR m_pwszStatName;
|
|
|
|
|
|
BOOL m_fPrimaryKey;
|
|
BOOL m_fForeignKey;
|
|
ULONG m_iOrdinalExpected;
|
|
BOOL m_fDetailCheck;
|
|
|
|
// Returns the count of columns and column info for the given table
|
|
HRESULT GetColumnInfo(LPBYTE pData, DBBINDING * pBinding);
|
|
|
|
void SetRowCount(ROW_COUNT eRowCount, DBORDINAL ulRowCount);
|
|
|
|
virtual HRESULT GetNextRows(DBROWOFFSET lOffset, DBROWCOUNT cRows, DBCOUNTITEM* pcRowsObtained, HROW** prghRow);
|
|
|
|
LPBYTE GetValuePtr(DBORDINAL iOrdinal, LPBYTE pData, DBBINDING * pBinding = NULL);
|
|
|
|
BOOL CheckHistogramColInfo(IRowset * pIHistogramRowset, DBTYPE wRangeColType,
|
|
DBORDINAL * pcBinding, DBBINDING ** ppBinding, DBLENGTH * pcbRowSize,
|
|
HACCESSOR * phAccessor);
|
|
|
|
// Returns cardinality (COUNT) information for the given table using ulColIndex index into
|
|
// columns info for table.
|
|
DBCOUNTITEM Cardinality(LPWSTR pwszTableName, ULONG ulColIndex, CARDINALITY eCardinality,
|
|
DBBINDING * pStartBind = NULL, DBBINDING * pEndBind = NULL, LPBYTE pDataHist = NULL,
|
|
DBLENGTH cbRowSize = 0);
|
|
|
|
CErrorCache m_EC;
|
|
|
|
};
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Init
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::Init()
|
|
{
|
|
ULONG iDBMS = 0;
|
|
WCHAR * pwszDBMSName = NULL;
|
|
|
|
m_cRowsetPropSet=0;
|
|
m_rgRowsetPropSet=NULL;
|
|
|
|
// Initialize error cache
|
|
m_EC.Init(GetModInfo()->GetDebugMode());
|
|
|
|
if(COLEDB::Init())
|
|
{
|
|
WCHAR * pwszOLEDBVER = NULL;
|
|
|
|
m_pwszDropProc=NULL;
|
|
|
|
// Set DSO pointer
|
|
if(m_pThisTestModule->m_pIUnknown)
|
|
{
|
|
m_pIDBInitialize = (IDBInitialize *)m_pThisTestModule->m_pIUnknown;
|
|
m_pIDBInitialize->AddRef();
|
|
}
|
|
|
|
// Set CSession pointer
|
|
SetDBSession((IDBCreateCommand *)m_pThisTestModule->m_pIUnknown2);
|
|
|
|
// Set Table pointer
|
|
SetTable((CTable *)m_pThisTestModule->m_pVoid, DELETETABLE_NO);
|
|
|
|
// Get IDBSchemaRowset pointer
|
|
if(m_pIOpenRowset)
|
|
{
|
|
if(FAILED(m_pIOpenRowset->QueryInterface(
|
|
IID_IDBSchemaRowset,
|
|
(void **) &m_pIDBSchemaRowset)))
|
|
return FALSE;
|
|
|
|
}
|
|
else //(m_pIDBCreateCommand)
|
|
{
|
|
if(FAILED(m_pIDBCreateCommand->QueryInterface(
|
|
IID_IDBSchemaRowset,
|
|
(void **) &m_pIDBSchemaRowset)))
|
|
return FALSE;
|
|
}
|
|
|
|
// First check for support for alter table syntax.
|
|
ULONG_PTR ulSQLSupport = 0;
|
|
GetProperty(DBPROP_SQLSUPPORT, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &ulSQLSupport);
|
|
|
|
if( ulSQLSupport & DBPROPVAL_SQL_ANSI89_IEF )
|
|
InitKeysOnTable();
|
|
|
|
// Get Supported Schemas
|
|
if(FAILED(m_pIDBSchemaRowset->GetSchemas(
|
|
&m_cSchemasSupported,
|
|
&m_rgSchemas,
|
|
&m_rgRestrictionSupport)))
|
|
{
|
|
m_pIDBSchemaRowset->Release();
|
|
m_pIDBSchemaRowset = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
if(m_cSchemasSupported==0)
|
|
{
|
|
odtLog << L"No schemas supported\n";
|
|
return FALSE;
|
|
}
|
|
if(FAILED(GetAllPropertySets()))
|
|
return FALSE;
|
|
|
|
if(FAILED(GetRowsetPropertySet()))
|
|
return FALSE;
|
|
|
|
// Get DBPROP_PROVIDEROLEDBVER for use in setting correct column count for each schema
|
|
if (GetProperty(DBPROP_PROVIDEROLEDBVER, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &pwszOLEDBVER))
|
|
{
|
|
if (!wcscmp(pwszOLEDBVER, L"02.00"))
|
|
m_ulOLEDBVer = VER_20;
|
|
else if (!wcscmp(pwszOLEDBVER, L"02.10"))
|
|
m_ulOLEDBVer = VER_21;
|
|
else if (!wcscmp(pwszOLEDBVER, L"02.50"))
|
|
m_ulOLEDBVer = VER_25;
|
|
else if (!wcscmp(pwszOLEDBVER, L"02.60"))
|
|
m_ulOLEDBVer = VER_26;
|
|
else if (!wcscmp(pwszOLEDBVER, L"02.70"))
|
|
m_ulOLEDBVer = VER_27;
|
|
else
|
|
ASSERT(!L"Unknown schema version.");
|
|
|
|
SAFE_FREE(pwszOLEDBVER);
|
|
|
|
}
|
|
|
|
// Call the GetProperty for the DBMS Name
|
|
if(GetProperty(DBPROP_DBMSNAME, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &pwszDBMSName))
|
|
{
|
|
if (!wcscmp(pwszDBMSName, L"Microsoft SQL Server"))
|
|
m_bSqlServer = TRUE;
|
|
|
|
// Get the DBMS specific command to create/update statistics and set sorts
|
|
for (iDBMS = 0; iDBMS < NUMELEM(g_DBMSList); iDBMS++)
|
|
{
|
|
if (!wcscmp(pwszDBMSName, g_DBMSList[iDBMS].pwszDBMSName))
|
|
{
|
|
m_pwszUpdateStatsFormat = g_DBMSList[iDBMS].pwszUpdateStatsFormat;
|
|
m_pwszSortSetting = g_DBMSList[iDBMS].pwszSortSetting;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set the sort sequence desired
|
|
if (m_pwszSortSetting)
|
|
{
|
|
CHECK(m_pTable->BuildCommand(m_pwszSortSetting, IID_IRowset,
|
|
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL, NULL), S_OK);
|
|
}
|
|
|
|
// if(!m_fDontCaptureRestrictions)
|
|
// CaptureRestrictions();
|
|
|
|
PROVIDER_FREE(pwszDBMSName);
|
|
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Terminate
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::Terminate()
|
|
{
|
|
|
|
// Release everything from the init
|
|
SAFE_RELEASE(m_pIDBSchemaRowset);
|
|
|
|
// Free the memory
|
|
PROVIDER_FREE(m_rgSchemas);
|
|
PROVIDER_FREE(m_rgRestrictionSupport);
|
|
PROVIDER_FREE(m_rgSupportedProperties);
|
|
|
|
// Free the Properties
|
|
FreeProperties(&m_cDBPROPINFOSET, &m_rgDBPROPINFOSET, &m_pDescBuffer);
|
|
FreeProperties(&m_cRowsetDBPROPINFOSET, &m_rgRowsetDBPROPINFOSET, &m_pRowsetDescBuffer);
|
|
FreeProperties(&m_cRowsetPropSet, &m_rgRowsetPropSet);
|
|
|
|
FreeRestrictions();
|
|
|
|
ULONG_PTR ulSQLSupport = 0;
|
|
if (m_pIDBInitialize)
|
|
GetProperty(DBPROP_SQLSUPPORT, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &ulSQLSupport);
|
|
|
|
if( ulSQLSupport & DBPROPVAL_SQL_ANSI89_IEF )
|
|
TerminateKeysOnTable();
|
|
|
|
ReleaseDBSession();
|
|
SAFE_RELEASE(m_pIDBInitialize);
|
|
|
|
if(!COLEDB::Terminate())
|
|
return FALSE;
|
|
|
|
return(CTestCases::Terminate());
|
|
}
|
|
|
|
// Is the property set GUID one of the Rowset property GUIDs
|
|
BOOL CSchemaTest::IsRowsetPropertySet(GUID guidPropset)
|
|
{
|
|
// Loop through all the Rowset property info from the DBPROPSET_ROWSETALL
|
|
// Includes provider specific
|
|
for (ULONG iPropertyInfoSet=0;
|
|
iPropertyInfoSet < m_cRowsetDBPROPINFOSET;
|
|
iPropertyInfoSet++
|
|
)
|
|
if (m_rgRowsetDBPROPINFOSET[iPropertyInfoSet].guidPropertySet == guidPropset)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Is rowset property supported by temp table
|
|
//
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::IsRowsetPropertySupported(DBPROPID propid)
|
|
{
|
|
ULONG i,j;
|
|
ULONG iRowsetSet=0;
|
|
|
|
for(i=0;i<m_rgRowsetPropSet[0].cProperties;i++)
|
|
{
|
|
if(propid==m_rgRowsetPropSet[0].rgProperties[i].dwPropertyID)
|
|
{
|
|
if (m_rgRowsetPropSet[0].rgProperties[i].dwStatus != DBPROPSTATUS_NOTSUPPORTED)
|
|
{
|
|
PRVTRACE(L"Property is supported\n");
|
|
goto CHECK_WRITABLE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"Property is not supported\n");
|
|
return FALSE;
|
|
|
|
|
|
CHECK_WRITABLE:
|
|
for(i=0;i<m_cDBPROPINFOSET;i++)
|
|
{
|
|
if(IsEqualGUID(m_rgDBPROPINFOSET[i].guidPropertySet,DBPROPSET_ROWSET))
|
|
{
|
|
for(j=0;j<m_rgDBPROPINFOSET[i].cPropertyInfos;j++)
|
|
{
|
|
if(m_rgDBPROPINFOSET[i].rgPropertyInfos[j].dwPropertyID==propid)
|
|
{
|
|
if(m_rgDBPROPINFOSET[i].rgPropertyInfos[j].dwFlags &DBPROPFLAGS_WRITE)
|
|
{
|
|
PRVTRACE(L"Property is writable\n");
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"Property is not writable\n");
|
|
//odtLog << L"Property is not writable\n";
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Find all rowset properties that temp table supports
|
|
//
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
HRESULT CSchemaTest::GetRowsetPropertySet()
|
|
{
|
|
HRESULT hr=E_FAIL;
|
|
IRowsetInfo * pIRowsetInfo=NULL;
|
|
|
|
if(!m_pIDBSchemaRowset)
|
|
goto CLEANUP;
|
|
|
|
// generate rowset with types as schema
|
|
// since it is mandatory
|
|
if(FAILED(hr=m_pIDBSchemaRowset->GetRowset(
|
|
NULL,
|
|
DBSCHEMA_PROVIDER_TYPES,
|
|
0,
|
|
NULL,
|
|
IID_IRowsetInfo,
|
|
0,
|
|
NULL,
|
|
(IUnknown **) &pIRowsetInfo)))
|
|
goto CLEANUP;
|
|
if(FAILED(hr=pIRowsetInfo->GetProperties(
|
|
0,
|
|
NULL,
|
|
&m_cRowsetPropSet,
|
|
&m_rgRowsetPropSet)))
|
|
goto CLEANUP;
|
|
|
|
CLEANUP:
|
|
|
|
if(pIRowsetInfo)
|
|
pIRowsetInfo->Release();
|
|
|
|
return hr;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Is Property a VT_BOOL
|
|
//
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::PropIsBool(DBPROPID prop)
|
|
{
|
|
if (( prop == DBPROP_ABORTPRESERVE) ||
|
|
(prop == DBPROP_APPENDONLY) ||
|
|
(prop == DBPROP_BLOCKINGSTORAGEOBJECTS) ||
|
|
(prop == DBPROP_BOOKMARKS) ||
|
|
(prop == DBPROP_BOOKMARKSKIPPED) ||
|
|
(prop == DBPROP_CACHEDEFERRED) ||
|
|
(prop == DBPROP_CANFETCHBACKWARDS) ||
|
|
(prop == DBPROP_CANHOLDROWS) ||
|
|
(prop == DBPROP_CANSCROLLBACKWARDS) ||
|
|
(prop == DBPROP_CHANGEINSERTEDROWS) ||
|
|
(prop == DBPROP_COLUMNRESTRICT) ||
|
|
(prop == DBPROP_COMMITPRESERVE) ||
|
|
(prop == DBPROP_DEFERRED) ||
|
|
(prop == DBPROP_DELAYSTORAGEOBJECTS) ||
|
|
(prop == DBPROP_IMMOBILEROWS) ||
|
|
(prop == DBPROP_LITERALBOOKMARKS) ||
|
|
(prop == DBPROP_LITERALIDENTITY) ||
|
|
(prop == DBPROP_MAYWRITECOLUMN) ||
|
|
(prop == DBPROP_ORDEREDBOOKMARKS) ||
|
|
(prop == DBPROP_OTHERINSERT) ||
|
|
(prop == DBPROP_OTHERUPDATEDELETE) ||
|
|
(prop == DBPROP_OWNINSERT) ||
|
|
(prop == DBPROP_OWNUPDATEDELETE) ||
|
|
(prop == DBPROP_QUICKRESTART) ||
|
|
(prop == DBPROP_REENTRANTEVENTS) ||
|
|
(prop == DBPROP_REMOVEDELETED) ||
|
|
(prop == DBPROP_REPORTMULTIPLECHANGES) ||
|
|
(prop == DBPROP_RETURNPENDINGINSERTS) ||
|
|
(prop == DBPROP_ROWRESTRICT) ||
|
|
(prop == DBPROP_SERVERCURSOR) ||
|
|
(prop == DBPROP_STRONGIDENTITY) ||
|
|
(prop == DBPROP_TRANSACTEDOBJECT) ||
|
|
(prop == DBPROP_OTHERINSERT) ||
|
|
(prop == DBPROP_IAccessor) ||
|
|
(prop == DBPROP_IColumnsInfo) ||
|
|
(prop == DBPROP_IColumnsRowset) ||
|
|
(prop == DBPROP_IConnectionPointContainer) ||
|
|
(prop == DBPROP_IRowset) ||
|
|
(prop == DBPROP_IRowsetChange) ||
|
|
(prop == DBPROP_IRowsetIdentity) ||
|
|
(prop == DBPROP_IRowsetInfo) ||
|
|
(prop == DBPROP_IRowsetLocate) ||
|
|
(prop == DBPROP_IRowsetResynch) ||
|
|
(prop == DBPROP_IRowsetScroll) ||
|
|
(prop == DBPROP_IRowsetUpdate) ||
|
|
(prop == DBPROP_ISupportErrorInfo) ||
|
|
(prop == DBPROP_ILockBytes) ||
|
|
(prop == DBPROP_ISequentialStream) ||
|
|
(prop == DBPROP_IStorage) ||
|
|
(prop == DBPROP_IStream))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
//
|
|
//
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
HRESULT CSchemaTest::GetAllPropertySets()
|
|
{
|
|
|
|
HRESULT hr=E_FAIL;
|
|
ULONG index1=0;
|
|
ULONG index2=0;
|
|
IDBProperties * pIDBProperties=NULL;
|
|
|
|
// make sure I have a DSO object
|
|
if(!m_pIDBInitialize)
|
|
goto CLEANUP;
|
|
|
|
// get necessary pointer
|
|
if(!CHECK(hr=m_pIDBInitialize->QueryInterface(IID_IDBProperties,(void**)&pIDBProperties),S_OK))
|
|
goto CLEANUP;
|
|
|
|
// get property info
|
|
if(FAILED(hr=pIDBProperties->GetPropertyInfo(0,NULL,&m_cDBPROPINFOSET,&m_rgDBPROPINFOSET,&m_pDescBuffer)))
|
|
goto CLEANUP;
|
|
|
|
// Get all the rowset properties
|
|
DBPROPIDSET rgRowsetIDSET[1];
|
|
rgRowsetIDSET[0].rgPropertyIDs=NULL;
|
|
rgRowsetIDSET[0].cPropertyIDs=0;
|
|
rgRowsetIDSET[0].guidPropertySet=DBPROPSET_ROWSETALL;
|
|
|
|
if(FAILED(hr=pIDBProperties->GetPropertyInfo(1,rgRowsetIDSET,&m_cRowsetDBPROPINFOSET,&m_rgRowsetDBPROPINFOSET,&m_pRowsetDescBuffer)))
|
|
goto CLEANUP;
|
|
|
|
for(index1=0;index1<m_cDBPROPINFOSET;index1++)
|
|
{
|
|
if(IsEqualGUID(m_rgDBPROPINFOSET[index1].guidPropertySet,DBPROPSET_COLUMN))
|
|
PRVTRACE(L"[DBPROPSET_COLUMN]\n");
|
|
else if(IsEqualGUID(m_rgDBPROPINFOSET[index1].guidPropertySet,DBPROPSET_DATASOURCE))
|
|
PRVTRACE(L"[DBPROPSET_DATASOURCE]\n");
|
|
else if(IsEqualGUID(m_rgDBPROPINFOSET[index1].guidPropertySet,DBPROPSET_DATASOURCEALL))
|
|
PRVTRACE(L"[DBPROPSET_DATASOURCEALL]\n");
|
|
else if(IsEqualGUID(m_rgDBPROPINFOSET[index1].guidPropertySet,DBPROPSET_DATASOURCEINFOALL))
|
|
PRVTRACE(L"[DBPROPSET_DATASOURCEINFOALL]\n");
|
|
else if(IsEqualGUID(m_rgDBPROPINFOSET[index1].guidPropertySet,DBPROPSET_DATASOURCEINFO))
|
|
PRVTRACE(L"[DBPROPSET_DATASOURCEINFO]\n");
|
|
else if(IsEqualGUID(m_rgDBPROPINFOSET[index1].guidPropertySet,DBPROPSET_DBINIT))
|
|
PRVTRACE(L"[DBPROPSET_DBINIT]\n");
|
|
else if(IsEqualGUID(m_rgDBPROPINFOSET[index1].guidPropertySet,DBPROPSET_DBINITALL))
|
|
PRVTRACE(L"[DBPROPSET_DBINITALL]\n");
|
|
else if(IsEqualGUID(m_rgDBPROPINFOSET[index1].guidPropertySet,DBPROPSET_INDEX))
|
|
PRVTRACE(L"[DBPROPSET_INDEX]\n");
|
|
else if(IsEqualGUID(m_rgDBPROPINFOSET[index1].guidPropertySet,DBPROPSET_ROWSET))
|
|
PRVTRACE(L"[DBPROPSET_ROWSET]\n");
|
|
else if(IsEqualGUID(m_rgDBPROPINFOSET[index1].guidPropertySet,DBPROPSET_ROWSETALL))
|
|
PRVTRACE(L"[DBPROPSET_ROWSETALL]\n");
|
|
else if(IsEqualGUID(m_rgDBPROPINFOSET[index1].guidPropertySet,DBPROPSET_SESSION))
|
|
PRVTRACE(L"[DBPROPSET_SESSION]\n");
|
|
else if(IsEqualGUID(m_rgDBPROPINFOSET[index1].guidPropertySet,DBPROPSET_SESSIONALL))
|
|
PRVTRACE(L"[DBPROPSET_SESSIONALL]\n");
|
|
else if(IsEqualGUID(m_rgDBPROPINFOSET[index1].guidPropertySet,DBPROPSET_TABLE))
|
|
PRVTRACE(L"[DBPROPSET_TABLE]\n");
|
|
else if(IsEqualGUID(m_rgDBPROPINFOSET[index1].guidPropertySet,DBPROPSET_PROPERTIESINERROR))
|
|
PRVTRACE(L"[DBPROPSET_PROPERTIESINERROR]\n");
|
|
else
|
|
PRVTRACE(L"[Unknown DBPROPSET]\n");
|
|
|
|
for(index2=0;index2<m_rgDBPROPINFOSET[index1].cPropertyInfos;index2++)
|
|
{
|
|
|
|
PRVTRACE(L"[desc=%s],[propid=%d],[dwflags=%d],[vartype=%d]\n",
|
|
m_rgDBPROPINFOSET[index1].rgPropertyInfos[index2].pwszDescription,
|
|
m_rgDBPROPINFOSET[index1].rgPropertyInfos[index2].dwPropertyID,
|
|
m_rgDBPROPINFOSET[index1].rgPropertyInfos[index2].dwFlags,
|
|
m_rgDBPROPINFOSET[index1].rgPropertyInfos[index2].vtType);
|
|
}
|
|
|
|
}
|
|
|
|
CLEANUP:
|
|
|
|
|
|
if(pIDBProperties)
|
|
pIDBProperties->Release();
|
|
|
|
return hr;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// ShouldTestSchemaRestriction
|
|
//
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
HRESULT CSchemaTest::ShouldTestSchemaRestriction(GUID schema,ULONG restrictions)
|
|
{
|
|
// Figure out the return code
|
|
for(ULONG index=0; index < m_cSchemasSupported; index++)
|
|
{
|
|
if(IsEqualGUID(schema,m_rgSchemas[index]))
|
|
{
|
|
if( (ALLRES & restrictions) ||
|
|
(m_rgRestrictionSupport[index] & restrictions) )
|
|
return S_OK;
|
|
|
|
if(restrictions <= NumberofRestrictions(schema))
|
|
return E_INVALIDARG;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return E_INVALIDARG;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// NumberofRestrictions
|
|
//
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
ULONG CSchemaTest::NumberofRestrictions(GUID schema)
|
|
{
|
|
// all schemas with 0 restrictions
|
|
// don't need to check schemas anyway
|
|
if(IsEqualGUID(schema,DBSCHEMA_SQL_LANGUAGES))
|
|
return 0;
|
|
|
|
// all schemas with 1 retriction
|
|
if(IsEqualGUID(schema,DBSCHEMA_CATALOGS))
|
|
return 1;
|
|
|
|
// all schemas with 2 restrictions
|
|
if(IsEqualGUID(schema,DBSCHEMA_PROVIDER_TYPES))
|
|
return 3;
|
|
|
|
// all schemas with 3 restrictions
|
|
if(IsEqualGUID(schema,DBSCHEMA_ASSERTIONS) ||
|
|
IsEqualGUID(schema,DBSCHEMA_CHARACTER_SETS) ||
|
|
IsEqualGUID(schema,DBSCHEMA_CHECK_CONSTRAINTS) ||
|
|
IsEqualGUID(schema,DBSCHEMA_COLLATIONS) ||
|
|
IsEqualGUID(schema,DBSCHEMA_CONSTRAINT_TABLE_USAGE) ||
|
|
IsEqualGUID(schema,DBSCHEMA_PRIMARY_KEYS) ||
|
|
IsEqualGUID(schema,DBSCHEMA_REFERENTIAL_CONSTRAINTS) ||
|
|
IsEqualGUID(schema,DBSCHEMA_SCHEMATA) ||
|
|
IsEqualGUID(schema,DBSCHEMA_STATISTICS) ||
|
|
IsEqualGUID(schema,DBSCHEMA_TRANSLATIONS) ||
|
|
IsEqualGUID(schema,DBSCHEMA_VIEW_COLUMN_USAGE) ||
|
|
IsEqualGUID(schema,DBSCHEMA_VIEW_TABLE_USAGE) ||
|
|
IsEqualGUID(schema,DBSCHEMA_VIEWS))
|
|
return 7;
|
|
|
|
// all schemas with 4 restrictions
|
|
if(IsEqualGUID(schema,DBSCHEMA_COLUMN_DOMAIN_USAGE) ||
|
|
IsEqualGUID(schema,DBSCHEMA_COLUMNS) ||
|
|
IsEqualGUID(schema,DBSCHEMA_CONSTRAINT_COLUMN_USAGE) ||
|
|
IsEqualGUID(schema,DBSCHEMA_PROCEDURE_COLUMNS) ||
|
|
IsEqualGUID(schema,DBSCHEMA_PROCEDURE_PARAMETERS) ||
|
|
IsEqualGUID(schema,DBSCHEMA_PROCEDURES) ||
|
|
IsEqualGUID(schema,DBSCHEMA_TABLES) ||
|
|
IsEqualGUID(schema,DBSCHEMA_TABLES_INFO))
|
|
return 15;
|
|
|
|
// all schemas with 5 restrictions
|
|
if(IsEqualGUID(schema,DBSCHEMA_INDEXES) ||
|
|
IsEqualGUID(schema,DBSCHEMA_TABLE_PRIVILEGES))
|
|
return 31;
|
|
|
|
// all schemas with 6 restrictions
|
|
if(IsEqualGUID(schema,DBSCHEMA_COLUMN_PRIVILEGES) ||
|
|
IsEqualGUID(schema,DBSCHEMA_FOREIGN_KEYS) ||
|
|
IsEqualGUID(schema,DBSCHEMA_USAGE_PRIVILEGES))
|
|
return 63;
|
|
|
|
// all schemas with 7 restrictions
|
|
if(IsEqualGUID(schema,DBSCHEMA_KEY_COLUMN_USAGE) ||
|
|
IsEqualGUID(schema,DBSCHEMA_TABLE_CONSTRAINTS)||
|
|
IsEqualGUID(schema,DBSCHEMA_TABLE_STATISTICS))
|
|
return 127;
|
|
|
|
return 0;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Set Bit
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void CSchemaTest::SetRestriction(ULONG bit)
|
|
{
|
|
m_restrict |= bit;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Clear Bit
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void CSchemaTest::ClearRestriction(ULONG bit)
|
|
{
|
|
m_restrict &= ~(bit);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Test Schema Restrictions
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::TestSchemaRestrictions(GUID schema, ULONG bit, ROW_COUNT eRowCount, ULONG cExpRows)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
HRESULT ExpHR = S_OK;
|
|
|
|
// Initialize the needed pointers
|
|
INIT;
|
|
|
|
// This is not initialized on purpose
|
|
ExpHR=ShouldTestSchemaRestriction(schema,bit);
|
|
|
|
if(FAILED(ExpHR))
|
|
{
|
|
odtLog <<wszRESTRICTIONNOTSUPPORTED;
|
|
m_fPassUnsupportedRestrictions = TRUE;
|
|
}
|
|
|
|
// Set the correct info
|
|
SetRestriction(bit);
|
|
m_iid = IID_IRowset;
|
|
|
|
if(GetSchemaInfo(SPECIFIC,0,schema))
|
|
{
|
|
// Update expected row count if required for this variation.
|
|
if (eRowCount != DEFAULT)
|
|
SetRowCount(eRowCount, cExpRows);
|
|
|
|
// Test method with invalid schema guid
|
|
hr=GetRowset();
|
|
|
|
// Provider either returns E_INVALIDARG or DB_E_NOTSUPPORTED
|
|
if( (FAILED(ExpHR) && (hr == E_INVALIDARG || hr == DB_E_NOTSUPPORTED)) ||
|
|
(CHECK(hr, ExpHR)) )
|
|
m_fResult = TEST_PASS;
|
|
}
|
|
|
|
FREE;
|
|
|
|
return m_fResult;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Test Schema Restrictions
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::TestReturnData(DBCOUNTITEM iRow, DATA * pColumn, ULONG bit, BOOL * fRes, WCHAR * wszRes, BOOL fNullable)
|
|
{
|
|
BOOL fResults = TRUE;
|
|
|
|
if(m_currentBitMask & bit || !fNullable)
|
|
{
|
|
// Check Status and Value
|
|
if( (*fRes) &&
|
|
((!COMPARE((iRow>=1), TRUE)) ||
|
|
(!COMPARE(pColumn->sStatus, DBSTATUS_S_OK)) ||
|
|
((m_restrict & bit) &&
|
|
((!COMPARE(pColumn->ulLength, wcslen(wszRes)*2)) ||
|
|
(!COMPARE(0, RelCompareString(wszRes, (TYPE_WSTR)pColumn->bValue)))))) )
|
|
*fRes = fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
COMPARE(pColumn->sStatus, DBSTATUS_S_ISNULL);
|
|
// COMPARE(pColumn->ulLength, 0); // Spec does not require this. Length should be ignored for NULL.
|
|
}
|
|
|
|
return fResults;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Test the Restriction for IDBSchemaRowset
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void CSchemaTest::SetRestriction(RESTRICTIONSENUM bit, ULONG ulRestriction, WCHAR ** pwszR, WCHAR * wszRestriction)
|
|
{
|
|
// Check if the restriction is supported
|
|
if((m_currentBitMask & bit) || m_fPassUnsupportedRestrictions)
|
|
{
|
|
if((m_restrict & bit) || (m_restrict & ALLRES))
|
|
{
|
|
// if NULL set to a bogus restriction
|
|
m_rgvarRestrict[ulRestriction-1].bstrVal = SysAllocString(wszRestriction ? wszRestriction : L"BogusRestriction");
|
|
*pwszR = wcsDuplicate(wszRestriction ? wszRestriction : L"BogusRestriction");
|
|
|
|
m_rgvarRestrict[ulRestriction-1].vt = VT_BSTR;
|
|
m_cRestrictionsCurrent ++;
|
|
SetRestriction(bit);
|
|
}
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Init_Stuff
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void CSchemaTest::Init_Stuff(void)
|
|
{
|
|
ULONG index;
|
|
|
|
m_fBOOKMARK_REQUESTED=FALSE;
|
|
m_fBOOKMARK_FOUND=FALSE;
|
|
m_fRes1=TRUE;
|
|
m_fRes2=TRUE;
|
|
m_fRes3=TRUE;
|
|
m_fRes4=TRUE;
|
|
m_fRes5=TRUE;
|
|
m_fRes6=TRUE;
|
|
m_fRes7=TRUE;
|
|
m_fMyTableCatalogFound=FALSE;
|
|
m_fMyTableSchemaFound=FALSE;
|
|
m_MyTableName1Found=FALSE;
|
|
m_MyTableName2Found=FALSE;
|
|
m_MyColumnNameFound=FALSE;
|
|
m_MyTableTypeFound=FALSE;
|
|
|
|
m_cErrors=0;
|
|
m_cColumns=0;
|
|
m_cRestrictions=0;
|
|
m_cRestrictionsCurrent=0;
|
|
m_cDBBINDING=0;
|
|
m_cDBPROPSET=0;
|
|
m_cDBCOLUMNINFO=0;
|
|
m_iid=IID_NULL;
|
|
m_guid=GUID_NULL;
|
|
m_restrict=0;
|
|
m_HR=E_FAIL;
|
|
m_fResult=FALSE;
|
|
m_fAtLeast1UnsupportedRestrictionIsSet=FALSE;
|
|
|
|
|
|
m_fRowsetPointerNULL=FALSE;
|
|
m_fCountRestrictionsNULL=FALSE;
|
|
m_fRangeRestrictionsNULL=FALSE;
|
|
m_fCountPropSetNULL=FALSE;
|
|
m_fRangePropSetNULL=FALSE;
|
|
m_fPassUnsupportedRestrictions=FALSE;
|
|
m_fRestrictionsAsInitVariants=FALSE;
|
|
|
|
|
|
m_wszR1=NULL;
|
|
m_wszR2=NULL;
|
|
m_wszR3=NULL;
|
|
m_wszR4=NULL;
|
|
m_wszR5=NULL;
|
|
m_wszR6=NULL;
|
|
m_wszR7=NULL;
|
|
m_ulR=0;
|
|
|
|
for(index=0;index<MAXRESTRICTION;index++)
|
|
VariantInit(&(m_rgvarRestrict[index]));
|
|
|
|
for(index=0;index<MAXPROP;index++)
|
|
VariantInit(&(m_rgDBPROP[index].vValue));
|
|
|
|
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Free_Stuff
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void CSchemaTest::Free_Stuff(void)
|
|
{
|
|
ULONG index;
|
|
|
|
// don't need to be freed because these aren't dynamic
|
|
m_rgColumnNames=NULL;
|
|
m_rgColumnTypes=NULL;
|
|
|
|
SAFE_RELEASE_(m_pIRowset);
|
|
SAFE_RELEASE_(m_pIAccessor);
|
|
SAFE_RELEASE_(m_pIRowsetInfo);
|
|
SAFE_RELEASE_(m_pIColumnsInfo);
|
|
SAFE_RELEASE_(m_pIRowsetChange);
|
|
SAFE_RELEASE_(m_pIUnknown);
|
|
|
|
PROVIDER_FREE(m_rgDBCOLUMNINFO);
|
|
PROVIDER_FREE(m_pStringsBuffer);
|
|
|
|
for(index=0;index<MAXRESTRICTION;index++)
|
|
VariantClear(&(m_rgvarRestrict[index]));
|
|
|
|
for(index=0;index<MAXPROP;index++)
|
|
VariantClear(&(m_rgDBPROP[index].vValue));
|
|
|
|
// Free the Restrictions
|
|
PROVIDER_FREE(m_wszR1);
|
|
PROVIDER_FREE(m_wszR2);
|
|
PROVIDER_FREE(m_wszR3);
|
|
PROVIDER_FREE(m_wszR4);
|
|
PROVIDER_FREE(m_wszR5);
|
|
PROVIDER_FREE(m_wszR6);
|
|
PROVIDER_FREE(m_wszR7);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// GetRowset, execute method and check results
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
HRESULT CSchemaTest::GetRowset(BOOL fFreeRowset)
|
|
{
|
|
IUnknown * pIUnknown = NULL;
|
|
IUnknown **ppIUnknown=&pIUnknown;
|
|
|
|
if(!m_fCaptureRestrictions && m_PrintSchemaName)
|
|
TraceSchemaName(m_guid, TRUE, TRUE);
|
|
|
|
if(m_iid==IID_IRowset)
|
|
ppIUnknown = (IUnknown **)&m_pIRowset;
|
|
else if(m_iid==IID_IAccessor)
|
|
ppIUnknown = (IUnknown **)&m_pIAccessor;
|
|
else if(m_iid==IID_IRowsetInfo)
|
|
ppIUnknown = (IUnknown **)&m_pIRowsetInfo;
|
|
else if(m_iid==IID_IColumnsInfo)
|
|
ppIUnknown = (IUnknown **)&m_pIColumnsInfo;
|
|
else if(m_iid==IID_IRowsetChange)
|
|
ppIUnknown = (IUnknown **)&m_pIRowsetChange;
|
|
else if(m_iid==IID_IUnknown)
|
|
ppIUnknown = (IUnknown **)&m_pIUnknown;
|
|
|
|
// Now get Schema rowset.
|
|
m_HR=m_pIDBSchemaRowset->GetRowset(
|
|
m_punkOuter, m_guid, (m_fCountRestrictionsNULL ? 0 : m_cRestrictions),
|
|
(m_fRangeRestrictionsNULL ? NULL : m_rgvarRestrict), m_iid,
|
|
(m_fCountPropSetNULL ? 0 : m_cDBPROPSET), (m_fRangePropSetNULL ? 0 : m_rgDBPROPSET),
|
|
(m_fRowsetPointerNULL ? NULL : ppIUnknown));
|
|
|
|
if (SUCCEEDED(m_HR))
|
|
CheckResults(*ppIUnknown, m_iid);
|
|
|
|
if (fFreeRowset && ppIUnknown)
|
|
SAFE_RELEASE(*ppIUnknown);
|
|
|
|
return m_HR;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// This routine should be called when the information for the next schema (guid) is needed
|
|
// I either want the next supported schema or a specific schema.
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::GetSchemaInfo
|
|
(
|
|
REQUESTED_SCHEMA schemaType, // [IN] if I want the schema supported, or not, or I have a specific schema in mind
|
|
ULONG ulIndexOfSchemaRequesting, // [IN] Index of supported Schema
|
|
GUID schema // [IN] specific schema
|
|
)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
m_cRestrictionsCurrent = 0;
|
|
|
|
// Set default row count information to expect 1 row but only
|
|
// warn if we get less
|
|
SetRowCount(MIN_VALUE, 1);
|
|
|
|
// Initialize Variants
|
|
VariantInit(&m_rgvarRestrict[0]);
|
|
VariantInit(&m_rgvarRestrict[1]);
|
|
VariantInit(&m_rgvarRestrict[2]);
|
|
VariantInit(&m_rgvarRestrict[3]);
|
|
VariantInit(&m_rgvarRestrict[4]);
|
|
VariantInit(&m_rgvarRestrict[5]);
|
|
VariantInit(&m_rgvarRestrict[6]);
|
|
|
|
// grab schema from list of supported schemas
|
|
if(schemaType==SUPPORTED)
|
|
memcpy(&m_guid,&(m_rgSchemas[ulIndexOfSchemaRequesting]),sizeof(GUID));
|
|
else if(schemaType==SPECIFIC)
|
|
memcpy(&m_guid,&schema,sizeof(GUID));
|
|
else
|
|
return FALSE;
|
|
|
|
for(ULONG index=0;index<m_cSchemasSupported;index++)
|
|
{
|
|
if(IsEqualGUID(m_guid,m_rgSchemas[index])) {
|
|
m_currentBitMask = m_rgRestrictionSupport[index];
|
|
break;
|
|
}
|
|
}
|
|
|
|
PRVTRACE(L"Getting ");
|
|
TraceSchemaName(m_guid,FALSE,TRUE);
|
|
PRVTRACE(L"\n");
|
|
|
|
// Find the schema
|
|
if(IsEqualGUID(DBSCHEMA_ASSERTIONS,m_guid))
|
|
fResult= PrepareParams_ASSERTIONS();
|
|
else if(IsEqualGUID(DBSCHEMA_CATALOGS,m_guid))
|
|
fResult= PrepareParams_CATALOGS();
|
|
else if(IsEqualGUID(DBSCHEMA_CHARACTER_SETS,m_guid))
|
|
fResult= PrepareParams_CHARACTER_SETS();
|
|
else if(IsEqualGUID(DBSCHEMA_CHECK_CONSTRAINTS,m_guid))
|
|
fResult= PrepareParams_CHECK_CONSTRAINTS();
|
|
else if(IsEqualGUID(DBSCHEMA_COLLATIONS,m_guid))
|
|
fResult= PrepareParams_COLLATIONS();
|
|
else if(IsEqualGUID(DBSCHEMA_COLUMN_DOMAIN_USAGE,m_guid))
|
|
fResult= PrepareParams_COLUMN_DOMAIN_USAGE();
|
|
else if(IsEqualGUID(DBSCHEMA_COLUMN_PRIVILEGES,m_guid))
|
|
fResult= PrepareParams_COLUMN_PRIVILEGES();
|
|
else if(IsEqualGUID(DBSCHEMA_COLUMNS,m_guid))
|
|
fResult= PrepareParams_COLUMNS();
|
|
else if(IsEqualGUID(DBSCHEMA_CONSTRAINT_COLUMN_USAGE,m_guid))
|
|
fResult= PrepareParams_CONSTRAINT_COLUMN_USAGE();
|
|
else if(IsEqualGUID(DBSCHEMA_CONSTRAINT_TABLE_USAGE,m_guid))
|
|
fResult= PrepareParams_CONSTRAINT_TABLE_USAGE();
|
|
else if(IsEqualGUID(DBSCHEMA_FOREIGN_KEYS,m_guid))
|
|
fResult= PrepareParams_FOREIGN_KEYS();
|
|
else if(IsEqualGUID(DBSCHEMA_INDEXES,m_guid))
|
|
fResult= PrepareParams_INDEXES();
|
|
else if(IsEqualGUID(DBSCHEMA_KEY_COLUMN_USAGE,m_guid))
|
|
fResult= PrepareParams_KEY_COLUMN_USAGE();
|
|
else if(IsEqualGUID(DBSCHEMA_PRIMARY_KEYS,m_guid))
|
|
fResult= PrepareParams_PRIMARY_KEYS();
|
|
else if(IsEqualGUID(DBSCHEMA_PROCEDURE_COLUMNS,m_guid))
|
|
fResult= PrepareParams_PROCEDURE_COLUMNS();
|
|
else if(IsEqualGUID(DBSCHEMA_PROCEDURE_PARAMETERS, m_guid))
|
|
fResult= PrepareParams_PROCEDURE_PARAMETERS();
|
|
else if(IsEqualGUID(DBSCHEMA_PROCEDURES,m_guid))
|
|
fResult= PrepareParams_PROCEDURES();
|
|
else if(IsEqualGUID(DBSCHEMA_PROVIDER_TYPES,m_guid))
|
|
fResult= PrepareParams_PROVIDER_TYPES();
|
|
else if(IsEqualGUID(DBSCHEMA_REFERENTIAL_CONSTRAINTS,m_guid))
|
|
fResult= PrepareParams_REFERENTIAL_CONSTRAINTS();
|
|
else if(IsEqualGUID(DBSCHEMA_SCHEMATA,m_guid))
|
|
fResult= PrepareParams_SCHEMATA();
|
|
else if(IsEqualGUID(DBSCHEMA_SQL_LANGUAGES,m_guid))
|
|
fResult= PrepareParams_SQL_LANGUAGES();
|
|
else if(IsEqualGUID(DBSCHEMA_STATISTICS,m_guid))
|
|
fResult= PrepareParams_STATISTICS();
|
|
else if(IsEqualGUID(DBSCHEMA_TABLES,m_guid))
|
|
fResult= PrepareParams_TABLES();
|
|
else if(IsEqualGUID(DBSCHEMA_TABLES_INFO,m_guid))
|
|
fResult= PrepareParams_TABLES_INFO();
|
|
else if(IsEqualGUID(DBSCHEMA_TABLE_CONSTRAINTS,m_guid))
|
|
fResult= PrepareParams_TABLE_CONSTRAINTS();
|
|
else if(IsEqualGUID(DBSCHEMA_TABLE_PRIVILEGES,m_guid))
|
|
fResult= PrepareParams_TABLE_PRIVILEGES();
|
|
else if(IsEqualGUID(DBSCHEMA_TABLE_STATISTICS,m_guid))
|
|
fResult= PrepareParams_TABLE_STATISTICS();
|
|
else if(IsEqualGUID(DBSCHEMA_TRANSLATIONS,m_guid))
|
|
fResult= PrepareParams_TRANSLATIONS();
|
|
else if(IsEqualGUID(DBSCHEMA_TRUSTEE,m_guid))
|
|
fResult = PrepareParams_TRUSTEE();
|
|
else if(IsEqualGUID(DBSCHEMA_USAGE_PRIVILEGES,m_guid))
|
|
fResult= PrepareParams_USAGE_PRIVILEGES();
|
|
else if(IsEqualGUID(DBSCHEMA_VIEW_COLUMN_USAGE,m_guid))
|
|
fResult= PrepareParams_VIEW_COLUMN_USAGE();
|
|
else if(IsEqualGUID(DBSCHEMA_VIEW_TABLE_USAGE,m_guid))
|
|
fResult= PrepareParams_VIEW_TABLE_USAGE();
|
|
else if(IsEqualGUID(DBSCHEMA_VIEWS,m_guid))
|
|
fResult= PrepareParams_VIEWS();
|
|
else
|
|
return FALSE;
|
|
|
|
if(!m_fRestrictionsAsInitVariants)
|
|
{
|
|
if(m_rgvarRestrict[0].vt == VT_EMPTY)
|
|
ClearRestriction(FIRST);
|
|
if(m_rgvarRestrict[1].vt == VT_EMPTY)
|
|
ClearRestriction(SECOND);
|
|
if(m_rgvarRestrict[2].vt == VT_EMPTY)
|
|
ClearRestriction(THIRD);
|
|
if(m_rgvarRestrict[3].vt == VT_EMPTY)
|
|
ClearRestriction(FOURTH);
|
|
if(m_rgvarRestrict[4].vt == VT_EMPTY)
|
|
ClearRestriction(FIFTH);
|
|
if(m_rgvarRestrict[5].vt == VT_EMPTY)
|
|
ClearRestriction(SIXTH);
|
|
if(m_rgvarRestrict[6].vt == VT_EMPTY)
|
|
ClearRestriction(SEVENTH);
|
|
}
|
|
|
|
return fResult;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRow
|
|
//
|
|
// Pass through function to VerifyRow for specific schema
|
|
//
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow
|
|
(
|
|
GUID m_guid,
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pRow
|
|
)
|
|
{
|
|
// 1. ASSERTIONS
|
|
if(IsEqualGUID(m_guid,DBSCHEMA_ASSERTIONS))
|
|
return VerifyRow_ASSERTIONS(iRow,pRow);
|
|
// 2. CATALOGS
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_CATALOGS))
|
|
return VerifyRow_CATALOGS(iRow,pRow);
|
|
// 3. CHARACTER_SETS
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_CHARACTER_SETS))
|
|
return VerifyRow_CHARACTER_SETS(iRow,pRow);
|
|
// 4. CHECK_CONSTRAINTS
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_CHECK_CONSTRAINTS))
|
|
return VerifyRow_CHECK_CONSTRAINTS(iRow,pRow);
|
|
// 5. COLLATIONS
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_COLLATIONS))
|
|
return VerifyRow_COLLATIONS(iRow,pRow);
|
|
// 6. COLUMN_DOMAIN_USAGE
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_COLUMN_DOMAIN_USAGE))
|
|
return VerifyRow_COLUMN_DOMAIN_USAGE(iRow,pRow);
|
|
// 7. COLUMN_PRIVILEGES
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_COLUMN_PRIVILEGES))
|
|
return VerifyRow_COLUMN_PRIVILEGES(iRow,pRow);
|
|
// 8. COLUMNS
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_COLUMNS))
|
|
return VerifyRow_COLUMNS(iRow,pRow);
|
|
// 9. CONSTRAINT_COLUMN_USAGE
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_CONSTRAINT_COLUMN_USAGE))
|
|
return VerifyRow_CONSTRAINT_COLUMN_USAGE(iRow,pRow);
|
|
// 10. CONSTRAINT_TABLE_USAGE
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_CONSTRAINT_TABLE_USAGE))
|
|
return VerifyRow_CONSTRAINT_TABLE_USAGE(iRow,pRow);
|
|
// 11. FOREIGN_KEYS
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_FOREIGN_KEYS))
|
|
return VerifyRow_FOREIGN_KEYS(iRow,pRow);
|
|
// 12. INDEXES
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_INDEXES))
|
|
return VerifyRow_INDEXES(iRow,pRow);
|
|
// 13. KEY_COLUMN_USAGE
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_KEY_COLUMN_USAGE))
|
|
return VerifyRow_KEY_COLUMN_USAGE(iRow,pRow);
|
|
// 14. PRIMARY_KEYS
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_PRIMARY_KEYS))
|
|
return VerifyRow_PRIMARY_KEYS(iRow,pRow);
|
|
// 14. PROCEDURE_COLUMNS
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_PROCEDURE_COLUMNS))
|
|
return VerifyRow_PROCEDURE_COLUMNS(iRow,pRow);
|
|
// 15. PROCEDURE_PARAMETERS
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_PROCEDURE_PARAMETERS))
|
|
return VerifyRow_PROCEDURE_PARAMETERS(iRow,pRow);
|
|
// 16. PROCEDURES
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_PROCEDURES))
|
|
return VerifyRow_PROCEDURES(iRow,pRow);
|
|
// 17. PROVIDER TYPES
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_PROVIDER_TYPES))
|
|
return VerifyRow_PROVIDER_TYPES(iRow,pRow);
|
|
// 18. REFERENTIAL_CONSTRAINTS
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_REFERENTIAL_CONSTRAINTS))
|
|
return VerifyRow_REFERENTIAL_CONSTRAINTS(iRow,pRow);
|
|
// 19. SCHEMATA
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_SCHEMATA))
|
|
return VerifyRow_SCHEMATA(iRow+1,pRow);
|
|
// 20. SQL_LANGUAGES
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_SQL_LANGUAGES))
|
|
return VerifyRow_SQL_LANGUAGES(iRow,pRow);
|
|
// 21. STATISTICS
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_STATISTICS))
|
|
return VerifyRow_STATISTICS(iRow,pRow);
|
|
// 22. TABLE_CONSTRAINTS
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_TABLE_CONSTRAINTS))
|
|
return VerifyRow_TABLE_CONSTRAINTS(iRow,pRow);
|
|
// 23. TABLE_PRIVILEGES
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_TABLE_PRIVILEGES))
|
|
return VerifyRow_TABLE_PRIVILEGES(iRow,pRow);
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_TABLE_STATISTICS))
|
|
return VerifyRow_TABLE_STATISTICS(iRow,pRow);
|
|
// 24. TABLES
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_TABLES))
|
|
return VerifyRow_TABLES(iRow,pRow);
|
|
// 25. TABLES_INFO
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_TABLES_INFO))
|
|
return VerifyRow_TABLES_INFO(iRow,pRow);
|
|
// 26. TRANSLATIONS
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_TRANSLATIONS))
|
|
return VerifyRow_TRANSLATIONS(iRow,pRow);
|
|
// 27. USAGE_PRIVILEGES
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_USAGE_PRIVILEGES))
|
|
return VerifyRow_USAGE_PRIVILEGES(iRow,pRow);
|
|
// 28. VIEW_COLUMN_USAGE
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_VIEW_COLUMN_USAGE))
|
|
return VerifyRow_VIEW_COLUMN_USAGE(iRow,pRow);
|
|
// 29. VIEW_TABLE_USAGE
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_VIEW_TABLE_USAGE))
|
|
return VerifyRow_VIEW_TABLE_USAGE(iRow,pRow);
|
|
// 30. VIEWS
|
|
else if(IsEqualGUID(m_guid,DBSCHEMA_VIEWS))
|
|
return VerifyRow_VIEWS(iRow,pRow);
|
|
else {
|
|
odtLog << L"Warning - Provider specific schema rowset found.\n";
|
|
_ASSERTE(!L"Unexpected schema rowset.");
|
|
return FALSE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Capture Restrictions from schema rowsets returned, if schema is
|
|
// supported
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::CaptureRestrictions()
|
|
{
|
|
// Need to turn Capture off
|
|
m_fCaptureRestrictions = TRUE;
|
|
|
|
Find_Catalog_and_Schema();
|
|
Find_TableInfo();
|
|
Find_Assertion_Constraint();
|
|
Find_Character_Set();
|
|
Find_Collation();
|
|
Find_Domain();
|
|
Find_Grantor_and_Grantee();
|
|
Find_Key_Column_Usage_Constraint();
|
|
Find_Procedure();
|
|
|
|
//I'm wrapping all procedure stuff into one place
|
|
//Find_ProcedureColumn();
|
|
//Find_Parameter();
|
|
Find_Referential_Constraint();
|
|
Find_Constraint_Type();
|
|
Find_Translation();
|
|
Find_View();
|
|
Find_BestMatch();
|
|
Find_PK_and_FK();
|
|
Find_Table_Statistics_Restrictions();
|
|
|
|
// Need to turn Capture off
|
|
m_fDontCaptureRestrictions = TRUE;
|
|
m_fCaptureRestrictions=FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Free Restrictions that were captured
|
|
//--------------------------------------------------------------------
|
|
void CSchemaTest::FreeRestrictions()
|
|
{
|
|
Release_Catalog_and_Schema();
|
|
Release_TableInfo();
|
|
Release_Assertion_Constraint();
|
|
Release_Character_Set();
|
|
Release_Collation();
|
|
Release_Domain();
|
|
Release_Grantor_and_Grantee();
|
|
Release_Key_Column_Usage_Constraint();
|
|
Release_Procedure();
|
|
Release_Parameter();
|
|
Release_Referential_Constraint();
|
|
Release_Constraint_Type();
|
|
Release_Translation();
|
|
Release_View();
|
|
Release_PK_and_FK();
|
|
Release_Table_Statistics_Restrictions();
|
|
|
|
// Need to Capture the Restrictions
|
|
m_fDontCaptureRestrictions = FALSE;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// Is this schema supported
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::IsSchemaSupported(GUID schema)
|
|
{
|
|
// grab schema from list of supported schemas
|
|
for(ULONG index=0; index<m_cSchemasSupported; index++)
|
|
{
|
|
if(IsEqualGUID(schema,m_rgSchemas[index]))
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// Find Catalog
|
|
//
|
|
// With DBSCHEMA_CATALOGS, will fill m_pwszCatalogRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_Catalog_and_Schema()
|
|
{
|
|
// Initialize the needed pointers
|
|
INIT;
|
|
|
|
// Call the GetProperty for the CurrentCatalog
|
|
GetProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, m_pIDBInitialize, &m_pwszCatalogRestriction);
|
|
|
|
// Call the GetProperty for the UserName
|
|
GetProperty(DBPROP_USERNAME, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &m_pwszSchemaRestriction);
|
|
|
|
FREE;
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Catalog
|
|
//
|
|
// With DBSCHEMA_CATALOGS, will fill m_pwszCatalogRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_Catalog_and_Schema()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszCatalogRestriction);
|
|
PROVIDER_FREE(m_pwszSchemaRestriction);
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Tables
|
|
//
|
|
// With DBSCHEMA_TABLES, will fill m_pwszTableRestriction and m_pwszTable_TypeRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_TableInfo()
|
|
{
|
|
// Initialize the needed pointers
|
|
INIT;
|
|
|
|
// Get Index Name
|
|
if(m_pTable->GetIndexName()) {
|
|
PROVIDER_FREE(m_pwszIndexRestriction);
|
|
m_pwszIndexRestriction = wcsDuplicate(m_pTable->GetIndexName());
|
|
}
|
|
|
|
// Get Table Name
|
|
if(m_pTable->GetTableName()) {
|
|
VARIANT Variant;
|
|
PROVIDER_FREE(m_pwszTableRestriction);
|
|
m_pwszTableRestriction = wcsDuplicate(m_pTable->GetTableName());
|
|
m_pwszTable_TypeRestriction = wcsDuplicate(L"TABLE");
|
|
|
|
// Adjust for identifier case
|
|
VariantInit(&Variant);
|
|
GetProperty(DBPROP_IDENTIFIERCASE,
|
|
DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &Variant);
|
|
switch(Variant.lVal)
|
|
{
|
|
case DBPROPVAL_IC_UPPER:
|
|
_wcsupr(m_pwszTableRestriction);
|
|
break;
|
|
case DBPROPVAL_IC_LOWER:
|
|
_wcslwr(m_pwszTableRestriction);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
// Get Column Name
|
|
CCol col;
|
|
DBORDINAL m_cOrdinals = m_pTable->CountColumnsOnTable();
|
|
|
|
for(ULONG ulIndex = 1; m_cOrdinals >= ulIndex; ulIndex++)
|
|
{
|
|
if(SUCCEEDED(m_pTable->GetColInfo(1,col)) && col.GetColName())
|
|
{
|
|
// Copy the new values
|
|
m_DataTypeRestriction = col.GetProviderType();
|
|
|
|
PROVIDER_FREE(m_pwszColumnRestriction);
|
|
m_pwszColumnRestriction = wcsDuplicate(col.GetColName());
|
|
break;
|
|
}
|
|
}
|
|
|
|
FREE;
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Release Tables
|
|
//
|
|
// With DBSCHEMA_TABLES, will free m_pwszTableRestriction, m_pwszColumnRestriction, and m_pwszIndexRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_TableInfo()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszTableRestriction);
|
|
PROVIDER_FREE(m_pwszTable_TypeRestriction);
|
|
PROVIDER_FREE(m_pwszColumnRestriction);
|
|
PROVIDER_FREE(m_pwszIndexRestriction);
|
|
return TRUE;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// Find Assertion Constraint
|
|
//
|
|
// With DBSCHEMA_ASSERTIONS, will fill m_pwszAssertion_ConstraintRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_Assertion_Constraint()
|
|
{
|
|
// Initialize the needed pointers
|
|
INIT;
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
if(!IsSchemaSupported(DBSCHEMA_ASSERTIONS))
|
|
return FALSE;
|
|
|
|
m_restrict |= FIRST;
|
|
m_restrict |= SECOND;
|
|
m_iid = IID_IRowset;
|
|
|
|
// If this is a schema I want then get information for schema
|
|
if(GetSchemaInfo(SPECIFIC,0,DBSCHEMA_ASSERTIONS))
|
|
GetRowset();
|
|
|
|
FREE;
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Assertion Constraint
|
|
//
|
|
// With DBSCHEMA_ASSERTIONS, will fill m_pwszAssertion_ConstraintRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_Assertion_Constraint()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszAssertion_ConstraintRestriction);
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Character Set
|
|
//
|
|
// With DBSCHEMA_CHARACTER_SETS, will fill m_pwszCharacter_SetRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_Character_Set()
|
|
{
|
|
// Initialize the needed pointers
|
|
INIT;
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
if(!IsSchemaSupported(DBSCHEMA_CHARACTER_SETS))
|
|
return FALSE;
|
|
|
|
m_restrict |= FIRST;
|
|
m_restrict |= SECOND;
|
|
m_iid = IID_IRowset;
|
|
|
|
// if this is a schema I want then get information for schema
|
|
if(GetSchemaInfo(SPECIFIC,0,DBSCHEMA_CHARACTER_SETS))
|
|
GetRowset();
|
|
|
|
FREE;
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Character Set
|
|
//
|
|
// With DBSCHEMA_CHARACTER_SETS, will fill m_pwszCharacter_SetRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_Character_Set()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszCharacter_SetRestriction);
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Check Constraint
|
|
//
|
|
// With DBSCHEMA_CHECK_CONSTRAINTS, will fill m_pwszCheck_ConstraintRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_Check_Constraint()
|
|
{
|
|
INIT
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
if(!IsSchemaSupported(DBSCHEMA_CHECK_CONSTRAINTS))
|
|
return FALSE;
|
|
|
|
m_restrict |= FIRST;
|
|
m_restrict |= SECOND;
|
|
m_iid = IID_IRowset;
|
|
|
|
// if this is a schema I want then get information for schema
|
|
if(GetSchemaInfo(SPECIFIC,0,DBSCHEMA_CHECK_CONSTRAINTS))
|
|
GetRowset();
|
|
|
|
FREE
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Check Constraint
|
|
//
|
|
// With DBSCHEMA_CHECK_CONSTRAINTS, will fill m_pwszCheck_ConstraintRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_Check_Constraint()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszCheck_ConstraintRestriction);
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Collation
|
|
//
|
|
// With DBSCHEMA_COLLATIONS, will fill m_pwszCollationRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_Collation()
|
|
{
|
|
INIT
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
if(!IsSchemaSupported(DBSCHEMA_COLLATIONS))
|
|
return FALSE;
|
|
|
|
m_restrict |= FIRST;
|
|
m_restrict |= SECOND;
|
|
m_iid = IID_IRowset;
|
|
|
|
// if this is a schema I want then get information for schema
|
|
if(GetSchemaInfo(SPECIFIC,0,DBSCHEMA_COLLATIONS))
|
|
GetRowset();
|
|
|
|
FREE
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Collation
|
|
//
|
|
// With DBSCHEMA_COLLATIONS, will fill m_pwszCollationRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_Collation()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszCollationRestriction);
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Domain
|
|
//
|
|
// With DBSCHEMA_COLUMN_DOMAIN_USAGE, will fill m_pwszDomainRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_Domain()
|
|
{
|
|
INIT;
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
if(!IsSchemaSupported(DBSCHEMA_COLUMN_DOMAIN_USAGE))
|
|
return FALSE;
|
|
|
|
m_restrict |= FIRST;
|
|
m_restrict |= SECOND;
|
|
m_restrict |= FOURTH;
|
|
m_iid = IID_IRowset;
|
|
|
|
// if this is a schema I want then get information for schema
|
|
if(GetSchemaInfo(SPECIFIC,0,DBSCHEMA_COLUMN_DOMAIN_USAGE))
|
|
GetRowset();
|
|
|
|
FREE;
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Domain
|
|
//
|
|
// With DBSCHEMA_COLUMN_DOMAIN_USAGE, will fill m_pwszDomainRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_Domain()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszDomainRestriction);
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Grantor and Grantee
|
|
//
|
|
// With DBSCHEMA_COLUMN_PRIVILEGES, will fill m_pwszGrantorRestriction and m_pwszGranteeRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_Grantor_and_Grantee()
|
|
{
|
|
INIT
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
if(!IsSchemaSupported(DBSCHEMA_COLUMN_PRIVILEGES))
|
|
return FALSE;
|
|
|
|
m_restrict |= FIRST;
|
|
m_restrict |= SECOND;
|
|
m_restrict |= THIRD;
|
|
m_restrict |= FOURTH;
|
|
|
|
m_iid = IID_IRowset;
|
|
|
|
// if this is a schema I want then get information for schema
|
|
if(GetSchemaInfo(SPECIFIC,0,DBSCHEMA_COLUMN_PRIVILEGES))
|
|
{
|
|
// Since we're restricting COLUMN_PRIVILEGES to a single column
|
|
// we need to adjust expected row count to one row minimum
|
|
SetRowCount(MIN_REQUIRED, 1);
|
|
|
|
GetRowset();
|
|
}
|
|
|
|
FREE
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Grantor and Grantee
|
|
//
|
|
// With DBSCHEMA_COLUMN_PRIVILEGES, will fill m_pwszGrantorRestriction and m_pwszGranteeRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_Grantor_and_Grantee()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszGrantorRestriction);
|
|
PROVIDER_FREE(m_pwszGranteeRestriction);
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Table Statistics Restrictions
|
|
//
|
|
// Uses DBSCHEMA_TABLE_STATISTICS to fill restrictions on
|
|
// STATISTICS_CATALOG, STATISTICS_SCHEMA, STATISTICS_NAME, and
|
|
// STATISTICS_TYPE
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_Table_Statistics_Restrictions()
|
|
{
|
|
INIT
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
if(!IsSchemaSupported(DBSCHEMA_TABLE_STATISTICS))
|
|
return FALSE;
|
|
|
|
m_restrict |= FIRST;
|
|
m_restrict |= SECOND;
|
|
m_restrict |= THIRD;
|
|
|
|
m_iid = IID_IRowset;
|
|
|
|
// if this is a schema I want then get information for schema
|
|
if(GetSchemaInfo(SPECIFIC,0,DBSCHEMA_TABLE_STATISTICS))
|
|
{
|
|
// Execute the provider-specific statement to update statistics
|
|
// for our test table
|
|
COMPARE(UpdateStatistics(), TRUE);
|
|
|
|
// We need at least one row in TABLE_STATISTICS rowset
|
|
SetRowCount(MIN_REQUIRED, 1);
|
|
|
|
GetRowset();
|
|
}
|
|
|
|
FREE
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Release Table Statistics Restrictions
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_Table_Statistics_Restrictions()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszStatisticsCatalogRestriction);
|
|
PROVIDER_FREE(m_pwszStatisticsSchemaRestriction);
|
|
PROVIDER_FREE(m_pwszStatisticsNameRestriction);
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Update Statistics
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::UpdateStatistics(void)
|
|
{
|
|
LPWSTR pwszUpdateStats = NULL;
|
|
size_t ccUpdateStats = 0;
|
|
BOOL fReturn = FALSE;
|
|
|
|
if (m_pwszUpdateStatsFormat)
|
|
{
|
|
ccUpdateStats = wcslen(m_pwszUpdateStatsFormat) +
|
|
wcslen(m_pTable->GetTableName() +1);
|
|
|
|
SAFE_ALLOC(pwszUpdateStats, WCHAR, ccUpdateStats);
|
|
|
|
swprintf(pwszUpdateStats, m_pwszUpdateStatsFormat, m_pTable->GetTableName());
|
|
|
|
TESTC_(m_pTable->BuildCommand(pwszUpdateStats, IID_IRowset,
|
|
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL), S_OK);
|
|
|
|
}
|
|
|
|
fReturn = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
SAFE_FREE(pwszUpdateStats);
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// Find Key Column Usage Constraint
|
|
//
|
|
// With DBSCHEMA_KEY_COLUMN_USAGE, will fill m_pwszKey_Column_Usage_ConstraintRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_Key_Column_Usage_Constraint()
|
|
{
|
|
INIT
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
if(!IsSchemaSupported(DBSCHEMA_KEY_COLUMN_USAGE))
|
|
return FALSE;
|
|
|
|
m_restrict |= FIRST;
|
|
m_restrict |= SECOND;
|
|
m_restrict |= FOURTH;
|
|
m_restrict |= FIFTH;
|
|
m_restrict |= SIXTH;
|
|
m_restrict |= SEVENTH;
|
|
|
|
m_iid = IID_IRowset;
|
|
|
|
// if this is a schema I want then get information for schema
|
|
if(GetSchemaInfo(SPECIFIC,0,DBSCHEMA_KEY_COLUMN_USAGE))
|
|
GetRowset();
|
|
|
|
FREE
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Key Column Usage Constraint
|
|
//
|
|
// With DBSCHEMA_KEY_COLUMN_USAGE, will fill m_pwszKey_Column_Usage_ConstraintRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_Key_Column_Usage_Constraint()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszKey_Column_Usage_ConstraintRestriction);
|
|
return TRUE;
|
|
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Procedure
|
|
//
|
|
// With DBSCHEMA_PROCEDURE, will fill in
|
|
// m_pwszProcedureRestriction and m_pwszProcedure_Type,
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_Procedure()
|
|
{
|
|
BOOL fSucceed = FALSE;
|
|
ICommandText * pICommandText = NULL;
|
|
WCHAR * pwszProcName = NULL;
|
|
WCHAR * pSQL = NULL;
|
|
|
|
// Initialize the needed pointers
|
|
INIT;
|
|
|
|
if(!m_pIDBInitialize) {
|
|
odtLog << L"m_pIDBInitialize is null\n";
|
|
return TEST_FAIL;
|
|
}
|
|
|
|
|
|
if (!m_bSqlServer)
|
|
{
|
|
// odtLog << L"Not a sql server so can't test stored proc restrictions\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
if(!(m_pTable->get_ICommandPTR()))
|
|
goto CLEANUP;
|
|
|
|
if(!CHECK(m_pTable->get_ICommandPTR()->QueryInterface(IID_ICommandText,(void**)&pICommandText),S_OK))
|
|
goto CLEANUP;
|
|
|
|
pwszProcName = (WCHAR *) PROVIDER_ALLOC(
|
|
(wcslen(m_pTable->GetTableName()) +
|
|
wcslen(wszProcDesignator)+1) * sizeof(WCHAR));
|
|
|
|
if(!pwszProcName) {
|
|
odtLog << L"out of memory\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
wcscpy(pwszProcName, m_pTable->GetTableName());
|
|
wcscat(pwszProcName, wszProcDesignator);
|
|
|
|
m_pwszDropProc = (WCHAR *) PROVIDER_ALLOC(
|
|
(wcslen(wszDropProc) +
|
|
wcslen(pwszProcName)+1) * sizeof(WCHAR));
|
|
|
|
if(!m_pwszDropProc) {
|
|
odtLog << L"out of memory\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
swprintf(m_pwszDropProc, wszDropProc, pwszProcName);
|
|
|
|
pSQL = (WCHAR *) PROVIDER_ALLOC(
|
|
(wcslen(wszCreateProc) +
|
|
wcslen(pwszProcName) +
|
|
wcslen(m_pTable->GetTableName()) +
|
|
1) * sizeof(WCHAR));
|
|
|
|
if(!pSQL)
|
|
{
|
|
COMPARE(pSQL,NULL);
|
|
odtLog << L"out of memory\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
swprintf(pSQL, wszCreateProc, pwszProcName, m_pTable->GetTableName());
|
|
|
|
//CREATE PROCEDURE <procname> (@IntIn int =1, @IntOut int =2 OUTPUT) AS Select * from %s RETURN (1)";
|
|
// will give me:
|
|
// 1 input
|
|
// 1 output
|
|
// 1 return
|
|
|
|
if(!CHECK(pICommandText->SetCommandText(DBGUID_DBSQL,m_pwszDropProc),S_OK))
|
|
goto CLEANUP;
|
|
|
|
pICommandText->Execute(NULL,IID_NULL,NULL,NULL,NULL);
|
|
|
|
if(!CHECK(pICommandText->SetCommandText(DBGUID_DBSQL,pSQL),S_OK))
|
|
goto CLEANUP;
|
|
|
|
if(!CHECK(pICommandText->Execute(NULL,IID_NULL,NULL,NULL,NULL),S_OK))
|
|
goto CLEANUP;
|
|
|
|
// fill these in
|
|
m_pwszProcedureRestriction = (WCHAR *) PROVIDER_ALLOC(
|
|
(wcslen(pwszProcName) +
|
|
1) * sizeof(WCHAR*));
|
|
|
|
if(!m_pwszProcedureRestriction)
|
|
{
|
|
COMPARE(m_pwszProcedureRestriction,NULL);
|
|
odtLog << L"out of memory\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
swprintf(m_pwszProcedureRestriction, pwszProcName);
|
|
|
|
//WCHAR * m_pwszProcedureColumnsRestriction;
|
|
// since we are doing select * from table we can use the
|
|
// column we found previously
|
|
m_pwszProcedureColumnsRestriction = (WCHAR *) PROVIDER_ALLOC(
|
|
(wcslen(m_pwszColumnRestriction) +
|
|
1) * sizeof(WCHAR*));
|
|
|
|
if(!m_pwszProcedureColumnsRestriction)
|
|
{
|
|
COMPARE(m_pwszProcedureColumnsRestriction,NULL);
|
|
odtLog << L"out of memory\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
swprintf(m_pwszProcedureColumnsRestriction, m_pwszColumnRestriction);
|
|
|
|
//WCHAR * m_pwszParameterRestriction;
|
|
m_pwszParameterRestriction = (WCHAR *) PROVIDER_ALLOC(
|
|
(wcslen(L"IntIn") +
|
|
1) * sizeof(WCHAR*));
|
|
|
|
if(!m_pwszParameterRestriction)
|
|
{
|
|
COMPARE(m_pwszParameterRestriction,NULL);
|
|
odtLog << L"out of memory\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
swprintf(m_pwszParameterRestriction, L"IntIn");
|
|
|
|
|
|
//WCHAR * m_pwszProcedureType;
|
|
// default will be return value but I'll have
|
|
// to add more variations in the Procedure Parameter class
|
|
// to test all 4 types.
|
|
m_ProcedureTypeRestriction = DBPARAMTYPE_RETURNVALUE;
|
|
m_uiProcedureType = DBPARAMTYPE_RETURNVALUE;
|
|
|
|
fSucceed = TRUE;
|
|
|
|
|
|
CLEANUP:
|
|
|
|
FREE;
|
|
|
|
SAFE_RELEASE(pICommandText);
|
|
|
|
// Free the memory
|
|
PROVIDER_FREE(pSQL);
|
|
PROVIDER_FREE(pwszProcName);
|
|
|
|
return fSucceed;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Procedure
|
|
//
|
|
// With DBSCHEMA_PROCEDURE, will fill in m_pwszProcedureRestriction and m_pwszProcedure_Type
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_Procedure()
|
|
{
|
|
BOOL fSucceed=FALSE;
|
|
|
|
ICommandText * pICommandText=NULL;
|
|
|
|
if(m_bSqlServer)
|
|
{
|
|
|
|
if(!(m_pTable->get_ICommandPTR()))
|
|
goto CLEANUP;
|
|
|
|
if(!CHECK(m_pTable->get_ICommandPTR()->QueryInterface(IID_ICommandText,(void**)&pICommandText),S_OK))
|
|
goto CLEANUP;
|
|
|
|
if (m_pwszDropProc)
|
|
{
|
|
if(!CHECK(pICommandText->SetCommandText(DBGUID_DBSQL,m_pwszDropProc),S_OK))
|
|
goto CLEANUP;
|
|
|
|
if(!CHECK(pICommandText->Execute(NULL,IID_NULL,NULL,NULL,NULL),S_OK))
|
|
goto CLEANUP;
|
|
}
|
|
|
|
CLEANUP:
|
|
|
|
SAFE_RELEASE(pICommandText);
|
|
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszDropProc);
|
|
PROVIDER_FREE(m_pwszProcedureRestriction);
|
|
PROVIDER_FREE(m_pwszProcedureColumnsRestriction);
|
|
PROVIDER_FREE(m_pwszParameterRestriction);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Find_ProcedureColumn
|
|
//
|
|
// With DBSCHEMA_PROCEDURE_COLUMNS, will fill in
|
|
// m_pwszProcedureColumnRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_ProcedureColumn()
|
|
{
|
|
INIT
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
if(!IsSchemaSupported(DBSCHEMA_PROCEDURE_COLUMNS))
|
|
return FALSE;
|
|
|
|
m_restrict |= FIRST;
|
|
m_restrict |= SECOND;
|
|
m_restrict |= THIRD;
|
|
|
|
m_iid = IID_IRowset;
|
|
|
|
// if this is a schema I want then get information for schema
|
|
if(GetSchemaInfo(SPECIFIC,0,DBSCHEMA_PROCEDURE_COLUMNS))
|
|
GetRowset();
|
|
|
|
FREE
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Procedure
|
|
//
|
|
// With DBSCHEMA_PROCEDURE, will fill in m_pwszProcedureRestriction and m_pwszProcedure_Type
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_ProcedureColumn()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszProcedureColumnsRestriction);
|
|
return TRUE;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// Find Parameter
|
|
//
|
|
// With DBSCHEMA_PROCEDURE_PARAMETER, will fill in m_pwszParameterRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_Parameter()
|
|
{
|
|
INIT
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
if(!IsSchemaSupported(DBSCHEMA_PROCEDURE_PARAMETERS))
|
|
return FALSE;
|
|
|
|
m_restrict |= FIRST;
|
|
m_restrict |= SECOND;
|
|
m_restrict |= THIRD;
|
|
|
|
m_iid = IID_IRowset;
|
|
|
|
// if this is a schema I want then get information for schema
|
|
if(GetSchemaInfo(SPECIFIC,0,DBSCHEMA_PROCEDURE_PARAMETERS))
|
|
GetRowset();
|
|
|
|
FREE
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Parameter
|
|
//
|
|
// With DBSCHEMA_PROCEDURE_PARAMETER, will fill in m_pwszParameterRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_Parameter()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszParameterRestriction);
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Referential Constraint
|
|
//
|
|
// With DBSCHEMA_REFERENTIAL_CONSTRAINTS, will fill m_pwszReferential_ConstraintRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_Referential_Constraint()
|
|
{
|
|
INIT
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
if(!IsSchemaSupported(DBSCHEMA_REFERENTIAL_CONSTRAINTS))
|
|
return FALSE;
|
|
|
|
m_restrict |= FIRST;
|
|
m_restrict |= SECOND;
|
|
|
|
m_iid = IID_IRowset;
|
|
|
|
// if this is a schema I want then get information for schema
|
|
if(GetSchemaInfo(SPECIFIC,0,DBSCHEMA_REFERENTIAL_CONSTRAINTS))
|
|
GetRowset();
|
|
|
|
FREE
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Referential Constraint
|
|
//
|
|
// With DBSCHEMA_REFERENTIAL_CONSTRAINTS, will fill m_pwszReferential_ConstraintRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_Referential_Constraint()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszReferential_ConstraintRestriction);
|
|
return TRUE;
|
|
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Table Constraint
|
|
//
|
|
// With DBSCHEMA_TABLE_CONSTRAINTS, will fill m_pwszTable_ConstraintRestriction
|
|
// and m_pwszTable_Constraint_Type
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_Constraint_Type()
|
|
{
|
|
INIT
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
if(!IsSchemaSupported(DBSCHEMA_TABLE_CONSTRAINTS))
|
|
return FALSE;
|
|
|
|
m_restrict |= FIRST;
|
|
m_restrict |= SECOND;
|
|
m_restrict |= FOURTH;
|
|
m_restrict |= FIFTH;
|
|
// m_restrict |= SIXTH; // No restriction on table name because we didn't add one
|
|
|
|
m_iid = IID_IRowset;
|
|
|
|
// if this is a schema I want then get information for schema
|
|
if(GetSchemaInfo(SPECIFIC,0,DBSCHEMA_TABLE_CONSTRAINTS))
|
|
GetRowset();
|
|
|
|
FREE
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Table Constraint
|
|
//
|
|
// With DBSCHEMA_TABLE_CONSTRAINTS, will fill m_pwszTable_ConstraintRestriction
|
|
// and m_pwszTable_Constraint_Type
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_Constraint_Type()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszTable_ConstraintRestriction);
|
|
PROVIDER_FREE(m_pwszConstraint_TypeRestriction);
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Translation
|
|
//
|
|
// With DBSCHEMA_TRANSLATIONS, will fill in m_pwszTranslationReplace
|
|
//
|
|
// While the translation should be the same as the
|
|
// character set, I'm not taking any chances
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_Translation()
|
|
{
|
|
INIT
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
if(!IsSchemaSupported(DBSCHEMA_TRANSLATIONS))
|
|
return FALSE;
|
|
|
|
m_restrict |= FIRST;
|
|
m_restrict |= SECOND;
|
|
|
|
m_iid = IID_IRowset;
|
|
|
|
// if this is a schema I want then get information for schema
|
|
if(GetSchemaInfo(SPECIFIC,0,DBSCHEMA_TRANSLATIONS))
|
|
GetRowset();
|
|
|
|
FREE
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find Translation
|
|
//
|
|
// With DBSCHEMA_TRANSLATIONS, will fill in m_pwszTranslationReplace
|
|
//
|
|
// While the translation should be the same as the
|
|
// character set, I'm not taking any chances
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_Translation()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszTranslationReplace);
|
|
return TRUE;
|
|
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find View
|
|
//
|
|
// With DBSCHEMA_VIEW_TABLE_USAGE, will fill in m_pwszViewRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_View()
|
|
{
|
|
INIT
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
if(!IsSchemaSupported(DBSCHEMA_VIEW_TABLE_USAGE))
|
|
return FALSE;
|
|
|
|
m_restrict |= FIRST;
|
|
m_restrict |= SECOND;
|
|
|
|
m_iid = IID_IRowset;
|
|
|
|
// if this is a schema I want then get information for schema
|
|
if(GetSchemaInfo(SPECIFIC,0,DBSCHEMA_VIEW_TABLE_USAGE))
|
|
GetRowset();
|
|
|
|
FREE
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find View
|
|
//
|
|
// With DBSCHEMA_VIEW_TABLE_USAGE, will fill in m_pwszViewRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_View()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszViewRestriction);
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find BestMatch for DBSCHEMA_PROVIDER_TYPES
|
|
//
|
|
// With DBSCHEMA_VIEW_TABLE_USAGE, will fill in m_pwszViewRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_BestMatch()
|
|
{
|
|
INIT
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
if(!IsSchemaSupported(DBSCHEMA_PROVIDER_TYPES))
|
|
return FALSE;
|
|
|
|
m_restrict |= FIRST;
|
|
m_iid = IID_IRowset;
|
|
|
|
// if this is a schema I want then get information for schema
|
|
if(GetSchemaInfo(SPECIFIC,0,DBSCHEMA_PROVIDER_TYPES))
|
|
GetRowset();
|
|
|
|
FREE
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find BestMatch for DBSCHEMA_PROVIDER_TYPES
|
|
//
|
|
// With DBSCHEMA_FOREIGN_KEYS,
|
|
// m_pwszPK_TableRestriction, m_pwszFK_TableRestriction;
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Find_PK_and_FK()
|
|
{
|
|
INIT
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
if(!IsSchemaSupported(DBSCHEMA_FOREIGN_KEYS))
|
|
return FALSE;
|
|
|
|
m_restrict |= FIRST;
|
|
m_restrict |= SECOND;
|
|
m_restrict |= FOURTH;
|
|
m_restrict |= FIFTH;
|
|
|
|
m_iid = IID_IRowset;
|
|
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
// PK TABLE_NAME
|
|
if ((g_pKeyTable2) && (g_pKeyTable2->GetTableName()))
|
|
{
|
|
m_pwszPK_TableRestriction = (WCHAR *) PROVIDER_ALLOC
|
|
((wcslen((WCHAR *) g_pKeyTable2->GetTableName())*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
|
|
if(m_pwszPK_TableRestriction)
|
|
wcscpy(m_pwszPK_TableRestriction,(TYPE_WSTR) g_pKeyTable2->GetTableName());
|
|
}
|
|
|
|
if ((g_pKeyTable1) && (g_pKeyTable1->GetTableName()))
|
|
{
|
|
// FK TABLE_NAME
|
|
m_pwszFK_TableRestriction = (WCHAR *) PROVIDER_ALLOC
|
|
((wcslen((WCHAR *) g_pKeyTable1->GetTableName())*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszFK_TableRestriction)
|
|
wcscpy(m_pwszFK_TableRestriction,(TYPE_WSTR)g_pKeyTable1->GetTableName());
|
|
}
|
|
|
|
}
|
|
|
|
|
|
FREE
|
|
|
|
return TRUE;
|
|
}
|
|
//--------------------------------------------------------------------
|
|
// Find BestMatch for DBSCHEMA_PROVIDER_TYPES
|
|
//
|
|
// With DBSCHEMA_VIEW_TABLE_USAGE, will fill in m_pwszViewRestriction
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::Release_PK_and_FK()
|
|
{
|
|
// Free the memory
|
|
PROVIDER_FREE(m_pwszPK_TableRestriction);
|
|
PROVIDER_FREE(m_pwszFK_TableRestriction);
|
|
return TRUE;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// ASSERTIONS
|
|
// 1. Constraint Catalog
|
|
// 2. Constraint Schema
|
|
// 3. Constraint Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_ASSERTIONS()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **) rgwszASSERTIONS;
|
|
m_rgColumnTypes = (DBTYPE *) rgtypeASSERTIONS;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cASSERTIONS;
|
|
m_cRestrictions = cASSERTIONS_RESTRICTIONS;
|
|
|
|
// Set Constraint Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszAssertion_ConstraintRestriction);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowASSERTIONS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_ASSERTIONS(DBCOUNTITEM iRow, BYTE * pData)
|
|
{
|
|
ULONG iBind=0; // Binding Count
|
|
DATA * pColumn=NULL; // Data Structure
|
|
CCol col;
|
|
BOOL fResults=TRUE;
|
|
|
|
// don't need to go farther if I have what I'm looking for
|
|
if(m_fCaptureRestrictions && m_pwszAssertion_ConstraintRestriction)
|
|
return FALSE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cASSERTIONS <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:ASSERTIONS:", iRow,m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// CONSTRAINT CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR) pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_ASSERTIONS:CONSTRAINT CATALOG restriction failed\n";
|
|
m_fRes1 = FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
PRVTRACE(L"= %s\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2://CONSTRAINT SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR) pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_ASSERTIONS:CONSTRAINT SCHEMA restriction failed\n";
|
|
m_fRes1 = FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
PRVTRACE(L"= %s\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3://CONSTRAINT NAME
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR) pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_ASSERTIONS:CONSTRAINT NAME restriction failed\n";
|
|
m_fRes3 = FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszAssertion_ConstraintRestriction = (TYPE_WSTR) PROVIDER_ALLOC
|
|
((wcslen((TYPE_WSTR) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszAssertion_ConstraintRestriction)
|
|
wcscpy(m_pwszAssertion_ConstraintRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
}
|
|
|
|
PRVTRACE(L"= %s\n",(WCHAR *)pColumn->bValue);
|
|
break;
|
|
case 4: //IS_DEFERRABLE
|
|
case 5: //INITIALLY_DEFERRED
|
|
if(*(TYPE_BOOL *)pColumn->bValue==VARIANT_TRUE)
|
|
PRVTRACE(L"TRUE\n");
|
|
else
|
|
PRVTRACE(L"FALSE\n");
|
|
break;
|
|
case 6: // DESCRIPTION
|
|
PRVTRACE(L"= %s\n",(TYPE_WSTR)pColumn->bValue );
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"ASSERTIONS: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - ASSERTIONS provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// CATALOGS
|
|
// 1. Catalog Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_CATALOGS()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **) rgwszCATALOGS;
|
|
m_rgColumnTypes = (DBTYPE *) rgtypeCATALOGS;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cCATALOGS;
|
|
m_cRestrictions = cCATALOGS_RESTRICTIONS;
|
|
|
|
// Set Catalog Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowCATALOGS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_CATALOGS(DBCOUNTITEM iRow, BYTE * pData)
|
|
{
|
|
ULONG iBind=0; // Binding Count
|
|
DATA * pColumn=NULL; // Data Structure
|
|
CCol col;
|
|
BOOL fResults=TRUE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cCATALOGS <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"CATALOGS:Row[%lu],Col[%d,%s]:",
|
|
// iRow,
|
|
// m_rgDBCOLUMNINFO[iBind].iOrdinal,
|
|
// m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// CATALOG_NAME
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR) pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_CATALOGS:CATALOG_NAME restriction failed\n";
|
|
m_fRes1 = FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"= %s\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2://DESCRIPTION
|
|
PRVTRACE(L"= %s\n",(TYPE_WSTR)pColumn->bValue );
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"CATALOGS: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - CATALOGS provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// CHARACTER_SETS
|
|
// 1. Character Set Catalog
|
|
// 2. Character Set Schema
|
|
// 3. Character Set Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_CHARACTER_SETS()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszCHARACTER_SETS;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeCHARACTER_SETS;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cCHARACTER_SETS;
|
|
m_cRestrictions = cCHARACTER_SETS_RESTRICTIONS;
|
|
|
|
// Set Character Sets Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszCharacter_SetRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::CHARACTER_SETS\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowCHARACTER_SETS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_CHARACTER_SETS(DBCOUNTITEM iRow, BYTE * pData)
|
|
{
|
|
ULONG iBind=0; // Binding Count
|
|
DATA * pColumn=NULL; // Data Structure
|
|
CCol col;
|
|
BOOL fResults=TRUE;
|
|
|
|
// don't need to go farther if I have what I'm looking for
|
|
if(m_fCaptureRestrictions && m_fCaptureRestrictions)
|
|
return FALSE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cCHARACTER_SETS <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:CHARACTER_SETS:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// CHARACTER SET CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_CHARACTER_SETS:CHARACTER SET CATALOG restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// CHARACTER SET SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_CHARACTER_SETS:CHARACTER SET SCHEMA restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3:// CHARACTER_SET_NAME
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_CHARACTER_SETS:CHARACTER SET NAME restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszCharacter_SetRestriction = (WCHAR *) PROVIDER_ALLOC((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszCharacter_SetRestriction)
|
|
wcscpy(m_pwszCharacter_SetRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
|
|
}
|
|
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// FORM_OF_USE
|
|
case 6:// DEFAULT_COLLATE_CATALOG
|
|
case 7:// DEFAULT_COLLATE_SCHEMA
|
|
case 8:// DEFAULT_COLLATE_NAME
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 5:// NUMBER OF CHARACTERS
|
|
PRVTRACE(L"%d\n",*(TYPE_I8 *)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"CHARACTER SETS: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - CHARACTER SETS provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// CHECK_CONSTRAINTS
|
|
// 1. Constraint Catalog
|
|
// 2. Constraint Schema
|
|
// 3. Constraint Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_CHECK_CONSTRAINTS()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszCHECK_CONSTRAINTS;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeCHECK_CONSTRAINTS;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cCHECK_CONSTRAINTS;
|
|
m_cRestrictions = cCHECK_CONSTRAINTS_RESTRICTIONS;
|
|
|
|
// Set Constraint Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszCheck_ConstraintRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::CHECK_CONSTRAINTS\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowCHECK_CONSTRAINTS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_CHECK_CONSTRAINTS(DBCOUNTITEM iRow, BYTE * pData)
|
|
{
|
|
ULONG iBind=0; // Binding Count
|
|
DATA * pColumn=NULL; // Data Structure
|
|
CCol col;
|
|
BOOL fResults=TRUE;
|
|
|
|
// don't need to go farther if I have what I'm looking for
|
|
if(m_fCaptureRestrictions && m_pwszCheck_ConstraintRestriction)
|
|
return FALSE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cCHECK_CONSTRAINTS <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:CHECK_CONSTRAINTS:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// CHECK_CONSTRAINTS CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_CHECK_CONSTRAINTS:CHECK_CONSTRAINTS CATALOG restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// CHECK_CONSTRAINTS SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_CHECK_CONSTRAINTS:CHECK_CONSTRAINTS SCHEMA restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3:// CHECK_CONSTRAINTS NAME
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog <<L"VerifyRow_CHECK_CONSTRAINTS:CHECK_CONSTRAINTS NAME restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszCheck_ConstraintRestriction = (WCHAR *) PROVIDER_ALLOC((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszCheck_ConstraintRestriction)
|
|
wcscpy(m_pwszCheck_ConstraintRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// CHECK_CLAUSE
|
|
case 5:// DESCRIPTION
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"CHECK CONSTRAINTS: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - CHECK CONSTRAINTS provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// COLLATIONS
|
|
// 1. Collation Catalog
|
|
// 2. Collation Schema
|
|
// 3. Collation Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_COLLATIONS()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszCOLLATIONS;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeCOLLATIONS;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cCOLLATIONS;
|
|
m_cRestrictions = cCOLLATIONS_RESTRICTIONS;
|
|
|
|
// Set Collation Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszCollationRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::COLLATIONS\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowCOLLATIONS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_COLLATIONS(DBCOUNTITEM iRow, BYTE * pData)
|
|
{
|
|
ULONG iBind=0; // Binding Count
|
|
DATA * pColumn=NULL; // Data Structure
|
|
CCol col;
|
|
BOOL fResults=TRUE;
|
|
|
|
// don't need to go farther if I have what I'm looking for
|
|
if(m_fCaptureRestrictions && m_pwszCollationRestriction)
|
|
return FALSE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cCOLLATIONS <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:COLLATIONS:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// COLLATIONS CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_COLLATIONS:COLLATIONS CATALOG restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// COLLATIONS SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_COLLATIONS:COLLATIONS SCHEMA restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3:// COLLATIONS_NAME
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_COLLATIONS:COLLATIONS NAME restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszCollationRestriction = (WCHAR *) PROVIDER_ALLOC((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszCollationRestriction)
|
|
wcscpy(m_pwszCollationRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// CHARACTER SET CATALOG
|
|
case 5:// CHARACTER SET SCHEMA
|
|
case 6:// CHARACTER SET NAME
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 7:// PAD ATTRIBUTE
|
|
if( (!COMPARE(0, wcscmp((TYPE_WSTR)pColumn->bValue,L"NO PAD")) && (0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"PAD SPACE"))))
|
|
{
|
|
odtLog << L"VerifyRow_COLLATIONS:PAD ATTRIBUTE expected NO PAD or PAD SPACE but recieved "
|
|
<< (TYPE_WSTR)pColumn->bValue << ENDL;
|
|
fResults = FALSE;
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"COLLATIONS: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - COLLATIONS provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// COLUMN_DOMAIN_USAGE
|
|
// 1. Domain Catalog
|
|
// 2. Domain Schema
|
|
// 3. Domain Name
|
|
// 4. Column Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_COLUMN_DOMAIN_USAGE()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszCOLUMN_DOMAIN_USAGE;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeCOLUMN_DOMAIN_USAGE;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cCOLUMN_DOMAIN_USAGE;
|
|
m_cRestrictions = cCOLUMN_DOMAIN_USAGE_RESTRICTIONS;
|
|
|
|
// Set Domain Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszDomainRestriction);
|
|
SetRestriction(FOURTH,4, &m_wszR4, m_pwszColumnRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::COLUMN_DOMAIN_USAGE\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowDOMAIN_COLUMN_USAGE
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_COLUMN_DOMAIN_USAGE(DBCOUNTITEM iRow, BYTE * pData)
|
|
{
|
|
ULONG iBind=0; // Binding Count
|
|
DATA * pColumn=NULL; // Data Structure
|
|
CCol col;
|
|
BOOL fResults=TRUE;
|
|
|
|
// don't need to go farther if I have what I'm looking for
|
|
if(m_fCaptureRestrictions && m_pwszDomainRestriction)
|
|
return FALSE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cCOLUMN_DOMAIN_USAGE <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:COLUMN_DOMAIN_USAGE:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// DOMAIN CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_COLUMN_DOMAIN_USAGE:DOMAIN CATALOG restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// DOMAIN SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_COLUMN_DOMAIN_USAGE:DOMAIN SCHEMA restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3:// DOMAIN_NAME
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_COLUMN_DOMAIN_USAGE:DOMAIN NAME restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszDomainRestriction = (WCHAR *) PROVIDER_ALLOC((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszDomainRestriction)
|
|
wcscpy(m_pwszDomainRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// TABLE CATALOG
|
|
case 5:// TABLE SCHEMA
|
|
case 6:// TABLE NAME
|
|
case 7:// COLUMN NAME
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 8:// COLUMN GUID
|
|
PRVTRACE(L"\n");
|
|
case 9:// COLUMN PROPID
|
|
PRVTRACE(L"%d\n",*(TYPE_UI4 *)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"COLUMN DOMAIN USAGE: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - COLUMN DOMAIN USAGE provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// COLUMN_PRIVILEGES
|
|
// 1. Table Catalog
|
|
// 2. Table Schema
|
|
// 3. Table Name
|
|
// 4. Column Name
|
|
// 5. Grantor
|
|
// 6. Grantee
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_COLUMN_PRIVILEGES()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszCOLUMN_PRIVILEGES;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeCOLUMN_PRIVILEGES;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cCOLUMN_PRIVILEGES;
|
|
m_cRestrictions = cCOLUMN_PRIVILEGES_RESTRICTIONS;
|
|
|
|
// Set Table Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszTableRestriction);
|
|
SetRestriction(FOURTH,4, &m_wszR4, m_pwszColumnRestriction);
|
|
SetRestriction(FIFTH, 5, &m_wszR5, m_pwszGrantorRestriction);
|
|
SetRestriction(SIXTH, 6, &m_wszR6, m_pwszGranteeRestriction);
|
|
|
|
// Set expected row count. Since we create a table and we know
|
|
// how many columns there are we must have at least that number of
|
|
// rows, unless restricted to a given column.
|
|
if (!m_wszR4)
|
|
SetRowCount(MIN_REQUIRED, m_pTable->CountColumnsOnTable());
|
|
|
|
PRVTRACE(L"GetSchemaInfo::COLUMN_PRIVILEGES\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowCOLUMN_PRIVILEGES
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_COLUMN_PRIVILEGES(DBCOUNTITEM iRow, BYTE * pData)
|
|
{
|
|
ULONG iBind=0; // Binding Count
|
|
DATA * pColumn=NULL; // Data Structure
|
|
CCol col;
|
|
BOOL fResults=TRUE;
|
|
|
|
int test=0;
|
|
|
|
// don't need to go farther if I have what I'm looking for
|
|
if(m_fCaptureRestrictions && m_pwszGrantorRestriction && m_pwszGranteeRestriction)
|
|
return FALSE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cCOLUMN_PRIVILEGES <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"COLUMN_PRIVILEGES:Row[%lu],Col[%d,%s]:",
|
|
// iRow,
|
|
// m_rgDBCOLUMNINFO[iBind].iOrdinal,
|
|
// m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// GRANTOR
|
|
if(m_restrict & FIFTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR5,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes5)
|
|
{
|
|
odtLog << L"VerifyRow_COLUMN_PRIVILEGES:GRANTOR 5 restriction failed\n";
|
|
m_fRes5=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszGrantorRestriction = (WCHAR *) PROVIDER_ALLOC((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszGrantorRestriction)
|
|
wcscpy(m_pwszGrantorRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
|
|
}
|
|
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// GRANTEE
|
|
if(m_restrict & SIXTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR6,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes6)
|
|
{
|
|
odtLog << L"VerifyRow_COLUMN_PRIVILEGES:GRANTEE 6 restriction failed\n";
|
|
m_fRes6=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszGranteeRestriction = (WCHAR *) PROVIDER_ALLOC((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszGranteeRestriction)
|
|
wcscpy(m_pwszGranteeRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3:// TABLE_CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_COLUMN_PRIVILEGES:TABLE_CATALOG 1 restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// TABLE_SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_COLUMN_PRIVILEGES:TABLE_SCHEMA 2 restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 5:// TABLE_NAME
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_COLUMN_PRIVILEGES:TABLE_NAME 3 restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 6:// COLUMN_NAME
|
|
if(m_restrict & FOURTH)
|
|
{
|
|
test=_wcsicmp((TYPE_WSTR)m_wszR4,(TYPE_WSTR)pColumn->bValue);
|
|
|
|
if(!COMPARE(0, _wcsicmp((WCHAR *)m_wszR4,(WCHAR *)pColumn->bValue)))
|
|
{
|
|
if(m_fRes4)
|
|
{
|
|
odtLog << L"VerifyRow_COLUMN_PRIVILEGES:COLUMN_NAME 4 restriction failed\n";
|
|
m_fRes4 = FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 7:// COLUMN_GUID
|
|
// TODO: Can I do anything interesting with a GUID?
|
|
PRVTRACE(L"\n");
|
|
break;
|
|
case 8:// COLUMN_PROPID
|
|
PRVTRACE(L"%ul\n",*(TYPE_UI4 *)pColumn->bValue);
|
|
break;
|
|
case 9:// PRIVILEGE_TYPE
|
|
if( (0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"SELECT")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"DELETE")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"INSERT")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"UPDATE")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"REFERENCES")))
|
|
{
|
|
odtLog << L"VerifyRow_COLUMN_PRIVILEGES:PRIVILEGE_TYPE expected SELECT,DELETE,INSERT,UPDATE, or REFERENCES but received "
|
|
<< (TYPE_WSTR)pColumn->bValue << ENDL;
|
|
fResults = FALSE;
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 10:// IS_GRANTABLE
|
|
if((*(TYPE_BOOL *)pColumn->bValue)==VARIANT_TRUE)
|
|
PRVTRACE(L"YES\n");
|
|
else
|
|
PRVTRACE(L"NO\n");
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"COLUMN PRIVILEGES: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - COLUMN PRIVILEGES provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
|
|
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// COLUMNS
|
|
// 1. Table Catalog
|
|
// 2. Table Schema
|
|
// 3. Table Name
|
|
// 4. Column Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_COLUMNS()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_cColumns = cCOLUMNS;
|
|
m_rgColumnNames = (WCHAR **)rgwszCOLUMNS;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeCOLUMNS;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cRestrictions = cCOLUMNS_RESTRICTIONS;
|
|
|
|
// Set Table Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszTableRestriction);
|
|
SetRestriction(FOURTH,4, &m_wszR4, m_pwszColumnRestriction);
|
|
|
|
// Set an Invalid Table Restriction
|
|
if(m_restrict & FIFTH) {
|
|
SetRestriction(FIFTH,5, &m_wszR5, m_pwszTableRestriction);
|
|
m_cRestrictions = 5;
|
|
}
|
|
|
|
// Set expected row count. Since we create a table and we know
|
|
// how many columns there are we must have at least that number of
|
|
// rows
|
|
SetRowCount(MIN_REQUIRED, m_pTable->CountColumnsOnTable());
|
|
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowCOLUMNS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_COLUMNS(DBCOUNTITEM iRow, BYTE * pData)
|
|
{
|
|
ULONG iBind=0; // Binding Count
|
|
ULONG iIndex = 0; // Index into rgColInfo array
|
|
CCol col;
|
|
BOOL fResults=TRUE;
|
|
ULONG cColumns = 0;
|
|
ULONG iOrdinalBinding = 6+!m_rgDBCOLUMNINFO[0].iOrdinal;
|
|
|
|
// Per spec, the columns rowset must list columns a user has access to, therefore the user
|
|
// must have access to the associated table. Retrieve columns info for the table if this is a new
|
|
// table.
|
|
if (S_OK != GetColumnInfo(pData, m_rgDBBINDING))
|
|
return FALSE;
|
|
|
|
// If we don't have an m_prgColInfo array, then GetColumnInfo returns S_FALSE above.
|
|
|
|
// Make our best guess of the index
|
|
iIndex = m_ulTableOrdinal-1+!m_prgColInfo[0].iOrdinal;
|
|
|
|
// If the provider returned the data out of order we have to find the ordinal
|
|
ASSERT(m_rgDBBINDING[iOrdinalBinding].iOrdinal == 7);
|
|
if (STATUS_BINDING(m_rgDBBINDING[iOrdinalBinding], pData) == DBSTATUS_S_OK)
|
|
{
|
|
DBORDINAL iOrdinal = (ULONG_PTR)VALUE_BINDING(m_rgDBBINDING[iOrdinalBinding], pData);
|
|
|
|
// If this isn't the right index ordinals won't match
|
|
if (m_prgColInfo[iIndex].iOrdinal != iOrdinal)
|
|
{
|
|
// Find the ordinal value in m_prgColInfo array as this row may not be in order
|
|
for (ULONG iColInfo = 0; iColInfo < m_cColumns; iColInfo++)
|
|
{
|
|
if (m_prgColInfo[iColInfo].iOrdinal == iOrdinal)
|
|
{
|
|
iIndex = iColInfo;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Make sure we don't crash, but this will cause lots of errors
|
|
if (!COMPARE(iIndex <= m_cColInfo - !m_prgColInfo[0].iOrdinal, TRUE))
|
|
iIndex = 0;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cCOLUMNS <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
DBBINDING * pBind = &m_rgDBBINDING[iBind];
|
|
DBORDINAL iOrdinal = m_rgDBCOLUMNINFO[iBind].iOrdinal;
|
|
DBSTATUS ulStatus = STATUS_BINDING(*pBind, pData);
|
|
DATA * pColumn=(DATA *) (pData + pBind->obStatus);
|
|
BYTE * pValue = pColumn->bValue;
|
|
|
|
if (m_fRes4 && m_fCaptureRestrictions)
|
|
{
|
|
m_fCaptureRestrictions = FALSE;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
switch(iOrdinal)
|
|
{
|
|
// TABLE_CATALOG
|
|
case 1:
|
|
fResults &= TestReturnData(iRow,pColumn,FIRST,&m_fRes1,m_wszR1);
|
|
break;
|
|
|
|
// TABLE_SCHEMA
|
|
case 2:
|
|
fResults &= TestReturnData(iRow,pColumn,SECOND,&m_fRes2,m_wszR2);
|
|
break;
|
|
|
|
// TABLE_NAME
|
|
case 3:
|
|
fResults &= TestReturnData(iRow,pColumn,THIRD,&m_fRes3,m_wszR3);
|
|
break;
|
|
|
|
// COLUMN_NAME
|
|
case 4:
|
|
fResults &= TestReturnData(iRow,pColumn,FOURTH,&m_fRes4,m_wszR4);
|
|
break;
|
|
|
|
case 5: // COLUMN_GUID
|
|
break;
|
|
case 13:// TYPE_GUID
|
|
break;
|
|
case 6: //COLUMN_PROPID
|
|
break;
|
|
case 7: // ORDINAL_POSITION
|
|
if (ulStatus == DBSTATUS_S_OK)
|
|
{
|
|
// Status is OK, warning if ordinals don't match
|
|
// Providers are not required to return results in ordinal order, since
|
|
// sort is only on catalog, schema, and name, so only a warning.
|
|
// If restriction is only on column then the ordinal may not match anyway.
|
|
if (!m_fRes4)
|
|
{
|
|
COMPAREW(m_ulTableOrdinal, (ULONG)(ULONG_PTR)VALUE_BINDING(*pBind, pData));
|
|
if (m_ulTableOrdinal != (ULONG)(ULONG_PTR)VALUE_BINDING(*pBind, pData))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Ordinal didn't match expected value.\n";
|
|
}
|
|
else
|
|
{
|
|
// We will assume if the index for the matching ordinal contains
|
|
// the proper column name that it was the right ordinal.
|
|
if (RelCompareString(m_wszR4, m_prgColInfo[iIndex].pwszName))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Ordinal didn't match expected value.\n";
|
|
}
|
|
}
|
|
else if (ulStatus == DBSTATUS_S_ISNULL)
|
|
{
|
|
// Status is NULL. While this is allowed, it's not normally the case, so warn
|
|
COMPAREW(ulStatus, DBSTATUS_S_OK);
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"DBSTATUS_S_ISNULL returned.\n";
|
|
}
|
|
else
|
|
{
|
|
// Otherwise this is a failure.
|
|
if (!COMPARE(ulStatus, DBSTATUS_S_OK))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Invalid value returned.\n";
|
|
}
|
|
break;
|
|
case 10:// COLUMN FLAGS
|
|
// This column cannot contain NULL
|
|
if (COMPARE(ulStatus, DBSTATUS_S_OK))
|
|
CCOMPARE(m_EC, m_prgColInfo[iIndex].dwFlags == *(DBCOLUMNFLAGS *)pValue,
|
|
EC_BAD_COLUMN_FLAGS,
|
|
L"COLUMN_FLAGS value did not match GetColumnInfo",
|
|
FALSE);
|
|
break;
|
|
case 14:// CHARACTER_MAXIMUM_LENGTH
|
|
switch(m_prgColInfo[iIndex].wType)
|
|
{
|
|
// case DBTYPE_BOOL: // We assume BOOL is not a "bit" column per spec.
|
|
case DBTYPE_BYTES:
|
|
case DBTYPE_STR:
|
|
case DBTYPE_WSTR:
|
|
if (COMPARE(ulStatus, DBSTATUS_S_OK))
|
|
{
|
|
if (m_prgColInfo[iIndex].ulColumnSize == ~0 &&
|
|
!COMPARE(*(ULONG *)pValue, 0))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Must be 0 for column without defined max length.\n";
|
|
else
|
|
CCOMPARE(m_EC, *(ULONG *)pValue == m_prgColInfo[iIndex].ulColumnSize,
|
|
EC_BAD_CHARACTER_MAXIMUM_LENGTH,
|
|
L"CHARACTER_MAXIMUM_LENGTH value did not match GetColumnInfo",
|
|
FALSE);
|
|
}
|
|
else
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Cannot be NULL for variable length column.\n";
|
|
break;
|
|
// NULL for all other data types
|
|
default:
|
|
if (!COMPARE(ulStatus, DBSTATUS_S_ISNULL))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Status was not DBSTATUS_S_ISNULL for non-char, binary, or bit column\n";
|
|
}
|
|
break;
|
|
case 15:// CHARACTER_OCTET_LENGTH
|
|
switch(m_prgColInfo[iIndex].wType)
|
|
{
|
|
case DBTYPE_BYTES:
|
|
case DBTYPE_STR:
|
|
case DBTYPE_WSTR:
|
|
if (COMPARE(ulStatus, DBSTATUS_S_OK))
|
|
{
|
|
if (m_prgColInfo[iIndex].ulColumnSize == ~0 &&
|
|
!COMPARE(*(ULONG *)pValue, 0))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Must be 0 for column without defined max length.\n";
|
|
else
|
|
{
|
|
DBLENGTH ulOctetLen = m_prgColInfo[iIndex].ulColumnSize;
|
|
if (m_prgColInfo[iIndex].wType == DBTYPE_WSTR)
|
|
ulOctetLen *= sizeof(WCHAR);
|
|
|
|
CCOMPARE(m_EC, ulOctetLen == *(ULONG *)pValue,
|
|
EC_BAD_CHARACTER_OCTET_LENGTH,
|
|
L"CHARACTER_OCTET_LENGTH value did not match GetColumnInfo",
|
|
FALSE);
|
|
}
|
|
}
|
|
break;
|
|
// NULL for all other data types
|
|
default:
|
|
if (!COMPARE(ulStatus, DBSTATUS_S_ISNULL))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Status was not DBSTATUS_S_ISNULL for non-char, binary, or bit column\n";
|
|
}
|
|
break;
|
|
case 18:// DATETIME_PRECISION
|
|
switch(m_prgColInfo[iIndex].wType)
|
|
{
|
|
case DBTYPE_DBTIMESTAMP:
|
|
if (COMPARE(ulStatus, DBSTATUS_S_OK))
|
|
CCOMPARE(m_EC, *(ULONG *)pValue == (ULONG)m_prgColInfo[iIndex].bScale,
|
|
EC_BAD_DATETIME_PRECISION,
|
|
L"DATETIME_PRECISION value did not match GetColumnInfo",
|
|
FALSE);
|
|
break;
|
|
// NULL for all other data types
|
|
default:
|
|
if (!COMPARE(ulStatus, DBSTATUS_S_ISNULL))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Status was not DBSTATUS_S_ISNULL for non-char, binary, or bit column\n";
|
|
}
|
|
break;
|
|
case 8: // COLUMN_HASDEFAULT
|
|
// We can't actually try the default value except for our test table, so we don't know
|
|
// if it actually would work or not for other tables.
|
|
// Note that COLUMN_DEFAULT may be NULL even if HASDEFAULT is TRUE but the converse
|
|
// is not true.
|
|
|
|
if (COMPARE(ulStatus, DBSTATUS_S_OK))
|
|
{
|
|
|
|
// Make sure we know the proper binding for DBCOLUMN_DEFAULT
|
|
ASSERT (m_rgDBBINDING[8+!m_rgDBCOLUMNINFO[0].iOrdinal].iOrdinal == 9);
|
|
DBSTATUS ulDefaultStatus = STATUS_BINDING(m_rgDBBINDING[8+!m_rgDBCOLUMNINFO[0].iOrdinal], pData);
|
|
|
|
// If the COLUMN_DEFAULT is non-NULL, then HASDEFAULT should be TRUE, otherwise
|
|
// we're not sure
|
|
if (S_OK == ulDefaultStatus && !COMPARE(*(VARIANT_BOOL *)pValue, VARIANT_TRUE))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Invalid value returned.\n";
|
|
|
|
// TODO: If the current table is the automaketable for this test try to use the default
|
|
// value and make sure it matches expected.
|
|
}
|
|
else
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Invalid status returned.\n";
|
|
break;
|
|
case 9: // COLUMN DEFAULT
|
|
if (ulStatus == DBSTATUS_S_OK)
|
|
{
|
|
// For now, just make sure the length is right so we read the default value
|
|
if (!COMPARE(wcslen((WCHAR *)pValue)*sizeof(WCHAR), LENGTH_BINDING(m_rgDBBINDING[iBind], pData)))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Default value has the wrong length.\n";
|
|
|
|
// TODO: If the current table is the automaketable for this test try to use the default
|
|
// value and make sure it matches expected.
|
|
}
|
|
else if (!COMPARE(ulStatus, DBSTATUS_S_ISNULL))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Invalid status returned.\n";
|
|
break;
|
|
case 11:// IS_NULLABLE
|
|
{
|
|
VARIANT_BOOL fNullable = m_prgColInfo[iIndex].dwFlags & DBCOLUMNFLAGS_ISNULLABLE ? VARIANT_TRUE : VARIANT_FALSE;
|
|
if (!COMPARE(fNullable, *(VARIANT_BOOL *)pValue))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Invalid value returned.\n";
|
|
break;
|
|
}
|
|
case 12:// DATA_TYPE
|
|
// This column cannot contain NULL
|
|
if (COMPARE(ulStatus, DBSTATUS_S_OK) &&
|
|
!COMPARE(m_prgColInfo[iIndex].wType, *(DBTYPE *)pValue))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Invalid value returned.\n";
|
|
break;
|
|
case 16:// NUMERIC_PRECISION
|
|
if (IsNumericType(m_prgColInfo[iIndex].wType))
|
|
{
|
|
if (COMPARE(ulStatus, DBSTATUS_S_OK) &&
|
|
!COMPARE(*(USHORT *)pValue, (USHORT)m_prgColInfo[iIndex].bPrecision))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Invalid value returned.\n";
|
|
}
|
|
// NULL for all other data types
|
|
else if (!COMPARE(ulStatus, DBSTATUS_S_ISNULL))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Status was not DBSTATUS_S_ISNULL for non-numeric column\n";
|
|
break;
|
|
case 17:// NUMERIC_SCALE
|
|
if (m_prgColInfo[iIndex].wType == DBTYPE_DECIMAL ||
|
|
m_prgColInfo[iIndex].wType == DBTYPE_NUMERIC ||
|
|
m_prgColInfo[iIndex].wType == DBTYPE_VARNUMERIC)
|
|
{
|
|
if (COMPARE(ulStatus, DBSTATUS_S_OK))
|
|
{
|
|
SHORT sScale = (SHORT)m_prgColInfo[iIndex].bScale;
|
|
|
|
// Account for negative scale values
|
|
if (m_prgColInfo[iIndex].dwFlags & DBCOLUMNFLAGS_SCALEISNEGATIVE)
|
|
sScale = -sScale;
|
|
|
|
if (!COMPARE(*(SHORT *)pValue, sScale))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Invalid value returned.\n";
|
|
}
|
|
}
|
|
// NULL for all other data types
|
|
else if (!COMPARE(ulStatus, DBSTATUS_S_ISNULL))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Status was not DBSTATUS_S_ISNULL for non-DECIMAL, NUMERIC column\n";
|
|
break;
|
|
case 19:// CHARACTER_SET_CATALOG
|
|
case 20:// CHARACTER_SET_SCHEMA
|
|
case 21:// CHARACTER_SET_NAME
|
|
case 22:// COLLATION_CATALOG
|
|
case 23:// COLLATION_SCHEMA
|
|
case 24:// COLLATION_NAME
|
|
case 25:// DOMAIN_CATALOG
|
|
case 26:// DOMAIN_SCHEMA
|
|
case 27:// DOMAIN_NAME
|
|
if (ulStatus == DBSTATUS_S_OK)
|
|
{
|
|
// For now, just make sure the length is right so we read the value
|
|
if (!COMPARE(wcslen((WCHAR *)pValue)*sizeof(WCHAR), LENGTH_BINDING(m_rgDBBINDING[iBind], pData)))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Length is incorrect.\n";
|
|
|
|
// We really don't expect empty strings for any of these
|
|
if (!COMPARE(wcslen((WCHAR *)pValue) > 0, TRUE))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Empty string returned.\n";
|
|
|
|
}
|
|
else if (!COMPARE(ulStatus, DBSTATUS_S_ISNULL))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Invalid status returned.\n";
|
|
break;
|
|
case 28:// DESCRIPTION
|
|
// If Description is valid it may still be an empty string. All we test
|
|
// here is if it's null terminated properly.
|
|
if (ulStatus == DBSTATUS_S_OK)
|
|
{
|
|
if (!COMPARE(wcslen((WCHAR *)pValue)*sizeof(WCHAR), LENGTH_BINDING(m_rgDBBINDING[iBind], pData)))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Length is incorrect.\n";
|
|
}
|
|
// Description is allowed to be NULL
|
|
else if (!COMPARE(ulStatus, DBSTATUS_S_ISNULL))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Unexpected status value found.\n";
|
|
break;
|
|
// PROVIDER SPECIFIC
|
|
default:
|
|
if (iRow == 1)
|
|
{
|
|
if(!m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
if(!COMPARE(GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset), TRUE))
|
|
odtLog << L"COLUMNS: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - COLUMNS provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
|
|
// We expect to retrieve the column successfully
|
|
if (ulStatus != DBSTATUS_S_OK &&
|
|
ulStatus != DBSTATUS_S_ISNULL &&
|
|
!COMPARE(ulStatus, DBSTATUS_S_OK))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Invalid status returned.\n";
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// CONSTRAINT_COLUMN_USAGE
|
|
// 1. Table Catalog
|
|
// 2. Table Schema
|
|
// 3. Table Name
|
|
// 4. Column Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_CONSTRAINT_COLUMN_USAGE()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszCONSTRAINT_COLUMN_USAGE;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeCONSTRAINT_COLUMN_USAGE;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cCONSTRAINT_COLUMN_USAGE;
|
|
m_cRestrictions = cCONSTRAINT_COLUMN_USAGE_RESTRICTIONS;
|
|
|
|
// Set Table Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszTableRestriction);
|
|
SetRestriction(FOURTH,4, &m_wszR4, m_pwszColumnRestriction);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowCONSTRAINT_COLUMN_USAGE
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_CONSTRAINT_COLUMN_USAGE
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cCONSTRAINT_COLUMN_USAGE <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:CONSTRAINT_COLUMN_USAGE:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// TABLE_CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_CONSTRAINT_COLUMN_USAGE:TABLE_CATALOG restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// TABLE_SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_CONSTRAINT_COLUMN_USAGE:TABLE_SCHEMA restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(WCHAR *)pColumn->bValue);
|
|
break;
|
|
case 3: // TABLE_NAME
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_CONSTRAINT_COLUMN_USAGE:TABLE_NAME restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// COLUMN_NAME
|
|
if(m_restrict & FOURTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR4,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes4)
|
|
{
|
|
odtLog << L"VerifyRow_CONSTRAINT_COLUMN_USAGE:COLUMN_NAME restriction failed\n";
|
|
m_fRes4=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 5: // COLUMN_GUID
|
|
PRVTRACE(L"\n");
|
|
break;
|
|
case 6: //COLUMN_PROPID
|
|
PRVTRACE(L"%d\n",*(TYPE_UI4 *)pColumn->bValue);
|
|
break;
|
|
case 7: // CONSTRAINT CATALOG
|
|
case 8: // CONSTRAINT SCHEMA
|
|
case 9: // CONSTRAINT NAME
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"CONSTRAINT COLUMN USAGE: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - CONSTRAINT COLUMN USAGE provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// CONSTRAINT_TABLE_USAGE
|
|
// 1. Table Catalog
|
|
// 2. Table Schema
|
|
// 3. Table Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_CONSTRAINT_TABLE_USAGE()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszCONSTRAINT_TABLE_USAGE;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeCONSTRAINT_TABLE_USAGE;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cCONSTRAINT_TABLE_USAGE;
|
|
m_cRestrictions = cCONSTRAINT_TABLE_USAGE_RESTRICTIONS;
|
|
|
|
// Set Table Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszTableRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::CONSTRAINT_TABLE_USAGE\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowCONSTRAINT_TABLE_USAGE
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_CONSTRAINT_TABLE_USAGE
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cCONSTRAINT_TABLE_USAGE <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:CONSTRAINT_TABLE_USAGE:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// TABLE_CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_CONSTRAINT_TABLE_USAGE:TABLE_CATALOG restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// TABLE_SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_CONSTRAINT_TABLE_USAGE:TABLE_SCHEMA restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: // TABLE_NAME
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_CONSTRAINT_TABLE_USAGE:TABLE_NAME restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4: // CONSTRAINT CATALOG
|
|
case 5: // CONSTRAINT SCHEMA
|
|
case 6: //CONSTRAINT NAME
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"CONSTRAINT TABLE USAGE: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - CONSTRAINT TABLE USAGE provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// FOREIGN_KEYS
|
|
// 1. PK_TABLE_CATALOG
|
|
// 2. PK TABLE SCHEMA
|
|
// 3. PK TABLE NAME
|
|
// 4. FK TABLE CATALOG
|
|
// 5. FK TABLE SCHEMA
|
|
// 6. FK TABLE ANEM
|
|
//
|
|
// Caveat: These restrictions will be tested as part of ad-hoc for the
|
|
// following reasons, The following code is a place holder in case
|
|
// the problems listed below are ever fixed:
|
|
// 1. Can't change private library's create table because not all
|
|
// drivers will support PK and FK systax, create table would fail
|
|
// 2. Can't use alter table statement because I can only add column
|
|
// that allow nulls and pk and fk are not nullable.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_FOREIGN_KEYS()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszFOREIGN_KEYS;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeFOREIGN_KEYS;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cFOREIGN_KEYS;
|
|
m_cRestrictions = cFOREIGN_KEYS_RESTRICTIONS;
|
|
|
|
// Set PK Table Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszPK_TableRestriction);
|
|
SetRestriction(FOURTH,4, &m_wszR4, m_pwszCatalogRestriction);
|
|
SetRestriction(FIFTH, 5, &m_wszR5, m_pwszSchemaRestriction);
|
|
SetRestriction(SIXTH, 6, &m_wszR6, m_pwszFK_TableRestriction);
|
|
|
|
// Set expected row count
|
|
if (m_fForeignKey)
|
|
// We created a foreign key, so there must be one row
|
|
SetRowCount(MIN_REQUIRED, 1);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::FOREIGN_KEYS\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowFOREIGN_KEYS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_FOREIGN_KEYS
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cFOREIGN_KEYS <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:FOREIGN_KEYS:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// PK TABLE_CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_FOREIGN_KEYS:PK TABLE_CATALOG restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults=FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// PK TABLE_SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_FOREIGN_KEYS:PK TABLE_SCHEMA restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults=FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: // PK TABLE_NAME
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_FOREIGN_KEYS:PK TABLE_NAME restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults=FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4: // PK COLUMN NAME
|
|
case 10:// FK_COLUMN NAME
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 14:// UPDATE RULE
|
|
case 15:// DELETE RULE
|
|
if( (0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"CASCADE")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"SET NULL")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"SET DEFAULT")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"NO ACTION")))
|
|
{
|
|
odtLog << L"VerifyRow_FOREIGN_KEYS:UPDATE or DELETE RULE expected CASCADE,SET NULL,SET DEFAULT, or NO ACTION but received "
|
|
<< (TYPE_WSTR)pColumn->bValue << ENDL;
|
|
fResults=FALSE;
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 5: // PK COLUMN GUID
|
|
case 11:// FK COLUMN GUID
|
|
case 16:// PK_NAME
|
|
case 17:// FK_NAME
|
|
case 18:// DEFERRABILITY
|
|
PRVTRACE(L"\n");
|
|
case 6: // PK COLUMN PROPID
|
|
case 12:// FK COLUMN PROPID
|
|
case 13:// ORDINAL
|
|
PRVTRACE(L"%d\n",*(TYPE_UI4 *)pColumn->bValue);
|
|
break;
|
|
case 7:// FK TABLE_CATALOG
|
|
if(m_restrict & FOURTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR4,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes4)
|
|
{
|
|
odtLog << L"VerifyRow_FOREIGN_KEYS:FK TABLE_CATALOG restriction failed\n";
|
|
m_fRes4=FALSE;
|
|
fResults=FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 8:// FK TABLE_SCHEMA
|
|
if(m_restrict & FIFTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR5,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes5)
|
|
{
|
|
odtLog << L"VerifyRow_FOREIGN_KEYS:FK TABLE_SCHEMA restriction failed\n";
|
|
m_fRes5=FALSE;
|
|
fResults=FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 9: // FK TABLE_NAME
|
|
if(m_restrict & SIXTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR6,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes6)
|
|
{
|
|
odtLog << L"VerifyRow_FOREIGN_KEYS:FK TABLE_NAME restriction failed\n";
|
|
m_fRes6=FALSE;
|
|
fResults=FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"FOREIGN KEYS: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - FOREIGN KEYS provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults=FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// INDEXES
|
|
// 1. Table Catalog
|
|
// 2. Table Schema
|
|
// 3. Index Name
|
|
// 4. Type
|
|
// 5. Table Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_INDEXES()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszINDEXES;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeINDEXES;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cINDEXES;
|
|
m_cRestrictions = cINDEXES_RESTRICTIONS;
|
|
|
|
// Set Table Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszIndexRestriction);
|
|
|
|
if((m_currentBitMask & FOURTH) || m_fPassUnsupportedRestrictions)
|
|
{
|
|
if((m_restrict & FOURTH)|| (m_restrict & ALLRES))
|
|
{
|
|
m_ulR = DBPROPVAL_IT_BTREE;
|
|
m_rgvarRestrict[3].vt = VT_UI2;
|
|
m_rgvarRestrict[3].lVal = DBPROPVAL_IT_BTREE;
|
|
m_cRestrictionsCurrent ++;
|
|
SetRestriction(FOURTH);
|
|
|
|
RESTRICTNOTSUPPORTED(FOURTH)
|
|
}
|
|
}
|
|
|
|
// TABLE NAME
|
|
SetRestriction(FIFTH, 5, &m_wszR5, m_pwszTableRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::INDEXES\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowINDEXES
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_INDEXES
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cINDEXES <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
DBBINDING * pBind = &m_rgDBBINDING[iBind];
|
|
DBORDINAL iOrdinal = m_rgDBCOLUMNINFO[iBind].iOrdinal;
|
|
DBSTATUS ulStatus = STATUS_BINDING(*pBind, pData);
|
|
DATA * pColumn=(DATA *) (pData + pBind->obStatus);
|
|
BYTE * pValue = pColumn->bValue;
|
|
|
|
// PRVTRACE(L"INDEXES:Row[%lu],Col[%d,%s]:",
|
|
// iRow,
|
|
// m_rgDBCOLUMNINFO[iBind].iOrdinal,
|
|
// m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// TABLE_CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_INDEXES:TABLE_CATALOG 1 restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// TABLE_SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_INDEXES:TABLE_SCHEMA 2 restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: // TABLE_NAME
|
|
if(m_restrict & FIFTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR5,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes5)
|
|
{
|
|
odtLog << L"VerifyRow_INDEXES:TABLE_NAME 5 restriction failed\n";
|
|
m_fRes5=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// INDEX_CATALOG
|
|
case 5: // INDEX_SCHEMA
|
|
case 18:// COLUMN_NAME
|
|
case 24:// FILTER_CONDIITON
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 6:// INDEX_NAME
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_INDEXES:INDEX_NAME 3 restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 7: // PRIMARY KEY
|
|
case 8: // UNIQUE
|
|
case 9: // CLUSTERED
|
|
case 14:// SORTBOOKMARKS
|
|
case 15:// AUTOUPDATE
|
|
case 25:// INTEGRATED
|
|
if((*(TYPE_BOOL *)pColumn->bValue)==VARIANT_TRUE)
|
|
PRVTRACE(L"TRUE\n");
|
|
else
|
|
PRVTRACE(L"FALSE\n");
|
|
break;
|
|
case 10:// TYPE
|
|
if(m_restrict & FOURTH)
|
|
{
|
|
if(m_ulR!=(*(TYPE_UI2*)pColumn->bValue))
|
|
{
|
|
odtLog << L"VerifyRow_INDEXES:INDEX_TYPE 4 restriction failed\n";
|
|
m_fRes4=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
PRVTRACE(L"%d\n",*(TYPE_UI2 *)pColumn->bValue);
|
|
break;
|
|
case 11:// FILLFACTOR
|
|
// This column cannot be NULL
|
|
if (COMPARE(ulStatus, DBSTATUS_S_OK))
|
|
{
|
|
ULONG ulFillFactor = *(ULONG *)pValue;
|
|
|
|
// Spec change: Fill factor may be 0
|
|
if (!COMPARE(ulFillFactor <= 100, TRUE))
|
|
odtLog << L"FillFactor: Invalid value returned.\n";
|
|
}
|
|
break;
|
|
case 12:// INITIALSIZE
|
|
case 13:// NULLS
|
|
case 16:// NULCOLLATION
|
|
case 22:// CARDINALITY
|
|
case 23:// PAGES
|
|
PRVTRACE(L"%d\n",*(TYPE_I4 *)pColumn->bValue);
|
|
break;
|
|
case 19: // COLUMN_GUID
|
|
PRVTRACE(L"\n");
|
|
break;
|
|
case 21:// COLLATION
|
|
PRVTRACE(L"%d\n",*(TYPE_I2 *)pColumn->bValue);
|
|
break;
|
|
case 20:// COLUMN_PROPID
|
|
case 17:// ORDINAL_POSITION
|
|
PRVTRACE(L"%d\n",*(TYPE_UI4 *)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"INDEXES: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - INDEXES provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
}
|
|
else
|
|
{
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// KEY_COLUMN_USAGE
|
|
// 1. Constraint Catalog Name
|
|
// 2. Constraint Schema Name
|
|
// 3. Constraint Name
|
|
// 4. Table Catalog
|
|
// 5. Table Schema
|
|
// 6. Table Name
|
|
// 7. Column Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_KEY_COLUMN_USAGE()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszKEY_COLUMN_USAGE;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeKEY_COLUMN_USAGE;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cKEY_COLUMN_USAGE;
|
|
m_cRestrictions = cKEY_COLUMN_USAGE_RESTRICTIONS;
|
|
|
|
// Set Constraint Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND, 2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszKey_Column_Usage_ConstraintRestriction);
|
|
SetRestriction(FOURTH, 4, &m_wszR4, m_pwszCatalogRestriction);
|
|
SetRestriction(FIFTH, 5, &m_wszR5, m_pwszSchemaRestriction);
|
|
SetRestriction(SIXTH, 6, &m_wszR6, m_pwszTableRestriction);
|
|
SetRestriction(SEVENTH,7, &m_wszR7, m_pwszColumnRestriction);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowKEY_COLUMN_USAGE
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_KEY_COLUMN_USAGE
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// don't need to go farther if I have what I'm looking for
|
|
if(m_fCaptureRestrictions && m_pwszKey_Column_Usage_ConstraintRestriction)
|
|
return FALSE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cKEY_COLUMN_USAGE <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:KEY_COLUMN_USAGE:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// CONSTRAINT CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_KEY_COLUMN_USAGE:CONSTRAINT CATALOG 1 restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// CONSTRAINT SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_KEY_COLUMN_USAGE:CONSTRAINT SCHEMA 2 restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: // CONSTRAINT NAME
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszKey_Column_Usage_ConstraintRestriction = (WCHAR *) PROVIDER_ALLOC
|
|
((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszKey_Column_Usage_ConstraintRestriction)
|
|
wcscpy(m_pwszKey_Column_Usage_ConstraintRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
|
|
}
|
|
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_KEY_COLUMN_USAGE:CONSTRAINT NAME 3 restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// TABLE_CATALOG
|
|
if(m_restrict & FOURTH)
|
|
{
|
|
if(!COMPARE(0,_wcsicmp((TYPE_WSTR)m_wszR4,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes4)
|
|
{
|
|
odtLog << L"VerifyRow_KEY_COLUMN_USAGE:TABLE_CATALOG 4 restriction failed\n";
|
|
m_fRes4=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 5:// TABLE_SCHEMA
|
|
if(m_restrict & FIFTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR5,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes5)
|
|
{
|
|
odtLog << L"VerifyRow_KEY_COLUMN_USAGE:TABLE_SCHEMA 5 restriction failed\n";
|
|
m_fRes5=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 6: // TABLE_NAME
|
|
if(m_restrict & SIXTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR6,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes6)
|
|
{
|
|
odtLog << L"VerifyRow_KEY_COLUMN_USAGE:TABLE_NAME 6 restriction failed\n";
|
|
m_fRes6=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 7:// COLUMN NAME
|
|
if(m_restrict & SEVENTH)
|
|
{
|
|
if(0,_wcsicmp((TYPE_WSTR)m_wszR7,(TYPE_WSTR)pColumn->bValue))
|
|
{
|
|
if(m_fRes7)
|
|
{
|
|
odtLog << L"VerifyRow_KEY_COLUMN_USAGE:COLUMN NAME 7 restriction failed\n";
|
|
m_fRes7=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 8: // COLUMN_GUID
|
|
PRVTRACE(L"\n");
|
|
break;
|
|
case 9: // COLUMN PROPID
|
|
case 10:// ORDINAL POSITION
|
|
PRVTRACE(L"%d\n",*(TYPE_UI4 *)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (!m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"KEY COLUMN USAGE: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - KEY COLUMN USAGE provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// PRIMARY_KEYS
|
|
// 1. Table Catalog
|
|
// 2. Table Name
|
|
// 3. Table Schem a
|
|
//
|
|
// Caveat: this will be handled in ad-hoc see PrepareParams_Foreign_keys()
|
|
// for explanation.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_PRIMARY_KEYS()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszPRIMARY_KEYS;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypePRIMARY_KEYS;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cPRIMARY_KEYS;
|
|
m_cRestrictions = cPRIMARY_KEYS_RESTRICTIONS;
|
|
|
|
// Set Table Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszPK_TableRestriction);
|
|
|
|
// Set expected count of rows
|
|
if (m_fPrimaryKey)
|
|
// We created a primary key, so there must be one row
|
|
SetRowCount(MIN_REQUIRED, 1);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::PRIMARY_KEYS\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowPRIMARY_KEYS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_PRIMARY_KEYS
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cPRIMARY_KEYS <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
DBBINDING * pBind = &m_rgDBBINDING[iBind];
|
|
DBORDINAL iOrdinal = m_rgDBCOLUMNINFO[iBind].iOrdinal;
|
|
DBSTATUS ulStatus = STATUS_BINDING(*pBind, pData);
|
|
DATA * pColumn=(DATA *) (pData + pBind->obStatus);
|
|
BYTE * pValue = pColumn->bValue;
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:PRIMARY_KEYS", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// TABLE CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_PRIMARY_KEYS:TABLE CATALOG restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// TABLE SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_PRIMARY_KEYS:TABLE SCHEMA restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: // TABLE NAME
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_PRIMARY_KEYS:TABLE NAME restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// COLUMN NAME
|
|
case 8:// PK_NAME
|
|
if (ulStatus == DBSTATUS_S_OK)
|
|
{
|
|
// For now, just make sure the length is right so we read the default value
|
|
if (!COMPARE(wcslen((WCHAR *)pValue)*sizeof(WCHAR), LENGTH_BINDING(m_rgDBBINDING[iBind], pData)))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Default value has the wrong length.\n";
|
|
|
|
// TODO: If the current table is the primary table for this test make sure it matches expected.
|
|
}
|
|
else if (!COMPARE(ulStatus, DBSTATUS_S_ISNULL))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Invalid status returned.\n";
|
|
break;
|
|
case 5: // COLUMN_GUID
|
|
case 6: // COLUMN PROPID
|
|
case 7: // ORDINAL POSITION
|
|
if (ulStatus != DBSTATUS_S_OK &&
|
|
!COMPARE(ulStatus, DBSTATUS_S_ISNULL))
|
|
odtLog << m_pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Invalid status returned.\n";
|
|
PRVTRACE(L"%d\n",*(TYPE_UI4 *)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"PRIMARY KEYS: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - PRIMARY KEYS provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// PROCEDURE_COLUMNS
|
|
// 1. Procedure Catalog
|
|
// 2. Procedure Schema
|
|
// 3. Procedure Name
|
|
// 4. Column Name
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_PROCEDURE_COLUMNS()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszPROCEDURE_COLUMNS;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypePROCEDURE_COLUMNS;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cPROCEDURE_COLUMNS;
|
|
m_cRestrictions = cPROCEDURE_COLUMNS_RESTRICTIONS;
|
|
|
|
// Set Procedure Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszProcedureRestriction);
|
|
SetRestriction(FOURTH,4, &m_wszR4, m_pwszProcedureColumnsRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::PROCEDURE_COLUMNS\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowPROCEDURE_COLUMNS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_PROCEDURE_COLUMNS
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cPROCEDURE_COLUMNS <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:PROCEDURE_COLUMNS", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// PROCEDURE CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_PROCEDURE_COLUMNS:PROCEDURE CATALOG 1 restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// PROCEDURE SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_PROCEDURE_COLUMNS:PROCEDURE SCHEMA 2 restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: // PROCEDURE NAME
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_PROCEDURE_COLUMNS:PROCEDURE NAME 3 restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// COLUMN NAME
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszProcedureColumnsRestriction = (WCHAR *) PROVIDER_ALLOC
|
|
((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszProcedureColumnsRestriction)
|
|
wcscpy(m_pwszProcedureColumnsRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
}
|
|
|
|
if(m_restrict & FOURTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR4,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes4)
|
|
{
|
|
odtLog << L"VerifyRow_PROCEDURE_COLUMNS:COLUMN NAME 4 restriction failed\n";
|
|
m_fRes4=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 5: // COLUMN_GUID
|
|
case 11:// TYPE_GUID
|
|
PRVTRACE(L"\n");
|
|
break;
|
|
case 6: // COLUMN PROPID
|
|
case 7: // ROWSET NUMBER
|
|
case 8: // ORDINAL POSITION
|
|
case 12:// CHARACTER_MAXIMUM_LENGTH
|
|
case 13:// CHARACTER_OCTET_LENGTH
|
|
PRVTRACE(L"%d\n",*(TYPE_UI4 *)pColumn->bValue);
|
|
break;
|
|
case 9:// IS_NULLABLE
|
|
PRVTRACE(L"%d\n",*(TYPE_BOOL *)pColumn->bValue);
|
|
break;
|
|
case 10:// DATA_TYPE
|
|
case 14:// NUMERIC_PRECISION
|
|
PRVTRACE(L"%d\n",*(TYPE_UI2 *)pColumn->bValue);
|
|
break;
|
|
case 15:// NUMERIC_SCALE
|
|
PRVTRACE(L"%d\n",*(TYPE_I2 *)pColumn->bValue);
|
|
break;
|
|
case 16:// DESCRIPTION
|
|
PRVTRACE(L"%d\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"PROCEDURE COLUMNS: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - PROCEDURE COLUMNS provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// PROCEDURE_PARAMETERS
|
|
// 1. Procedure Catalog
|
|
// 2. Procedure Schema
|
|
// 3. Procedure Name
|
|
// 4. Parameter Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_PROCEDURE_PARAMETERS()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszPROCEDURE_PARAMETERS;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypePROCEDURE_PARAMETERS;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cPROCEDURE_PARAMETERS;
|
|
m_cRestrictions = cPROCEDURE_PARAMETERS_RESTRICTIONS;
|
|
|
|
// Set Procedure Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszProcedureRestriction);
|
|
SetRestriction(FOURTH,4, &m_wszR4, m_pwszParameterRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::PROCEDURES\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowPROCEDURE_PARAMETERS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_PROCEDURE_PARAMETERS(DBCOUNTITEM iRow, BYTE * pData)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
|
|
// don't need to go farther if I have what I'm looking for
|
|
if(m_fCaptureRestrictions && m_pwszParameterRestriction)
|
|
return FALSE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cPROCEDURE_PARAMETERS <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:PROCEDURE_PARAMETERS", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// PROCEDURE CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_PROCEDURE_PARAMETERS:PROCEDURE CATALOG restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// PROCEDURE SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_PROCEDURE_PARAMETERS:PROCEDURE SCHEMA restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: // PROCEDURE_NAME
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsnicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue,wcslen(m_wszR3))))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_PROCEDURE_PARAMETERS:PROCEDURE_NAME restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Check the length of the proc name
|
|
if( (wcslen(m_wszR3) != wcslen((TYPE_WSTR)pColumn->bValue)) &&
|
|
(!COMPARE(_wcsicmp((TYPE_WSTR)&pColumn->bValue[wcslen(m_wszR3)*sizeof(WCHAR)], L";1")==0,TRUE)) )
|
|
{
|
|
odtLog << L"VerifyRow_PROCEDURE_PARAMETERS:PROCEDURE_NAME length did not match\n";
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// PARAMETER NAME
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszParameterRestriction = (WCHAR *) PROVIDER_ALLOC
|
|
((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszParameterRestriction)
|
|
wcscpy(m_pwszParameterRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
}
|
|
|
|
if(m_restrict & FOURTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR4,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes4)
|
|
{
|
|
odtLog << L"VerifyRow_PROCEDURE_PARAMETERS:PROCEDURE NAME restriction failed\n";
|
|
m_fRes4=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 5: // ORDINAL POSITION
|
|
case 6: // PARAMETER TYPE
|
|
case 10:// DATA TYPE
|
|
PRVTRACE(L"%d\n",*(TYPE_UI2 *)pColumn->bValue);
|
|
break;
|
|
case 7: // PARAMETER_HASDEFAULT
|
|
case 9: // IS NULLABLE
|
|
if((*(TYPE_BOOL *)pColumn->bValue)==VARIANT_TRUE)
|
|
PRVTRACE(L"TRUE\n");
|
|
else
|
|
PRVTRACE(L"FALSE\n");
|
|
break;
|
|
case 11:// CHARACTER_MAXIMUM_LENGTH
|
|
case 12:// CHARACTER_OCTECT_LENGTH
|
|
PRVTRACE(L"%d\n",*(TYPE_UI4 *)pColumn->bValue);
|
|
break;
|
|
case 13:// NUMERIC_PRECISION
|
|
PRVTRACE(L"%d\n",*(TYPE_UI2 *)pColumn->bValue);
|
|
break;
|
|
case 14:// NUMERIC_SCALE
|
|
PRVTRACE(L"%d\n",*(TYPE_I2 *)pColumn->bValue);
|
|
break;
|
|
case 8: // PARAMETER DEFAULT
|
|
case 15:// DESCRIPTION
|
|
case 16:// TYPE_NAME
|
|
case 17:// LOCAL_TYPE_NAME
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR *)pColumn->bValue);
|
|
break;
|
|
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"PROCEDURE PARAMETERS: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - PROCEDURE PARAMETERS provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// PROCEDURES
|
|
// 1. Catalog Name
|
|
// 2. Schema Name
|
|
// 3. Procedure Name
|
|
// 4. Procedure Type
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_PROCEDURES()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszPROCEDURES;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypePROCEDURES;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cPROCEDURES;
|
|
m_cRestrictions = cPROCEDURES_RESTRICTIONS;
|
|
|
|
// Set Procedure Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszProcedureRestriction);
|
|
|
|
if((m_currentBitMask & FOURTH) || m_fPassUnsupportedRestrictions)
|
|
{
|
|
if((m_restrict & FOURTH)|| (m_restrict & ALLRES))
|
|
{
|
|
if(m_ProcedureTypeRestriction || m_fPassUnsupportedRestrictions)
|
|
{
|
|
m_ulR = (m_fPassUnsupportedRestrictions) ? DB_PT_PROCEDURE : m_ProcedureTypeRestriction;
|
|
m_rgvarRestrict[3].vt = VT_I2;
|
|
V_I2(&m_rgvarRestrict[3]) = (SHORT)m_ulR;
|
|
m_cRestrictionsCurrent ++;
|
|
SetRestriction(FOURTH);
|
|
|
|
RESTRICTNOTSUPPORTED(FOURTH)
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
PRVTRACE(L"GetSchemaInfo::PROCEDURES\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowPROCEDURES
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_PROCEDURES
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// don't need to go farther if I have what I'm looking for
|
|
if(m_fCaptureRestrictions && m_pwszProcedureRestriction && m_ProcedureTypeRestriction)
|
|
return FALSE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cPROCEDURES <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"PROCEDURES:Row[%lu],Col[%d.%s]:",
|
|
// iRow,
|
|
// m_rgDBCOLUMNINFO[iBind].iOrdinal,
|
|
// m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// PROCEDURE_CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_PROCEDURES:PROCEDURE_CATALOG 1 restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// PROCEDURE_SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_PROCEDURES:PROCEDURE_SCHEMA 2 restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: // PROCEDURE_NAME
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszProcedureRestriction = (WCHAR *) PROVIDER_ALLOC
|
|
((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszProcedureRestriction)
|
|
wcscpy(m_pwszProcedureRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
}
|
|
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsnicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue,wcslen(m_wszR3))))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_PROCEDURES:PROCEDURE_NAME restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Check the length of the proc name
|
|
if( (wcslen(m_wszR3) != wcslen((TYPE_WSTR)pColumn->bValue)) &&
|
|
(!COMPARE(_wcsicmp((TYPE_WSTR)&pColumn->bValue[wcslen(m_wszR3)*sizeof(WCHAR)], L";1")==0,TRUE)) )
|
|
{
|
|
odtLog << L"VerifyRow_PROCEDURE_PARAMETERS:PROCEDURE_NAME length did not match\n";
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4: // PROCEDURE_TYPE
|
|
if(m_fCaptureRestrictions)
|
|
m_ProcedureTypeRestriction = *(TYPE_I2 *) pColumn->bValue;
|
|
|
|
if(m_restrict & FOURTH)
|
|
{
|
|
if((TYPE_I2) m_ulR != (*(TYPE_I2 *)pColumn->bValue))
|
|
{
|
|
if(m_fRes4)
|
|
{
|
|
odtLog << L"VerifyRow_PROCEDURES:DATA_TYPE restriction failed\n";
|
|
m_fRes4=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"%d\n",*(TYPE_I2 *)pColumn->bValue);
|
|
break;
|
|
case 5:// PROCEDURE DEFINITION
|
|
case 6:// DESCRIPTION
|
|
PRVTRACE(L"%d\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
// DATE_CREATED
|
|
// DATE_MODIFIED
|
|
case 7:
|
|
case 8:
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"PROCEDURES: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - PROCEDURES provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// PROVIDER_TYPES
|
|
// 1. Data Type
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_PROVIDER_TYPES()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszPROVIDER_TYPES;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypePROVIDER_TYPES;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cPROVIDER_TYPES;
|
|
m_cRestrictions = cPROVIDER_TYPES_RESTRICTIONS;
|
|
|
|
if((m_currentBitMask & FIRST) || m_fPassUnsupportedRestrictions)
|
|
{
|
|
if((m_restrict & FIRST) || (m_restrict & ALLRES))
|
|
{
|
|
if(m_DataTypeRestriction)
|
|
{
|
|
m_ulR = m_DataTypeRestriction;
|
|
m_rgvarRestrict[0].vt = VT_UI2;
|
|
m_rgvarRestrict[0].iVal = m_DataTypeRestriction;
|
|
m_cRestrictionsCurrent ++;
|
|
SetRestriction(FIRST);
|
|
|
|
RESTRICTNOTSUPPORTED(FIRST)
|
|
|
|
}
|
|
}
|
|
}
|
|
if((m_currentBitMask & SECOND) || m_fPassUnsupportedRestrictions)
|
|
{
|
|
if((m_restrict & SECOND) || (m_restrict & ALLRES))
|
|
{
|
|
m_fR = (m_BestMatchRestriction==VARIANT_TRUE) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
m_rgvarRestrict[1].vt = VT_BOOL;
|
|
m_rgvarRestrict[1].boolVal = (m_BestMatchRestriction==VARIANT_TRUE) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
m_cRestrictionsCurrent ++;
|
|
SetRestriction(SECOND);
|
|
|
|
RESTRICTNOTSUPPORTED(SECOND)
|
|
}
|
|
}
|
|
|
|
PRVTRACE(L"GetSchemaInfo::PROVIDER_TYPES\n");
|
|
return TRUE;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRow_PROVIDER_TYPES
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_PROVIDER_TYPES
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cPROVIDER_TYPES <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"PROVIDER_TYPES:Row[%lu],Col[%d,%s]:",
|
|
// iRow,
|
|
// m_rgDBCOLUMNINFO[iBind].iOrdinal,
|
|
// m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1: // TYPE_NAME
|
|
case 4: // LITERAL_PREFIX
|
|
case 5: // LITERAL_SUFFIX
|
|
case 6: // CREATE PARAMS
|
|
case 13:// LOCAL_TYPE_NAME
|
|
case 17:// TYPELIB
|
|
case 18:// VERSION
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// DATA TYPE
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(m_ulR!= (*(TYPE_UI2 *)pColumn->bValue))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_PROVIDER_TYPES:TYPE NAME restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"%d\n",*(TYPE_UI2 *)pColumn->bValue);
|
|
break;
|
|
case 3: // COLUMN SIZE
|
|
case 9: // SEARCHABLE
|
|
PRVTRACE(L"%d\n",*(TYPE_UI4 *)pColumn->bValue);
|
|
break;
|
|
case 7: // IS_NULLABLE
|
|
case 8: // CASE_SENSITIVE
|
|
case 10:// UNSIGNED_ATTRIBUTE
|
|
case 11:// FIXED PREC SCALE
|
|
case 12:// AUTO_UNIQUE_VALUE
|
|
case 19:// IS_LONG
|
|
case 21:// IS_FIXEDLENGTH
|
|
if((*(TYPE_BOOL *)pColumn->bValue)==VARIANT_TRUE)
|
|
PRVTRACE(L"TRUE\n");
|
|
else
|
|
PRVTRACE(L"FALSE\n");
|
|
break;
|
|
case 14:// MINIMUM_SCALE
|
|
case 15: // MAXIMUM_SCALE
|
|
PRVTRACE(L"%d\n",*(TYPE_I2 *)pColumn->bValue);
|
|
break;
|
|
case 20: // BEST_MATCH
|
|
if(m_fCaptureRestrictions)
|
|
m_BestMatchRestriction = *(TYPE_BOOL *) pColumn->bValue;
|
|
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(m_fR != (*(TYPE_BOOL *)pColumn->bValue))
|
|
{
|
|
odtLog << L"VerifyRow_PROVIDER_TYPES:BEST_MATCH restriction failed\n";
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
|
|
if((*(TYPE_BOOL *)pColumn->bValue)==VARIANT_TRUE)
|
|
PRVTRACE(L"TRUE\n");
|
|
else
|
|
PRVTRACE(L"FALSE\n");
|
|
break;
|
|
|
|
case 16:// GUID
|
|
PRVTRACE(L"\n");
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"PROVIDER TYPES: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - PROVIDER TYPES provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// REFERENTIAL_CONSTRAINTS
|
|
// 1. Constraint Catalog
|
|
// 2. Constraint Schema
|
|
// 3. Constraint Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_REFERENTIAL_CONSTRAINTS()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszREFERENTIAL_CONSTRAINTS;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeREFERENTIAL_CONSTRAINTS;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cREFERENTIAL_CONSTRAINTS;
|
|
m_cRestrictions = cREFERENTIAL_CONSTRAINTS_RESTRICTIONS;
|
|
|
|
// Set Constraint Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszReferential_ConstraintRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::REFERENTIAL_CONSTRAINTS\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowREFERENTIAL_CONSTRAINTS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_REFERENTIAL_CONSTRAINTS
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// don't need to go farther if I have what I'm looking for
|
|
if(m_fCaptureRestrictions && m_pwszReferential_ConstraintRestriction)
|
|
return FALSE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cREFERENTIAL_CONSTRAINTS <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"REFERENTIAL_CONSTRAINTS:Row[%lu],Col[%d,%s]:",
|
|
// iRow,
|
|
// m_rgDBCOLUMNINFO[iBind].iOrdinal,
|
|
// m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
// TODO: not currently supported
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1: // CONSTRAINT_CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_REFERENTIAL_CONSTRAINTS:CONSTRAINT_CATALOG restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2: // CONSTRAINT_SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_REFERENTIAL_CONSTRAINTS:CONSTRAINT_SCHEMA restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: // CONSTRAINT_NAME
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszReferential_ConstraintRestriction = (WCHAR *) PROVIDER_ALLOC
|
|
((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR *)) + sizeof(WCHAR));
|
|
if(m_pwszReferential_ConstraintRestriction)
|
|
wcscpy(m_pwszReferential_ConstraintRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
}
|
|
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_REFERENTIAL_CONSTRAINTS:CONSTRAINT_NAME restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4: // UNIQUE_CONSTRAINT_CATALOG
|
|
case 5: // UNIQUE_CONSTRAINT_SCHEMA
|
|
case 6: // UNIQUE_CONSTRAINT_NAME
|
|
case 10: // DESCRIPTION
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 7: // MATCH_OPTION
|
|
if( (0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"NONE")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"PARTIAL"))&&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"FULL")))
|
|
{
|
|
odtLog << L"VerifyRow_REFERENTIAL_CONSTRAINTS:MATCH OPTION expected NONE/PARTIAL/FULL but recieved "
|
|
<< (TYPE_WSTR)pColumn->bValue << ENDL;
|
|
fResults = FALSE;
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
|
|
case 8: // UPDATE_RULE
|
|
case 9: // DELETE_RULL
|
|
if( (0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"CASCASE")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"SET NULL")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"SET DEFAULT"))&&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"NO ACTION")))
|
|
{
|
|
odtLog << L"VerifyRow_REFERENTIAL_CONSTRAINTS:UPDATE/DELETE RULE expected SELECT,DELETE,INSERT,UPDATE, or REFERENCES but recieved "
|
|
<< (TYPE_WSTR)pColumn->bValue << ENDL;
|
|
fResults = FALSE;
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"REFERENTIAL CONSTRAINTS: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - REFERENTIAL CONSTRAINTS provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// SCHEMATA
|
|
// 1. Catalog Name
|
|
// 2. Schema Name
|
|
// 3. Schema Owner
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_SCHEMATA()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszSCHEMATA;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeSCHEMATA;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cSCHEMATA;
|
|
m_cRestrictions = cSCHEMATA_RESTRICTIONS;
|
|
|
|
// Set Schema Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszSchemaRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::SCHEMATA\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowSCHEMATA
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_SCHEMATA
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cSCHEMATA <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn=(DATA *)(pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
if(pColumn->sStatus == DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBBINDING[iBind].iOrdinal)
|
|
{
|
|
case 1:// CATALOG_NAME
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_SCHEMATA:CATALOG_NAME restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
|
|
case 2:// SCHEMA_NAME
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_SCHEMATA:SCHEMA_NAME restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
|
|
case 3: // SCHEMA_OWNER
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_SCHEMATA:SCHEMA_OWNER restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
|
|
case 4: // DEFAULT_CHARACTER_SET_CATALOG
|
|
case 5: // DEFAULT_CHARACTER_SET_SCHEMA
|
|
case 6: // DEFAULT_CHARACTER_SET_NAME
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"SCHEMATA: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - SCHEMATA provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// SQL_LANGUAGES
|
|
// No Constraints
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_SQL_LANGUAGES()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszSQL_LANGUAGES;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeSQL_LANGUAGES;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cSQL_LANGUAGES;
|
|
m_cRestrictions = cSQL_LANGUAGES_RESTRICTIONS;
|
|
|
|
m_cRestrictionsCurrent = 0;
|
|
|
|
PRVTRACE(L"GetSchemaInfo::SQL_LANGUAGES\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowSQL_LANGUAGES
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_SQL_LANGUAGES
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cSQL_LANGUAGES <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:VerifyRow_SQL_LANGUAGES:", iRow,m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(iBind)
|
|
{
|
|
case 1: // SQL LANGUAGE SOURCE
|
|
if(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"ISO 9075"))
|
|
{
|
|
odtLog << L"VerifyRow_SQL_LANGUAGES:SQL_LANGUAGE_SOURCE expected ISO 9075 but recieved "
|
|
<< (TYPE_WSTR)pColumn->bValue << ENDL;
|
|
fResults = FALSE;
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2: // SQL LANGUAGE YEAR
|
|
if(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"ISO 9075"))
|
|
{
|
|
odtLog << L"VerifyRow_SQL_LANGUAGES:SQL_LANGUAGE_YEAR expected 1992 but recieved "
|
|
<< (TYPE_WSTR)pColumn->bValue << ENDL;
|
|
fResults = FALSE;
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: // SQL LANGUAGE CONFORMANCE
|
|
if( (0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"ENTRY")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"INTERMEDIATE")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"FULL")))
|
|
{
|
|
odtLog << L"VerifyRow_REFERENTIAL_CONSTRAINTS:SQL_LANGUAGE_CONFORMANCE expected ENTRY/INTERMEDIATE/FULL but recieved "
|
|
<< (TYPE_WSTR)pColumn->bValue << ENDL;
|
|
fResults = FALSE;
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4: // SQL LANGUAGE INTEGRITY
|
|
if( (0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"YES")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"NO")))
|
|
{
|
|
odtLog << L"VerifyRow_REFERENTIAL_CONSTRAINTS:SQL_LANGUAGE_INTEGRITY expected YES/NO but recieved "
|
|
<< (TYPE_WSTR)pColumn->bValue << ENDL;
|
|
fResults = FALSE;
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 5: // SQL LANGUAGE IMPLEMENTATION, should be null if SQL_LANGUAGE_SOURCE is 'ISO_9075'
|
|
case 6: // SQL LANGUAGE BINDING SYTLE
|
|
case 7: // SQL LANGUAGE PROGRAMMING LANGUAGE
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
default:
|
|
PRVTRACE(L"%s not expected\n",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// STATISTICS
|
|
// 1. Catalog Name
|
|
// 2. Schema Name
|
|
// 3. Table Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_STATISTICS()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszSTATISTICS;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeSTATISTICS;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cSTATISTICS;
|
|
m_cRestrictions = cSTATISTICS_RESTRICTIONS;
|
|
|
|
// Set Table Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszTableRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::STATISTICS\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowSTATISTICS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_STATISTICS
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cSTATISTICS <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:STATISTICS:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// TABLE CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_STATISTICS:TABLE_CATALOG restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// TABLE SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_STATISTICS:TABLE_SCHEMA restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: //TABLE NAME
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_STATISTICS:TABLE_NAME restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4: // CARDINALITY
|
|
PRVTRACE(L"%d\n",*(TYPE_I4 *)pColumn->bValue);
|
|
break;
|
|
default:
|
|
PRVTRACE(L"%s not expected\n",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// TABLE_CONSTRAINTS
|
|
// 1. Constraint Catalog
|
|
// 2. Constraint Schema
|
|
// 3. Constraint Name
|
|
// 4. Table Catalog
|
|
// 5. Table Schema
|
|
// 6. Table Name
|
|
// 7. Constraint Type
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_TABLE_CONSTRAINTS()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszTABLE_CONSTRAINTS;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeTABLE_CONSTRAINTS;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cTABLE_CONSTRAINTS;
|
|
m_cRestrictions = cTABLE_CONSTRAINTS_RESTRICTIONS;
|
|
|
|
// Set Constraint Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszTable_ConstraintRestriction);
|
|
SetRestriction(FOURTH,4, &m_wszR4, m_pwszCatalogRestriction);
|
|
SetRestriction(FIFTH, 5, &m_wszR5, m_pwszSchemaRestriction);
|
|
SetRestriction(SIXTH, 6, &m_wszR6, m_pwszTableRestriction);
|
|
SetRestriction(THIRD, 7, &m_wszR7, m_pwszConstraint_TypeRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::TABLE_CONSTRAINTS\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowTABLE_CONSTRAINTS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_TABLE_CONSTRAINTS
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// don't need to go farther if I have what I'm looking for
|
|
if(m_fCaptureRestrictions && m_pwszTable_ConstraintRestriction && m_pwszConstraint_TypeRestriction)
|
|
return FALSE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cTABLE_CONSTRAINTS <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:TABLE_CONSTRAINTS:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1://CONSTRAINT CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_CONSTRAINTS:CONSTRAINT CATALOG restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// CONSTRAINT SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_CONSTRAINTS:CONSTRAINT SCHEMA restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: // CONSTRAINT NAME
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszTable_ConstraintRestriction = (WCHAR *) PROVIDER_ALLOC
|
|
((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszTable_ConstraintRestriction)
|
|
wcscpy(m_pwszTable_ConstraintRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
}
|
|
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_CONSTRAINTS:CONSTRAINT NAME restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// TABLE CATALOG
|
|
if(m_restrict & FOURTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR4,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes4)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_CONSTRAINTS:TABLE CATALOG restriction failed\n";
|
|
m_fRes4=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 5:// TABLE SCHEMA
|
|
if(m_restrict & FIFTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR5,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes5)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_CONSTRAINTS:TABLE SCHEMA restriction failed\n";
|
|
m_fRes5=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 6: // TABLE NAME
|
|
if(m_restrict & SIXTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR6,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes6)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_CONSTRAINTS:CONSTRAINT NAME restriction failed\n";
|
|
m_fRes6=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(WCHAR *)pColumn->bValue);
|
|
break;
|
|
case 7: // CONSTRAINT TYPE
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszConstraint_TypeRestriction = (WCHAR *) PROVIDER_ALLOC((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszConstraint_TypeRestriction)
|
|
wcscpy(m_pwszConstraint_TypeRestriction,(WCHAR *) pColumn->bValue);
|
|
}
|
|
|
|
if(m_restrict & SEVENTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((WCHAR* )m_wszR7,(const WCHAR *)pColumn->bValue)))
|
|
{
|
|
if(m_fRes7)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_CONSTRAINTS:CONSTRAINT NAME restriction failed\n";
|
|
m_fRes7=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if( (0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"UNIQUE")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"PRIMARY KEY")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"FOREIGN KEY"))&&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"CHECK")))
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_CONSTRAINTS:CONSTRAINT TYPE expected UNIQUE/PRIMARYKEY/FOREIGNKEY/CHECK but recieved "
|
|
<< (TYPE_WSTR)pColumn->bValue << ENDL;
|
|
fResults = FALSE;
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 8: // IS_DEFERRABLE
|
|
case 9: // INITIALLY_DEFERRED
|
|
if(*(TYPE_BOOL *)pColumn->bValue==VARIANT_TRUE)
|
|
PRVTRACE(L"TRUE\n");
|
|
else
|
|
PRVTRACE(L"FALSE\n");
|
|
break;
|
|
case 10: // DESCRIPTION
|
|
PRVTRACE(L"%d\n",(TYPE_WSTR *)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"TABLE CONSTRAINTS: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - TABLE CONSTRAINTS provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// TABLE_PRIVILEGES
|
|
// 1. Catalog Name
|
|
// 2. Schema Name
|
|
// 3. Table Name
|
|
// 4. Grantor
|
|
// 5. Grantee
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_TABLE_PRIVILEGES()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszTABLE_PRIVILEGES;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeTABLE_PRIVILEGES;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cTABLE_PRIVILEGES;
|
|
m_cRestrictions = cTABLE_PRIVILEGES_RESTRICTIONS;
|
|
|
|
// Set Table Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszTableRestriction);
|
|
SetRestriction(FOURTH,4, &m_wszR4, m_pwszGrantorRestriction);
|
|
SetRestriction(FIFTH, 5, &m_wszR5, m_pwszGranteeRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::TABLE_PRIVILEGES\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowTABLE_PRIVILEGES
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_TABLE_PRIVILEGES
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cTABLE_PRIVILEGES <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:TABLE_PRIVILEGES:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1://GRANTOR
|
|
if(m_restrict & FOURTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR4,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes4)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_PRIVILEGES:GRANTOR restriction failed\n";
|
|
m_fRes4=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(WCHAR *)pColumn->bValue);
|
|
break;
|
|
case 2:// GRANTEE
|
|
if(m_restrict & FIFTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR5,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes5)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_PRIVILEGES:GRANTEE restriction failed\n";
|
|
m_fRes5=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: // TABLE CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_PRIVILEGES:TABLE CATALOG restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// TABLE SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_PRIVILEGES:TABLE SCHEMA restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 5:// TABLE NAME
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_PRIVILEGES:TABLE NAME restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 6: // PRIVILEGE TYPE
|
|
if( (0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"SELECT")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"INSERT")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"DELETE")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"REFERENCES")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"UPDATE")))
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_PRIVILEGES:PRIVILEGE TYPE expected SELECT/INSERT/DELETE/REFERENCES/UPDATE but recieved "
|
|
<< (TYPE_WSTR)pColumn->bValue << ENDL;
|
|
fResults = FALSE;
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 7: // IS_GRANTABLE
|
|
if(*(TYPE_BOOL *)pColumn->bValue==VARIANT_TRUE)
|
|
PRVTRACE(L"TRUE\n");
|
|
else
|
|
PRVTRACE(L"FALSE\n");
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"TABLE PRIVILEGES: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - TABLE PRIVILEGES provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// TABLE_STATISTICS
|
|
// 1. Catalog Name
|
|
// 2. Schema Name
|
|
// 3. Table Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_TABLE_STATISTICS()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszTABLESTATISTICS;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeTABLESTATISTICS;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cTABLE_STATISTICS;
|
|
m_cRestrictions = cTABLE_STATISTICS_RESTRICTIONS;
|
|
|
|
// Set Table Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszTableRestriction);
|
|
SetRestriction(FOURTH,4, &m_wszR4, m_pwszStatisticsCatalogRestriction);
|
|
SetRestriction(FIFTH, 5, &m_wszR5, m_pwszStatisticsSchemaRestriction);
|
|
SetRestriction(SIXTH, 6, &m_wszR6, m_pwszStatisticsNameRestriction);
|
|
|
|
// Seventh restriction
|
|
if((m_currentBitMask & SEVENTH) || m_fPassUnsupportedRestrictions)
|
|
{
|
|
if((m_restrict & SEVENTH)|| (m_restrict & ALLRES))
|
|
{
|
|
m_ulR = m_uiStatisticsTypeRestriction;
|
|
V_VT(&m_rgvarRestrict[6]) = VT_UI2;
|
|
V_UI2(&m_rgvarRestrict[6]) = m_uiStatisticsTypeRestriction;
|
|
m_cRestrictionsCurrent ++;
|
|
SetRestriction(SEVENTH);
|
|
|
|
RESTRICTNOTSUPPORTED(SEVENTH)
|
|
}
|
|
}
|
|
|
|
PRVTRACE(L"GetSchemaInfo::TABLE_STATISTICS\n");
|
|
return TRUE;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowTABLE_STATISTICS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_TABLE_STATISTICS
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
HRESULT hrOpenTable = E_FAIL;
|
|
LPWSTR pwszTableName = (LPWSTR)GetValuePtr(TS_TABLE_NAME, pData);
|
|
LPWSTR pwszStatName = (LPWSTR)GetValuePtr(TS_STATISTICS_NAME, pData);
|
|
LPWSTR pwszColumnName = (LPWSTR)GetValuePtr(TS_COLUMN_NAME, pData);
|
|
ULONG * pulTableCardinality = (ULONG *)GetValuePtr(TS_TABLE_CARDINALITY, pData);
|
|
ULONG * pulOrdinal = (ULONG *)GetValuePtr(TS_ORDINAL_POSITION, pData);
|
|
ULONG ulStatType = 0;
|
|
ULONG ulIndex = 0;
|
|
DBID dbidTable = DB_NULLID;
|
|
BOOL fNewTable = (!m_pwszTableName || !pwszTableName || (pwszTableName && RelCompareString(pwszTableName, m_pwszTableName)));
|
|
BOOL fNewStat = fNewTable | (!m_pwszStatName || !pwszStatName || (pwszStatName && RelCompareString(pwszStatName, m_pwszStatName)));
|
|
CARDINALITY eCardinality = TUPLE_CARDINALITY;
|
|
LPWSTR pwszCat = (LPWSTR)GetValuePtr(TS_TABLE_CATALOG, pData);
|
|
LPWSTR pwszSch = (LPWSTR)GetValuePtr(TS_TABLE_SCHEMA, pData);
|
|
LPWSTR pwszQualifiedName = NULL;
|
|
|
|
TESTC_(m_pTable->GetQualifiedName(pwszCat, pwszSch,
|
|
pwszTableName,&pwszQualifiedName, TRUE), S_OK);
|
|
|
|
// *********************************************************************
|
|
// For current time, set this on for debugging test code.
|
|
// *********************************************************************
|
|
m_fDetailCheck = TRUE;
|
|
|
|
if (m_fDetailCheck)
|
|
{
|
|
ULONG * pulStatType = (ULONG *)GetValuePtr(TS_STATISTICS_TYPE, pData);
|
|
|
|
// Attempt to open table and get columns info
|
|
if (fNewTable)
|
|
{
|
|
hrOpenTable = GetColumnInfo(pData, m_rgDBBINDING);
|
|
|
|
// Should be S_OK, or perhaps DB_E_NOTABLE
|
|
if (DB_E_NOTABLE != hrOpenTable)
|
|
CHECK(hrOpenTable, S_OK);
|
|
else
|
|
// We warn here because it's possible the table name is
|
|
// bogus, or just deleted.
|
|
CHECKW(hrOpenTable, S_OK);
|
|
}
|
|
else
|
|
// If we obtained col info for the table we successfully opened it.
|
|
hrOpenTable = (m_prgColInfo) ? S_OK : E_FAIL;
|
|
|
|
#ifdef BASE_TABLE_ORDINALS
|
|
// Set index into columns info given ordinal
|
|
if (m_prgColInfo && pulOrdinal)
|
|
ulIndex = *pulOrdinal-1+!m_prgColInfo[0].iOrdinal;
|
|
#else
|
|
// Set index into columns info given column name
|
|
if (m_prgColInfo && pwszColumnName)
|
|
{
|
|
for (ulIndex = 0; ulIndex < m_cColInfo; ulIndex++)
|
|
{
|
|
if (!wcscmp(m_prgColInfo[ulIndex].pwszName, pwszColumnName))
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// Set up table dbid
|
|
dbidTable.eKind = DBKIND_NAME;
|
|
dbidTable.uName.pwszName = pwszTableName;
|
|
|
|
// Get statistic type
|
|
if (pulStatType)
|
|
ulStatType = *pulStatType;
|
|
|
|
}
|
|
|
|
// Only capture restrictions once. Note we assume catalog and schema
|
|
// may not be supported but that statistics name will be
|
|
if(m_fCaptureRestrictions && m_pwszStatisticsNameRestriction)
|
|
{
|
|
m_fCaptureRestrictions = FALSE;
|
|
return FALSE;
|
|
}
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cTABLE_STATISTICS <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:TABLE_STATISTICS:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
// Set cardinality
|
|
eCardinality = TUPLE_CARDINALITY;
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK ||
|
|
pColumn->sStatus==DBSTATUS_S_ISNULL)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case TS_TABLE_CATALOG:
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_STATISTICS:TABLE_CATALOG restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
// Column must have non-empty string
|
|
if (pColumn->sStatus == DBSTATUS_S_OK)
|
|
COMPARE(wcslen((TYPE_WSTR)pColumn->bValue) > 0, TRUE);
|
|
PRVTRACE(L"'%s'\n",(WCHAR *)pColumn->bValue);
|
|
break;
|
|
case TS_TABLE_SCHEMA:
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_STATISTICS:TABLE_SCHEMA restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
// Column must have non-empty string
|
|
if (pColumn->sStatus == DBSTATUS_S_OK)
|
|
COMPARE(wcslen((TYPE_WSTR)pColumn->bValue) > 0, TRUE);
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case TS_TABLE_NAME:
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_STATISTICS:TABLE NAME restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
// Column must have non-empty, non-null string
|
|
if (COMPARE(pColumn->sStatus, DBSTATUS_S_OK))
|
|
COMPARE(wcslen((TYPE_WSTR)pColumn->bValue) > 0, TRUE);
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case TS_STATISTICS_CATALOG:
|
|
if(m_restrict & FOURTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR4,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes4)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_STATISTICS:STATISTICS_CATALOG restriction failed\n";
|
|
m_fRes4=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszStatisticsCatalogRestriction = (WCHAR *) PROVIDER_ALLOC((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszStatisticsCatalogRestriction)
|
|
wcscpy(m_pwszStatisticsCatalogRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
}
|
|
// Column must have non-empty string
|
|
if (pColumn->sStatus == DBSTATUS_S_OK)
|
|
COMPARE(wcslen((TYPE_WSTR)pColumn->bValue) > 0, TRUE);
|
|
PRVTRACE(L"'%s'\n",(WCHAR *)pColumn->bValue);
|
|
break;
|
|
case TS_STATISTICS_SCHEMA:
|
|
if(m_restrict & FIFTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR5,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes5)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_STATISTICS:STATISTICS_SCHEMA restriction failed\n";
|
|
m_fRes5=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszStatisticsSchemaRestriction = (WCHAR *) PROVIDER_ALLOC((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszStatisticsSchemaRestriction)
|
|
wcscpy(m_pwszStatisticsSchemaRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
}
|
|
// Column must have non-empty string
|
|
if (pColumn->sStatus == DBSTATUS_S_OK)
|
|
COMPARE(wcslen((TYPE_WSTR)pColumn->bValue) > 0, TRUE);
|
|
PRVTRACE(L"'%s'\n",(WCHAR *)pColumn->bValue);
|
|
break;
|
|
case TS_STATISTICS_NAME:
|
|
if(m_restrict & SIXTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR6,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes6)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_STATISTICS:STATISTICS_NAME restriction failed\n";
|
|
m_fRes6=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszStatisticsNameRestriction = (WCHAR *) PROVIDER_ALLOC((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszStatisticsNameRestriction)
|
|
wcscpy(m_pwszStatisticsNameRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
}
|
|
// Column must have non-empty string and cannot be NULL
|
|
if (COMPARE(pColumn->sStatus, DBSTATUS_S_OK))
|
|
COMPARE(wcslen((TYPE_WSTR)pColumn->bValue) > 0, TRUE);
|
|
PRVTRACE(L"'%s'\n",(WCHAR *)pColumn->bValue);
|
|
break;
|
|
case TS_STATISTICS_TYPE:
|
|
{
|
|
TYPE_UI2 ulStatType = 0;
|
|
|
|
// Column cannot be NULL
|
|
if (COMPARE(pColumn->sStatus, DBSTATUS_S_OK))
|
|
{
|
|
ulStatType = *(TYPE_UI2 *)pColumn->bValue;
|
|
|
|
if(m_restrict & SEVENTH)
|
|
{
|
|
if(!COMPARE(m_uiStatisticsTypeRestriction, ulStatType))
|
|
{
|
|
if(m_fRes7)
|
|
{
|
|
odtLog << L"VerifyRow_TABLE_STATISTICS:STATISTICS_TYPE restriction failed\n";
|
|
m_fRes7=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_uiStatisticsTypeRestriction = ulStatType;
|
|
// Avoid posting failures when just capturing restrictions
|
|
continue;
|
|
}
|
|
|
|
// Make sure no other bits are set than those spec'd
|
|
COMPARE(0, ulStatType & (~(DBSTAT_HISTOGRAM | DBSTAT_COLUMN_CARDINALITY |
|
|
DBSTAT_TUPLE_CARDINALITY)));
|
|
|
|
// If we claim histogram support then NO_OF_RANGES cannot be null
|
|
// but may be 0 if the table is empty.
|
|
if (ulStatType & DBSTAT_HISTOGRAM)
|
|
COMPARE(GetValuePtr(TS_NO_OF_RANGES, pData) != NULL, TRUE);
|
|
else
|
|
{
|
|
CCOMPARE(m_EC, GetValuePtr(TS_NO_OF_RANGES, pData) == NULL,
|
|
EC_NULL_RANGE_COUNT,
|
|
L"DBSTAT_HISTOGRAM not set but NO_OF_RANGES is non-NULL",
|
|
FALSE);
|
|
}
|
|
|
|
// If we claim column cardinality support then it must not be null
|
|
if (ulStatType & DBSTAT_COLUMN_CARDINALITY)
|
|
{
|
|
COMPARE(GetValuePtr(TS_COLUMN_CARDINALITY, pData) != NULL, TRUE);
|
|
}
|
|
else
|
|
COMPARE(GetValuePtr(TS_COLUMN_CARDINALITY, pData) == NULL, TRUE);
|
|
|
|
// If we claim tuple cardinality support then not be null
|
|
if (ulStatType & DBSTAT_TUPLE_CARDINALITY)
|
|
{
|
|
COMPARE(GetValuePtr(TS_TUPLE_CARDINALITY, pData) != NULL, TRUE);
|
|
}
|
|
else
|
|
COMPARE(GetValuePtr(TS_TUPLE_CARDINALITY, pData) == NULL, TRUE);
|
|
|
|
// DetailCheckStatType(ulStatType, pData);
|
|
|
|
// Detail check
|
|
if (m_fDetailCheck)
|
|
{
|
|
IRowset * pIRowset = NULL;
|
|
DBID dbidStat;
|
|
LPWSTR pwszStatName = (LPWSTR)GetValuePtr(TS_STATISTICS_NAME, pData);
|
|
HRESULT hrOpenHistogram = E_FAIL;
|
|
|
|
dbidStat.eKind = DBKIND_GUID_NAME;
|
|
dbidStat.uName.pwszName = pwszStatName;
|
|
dbidStat.uGuid.guid = g_guidHistogramRowset;
|
|
|
|
// Attempt to open histogram rowset
|
|
hrOpenHistogram = m_pIOpenRowset->OpenRowset(NULL,
|
|
&dbidTable,
|
|
&dbidStat,
|
|
IID_IRowset,
|
|
0,
|
|
NULL,
|
|
(IUnknown **)&pIRowset);
|
|
|
|
// If there's a histogram then validate values
|
|
if (ulStatType & DBSTAT_HISTOGRAM)
|
|
{
|
|
// Histograms are only supported on first column
|
|
// of a multicolumn statistic.
|
|
if (pulOrdinal && *pulOrdinal == 1)
|
|
{
|
|
|
|
ULONG * pcRanges = (ULONG *)GetValuePtr(TS_NO_OF_RANGES, pData);
|
|
|
|
// It's possible the table was deleted after we opened
|
|
// the schema rowset
|
|
if (S_OK == hrOpenHistogram)
|
|
{
|
|
if (CHECK(pIRowset != NULL, TRUE))
|
|
{
|
|
HRESULT hrGetNextRows = S_OK;
|
|
ULONG cRows = 0;
|
|
HROW * phRows = NULL;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DBORDINAL cBinding = 0;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBBINDING * pBinding = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
LPBYTE pDataRows = NULL;
|
|
|
|
// Check histogram rowset columns info
|
|
if (m_prgColInfo && !COMPARE(CheckHistogramColInfo(
|
|
pIRowset,
|
|
m_prgColInfo[ulIndex].wType,
|
|
&cBinding,
|
|
&pBinding,
|
|
&cbRowSize,
|
|
&hAccessor
|
|
), TRUE))
|
|
odtLog << L"Histogram colinfo doesn't match.\n";
|
|
|
|
// Make sure the provider returned valid info
|
|
if (cBinding > 0 &&
|
|
pBinding &&
|
|
cbRowSize > 0 &&
|
|
hAccessor != DB_NULL_HACCESSOR)
|
|
{
|
|
LPBYTE pDataHist = NULL;
|
|
DBBINDING dbBind;
|
|
DBCOUNTITEM ulRangeCount = 0;
|
|
DBCOUNTITEM ulTotal = 0;
|
|
|
|
// We need the table cardinality so if not available
|
|
// we must compute ourselves
|
|
if (pulTableCardinality)
|
|
ulTotal = *pulTableCardinality;
|
|
else
|
|
ulTotal = Cardinality(pwszQualifiedName, 0, TABLE_CARDINALITY);
|
|
|
|
// Create a binding structure for the other row
|
|
// data
|
|
memcpy(&dbBind, pBinding, sizeof(DBBINDING));
|
|
dbBind.obStatus+=cbRowSize;
|
|
dbBind.obLength+=cbRowSize;
|
|
dbBind.obValue+=cbRowSize;
|
|
|
|
// Allocate memory for two rows of histogram
|
|
SAFE_ALLOC(pDataRows, BYTE, cbRowSize*2);
|
|
|
|
pDataHist = pDataRows;
|
|
|
|
while ((hrGetNextRows = pIRowset->GetNextRows(
|
|
NULL,
|
|
0,
|
|
1,
|
|
&cRowsObtained,
|
|
&phRows)) == S_OK)
|
|
{
|
|
|
|
cRows++;
|
|
|
|
if (COMPARE(cRowsObtained, 1) &&
|
|
COMPARE(phRows != NULL, TRUE) &&
|
|
CHECK(pIRowset->GetData(phRows[0], hAccessor, pDataHist), S_OK))
|
|
{
|
|
LPBYTE pRANGE_HI_KEY = GetValuePtr(HR_RANGE_HI_KEY, pDataHist, pBinding);
|
|
TYPE_R8 * pRANGE_ROWS = (TYPE_R8 *)GetValuePtr(HR_RANGE_ROWS, pDataHist, pBinding);
|
|
TYPE_R8 * pEQ_ROWS = (TYPE_R8 *)GetValuePtr(HR_EQ_ROWS, pDataHist, pBinding);
|
|
TYPE_I8 * pDISTINCT_RANGE_ROWS =
|
|
(TYPE_I8 *)GetValuePtr(HR_DISTINCT_RANGE_ROWS, pDataHist, pBinding);
|
|
DBBINDING * pPrevBind=NULL;
|
|
DBBINDING * pCurrentBind = pBinding;
|
|
double fFraction, fPercent;
|
|
|
|
// Set pointers to previous and current bindings for RANGE_HIGH_KEY
|
|
if (cRows > 1)
|
|
{
|
|
if (pDataHist == pDataRows)
|
|
{
|
|
pCurrentBind = pBinding;
|
|
pPrevBind = &dbBind;
|
|
}
|
|
else
|
|
{
|
|
pCurrentBind = &dbBind;
|
|
pPrevBind = pBinding;
|
|
}
|
|
}
|
|
|
|
|
|
// Validate this row
|
|
|
|
// RANGE_HI_KEY is mandatory
|
|
COMPARE(pRANGE_HI_KEY != NULL, TRUE);
|
|
|
|
// One of RANGE_ROWS or EQ_ROWS is required
|
|
COMPARE(pRANGE_ROWS != NULL ||
|
|
pEQ_ROWS != NULL, TRUE);
|
|
|
|
// Validate sort is by RANGE_HI_KEY, ascending order
|
|
|
|
// Validate data for each returned column
|
|
// RANGE_HI_KEY
|
|
|
|
/* Actually, this may not necessarily be a value in the column
|
|
It may not even be within the range of values in the table, so we
|
|
really can't test this.
|
|
|
|
// Must be a value in the column
|
|
if (pRANGE_HI_KEY)
|
|
{
|
|
ulRangeCount = Cardinality(pwszQualifiedName, ulIndex, EQ_ROWS_CARDINALITY,
|
|
NULL, pCurrentBind, pDataRows, cbRowSize*2);
|
|
|
|
// Fail if no value in table == RANGE_HIGH_KEY
|
|
if (!COMPARE(ulRangeCount > 0, TRUE))
|
|
odtLog << pwszTableName << L": RANGE_HI_KEY not in base table.\n";
|
|
}
|
|
*/
|
|
|
|
// RANGE_ROWS
|
|
// Fraction of number of rows that fall in this histogram
|
|
// range. Select rows in this range and
|
|
// divide by table cardinality.
|
|
if (pRANGE_ROWS)
|
|
{
|
|
ulRangeCount = Cardinality(pwszQualifiedName, ulIndex, RANGE_ROWS_CARDINALITY,
|
|
pPrevBind, pCurrentBind, pDataRows, cbRowSize*2);
|
|
fFraction = (float)(DB_LORDINAL)ulRangeCount/(float)(DB_LORDINAL)ulTotal;
|
|
|
|
// Compute percentage error in result, avoid division by 0
|
|
if (fFraction > 0.0)
|
|
fPercent = fabs((*(double *)pRANGE_ROWS - fFraction)/fFraction);
|
|
else
|
|
fPercent = 0.0;
|
|
|
|
// Fail if off by more than 10%
|
|
CCOMPARE(m_EC, fPercent < MAX_STATISTIC_ERROR,
|
|
EC_BAD_RANGE_ROWS,
|
|
L"RANGE_ROWS not within 10%",
|
|
FALSE);
|
|
}
|
|
|
|
|
|
// EQ_ROWS
|
|
// Fraction of rows equal to RANGE_HIGH_KEY.
|
|
// Select rows equal and divide by table cardinality.
|
|
if (pEQ_ROWS)
|
|
{
|
|
ulRangeCount = Cardinality(pwszQualifiedName, ulIndex, EQ_ROWS_CARDINALITY,
|
|
NULL, pCurrentBind, pDataRows, cbRowSize*2);
|
|
fFraction = (float)(DB_LORDINAL)ulRangeCount/(float)(DB_LORDINAL)ulTotal;
|
|
|
|
// Compute percentage error in result, avoid division by 0
|
|
if (fFraction > 0.0)
|
|
fPercent = fabs((*(double *)pEQ_ROWS - fFraction)/fFraction);
|
|
else
|
|
fPercent = 0.0;
|
|
|
|
// Fail if off by more than 10%
|
|
CCOMPARE(m_EC, fPercent < MAX_STATISTIC_ERROR,
|
|
EC_BAD_EQ_ROWS,
|
|
L"EQ_ROWS not within 10%",
|
|
FALSE);
|
|
}
|
|
|
|
// DISTINCT_RANGE_ROWS
|
|
// Number of distinct values in this range.
|
|
// Select distinct rows in this range.
|
|
if (pDISTINCT_RANGE_ROWS)
|
|
{
|
|
ulRangeCount = Cardinality(pwszQualifiedName, ulIndex, DISTINCT_RANGE_ROWS_CARDINALITY,
|
|
pPrevBind, pCurrentBind, pDataRows, cbRowSize*2);
|
|
|
|
// Compute percentage error in result, avoid division by 0
|
|
if (ulRangeCount)
|
|
fPercent = fabs(float((*(LONGLONG *)pDISTINCT_RANGE_ROWS - (LONGLONG)ulRangeCount))/(float)(DB_LORDINAL)ulRangeCount);
|
|
else
|
|
fPercent = 0.0;
|
|
|
|
// Fail if off by more than 10%
|
|
CCOMPARE(m_EC, fPercent < MAX_STATISTIC_ERROR,
|
|
EC_BAD_DISTINCT_RANGE_ROWS,
|
|
L"DISTINCT_RANGE_ROWS not within 10%",
|
|
FALSE);
|
|
}
|
|
|
|
}
|
|
|
|
// Release the row
|
|
CHECK(pIRowset->ReleaseRows(1, phRows, NULL, NULL, NULL), S_OK);
|
|
|
|
// Point the pDataHist buffer to other half of total buffer
|
|
pDataHist = pDataRows+cbRowSize*(cRows % 2);
|
|
ReleaseInputBindingsMemory(cBinding, pBinding, pDataHist, FALSE);
|
|
}
|
|
|
|
// Free the row handles
|
|
SAFE_FREE(phRows);
|
|
|
|
// Release memory for the previous row we retrieved
|
|
if (cRows)
|
|
ReleaseInputBindingsMemory(cBinding, pBinding, pDataRows+cbRowSize*((cRows-1) % 2), FALSE);
|
|
|
|
SAFE_FREE(pDataRows);
|
|
|
|
// Make sure we got DB_S_ENDOFROWSET
|
|
CHECK(hrGetNextRows, DB_S_ENDOFROWSET);
|
|
|
|
// Make sure row count matches NO_OF_RANGES
|
|
if (pcRanges)
|
|
COMPARE(cRows, *pcRanges);
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
CHECK(pIRowset == NULL, TRUE);
|
|
// We allow the histogram failure if the table no longer
|
|
// exists.
|
|
if (!CHECK(hrOpenHistogram, DB_E_NOTABLE))
|
|
odtLog << L"Histogram rowset not returned.\n";
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// If the table was deleted the provider may return
|
|
// DB_E_NOTABLE instead of DB_E_NOSTATISTIC
|
|
if (hrOpenHistogram != DB_E_NOTABLE)
|
|
{
|
|
CCHECK(m_EC, hrOpenHistogram, DB_E_NOSTATISTIC,
|
|
EC_BAD_HR_OPENHISTOGRAM,
|
|
L"Unexpected return code from OpenRowset on histogram.",
|
|
FALSE);
|
|
}
|
|
}
|
|
|
|
SAFE_RELEASE(pIRowset);
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PRVTRACE(L"'%d'\n",(WCHAR *)pColumn->bValue);
|
|
break;
|
|
}
|
|
case TS_COLUMN_NAME:
|
|
// Sanity check
|
|
|
|
// Column must have non-empty string and cannot be NULL
|
|
if (COMPARE(pColumn->sStatus, DBSTATUS_S_OK))
|
|
{
|
|
COMPARE(wcslen((TYPE_WSTR)pColumn->bValue) > 0, TRUE);
|
|
|
|
// Detail check
|
|
if (m_fDetailCheck && SUCCEEDED(hrOpenTable))
|
|
// Column name must match columns info for this ordinal
|
|
COMPARE(RelCompareString(m_prgColInfo[ulIndex].pwszName, (TYPE_WSTR)pColumn->bValue), 0);
|
|
}
|
|
break;
|
|
case TS_COLUMN_GUID:
|
|
// Sanity check: none
|
|
|
|
// Detail check
|
|
if (m_fDetailCheck && SUCCEEDED(hrOpenTable))
|
|
{
|
|
// Column guid must match columns info
|
|
if (S_OK == pColumn->sStatus)
|
|
{
|
|
COMPARE(m_prgColInfo[ulIndex].columnid.uGuid.guid == *(GUID *)pColumn->bValue, TRUE);
|
|
}
|
|
else
|
|
{
|
|
// Must be NULL
|
|
// COMPARE(m_prgColInfo[ulIndex].columnid.uGuid.guid == DB_NULLGUID, TRUE);
|
|
}
|
|
}
|
|
break;
|
|
case TS_COLUMN_PROPID:
|
|
// Sanity check: none
|
|
|
|
// Detail check
|
|
if (m_fDetailCheck && SUCCEEDED(hrOpenTable))
|
|
{
|
|
// Column propid must match columns info
|
|
if (S_OK == pColumn->sStatus)
|
|
COMPARE(m_prgColInfo[ulIndex].columnid.uName.ulPropid == *(ULONG *)pColumn->bValue, TRUE);
|
|
|
|
// If status == DBSTATUS_S_ISNULL, then value is undefined and can't be
|
|
// compared. And it appears ulPropid in columnsinfo is uninitialized.
|
|
}
|
|
break;
|
|
case TS_ORDINAL_POSITION:
|
|
// The ordinal position must be sequential within the table
|
|
{
|
|
// Column cannot be null
|
|
if (COMPARE(pColumn->sStatus, DBSTATUS_S_OK))
|
|
{
|
|
// If we have a valid column name
|
|
if (pwszTableName && pwszStatName)
|
|
{
|
|
if (fNewStat)
|
|
{
|
|
// This is a new statistic, ordinal must be 1
|
|
m_iOrdinalExpected = 1;
|
|
SAFE_FREE(m_pwszTableName);
|
|
SAFE_FREE(m_pwszStatName);
|
|
m_pwszTableName = wcsDuplicate(pwszTableName);
|
|
m_pwszStatName = wcsDuplicate(pwszStatName);
|
|
}
|
|
else
|
|
m_iOrdinalExpected++;
|
|
|
|
// Compare Ordinal returned with expected
|
|
if (!COMPARE(m_iOrdinalExpected, *(TYPE_UI4 *)pColumn->bValue))
|
|
odtLog << pwszTableName << L": Invalid ordinal value returned.\n";
|
|
}
|
|
|
|
}
|
|
break;
|
|
}
|
|
case TS_SAMPLE_PCT:
|
|
case TS_LAST_UPDATE_TIME:
|
|
case TS_NO_OF_RANGES:
|
|
// This is tested for accuracy by counting rows in histogram rowset.
|
|
break;
|
|
case TS_COLUMN_CARDINALITY:
|
|
eCardinality = COLUMN_CARDINALITY;
|
|
// Fall through
|
|
case TS_TUPLE_CARDINALITY:
|
|
// This should equal number distinct rows in table for this column
|
|
if (m_fDetailCheck && SUCCEEDED(hrOpenTable) &&
|
|
pColumn->sStatus == DBSTATUS_S_OK)
|
|
{
|
|
DBCOUNTITEM cRows = Cardinality(pwszQualifiedName, ulIndex, eCardinality);
|
|
|
|
// Note test bug here Cardinality() doesn't include NULL rows.
|
|
CCOMPARE(m_EC, cRows == *(ULONG *)pColumn->bValue,
|
|
EC_BAD_COL_OR_TUPLE_CARD,
|
|
L"Column or Tuple cardinality is incorrect",
|
|
FALSE);
|
|
}
|
|
break;
|
|
case TS_TABLE_CARDINALITY:
|
|
// Spec doesn't indicate this can be NULL.
|
|
COMPARE(pColumn->sStatus, DBSTATUS_S_OK);
|
|
|
|
// Detail check
|
|
|
|
// This should equal number of rows in table
|
|
if (m_fDetailCheck && SUCCEEDED(hrOpenTable) &&
|
|
pColumn->sStatus == DBSTATUS_S_OK)
|
|
{
|
|
DBCOUNTITEM cRows = Cardinality(pwszQualifiedName, ulIndex, TABLE_CARDINALITY);
|
|
|
|
CCOMPARE(m_EC, cRows == *(ULONG *)pColumn->bValue,
|
|
EC_BAD_TABLE_CARDINALITY,
|
|
L"Table cardinality is incorrect",
|
|
FALSE);
|
|
}
|
|
break;
|
|
case TS_AVG_COLUMN_LENGTH:
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"TABLE STATISTICS: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - TABLE STATISTICS provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
COMPARE(pColumn->sStatus, DBSTATUS_S_OK);
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
COMPARE(pColumn->sStatus, DBSTATUS_S_OK);
|
|
}
|
|
}
|
|
|
|
CLEANUP:
|
|
|
|
SAFE_FREE(pwszQualifiedName);
|
|
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// TABLES
|
|
// 1. Catalog Name
|
|
// 2. Schema Name
|
|
// 3. Table Name
|
|
// 4. Table Type
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_TABLES()
|
|
{
|
|
// Set the Schema column Count, Names and Types
|
|
m_cColumns = cTABLES;
|
|
m_rgColumnNames = (WCHAR **) rgwszTABLES;
|
|
m_rgColumnTypes = (DBTYPE *) rgtypeTABLES;
|
|
|
|
// Set the count of restrictions
|
|
m_cRestrictions = cTABLES_RESTRICTIONS;
|
|
|
|
// Set Valid Table Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszTableRestriction);
|
|
SetRestriction(FOURTH,4, &m_wszR4, m_pwszTable_TypeRestriction);
|
|
|
|
// Set an Invalid Table Restriction
|
|
if(m_restrict & FIFTH) {
|
|
SetRestriction(FIFTH,5, &m_wszR5, m_pwszTableRestriction);
|
|
m_cRestrictions = 5;
|
|
}
|
|
|
|
// Set expected row count. Since we create a table there must be
|
|
// at least one.
|
|
SetRowCount(MIN_REQUIRED, 1);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowTABLES
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_TABLES(DBCOUNTITEM iRow, BYTE * pData)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// Try to open a rowset on the table
|
|
GetColumnInfo(pData, m_rgDBBINDING);
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cTABLES <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
// TABLE_CATALOG
|
|
case 1:
|
|
fResults &= TestReturnData(iRow,pColumn,FIRST,&m_fRes1,m_wszR1);
|
|
break;
|
|
|
|
// TABLE_SCHEMA
|
|
case 2:
|
|
fResults &= TestReturnData(iRow,pColumn,SECOND,&m_fRes2,m_wszR2);
|
|
break;
|
|
|
|
// TABLE_NAME
|
|
case 3:
|
|
fResults &= TestReturnData(iRow,pColumn,THIRD,&m_fRes3,m_wszR3);
|
|
break;
|
|
|
|
// TABLE_TYPE
|
|
case 4:
|
|
fResults &= TestReturnData(iRow,pColumn,FOURTH,&m_fRes4,m_wszR4,FALSE);
|
|
|
|
// Check the only spec'ed Types
|
|
if( (0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"ALIAS")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"TABLE")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"SYNONYM")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"SYSTEM TABLE")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"GLOBAL TEMPORARY")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"LOCAL TEMPORARY")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"SYSTEM VIEW")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"VIEW")))
|
|
{
|
|
odtLog << L"Provider specific TABLE TYPE was returned by the provider: "
|
|
<< (TYPE_WSTR)pColumn->bValue << ENDL;
|
|
fResults = FALSE;
|
|
}
|
|
break;
|
|
|
|
// TABLE_GUID
|
|
case 5:
|
|
if(pColumn->sStatus == DBSTATUS_S_OK)
|
|
COMPARE(pColumn->ulLength, sizeof(GUID));
|
|
else if(pColumn->sStatus == DBSTATUS_S_ISNULL)
|
|
{
|
|
// COMPARE(pColumn->ulLength, 0); // Not required per spec.
|
|
}
|
|
break;
|
|
|
|
// DESCRIPTION
|
|
case 6:
|
|
if(pColumn->sStatus == DBSTATUS_S_ISNULL)
|
|
{
|
|
// COMPARE(pColumn->ulLength, 0); // Not required per spec.
|
|
}
|
|
break;
|
|
|
|
// TABLE_PROPID
|
|
case 7:
|
|
if(pColumn->sStatus == DBSTATUS_S_OK)
|
|
COMPARE(pColumn->ulLength, sizeof(ULONG));
|
|
else if(pColumn->sStatus == DBSTATUS_S_ISNULL)
|
|
{
|
|
// COMPARE(pColumn->ulLength, 0); // Not required per spec.
|
|
}
|
|
break;
|
|
|
|
// DATE_CREATED
|
|
// DATE_MODIFIED
|
|
case 8:
|
|
case 9:
|
|
if(pColumn->sStatus == DBSTATUS_S_OK)
|
|
COMPARE(pColumn->ulLength, sizeof(DATE));
|
|
else if(pColumn->sStatus == DBSTATUS_S_ISNULL)
|
|
{
|
|
// COMPARE(pColumn->ulLength, 0); // Not required per spec.
|
|
}
|
|
break;
|
|
|
|
// PROVIDER SPECIFIC
|
|
default:
|
|
if (iRow == 1)
|
|
{
|
|
if(!m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"TABLES: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - TABLES provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// TABLES_INFO
|
|
// 1. Catalog Name
|
|
// 2. Schema Name
|
|
// 3. Table Name
|
|
// 4. Table Type
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_TABLES_INFO()
|
|
{
|
|
// Set the Schema column Count, Names and Types
|
|
m_cColumns = cTABLES_INFO;
|
|
m_rgColumnNames = (WCHAR **) rgwszTABLES_INFO;
|
|
m_rgColumnTypes = (DBTYPE *) rgtypeTABLES_INFO;
|
|
|
|
// Set the count of restrictions
|
|
m_cRestrictions = cTABLES_INFO_RESTRICTIONS;
|
|
|
|
// Set Valid TableInfo Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszTableRestriction);
|
|
SetRestriction(FOURTH,4, &m_wszR4, m_pwszTable_TypeRestriction);
|
|
|
|
// Set an Invalid TableInfo Restriction
|
|
if(m_restrict & FIFTH) {
|
|
SetRestriction(FIFTH,5, &m_wszR5, m_pwszTableRestriction);
|
|
m_cRestrictions = 5;
|
|
}
|
|
|
|
// Set expected row count. Since we create a table there must be
|
|
// at least one.
|
|
SetRowCount(MIN_REQUIRED, 1);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowTABLES_INFO
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_TABLES_INFO(DBCOUNTITEM iRow, BYTE * pData)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cTABLES_INFO <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
// TABLE_CATALOG
|
|
case 1:
|
|
fResults &= TestReturnData(iRow,pColumn,FIRST,&m_fRes1,m_wszR1);
|
|
break;
|
|
|
|
// TABLE_SCHEMA
|
|
case 2:
|
|
fResults &= TestReturnData(iRow,pColumn,SECOND,&m_fRes2,m_wszR2);
|
|
break;
|
|
|
|
// TABLE_NAME
|
|
case 3:
|
|
fResults &= TestReturnData(iRow,pColumn,THIRD,&m_fRes3,m_wszR3);
|
|
break;
|
|
|
|
// TABLE_TYPE
|
|
case 4:
|
|
fResults &= TestReturnData(iRow,pColumn,FOURTH,&m_fRes4,m_wszR4);
|
|
|
|
// Check the only spec'ed Types
|
|
if( (0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"ALIAS")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"TABLE")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"SYNONYM")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"SYSTEM TABLE")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"GLOBAL TEMPORARY")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"SYSTEM TEMPORARY")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"SYSTEM VIEW")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"VIEW")))
|
|
{
|
|
odtLog << L"VerifyRow_TABLES_INFO:TABLE TYPE expected ALIAS/TABLE/SYNONYM/SYSTEM TABLE/GLOBAL/SYSTEM/VIEW but recieved "
|
|
<< (TYPE_WSTR)pColumn->bValue << ENDL;
|
|
fResults = FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
// TABLE_GUID
|
|
case 5:
|
|
break;
|
|
|
|
// BOOKMARKS
|
|
case 6:
|
|
break;
|
|
|
|
// BOOKMARK_TYPE
|
|
// BOOKMARK_DATATYPE
|
|
// BOOKMARK_MAXIMUM
|
|
// BOOKMARK_INFORMATION
|
|
case 7:
|
|
case 8:
|
|
case 9:
|
|
case 10:
|
|
break;
|
|
|
|
// TABLE_VERSION
|
|
case 11:
|
|
break;
|
|
|
|
// CARDINALITY
|
|
case 12:
|
|
break;
|
|
|
|
// DESCRIPTION
|
|
case 13:
|
|
break;
|
|
|
|
// TABLE_PROPID
|
|
case 14:
|
|
break;
|
|
|
|
// PROVIDER SPECIFIC
|
|
default:
|
|
if (iRow == 1)
|
|
{
|
|
if(!m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"TABLES_INFO: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - TABLES_INFO provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// TRANSLATIONS
|
|
// 1. Catalog Name
|
|
// 2. Schema Name
|
|
// 3. Translation Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_TRANSLATIONS()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszTRANSLATIONS;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeTRANSLATIONS;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cTRANSLATIONS;
|
|
m_cRestrictions = cTRANSLATIONS_RESTRICTIONS;
|
|
|
|
// Set Transalation Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszTranslationReplace);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::TRANSLATIONS\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowTRANSLATIONS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_TRANSLATIONS
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// don't need to go farther if I have what I'm looking for
|
|
if(m_fCaptureRestrictions && m_pwszTranslationReplace)
|
|
return FALSE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cTRANSLATIONS <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:TRANSLATIONS:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// TABLE_CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_TRANSLATIONS: TRANSLATION CATALOG restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// TABLE_SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_TRANSLATIONS: TRANSLATION SCHEMA restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3:// Translation Name
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszTranslationReplace = (TYPE_WSTR) PROVIDER_ALLOC
|
|
((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszTranslationReplace)
|
|
wcscpy(m_pwszTranslationReplace,(TYPE_WSTR) pColumn->bValue);
|
|
}
|
|
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_TRANSLATIONS: TRANSLATION NAME restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(WCHAR *)pColumn->bValue);
|
|
break;
|
|
case 4: // SOURCE CHARACTER SET CATALOG
|
|
case 5: // SOURCE CHARACTER SET SCHEMA
|
|
case 6: // SOURCE CHARACTER SET NAME
|
|
case 7: // TARGET CHARACTER SET CATALOG
|
|
case 8: // TARGET CHARACTER SET SCHEMA
|
|
case 9: // TARGET CHARACTER SET NAME
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"TRANSLATIONS: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - TRANSLATIONS provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
|
|
return fResults;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// TRUSTEE
|
|
// 1. TRUSTEE_NAME
|
|
// 2. TRUSTEE_GUID
|
|
// 3. TRUSTEE_TYPE
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_TRUSTEE()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszTRUSTEE;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeTRUSTEE;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cTRUSTEE;
|
|
m_cRestrictions = cTRUSTEE_RESTRICTIONS;
|
|
|
|
odtLog << L"*** Add restriction values for DBSCHEMA_TRUSTEE.\n";
|
|
|
|
// Set TRUSTEE Restrictions
|
|
// SetRestriction(FIRST, 1, &m_wszR1, m_pwszTrusteeName);
|
|
// SetRestriction(SECOND,2, &m_wszR2, m_pwszTrusteeGUID);
|
|
// SetRestriction(THIRD, 3, &m_wszR3, m_pwszTrusteePROPID);
|
|
// SetRestriction(FOURTH,4, &m_wszR4, m_pwszTrusteeType);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::TRUSTEE\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowTRANSLATIONS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_TRUSTEE
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// don't need to go farther if I have what I'm looking for
|
|
if(m_fCaptureRestrictions && m_pwszTranslationReplace)
|
|
return FALSE;
|
|
|
|
odtLog << L"*** Currently not testing values returned from DBSCHEMA_TRUSTEE.\n";
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cTRUSTEE <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:TRUSTEE:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1:// TRUSTEE_NAME
|
|
/*
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_TRUSTEE: TRUSTEE_NAME restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// TRUSTEE_GUID
|
|
/*
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_TRUSTEE: TRUSTEE_GUID restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3:// TRUSTEE_PROPID
|
|
/*
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszTranslationReplace = (TYPE_WSTR) PROVIDER_ALLOC
|
|
((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszTranslationReplace)
|
|
wcscpy(m_pwszTranslationReplace,(TYPE_WSTR) pColumn->bValue);
|
|
}
|
|
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_TRUSTEE: TRUSTEE_PROPID restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
PRVTRACE(L"'%s'\n",(WCHAR *)pColumn->bValue);
|
|
break;
|
|
case 4: // TRUSTEE_TYPE
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"TRANSLATIONS: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - TRANSLATIONS provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
|
|
return fResults;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// USAGE_PRIVILGES
|
|
// 1. Catalog Name
|
|
// 2. Schema Name
|
|
// 3. Object Name
|
|
// 4. Object Type
|
|
// 5. Grantor
|
|
// 6. Grantee
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_USAGE_PRIVILEGES()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszUSAGE_PRIVILEGES;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeUSAGE_PRIVILEGES;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cUSAGE_PRIVILEGES;
|
|
m_cRestrictions = cUSAGE_PRIVILEGES_RESTRICTIONS;
|
|
|
|
// Set Object Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszObjectRestriction);
|
|
SetRestriction(FOURTH,4, &m_wszR4, m_pwszObject_TypeRestriction);
|
|
SetRestriction(FIFTH, 5, &m_wszR5, m_pwszGrantorRestriction);
|
|
SetRestriction(SIXTH, 6, &m_wszR6, m_pwszGranteeRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::USAGE_PRIVILGES\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowUSAGE_PRIVILEGES
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_USAGE_PRIVILEGES
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// don't need to go farther if I have what I'm looking for
|
|
if(m_fCaptureRestrictions && m_pwszObjectRestriction && m_pwszObject_TypeRestriction)
|
|
return FALSE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cUSAGE_PRIVILEGES <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:USAGE_PRIVILEGES:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1://GRANTOR
|
|
if(m_restrict & FIFTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR5,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes5)
|
|
{
|
|
odtLog << L"VerifyRow_USAGE_PRIVILEGES:GRANTOR restriction failed\n";
|
|
m_fRes5=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// GRANTEE
|
|
if(m_restrict & SIXTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR6,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes6)
|
|
{
|
|
odtLog << L"VerifyRow_USAGE_PRIVILEGES:GRANTEE restriction failed\n";
|
|
m_fRes6=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: // OBJECT CATALOG
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_USAGE_PRIVILEGES:OBJECT CATALOG restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// OBJECT SCHEMA
|
|
if(m_restrict & SECOND)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR2,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes2)
|
|
{
|
|
odtLog << L"VerifyRow_USAGE_PRIVILEGES:OBJECT SCHEMA restriction failed\n";
|
|
m_fRes2=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 5:// OBJECT NAME
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszObjectRestriction = (WCHAR *) PROVIDER_ALLOC
|
|
((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszObjectRestriction)
|
|
wcscpy(m_pwszObjectRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
}
|
|
|
|
if(m_restrict & THIRD)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR3,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes3)
|
|
{
|
|
odtLog << L"VerifyRow_USAGE_PRIVILEGES:OBJECT NAME restriction failed\n";
|
|
m_fRes3=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 6: // OBJECT TYPE
|
|
if(m_restrict & FOURTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR4,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes4)
|
|
{
|
|
odtLog << L"VerifyRow_USAGE_PRIVILEGES:OBJECT TYPE restriction failed\n";
|
|
m_fRes4=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszObject_TypeRestriction = (WCHAR *) PROVIDER_ALLOC
|
|
((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR)) + sizeof(WCHAR));
|
|
if(m_pwszObject_TypeRestriction)
|
|
wcscpy(m_pwszObject_TypeRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
}
|
|
if( (0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"DOMAIN")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"CHARACTER SET")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"COLLATION")) &&
|
|
(0!=wcscmp((TYPE_WSTR)pColumn->bValue,L"TRANSLATION")))
|
|
{
|
|
odtLog << L"VerifyRow_USAGE_PRIVILEGES:OBJECT TYPE expected DOMAIN/CHARACTERSET/COLLATION/TRANSLATION but recieved "
|
|
<< (TYPE_WSTR)pColumn->bValue << ENDL;
|
|
fResults = FALSE;
|
|
}
|
|
PRVTRACE(L"'%s'\n",(WCHAR *)pColumn->bValue);
|
|
break;
|
|
case 7: // PRIVILEGE TYPE
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 8: // IS_GRANTABLE
|
|
if(*(TYPE_BOOL *)pColumn->bValue==VARIANT_TRUE)
|
|
PRVTRACE(L"TRUE\n");
|
|
else
|
|
PRVTRACE(L"FALSE\n");
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"USAGE PRIVILEGES: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - USAGE PRIVILEGES provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// VIEW_COLUMN_USAGE
|
|
// 1. Catalog Name
|
|
// 2. Schema Name
|
|
// 3. View Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_VIEW_COLUMN_USAGE()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszVIEW_COLUMN_USAGE;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeVIEW_COLUMN_USAGE;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cVIEW_COLUMN_USAGE;
|
|
m_cRestrictions = cVIEW_COLUMN_USAGE_RESTRICTIONS;
|
|
|
|
// Set View Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszViewRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::VIEW_COLUMN_USAGE\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowVIEW_COLUMN_USAGE
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_VIEW_COLUMN_USAGE
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cVIEW_COLUMN_USAGE <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:VIEW_COLUMN_USAGE:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1://VIEW CATALOG
|
|
if(m_restrict & FIFTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR5,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes5)
|
|
{
|
|
odtLog << L"VerifyRow_VIEW_COLUMN_USAGE: VIEW CATALOG restriction failed\n";
|
|
m_fRes5=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// VIEW SCHEMA
|
|
if(m_restrict & SIXTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR6,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes6)
|
|
{
|
|
odtLog << L"VerifyRow_VIEW_COLUMN_USAGE:VIEW SCHEMA restriction failed\n";
|
|
m_fRes6=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: // VIEW NAME
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_VIEW_COLUMN_USAGE:VIEW NAME restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// TABLE CATALOG
|
|
case 5:// TABLE SCHEMA
|
|
case 6:// TABLE NAME
|
|
case 7:// COLUMN NAME
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 8: // COLUMN GUID
|
|
PRVTRACE(L"\n");
|
|
break;
|
|
case 9: // COLUMN PROPID
|
|
PRVTRACE(L"%d\n",*(TYPE_UI4 *)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"VIEW COLUMN USAGE: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - VIEW COLUMN USAGE provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// VIEW_TABLE_USAGE
|
|
// 1. Catalog Name
|
|
// 2. Schema Name
|
|
// 3. View Name
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_VIEW_TABLE_USAGE()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszVIEW_TABLE_USAGE;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeVIEW_TABLE_USAGE;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cVIEW_TABLE_USAGE;
|
|
m_cRestrictions = cVIEW_TABLE_USAGE_RESTRICTIONS;
|
|
|
|
// Set View Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszViewRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::VIEW_TABLE_USAGE\n");
|
|
return TRUE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowVIEW_TABLE_USAGE
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_VIEW_TABLE_USAGE
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// don't need to go farther if I have what I'm looking for
|
|
if(m_fCaptureRestrictions && m_pwszViewRestriction)
|
|
return FALSE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cVIEW_TABLE_USAGE <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:VIEW_TABLE_USAGE:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1://VIEW CATALOG
|
|
if(m_restrict & FIFTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR5,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes5)
|
|
{
|
|
odtLog << L"VerifyRow_VIEW_TABLE_USAGE: VIEW CATALOG restriction failed\n";
|
|
m_fRes5=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// VIEW SCHEMA
|
|
if(m_restrict & SIXTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR6,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes6)
|
|
{
|
|
odtLog << L"VerifyRow_VIEW_TABLE_USAGE:VIEW SCHEMA restriction failed\n";
|
|
m_fRes6=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: // VIEW NAME
|
|
if(m_fCaptureRestrictions)
|
|
{
|
|
m_pwszViewRestriction = (WCHAR *) PROVIDER_ALLOC
|
|
((wcslen((WCHAR *) pColumn->bValue)*sizeof(WCHAR*)) + sizeof(WCHAR));
|
|
if(m_pwszViewRestriction)
|
|
wcscpy(m_pwszViewRestriction,(TYPE_WSTR) pColumn->bValue);
|
|
}
|
|
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_VIEW_TABLE_USAGE:VIEW NAME restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// TABLE CATALOG
|
|
case 5:// TABLE SCHEMA
|
|
case 6:// TABLE NAME
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"VIEW TABLE USAGE: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - VIEW TABLE USAGE provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
|
|
|
|
return fResults;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// VIEWS
|
|
// 1. Table Catalog
|
|
// 2. Table Schema
|
|
// 3. Table View
|
|
//--------------------------------------------------------------------
|
|
BOOL CSchemaTest::PrepareParams_VIEWS()
|
|
{
|
|
// Set the Schema column Names and Types
|
|
m_rgColumnNames = (WCHAR **)rgwszVIEWS;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeVIEWS;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cVIEWS;
|
|
m_cRestrictions = cVIEWS_RESTRICTIONS;
|
|
|
|
// Set View Restrictions
|
|
SetRestriction(FIRST, 1, &m_wszR1, m_pwszCatalogRestriction);
|
|
SetRestriction(SECOND,2, &m_wszR2, m_pwszSchemaRestriction);
|
|
SetRestriction(THIRD, 3, &m_wszR3, m_pwszTableRestriction);
|
|
|
|
PRVTRACE(L"GetSchemaInfo::VIEWS\n");
|
|
return TRUE;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowVIEWS
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRow_VIEWS
|
|
(
|
|
DBCOUNTITEM iRow,
|
|
BYTE * pData
|
|
)
|
|
{
|
|
ULONG iBind; // Binding Count
|
|
DATA * pColumn; // Data Structure
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
|
|
// Check the count of columns returned
|
|
if(iRow == 1)
|
|
COMPARE(cVIEWS <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:VIEWS:", iRow, m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
switch(m_rgDBCOLUMNINFO[iBind].iOrdinal)
|
|
{
|
|
case 1://TABLE CATALOG
|
|
if(m_restrict & FIFTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR5,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes5)
|
|
{
|
|
odtLog << L"VerifyRow_VIEWS: TABLE CATALOG restriction failed\n";
|
|
m_fRes5=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2:// TABLE SCHEMA
|
|
if(m_restrict & SIXTH)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR6,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes6)
|
|
{
|
|
odtLog << L"VerifyRow_VIEWS:TABLE SCHEMA restriction failed\n";
|
|
m_fRes6=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3: // TABLE NAME
|
|
if(m_restrict & FIRST)
|
|
{
|
|
if(!COMPARE(0, _wcsicmp((TYPE_WSTR)m_wszR1,(TYPE_WSTR)pColumn->bValue)))
|
|
{
|
|
if(m_fRes1)
|
|
{
|
|
odtLog << L"VerifyRow_VIEWS:TABLE NAME restriction failed\n";
|
|
m_fRes1=FALSE;
|
|
fResults = FALSE;
|
|
}
|
|
}
|
|
}
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 4:// VIEW_DEFINITION
|
|
case 7:// DESCRIPTION
|
|
PRVTRACE(L"'%s'\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 5:// CHECK_OPTION
|
|
case 6:// IS_UPDATEABLE
|
|
if(*(TYPE_BOOL *)pColumn->bValue==VARIANT_TRUE)
|
|
PRVTRACE(L"TRUE\n");
|
|
else
|
|
PRVTRACE(L"FALSE\n");
|
|
break;
|
|
// DATE_CREATED
|
|
// DATE_MODIFIED
|
|
case 8:
|
|
case 9:
|
|
break;
|
|
default:
|
|
// We found a column not spec'd for this schema rowset, print a warning.
|
|
if (iRow == 1)
|
|
{
|
|
if (m_rgDBCOLUMNINFO[iBind].iOrdinal == 0)
|
|
{
|
|
if(!GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset))
|
|
odtLog << L"VIEWS: Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
else
|
|
odtLog << L"Warning - VIEWS provider specific column name: " << m_rgDBCOLUMNINFO[iBind].pwszName << "\n";
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (pColumn->sStatus==DBSTATUS_S_TRUNCATED)
|
|
{
|
|
// Have to flag error.
|
|
odtLog << L"DBSTATUS_S_TRUNCATED: " << (TYPE_WSTR)pColumn->bValue << L"\n";
|
|
// We shouldn't be flagging an error for LONG columns, we expect truncation.
|
|
if (!(m_rgDBCOLUMNINFO[iBind].dwFlags & DBCOLUMNFLAGS_ISLONG))
|
|
fResults = FALSE;
|
|
}
|
|
else
|
|
{
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus);
|
|
}
|
|
}
|
|
|
|
return fResults;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
//
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::CheckResults(IUnknown * pIRowset, IID iid)
|
|
{
|
|
BOOL fResult = TRUE;
|
|
|
|
// if I didn't get rowset back when I expected FIRST, return error
|
|
if(SUCCEEDED(m_HR))
|
|
{
|
|
if( ((m_iid==IID_IRowset) && (!m_pIRowset)) ||
|
|
((m_iid==IID_IAccessor) && (!m_pIAccessor)) ||
|
|
((m_iid==IID_IRowsetInfo) && (!m_pIRowsetInfo)) ||
|
|
((m_iid==IID_IColumnsInfo) && (!m_pIColumnsInfo))||
|
|
((m_iid==IID_IRowsetChange) && (!m_pIRowsetChange)) )
|
|
{
|
|
odtLog << L"CheckResults:expected rowset but didn't get FIRST\n";
|
|
return FALSE;
|
|
}
|
|
|
|
// check that the riid pointer can be used,
|
|
// regardless of which riid it is
|
|
fResult &= CheckRIID(pIRowset, iid);
|
|
fResult &= VerifyRowset(pIRowset);
|
|
}
|
|
else // make sure rowset if empty
|
|
{
|
|
if( ((m_iid==IID_IRowset) && (m_pIRowset)) ||
|
|
((m_iid==IID_IAccessor) && (m_pIAccessor)) ||
|
|
((m_iid==IID_IRowsetInfo) && (m_pIRowsetInfo))||
|
|
((m_iid==IID_IColumnsInfo) && (m_pIColumnsInfo))||
|
|
((m_iid==IID_IRowsetChange) && (m_pIRowsetChange)))
|
|
{
|
|
odtLog << L"CheckResults: method returned error and valid rowset pointer!\n";
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return fResult;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CheckAgainstIColumnsInfo
|
|
//
|
|
// Checks the DBCOLUMNINFO array returned by IColumnsInfo::GetColumnsInfo against
|
|
// the what the spec says the column name, type and order should be
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::CheckAgainstIColumnsInfo()
|
|
{
|
|
BOOL fResult = TRUE;
|
|
BOOL fCountNotChecked= FALSE;
|
|
ULONG ulIndex = 0;
|
|
|
|
COMPARE(m_cColumns <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// Make sure the rowset is not null
|
|
if((!m_pIRowset) || (!m_cDBCOLUMNINFO) || (!m_rgDBCOLUMNINFO) || (!m_pStringsBuffer)) {
|
|
odtLog << L"CheckAgainstIColumnsInfo:Either rowset or DBCOLUMNINFO variables are null."<<ENDL;
|
|
return FALSE;
|
|
}
|
|
|
|
// Check for the Bookmark
|
|
if(!m_rgDBCOLUMNINFO[0].iOrdinal)
|
|
m_fBOOKMARK_FOUND=TRUE;
|
|
else
|
|
m_fBOOKMARK_FOUND=FALSE;
|
|
|
|
// Check column ordering, column name and data type, skip bookmark column
|
|
for(ulIndex = (0 + m_fBOOKMARK_FOUND); ulIndex < m_cDBCOLUMNINFO; ulIndex ++)
|
|
{
|
|
// only check spec'd columns, not any provider-specific columns
|
|
if((ulIndex-m_fBOOKMARK_FOUND) < m_cColumns)
|
|
{
|
|
// Check column ordinal
|
|
if(m_rgDBCOLUMNINFO[ulIndex].iOrdinal != (ulIndex + 1 - m_fBOOKMARK_FOUND))
|
|
{
|
|
odtLog << L"ORDINAL [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex
|
|
<< L"]: Expected "<< ulIndex << L", Received " << m_rgDBCOLUMNINFO[ulIndex].iOrdinal << ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
|
|
// If there is a name in this column, check to make sure it is correct
|
|
if( (m_rgDBCOLUMNINFO[ulIndex].pwszName) &&
|
|
(!COMPARE(0, _wcsicmp(m_rgDBCOLUMNINFO[ulIndex].pwszName,m_rgColumnNames[ulIndex-m_fBOOKMARK_FOUND]))) )
|
|
{
|
|
odtLog << L"NAME [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L","
|
|
<< ulIndex << L"]: Expected " << m_rgColumnNames[ulIndex-m_fBOOKMARK_FOUND] << L", Received "
|
|
<< m_rgDBCOLUMNINFO[ulIndex].pwszName << ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
|
|
// Check column type
|
|
if(m_rgDBCOLUMNINFO[ulIndex].wType != m_rgColumnTypes[ulIndex-m_fBOOKMARK_FOUND])
|
|
{
|
|
odtLog << L"TYPE [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex << L"]: Expected "
|
|
<< m_rgColumnTypes[ulIndex-m_fBOOKMARK_FOUND] << L", Received " << m_rgDBCOLUMNINFO[ulIndex].wType << ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
|
|
// Check column size
|
|
if((!IsFixedLength(m_rgDBCOLUMNINFO[ulIndex].wType)) && (!m_rgDBCOLUMNINFO[ulIndex].ulColumnSize))
|
|
{
|
|
odtLog << L"COLUMNSIZE [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex << L"]: "
|
|
<< L"Column Size for variable length Column is ZERO, expected non-zero." << ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
else if((IsFixedLength(m_rgDBCOLUMNINFO[ulIndex].wType)) &&
|
|
((ULONG)GetDBTypeSize(m_rgDBCOLUMNINFO[ulIndex].wType) != m_rgDBCOLUMNINFO[ulIndex].ulColumnSize))
|
|
{
|
|
odtLog << L"COLUMNSIZE [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex << L"]: Expected "
|
|
<< L"Column Size for the Column is incorrect. " << ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
|
|
// Check column precision and scale
|
|
// Note some provider return an alternate precision/scale for
|
|
// DBTYPE_CY
|
|
if(IsNumericType(m_rgDBCOLUMNINFO[ulIndex].wType) &&
|
|
m_rgDBCOLUMNINFO[ulIndex].wType != DBTYPE_CY)
|
|
{
|
|
ULONG MaxPrecision = 0;
|
|
|
|
// Switch on the Type
|
|
switch(m_rgDBCOLUMNINFO[ulIndex].wType)
|
|
{
|
|
case DBTYPE_I1:
|
|
case DBTYPE_UI1:
|
|
MaxPrecision = 3;
|
|
break;
|
|
case DBTYPE_I2:
|
|
case DBTYPE_UI2:
|
|
MaxPrecision = 5;
|
|
break;
|
|
case DBTYPE_R4:
|
|
MaxPrecision = 7;
|
|
break;
|
|
case DBTYPE_I4:
|
|
case DBTYPE_UI4:
|
|
MaxPrecision = 10;
|
|
break;
|
|
case DBTYPE_R8:
|
|
MaxPrecision = 15;
|
|
break;
|
|
case DBTYPE_CY:
|
|
case DBTYPE_I8:
|
|
MaxPrecision = 19;
|
|
break;
|
|
case DBTYPE_UI8:
|
|
MaxPrecision = 20;
|
|
break;
|
|
}
|
|
|
|
// Precision is valid
|
|
if (((m_rgDBCOLUMNINFO[ulIndex].wType != DBTYPE_DECIMAL) &&
|
|
(m_rgDBCOLUMNINFO[ulIndex].wType != DBTYPE_NUMERIC) &&
|
|
(m_rgDBCOLUMNINFO[ulIndex].wType != DBTYPE_VARNUMERIC)) &&
|
|
(MaxPrecision != m_rgDBCOLUMNINFO[ulIndex].bPrecision) )
|
|
{
|
|
odtLog << L"PRECISION [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex << L"]: Expected "
|
|
<< MaxPrecision << L", Received " << m_rgDBCOLUMNINFO[ulIndex].bPrecision << ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
|
|
// Scale is ~0
|
|
if (((m_rgDBCOLUMNINFO[ulIndex].wType != DBTYPE_DECIMAL) &&
|
|
(m_rgDBCOLUMNINFO[ulIndex].wType != DBTYPE_NUMERIC) &&
|
|
(m_rgDBCOLUMNINFO[ulIndex].wType != DBTYPE_VARNUMERIC)) &&
|
|
((BYTE)(~0) != m_rgDBCOLUMNINFO[ulIndex].bScale) )
|
|
{
|
|
odtLog << L"SCALE [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex
|
|
<< L"]: Expected the Scale to be ~0" << L", Received " << m_rgDBCOLUMNINFO[ulIndex].bScale << ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
else if (m_rgDBCOLUMNINFO[ulIndex].wType == DBTYPE_DBTIMESTAMP ||
|
|
m_rgDBCOLUMNINFO[ulIndex].wType == DBTYPE_CY)
|
|
{
|
|
CCol TempCol;
|
|
BYTE bPrecision = 0;
|
|
BYTE bScale = 0;
|
|
|
|
// Get bPrecision and bScale for DBTYPE_DBTIMESTAMP or
|
|
// DBTYPE_CY from CCol object
|
|
for (DBORDINAL iCol = 1; iCol <= m_pTable->CountColumnsOnTable(); iCol++)
|
|
{
|
|
// Get the information about the column
|
|
if (!CHECK(m_pTable->GetColInfo(iCol, TempCol), S_OK))
|
|
{
|
|
fResult = FALSE;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// If this is DBTYPE_DBTIMESTAMP it may be the right one
|
|
if (m_rgDBCOLUMNINFO[ulIndex].wType == TempCol.GetProviderType())
|
|
{
|
|
bPrecision = TempCol.GetPrecision();
|
|
bScale = TempCol.GetScale();
|
|
|
|
if (bPrecision == m_rgDBCOLUMNINFO[ulIndex].bPrecision &&
|
|
bScale == m_rgDBCOLUMNINFO[ulIndex].bScale)
|
|
{
|
|
// We found a matching value for precision and scale
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Precision is defined as length of string representation assuming max
|
|
// allowed precision of fractional seconds component.
|
|
// TODO: Compare against CCol.
|
|
if (m_rgDBCOLUMNINFO[ulIndex].bPrecision != bPrecision)
|
|
{
|
|
odtLog <<L"PRECISION [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex <<"]:expected valid precision."<<ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
|
|
// Scale is just the maximum length of the string representation of
|
|
// fractional seconds component.
|
|
if (m_rgDBCOLUMNINFO[ulIndex].bScale != bScale)
|
|
{
|
|
odtLog <<L"SCALE [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex <<"]:expected valid scale."<<ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Precision and scale are ~0
|
|
if (((BYTE)(~0) != m_rgDBCOLUMNINFO[ulIndex].bPrecision) || ((BYTE)(~0) != m_rgDBCOLUMNINFO[ulIndex].bScale))
|
|
{
|
|
odtLog <<L"PRECISION & SCALE [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex <<"]:non-numeric expect ~0."<<ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CLEANUP:
|
|
|
|
return fResult;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CheckRIID, QI for every mandatory interface on this object
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::CheckRIID(IUnknown * pColRowset, IID iid)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
ULONG cErrors = 0;
|
|
IUnknown* pInterface = NULL;
|
|
|
|
if(!pColRowset || iid == IID_NULL)
|
|
return FALSE;
|
|
|
|
// QI for IID_IRowset
|
|
if(FAILED(hr=pColRowset->QueryInterface(IID_IRowset,(void **) &pInterface)))
|
|
cErrors++;
|
|
|
|
SAFE_RELEASE(pInterface);
|
|
|
|
// QI for IID_IAccessor
|
|
if(FAILED(hr=pColRowset->QueryInterface(IID_IAccessor,(void **) &pInterface)))
|
|
cErrors++;
|
|
|
|
SAFE_RELEASE(pInterface);
|
|
|
|
// QI for IID_IColumnsInfo
|
|
if(FAILED(hr=pColRowset->QueryInterface(IID_IColumnsInfo,(void **) &pInterface)))
|
|
cErrors++;
|
|
|
|
SAFE_RELEASE(pInterface);
|
|
|
|
// QI for IID_IRowsetInfo
|
|
if(FAILED(hr=pColRowset->QueryInterface(IID_IRowsetInfo,(void **) &pInterface)))
|
|
cErrors++;
|
|
|
|
SAFE_RELEASE(pInterface);
|
|
|
|
// QI for IID_IConvertType
|
|
if(FAILED(hr=pColRowset->QueryInterface(IID_IConvertType,(void **) &pInterface)))
|
|
cErrors++;
|
|
|
|
SAFE_RELEASE(pInterface);
|
|
|
|
if(!cErrors)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// VerifyRowset, verify rowset and row order
|
|
//
|
|
// 1) Verify Maxlength, Precision, and Scale for non-applicable datatypes
|
|
// 2) Check ComputeMode
|
|
// 3) Order of rows is order of columns in query
|
|
//
|
|
// ----------------------------------------------
|
|
// 1. IColumnsInfo::GetColumnInfo, build binding (from GetAccessorAndBindings)
|
|
// 2. IAccessor::CreateAccessor (from GetAccessorAndBindings)
|
|
// Loop
|
|
// 3. IRowset::GetNextRows
|
|
// 4. IRowset::GetData
|
|
// 5. IRowset::ReleaseRows
|
|
// End Loop
|
|
//
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CSchemaTest::VerifyRowset(IUnknown * pIUnknown)
|
|
{
|
|
BOOL fVerifyRow = TRUE;
|
|
BOOL fFirstTimeThruLoop = TRUE;
|
|
HRESULT hr = E_FAIL;
|
|
BOOL fReleaseRowset = FALSE; // whether I should release pIRowset;
|
|
HACCESSOR hAccessor=DB_NULL_HACCESSOR; // handle to accessor
|
|
ULONG iBind = 0; // current binding
|
|
ULONG iRow = 0; // current row
|
|
DBLENGTH cbRowSize = 0; // size of row
|
|
DBCOUNTITEM cRowsObtained = 0; // total rows obtained from getnextrows
|
|
DBCOUNTITEM cTotalRows = 0; // total row count
|
|
BYTE * pRow = NULL; // row of Data
|
|
HROW * prghRows = NULL; // array of hrows
|
|
IAccessor * pIAccessor = NULL;
|
|
ULONG ulRowsToVerify;
|
|
BOOL fCapturingRestrictions = m_fCaptureRestrictions;
|
|
BOOL fContinue = TRUE;
|
|
|
|
m_fResult = FALSE;
|
|
m_fRes1=m_fRes2=m_fRes3=m_fRes4=m_fRes5=m_fRes6=m_fRes7=TRUE;
|
|
|
|
// if I don't have the rowset pointer, I need to go get FIRST
|
|
if (!pIUnknown)
|
|
{
|
|
if(m_iid == IID_IColumnsInfo)
|
|
pIUnknown = m_pIColumnsInfo;
|
|
else if(m_iid == IID_IAccessor)
|
|
pIUnknown = m_pIAccessor;
|
|
else if(m_iid == IID_IRowsetChange)
|
|
pIUnknown = m_pIRowsetChange;
|
|
else if(m_iid == IID_IRowsetInfo)
|
|
pIUnknown = m_pIRowsetInfo;
|
|
else if((m_iid == IID_IRowset) && (!m_pIRowset))
|
|
return FALSE;
|
|
}
|
|
|
|
if(pIUnknown && !m_pIRowset && FAILED(hr=pIUnknown->QueryInterface(IID_IRowset,(void **)&m_pIRowset)) )
|
|
return FALSE;
|
|
|
|
if (!VerifyInterface(m_pIRowset, IID_IAccessor, ROWSET_INTERFACE, (IUnknown**)&pIAccessor))
|
|
goto CLEANUP;
|
|
|
|
fReleaseRowset = TRUE;
|
|
|
|
// get bindings and column info
|
|
if(!CHECK(hr=GetAccessorAndBindings(
|
|
m_pIRowset, // @parmopt [IN] Rowset to create Accessor for
|
|
DBACCESSOR_ROWDATA, // @parmopt [IN] Properties of the Accessor
|
|
&hAccessor, // @parmopt [OUT] Accessor created
|
|
&m_rgDBBINDING, // @parmopt [OUT] Array of DBBINDINGS
|
|
&m_cDBBINDING, // @parmopt [OUT] Count of bindings
|
|
&cbRowSize, // @parmopt [OUT] Length of a row, DATA
|
|
DBPART_VALUE|DBPART_STATUS |DBPART_LENGTH,
|
|
ALL_COLS_BOUND, // @parmopt [IN] Which columns will be used in the bindings
|
|
FORWARD, // @parmopt [IN] Order to bind columns in accessor
|
|
NO_COLS_BY_REF, // @parmopt [IN] Which column types to bind by reference
|
|
&m_rgDBCOLUMNINFO, // @parmopt [OUT] Array of DBCOLUMNINFO
|
|
&m_cDBCOLUMNINFO, // @parmopt [OUT] Count of Columns, also count of ColInfo elements
|
|
&m_pStringsBuffer,
|
|
DBTYPE_EMPTY, // @parmopt [IN] Modifier to be OR'd with each binding type.
|
|
0, // @parmopt [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
|
|
NULL, // @parmopt [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
|
|
NULL, // @parmopt [IN] Corresponds to what ordinals are specified for each binding, if
|
|
NO_COLS_OWNED_BY_PROV, // @parmopt [IN] Which columns' memory is to be owned by the provider
|
|
DBPARAMIO_NOTPARAM, // @parmopt [IN] Parameter kind specified for all bindings
|
|
BLOB_LONG, // @parmopt [IN] how to bind BLOB Columns
|
|
NULL),S_OK)) // @parmopt [OUT] returned status array from CreateAccessor
|
|
goto CLEANUP;
|
|
|
|
// Don't need to check if only capturing restrictions
|
|
if(!m_fCaptureRestrictions)
|
|
fVerifyRow &= CheckAgainstIColumnsInfo();
|
|
|
|
// check if we need to go on
|
|
if((!m_cDBBINDING) || (!m_cDBCOLUMNINFO) || (!m_rgDBBINDING) || (!m_rgDBCOLUMNINFO))
|
|
goto CLEANUP;
|
|
|
|
if(m_fPassUnsupportedRestrictions)
|
|
{
|
|
m_fResult = TRUE;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// create space for row of data
|
|
pRow = (BYTE *) PROVIDER_ALLOC(cbRowSize);
|
|
if(!pRow)
|
|
goto CLEANUP;
|
|
|
|
if(GetModInfo()->GetDebugMode() & DEBUGMODE_FULL )
|
|
ulRowsToVerify = 90000;
|
|
else
|
|
// This should be larger than NUMROWS_CHUNK to force at least one additional
|
|
// GetNextRows call below.
|
|
ulRowsToVerify = 100;
|
|
|
|
// Process all the rows, NUMROWS_CHUNK rows at a time
|
|
while(fContinue)
|
|
{
|
|
// get rows to process
|
|
hr=GetNextRows(0,30,&cRowsObtained,&prghRows);
|
|
|
|
|
|
TEST4C_(hr, S_OK, DB_S_ENDOFROWSET, DB_S_STOPLIMITREACHED, DB_S_ROWLIMITEXCEEDED);
|
|
|
|
|
|
// verify that we have rows to process
|
|
if(cRowsObtained==0)
|
|
{
|
|
if (CHECK(hr, DB_S_ENDOFROWSET))
|
|
break;
|
|
else
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// Only verify required number of rows
|
|
if (cTotalRows < ulRowsToVerify)
|
|
{
|
|
// Make sure we don't call verify with no valid restrictions.
|
|
ASSERT((m_restrict != ALLRES) || (m_currentBitMask == 0));
|
|
|
|
// Loop over rows obtained, getting data for each
|
|
for(iRow=0;iRow<cRowsObtained && fContinue;iRow++)
|
|
{
|
|
cTotalRows++;
|
|
|
|
// get row
|
|
if(FAILED(hr=m_pIRowset->GetData(prghRows[iRow],hAccessor,pRow)))
|
|
goto CLEANUP;
|
|
|
|
// make sure we got the row
|
|
if(pRow==NULL)
|
|
goto CLEANUP;
|
|
|
|
// do something with row
|
|
fVerifyRow &= VerifyRow(m_guid,cTotalRows,pRow);
|
|
|
|
// If we know we've filled the restriction then break out of loop
|
|
// Otherwise we continue for all rows
|
|
if (fCapturingRestrictions && !m_fCaptureRestrictions)
|
|
{
|
|
m_fCaptureRestrictions = fCapturingRestrictions;
|
|
fContinue = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
cTotalRows += cRowsObtained;
|
|
|
|
if (!CHECK(hr=m_pIRowset->ReleaseRows(cRowsObtained,prghRows,NULL,NULL,NULL),S_OK))
|
|
goto CLEANUP;
|
|
|
|
fFirstTimeThruLoop = FALSE;
|
|
|
|
}
|
|
|
|
switch (m_eRowCount)
|
|
{
|
|
case MIN_VALUE:
|
|
// Warn if we didn't get any rows but expected some
|
|
if (m_ulRowCount && !cTotalRows)
|
|
odtLog << L"Warning - this rowset didn't return any rows so no values were checked.\n";
|
|
|
|
// Fail if we got some rows but less than minimum expected
|
|
if (cTotalRows)
|
|
TESTC(cTotalRows >= m_ulRowCount);
|
|
break;
|
|
case MIN_REQUIRED:
|
|
// Fail if we got less than minimum expected
|
|
TESTC(cTotalRows >= m_ulRowCount);
|
|
break;
|
|
case EXACT_VALUE:
|
|
// ASSERT(cTotalRows == m_ulRowCount);
|
|
TESTC(cTotalRows == m_ulRowCount);
|
|
break;
|
|
default:
|
|
ASSERT(!L"Unexpected row count value for schema rowset.");
|
|
}
|
|
|
|
// If we made it to here and verified each row then set success
|
|
if (fVerifyRow)
|
|
m_fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
// Clear any table name information that might be left over
|
|
SAFE_FREE(m_pwszTableName);
|
|
|
|
if (pIAccessor && hAccessor != DB_NULL_HACCESSOR)
|
|
CHECK(pIAccessor->ReleaseAccessor(hAccessor, NULL), S_OK);
|
|
|
|
SAFE_RELEASE(pIAccessor);
|
|
SAFE_RELEASE(m_pIRowset);
|
|
|
|
m_cDBCOLUMNINFO = 0;
|
|
m_cDBBINDING = 0;
|
|
|
|
// Free the memory
|
|
PROVIDER_FREE(m_rgDBCOLUMNINFO);
|
|
PROVIDER_FREE(m_pStringsBuffer);
|
|
PROVIDER_FREE(m_rgDBBINDING);
|
|
PROVIDER_FREE(pRow);
|
|
PROVIDER_FREE(prghRows);
|
|
|
|
return m_fResult;
|
|
}
|
|
|
|
ULONG CSchemaTest::SchemaCatalogRestriction(ULONG ulIndex)
|
|
{
|
|
GUID guidSchema = m_rgSchemas[ulIndex];
|
|
|
|
return SchemaCatalogRestriction(guidSchema);
|
|
}
|
|
|
|
ULONG CSchemaTest::SchemaCatalogRestriction(GUID guidSchema)
|
|
{
|
|
// If the GUID is one for which we know a catalog restriction exists then return FIRST.
|
|
// Catalog restriction is always the first one.
|
|
// This is most of them but we can't use negative logic 'cause we might get a guid we
|
|
// don't recognize.
|
|
if (guidSchema == DBSCHEMA_ASSERTIONS ||
|
|
guidSchema == DBSCHEMA_CATALOGS ||
|
|
guidSchema == DBSCHEMA_CHARACTER_SETS ||
|
|
guidSchema == DBSCHEMA_CHECK_CONSTRAINTS ||
|
|
guidSchema == DBSCHEMA_COLLATIONS ||
|
|
guidSchema == DBSCHEMA_COLUMN_DOMAIN_USAGE ||
|
|
guidSchema == DBSCHEMA_COLUMN_PRIVILEGES ||
|
|
guidSchema == DBSCHEMA_COLUMNS ||
|
|
guidSchema == DBSCHEMA_CONSTRAINT_COLUMN_USAGE ||
|
|
guidSchema == DBSCHEMA_CONSTRAINT_TABLE_USAGE ||
|
|
guidSchema == DBSCHEMA_FOREIGN_KEYS ||
|
|
guidSchema == DBSCHEMA_INDEXES ||
|
|
guidSchema == DBSCHEMA_KEY_COLUMN_USAGE ||
|
|
guidSchema == DBSCHEMA_PRIMARY_KEYS ||
|
|
guidSchema == DBSCHEMA_PROCEDURE_COLUMNS ||
|
|
guidSchema == DBSCHEMA_PROCEDURE_PARAMETERS ||
|
|
guidSchema == DBSCHEMA_PROCEDURES ||
|
|
guidSchema == DBSCHEMA_REFERENTIAL_CONSTRAINTS ||
|
|
guidSchema == DBSCHEMA_SCHEMATA ||
|
|
guidSchema == DBSCHEMA_STATISTICS ||
|
|
guidSchema == DBSCHEMA_TABLE_CONSTRAINTS ||
|
|
guidSchema == DBSCHEMA_TABLE_PRIVILEGES ||
|
|
guidSchema == DBSCHEMA_TABLE_STATISTICS ||
|
|
guidSchema == DBSCHEMA_TABLES ||
|
|
guidSchema == DBSCHEMA_TABLES_INFO ||
|
|
guidSchema == DBSCHEMA_TRANSLATIONS ||
|
|
guidSchema == DBSCHEMA_USAGE_PRIVILEGES ||
|
|
guidSchema == DBSCHEMA_VIEW_COLUMN_USAGE ||
|
|
guidSchema == DBSCHEMA_VIEW_TABLE_USAGE ||
|
|
guidSchema == DBSCHEMA_VIEWS)
|
|
return FIRST;
|
|
|
|
// else return ZERO restrictions
|
|
return ZERO;
|
|
}
|
|
|
|
ULONG CSchemaTest::SchemaSchemaRestriction(ULONG ulIndex)
|
|
{
|
|
GUID guidSchema = m_rgSchemas[ulIndex];
|
|
|
|
return SchemaSchemaRestriction(guidSchema);
|
|
}
|
|
|
|
ULONG CSchemaTest::SchemaSchemaRestriction(GUID guidSchema)
|
|
{
|
|
// If the GUID is one for which we know a catalog restriction exists then return FIRST.
|
|
// Catalog restriction is always the first one.
|
|
// This is most of them but we can't use negative logic 'cause we might get a guid we
|
|
// don't recognize.
|
|
if (guidSchema == DBSCHEMA_ASSERTIONS ||
|
|
guidSchema == DBSCHEMA_CHARACTER_SETS ||
|
|
guidSchema == DBSCHEMA_CHECK_CONSTRAINTS ||
|
|
guidSchema == DBSCHEMA_COLLATIONS ||
|
|
guidSchema == DBSCHEMA_COLUMN_DOMAIN_USAGE ||
|
|
guidSchema == DBSCHEMA_COLUMN_PRIVILEGES ||
|
|
guidSchema == DBSCHEMA_COLUMNS ||
|
|
guidSchema == DBSCHEMA_CONSTRAINT_COLUMN_USAGE ||
|
|
guidSchema == DBSCHEMA_CONSTRAINT_TABLE_USAGE ||
|
|
guidSchema == DBSCHEMA_FOREIGN_KEYS ||
|
|
guidSchema == DBSCHEMA_INDEXES ||
|
|
guidSchema == DBSCHEMA_KEY_COLUMN_USAGE ||
|
|
guidSchema == DBSCHEMA_PRIMARY_KEYS ||
|
|
guidSchema == DBSCHEMA_PROCEDURE_COLUMNS ||
|
|
guidSchema == DBSCHEMA_PROCEDURE_PARAMETERS ||
|
|
guidSchema == DBSCHEMA_PROCEDURES ||
|
|
guidSchema == DBSCHEMA_REFERENTIAL_CONSTRAINTS ||
|
|
guidSchema == DBSCHEMA_SCHEMATA ||
|
|
guidSchema == DBSCHEMA_STATISTICS ||
|
|
guidSchema == DBSCHEMA_TABLE_CONSTRAINTS ||
|
|
guidSchema == DBSCHEMA_TABLE_PRIVILEGES ||
|
|
guidSchema == DBSCHEMA_TABLE_STATISTICS ||
|
|
guidSchema == DBSCHEMA_TABLES ||
|
|
guidSchema == DBSCHEMA_TABLES_INFO ||
|
|
guidSchema == DBSCHEMA_TRANSLATIONS ||
|
|
guidSchema == DBSCHEMA_USAGE_PRIVILEGES ||
|
|
guidSchema == DBSCHEMA_VIEW_COLUMN_USAGE ||
|
|
guidSchema == DBSCHEMA_VIEW_TABLE_USAGE ||
|
|
guidSchema == DBSCHEMA_VIEWS)
|
|
return SECOND;
|
|
|
|
// else return ZERO restrictions
|
|
return ZERO;
|
|
}
|
|
|
|
ULONG CSchemaTest::SchemaTableRestriction(ULONG ulIndex)
|
|
{
|
|
GUID guidSchema = m_rgSchemas[ulIndex];
|
|
|
|
return SchemaTableRestriction(guidSchema);
|
|
}
|
|
|
|
ULONG CSchemaTest::SchemaTableRestriction(GUID guidSchema)
|
|
{
|
|
// This is most of them but we can't use negative logic 'cause we might get a guid we
|
|
// don't recognize.
|
|
if (guidSchema == DBSCHEMA_COLUMN_PRIVILEGES ||
|
|
guidSchema == DBSCHEMA_COLUMNS ||
|
|
guidSchema == DBSCHEMA_CHECK_CONSTRAINTS_BY_TABLE ||
|
|
guidSchema == DBSCHEMA_CONSTRAINT_COLUMN_USAGE ||
|
|
guidSchema == DBSCHEMA_CONSTRAINT_TABLE_USAGE ||
|
|
guidSchema == DBSCHEMA_FOREIGN_KEYS || // This is really PK_TABLE_NAME, but it will suffice
|
|
guidSchema == DBSCHEMA_INDEXES || // This is really INDEX_NAME, but we always use table name
|
|
guidSchema == DBSCHEMA_PRIMARY_KEYS ||
|
|
guidSchema == DBSCHEMA_STATISTICS ||
|
|
guidSchema == DBSCHEMA_TABLE_PRIVILEGES ||
|
|
guidSchema == DBSCHEMA_TABLE_STATISTICS ||
|
|
guidSchema == DBSCHEMA_TABLES ||
|
|
guidSchema == DBSCHEMA_TABLES_INFO ||
|
|
guidSchema == DBSCHEMA_VIEWS)
|
|
return THIRD;
|
|
else if (guidSchema == DBSCHEMA_KEY_COLUMN_USAGE ||
|
|
guidSchema == DBSCHEMA_TABLE_CONSTRAINTS)
|
|
return SIXTH;
|
|
|
|
// else return ZERO restrictions
|
|
return ZERO;
|
|
}
|
|
|
|
void CSchemaTest::LimitRestrictions(ULONG ulIndex)
|
|
{
|
|
|
|
// Don't pass restrictions for most schemas, but for those that have a catalog, schema,
|
|
// or table name limit to current catalog, schema, table. This is done to keep the test
|
|
// run time shorter. It took several hours on some providers without these restrictions.
|
|
// Without a catalog restriction ALL catalogs (databases) should be returned.
|
|
SetRestriction(SchemaCatalogRestriction(ulIndex));
|
|
SetRestriction(SchemaSchemaRestriction(ulIndex));
|
|
SetRestriction(SchemaTableRestriction(ulIndex));
|
|
}
|
|
|
|
// GetValuePtr
|
|
// Assumptions: All columns are bound
|
|
LPBYTE CSchemaTest::GetValuePtr(DBORDINAL iOrdinal, LPBYTE pData, DBBINDING * pBinding)
|
|
{
|
|
LPBYTE pValue = NULL;
|
|
DBORDINAL iBind = 0;
|
|
|
|
// If no binding structure passed in assume user wants m_rgDBBINDING
|
|
if (!pBinding)
|
|
pBinding = m_rgDBBINDING;
|
|
|
|
if (pBinding)
|
|
{
|
|
iBind = iOrdinal - !pBinding[0].iOrdinal - 1;
|
|
|
|
if (STATUS_BINDING(pBinding[iBind], pData) == DBSTATUS_S_OK)
|
|
{
|
|
pValue = (LPBYTE)&VALUE_BINDING(pBinding[iBind], pData);
|
|
}
|
|
}
|
|
|
|
return pValue;
|
|
}
|
|
|
|
// Compare histogram rowset columns info
|
|
BOOL CSchemaTest::CheckHistogramColInfo(IRowset * pIHistogramRowset, DBTYPE wRangeColType,
|
|
DBORDINAL * pcBinding, DBBINDING ** ppBinding, DBLENGTH * pcbRowSize, HACCESSOR * phAccessor)
|
|
{
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBLENGTH cbRowSize = 0;
|
|
BOOL fColInfo = FALSE;
|
|
DBORDINAL cActualCols = 0; // Count of columns returned in histogram rowset
|
|
|
|
// Save off member vars so we can call CheckAgainstIColumnsInfo()
|
|
DBBINDING * pBinding = m_rgDBBINDING;
|
|
DBCOUNTITEM cBinding = m_cDBBINDING;
|
|
DBCOLUMNINFO * pColInfo = m_rgDBCOLUMNINFO;
|
|
DBORDINAL cColInfo = m_cDBCOLUMNINFO;
|
|
LPWSTR pStringsBuf = m_pStringsBuffer;
|
|
LPWSTR * ppColNames = m_rgColumnNames;
|
|
DBTYPE * pColTypes = m_rgColumnTypes;
|
|
ULONG cCols = m_cColumns;
|
|
|
|
m_cDBCOLUMNINFO = 0;
|
|
m_rgDBCOLUMNINFO = NULL;
|
|
m_pStringsBuffer = NULL;
|
|
|
|
// Set up pointers to column name and type information
|
|
m_rgColumnNames = (WCHAR **)rgwszHistogramCols;
|
|
m_rgColumnTypes = (DBTYPE *)rgtypeHistogramCols;
|
|
|
|
// Set the count of columns and restrictions
|
|
m_cColumns = cHistogramCols;
|
|
|
|
// Update expected type for RANGE_HI_KEY
|
|
m_rgColumnTypes[0] = wRangeColType;
|
|
|
|
// get bindings and column info
|
|
if(!CHECK(GetAccessorAndBindings(
|
|
pIHistogramRowset, // @parmopt [IN] Rowset to create Accessor for
|
|
DBACCESSOR_ROWDATA, // @parmopt [IN] Properties of the Accessor
|
|
&hAccessor, // @parmopt [OUT] Accessor created
|
|
&m_rgDBBINDING, // @parmopt [OUT] Array of DBBINDINGS
|
|
&m_cDBBINDING, // @parmopt [OUT] Count of bindings
|
|
&cbRowSize, // @parmopt [OUT] Length of a row, DATA
|
|
DBPART_VALUE|DBPART_STATUS |DBPART_LENGTH,
|
|
ALL_COLS_BOUND, // @parmopt [IN] Which columns will be used in the bindings
|
|
FORWARD, // @parmopt [IN] Order to bind columns in accessor
|
|
NO_COLS_BY_REF, // @parmopt [IN] Which column types to bind by reference
|
|
&m_rgDBCOLUMNINFO, // @parmopt [OUT] Array of DBCOLUMNINFO
|
|
&m_cDBCOLUMNINFO, // @parmopt [OUT] Count of Columns, also count of ColInfo elements
|
|
&m_pStringsBuffer,
|
|
DBTYPE_EMPTY, // @parmopt [IN] Modifier to be OR'd with each binding type.
|
|
0, // @parmopt [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
|
|
NULL, // @parmopt [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
|
|
NULL, // @parmopt [IN] Corresponds to what ordinals are specified for each binding, if
|
|
NO_COLS_OWNED_BY_PROV, // @parmopt [IN] Which columns' memory is to be owned by the provider
|
|
DBPARAMIO_NOTPARAM, // @parmopt [IN] Parameter kind specified for all bindings
|
|
BLOB_LONG, // @parmopt [IN] how to bind BLOB Columns
|
|
NULL),S_OK)) // @parmopt [OUT] returned status array from CreateAccessor
|
|
goto CLEANUP;
|
|
|
|
fColInfo = CheckAgainstIColumnsInfo();
|
|
|
|
// CheckAgainstIColumnsInfo doesn't test for any extra columns, so warn here
|
|
// if there are extras
|
|
cActualCols = m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal;
|
|
|
|
// Check for extra columns in histogram rowset. This is only a warning
|
|
// since it's allowed to return extra columns. Cache the warning so we don't
|
|
// get it for every histogram over and over.
|
|
CCOMPARE(m_EC, cHistogramCols == cActualCols, EC_EXTRA_COLUMN,
|
|
L"Extra column in Histogram rowset.", TRUE);
|
|
|
|
CLEANUP:
|
|
|
|
// Populate output params
|
|
if (pcBinding)
|
|
*pcBinding = m_cDBCOLUMNINFO;
|
|
if (ppBinding)
|
|
*ppBinding = m_rgDBBINDING;
|
|
else
|
|
SAFE_FREE(m_rgDBBINDING);
|
|
if (pcbRowSize)
|
|
*pcbRowSize = cbRowSize;
|
|
if (phAccessor)
|
|
*phAccessor = hAccessor;
|
|
|
|
SAFE_FREE(m_rgDBCOLUMNINFO);
|
|
SAFE_FREE(m_pStringsBuffer);
|
|
|
|
// Restore member vars to avoid side effects
|
|
m_rgDBBINDING = pBinding;
|
|
m_cDBBINDING = cBinding;
|
|
m_rgDBCOLUMNINFO= pColInfo;
|
|
m_cDBCOLUMNINFO = cColInfo;
|
|
m_pStringsBuffer= pStringsBuf;
|
|
m_rgColumnNames = ppColNames;
|
|
m_rgColumnTypes = pColTypes;
|
|
m_cColumns = cCols;
|
|
|
|
return fColInfo;
|
|
}
|
|
|
|
DBCOUNTITEM CSchemaTest::Cardinality(LPWSTR pwszTableName, ULONG ulColIndex, CARDINALITY eCardinality,
|
|
DBBINDING * pStartBind, DBBINDING * pEndBind, LPBYTE pDataRows, DBLENGTH cbRowSize)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndexFirst = 0;
|
|
size_t cChars = 0;
|
|
LPWSTR pwszColList = NULL;
|
|
LPWSTR pwszSelectFmt = (LPWSTR)wszSELECT_DISTINCTCOLLIST;
|
|
LPWSTR pwszSelect = NULL;
|
|
LPWSTR pwszGreaterFmt = L"%s > ?";
|
|
LPWSTR pwszLessThanEqFmt = L"%s <= ?";
|
|
LPWSTR pwszEqFmt = L"%s = ?";
|
|
LPWSTR pwszRange = NULL;
|
|
DBCOUNTITEM ulCardinality = 0;
|
|
IRowset * pIRowset = NULL;
|
|
IAccessor * pIAccessor = NULL;
|
|
ICommand * pICommand = NULL;
|
|
IAccessor * pICmdAccessor = NULL;
|
|
DBBINDING dbCountBind;
|
|
DBBINDING dbParamBind[2]; // Only two params required for all cases
|
|
ULONG cParams = 0;
|
|
HACCESSOR hAcc = DB_NULL_HACCESSOR;
|
|
HACCESSOR hParamAcc = DB_NULL_HACCESSOR;
|
|
HROW * phRows = NULL;
|
|
ULONG * pulCardinality = NULL;
|
|
DBORDINAL iCol;
|
|
DBCOUNTITEM cRowsObtained;
|
|
DBPARAMS dbParams;
|
|
DBBINDSTATUS rgStatus[2];
|
|
|
|
// Previously used the count aggregate function, but that was bad because:
|
|
// 1) Doesn't include NULL rows
|
|
// 2) Fails against GUID column on some providers.
|
|
// select count(*) from (select distinct col1,col2 from <table> where col1 > ? and
|
|
// col1 <= ?) t1
|
|
|
|
// Now we use just the select distinct, but this still will fail for BLOB columns,
|
|
// so we have to avoid calling this function for BLOBS.
|
|
// TODO: If this function is made more sophisticated we can actually call for BLOBS.
|
|
// Possible improvements 1) Use conversion function, 2) actually retrieve data
|
|
// ourselves and count distinct values.
|
|
// select distinct col1,col2 from <table> where col1 > ? and col1 <= ?
|
|
|
|
// Initialize binding structures
|
|
memset(&dbCountBind, 0, sizeof(DBBINDING));
|
|
memset(&dbParamBind, 0, sizeof(DBBINDING)*2);
|
|
|
|
// Initialize dbParams
|
|
memset(&dbParams, 0, sizeof(DBPARAMS));
|
|
|
|
// Note we use params for this to avoid having to convert range limits to strings and
|
|
// obtain the appropriate literal prefix and suffix. I am assuming that any provider
|
|
// that has gone to the trouble to provide extensive support for query processors has
|
|
// also supported parameters.
|
|
|
|
switch (eCardinality)
|
|
{
|
|
// Both range rows and eq rows are non-distinct, and all the cardinalities
|
|
// for histogram are for only one column. But they all need a 'where' clause
|
|
case EQ_ROWS_CARDINALITY:
|
|
// We don't have a range for this cardinality, we're only looking for
|
|
// values equal to RANGE_HIGH_KEY
|
|
ASSERT(!pStartBind);
|
|
// Fall through
|
|
case RANGE_ROWS_CARDINALITY:
|
|
// Both of these counts are non-distinct, so change our select
|
|
// clause to not return distinct counts.
|
|
pwszSelectFmt = (LPWSTR)wszSELECT_COLLISTFROMTBL;
|
|
// Fall through
|
|
case DISTINCT_RANGE_ROWS_CARDINALITY:
|
|
{
|
|
size_t cchWhere = wcslen(wszWHERE); // Length of " where "
|
|
size_t cchColName = wcslen(m_prgColInfo[ulColIndex].pwszName);
|
|
LPWSTR pwszFmt = pwszLessThanEqFmt;
|
|
|
|
if (eCardinality == EQ_ROWS_CARDINALITY)
|
|
pwszFmt = pwszEqFmt;
|
|
|
|
// Fill out param info
|
|
if (pStartBind)
|
|
{
|
|
cchWhere += wcslen(pwszGreaterFmt) -2 + cchColName + wcslen(wszAND);
|
|
|
|
// Set parameter binding info
|
|
memcpy(&dbParamBind[cParams], pStartBind, sizeof(DBBINDING));
|
|
dbParamBind[cParams].eParamIO = DBPARAMIO_INPUT;
|
|
dbParamBind[cParams].iOrdinal = cParams+1;
|
|
|
|
cParams++;
|
|
}
|
|
if (pEndBind)
|
|
{
|
|
cchWhere += wcslen(pwszFmt) -2 + cchColName;
|
|
|
|
// Set parameter binding info
|
|
memcpy(&dbParamBind[cParams], pEndBind, sizeof(DBBINDING));
|
|
dbParamBind[cParams].eParamIO = DBPARAMIO_INPUT;
|
|
dbParamBind[cParams].iOrdinal = cParams+1;
|
|
|
|
cParams++;
|
|
}
|
|
|
|
// Now we know all the pieces for the range clause, allocate memory and create
|
|
SAFE_ALLOC(pwszRange, WCHAR, cchWhere+1);
|
|
|
|
wcscpy(pwszRange, wszWHERE);
|
|
|
|
// Put in the starting range clause
|
|
if (pStartBind)
|
|
{
|
|
swprintf(pwszRange+wcslen(pwszRange), pwszGreaterFmt, m_prgColInfo[ulColIndex].pwszName);
|
|
wcscat(pwszRange, wszAND);
|
|
}
|
|
|
|
// Put in ending range clause (always needed)
|
|
swprintf(pwszRange+wcslen(pwszRange), pwszFmt, m_prgColInfo[ulColIndex].pwszName);
|
|
|
|
}
|
|
// Fall through
|
|
case COLUMN_CARDINALITY:
|
|
ulIndexFirst = ulColIndex;
|
|
// Fall through
|
|
case TUPLE_CARDINALITY:
|
|
// Compute memory for column list (column name plus comma)
|
|
for (iCol = 0; iCol < ulColIndex-ulIndexFirst+1; iCol++)
|
|
cChars+=wcslen(m_prgColInfo[iCol+ulIndexFirst].pwszName)+1;
|
|
|
|
// Allocate memory for col list
|
|
SAFE_ALLOC(pwszColList, WCHAR, cChars+1);
|
|
|
|
// Fill col list
|
|
// Note we leave out BLOB cols because providers can't do a
|
|
// select distinct on a BLOB, which may have some impact on
|
|
// the cardinality results.
|
|
pwszColList[0] = L'\0';
|
|
for (iCol = 0; iCol < ulColIndex-ulIndexFirst+1; iCol++)
|
|
{
|
|
if (m_prgColInfo[iCol+ulIndexFirst].dwFlags & DBCOLUMNFLAGS_ISLONG)
|
|
continue;
|
|
|
|
// Put in comma separator if needed
|
|
if (pwszColList[0])
|
|
wcscat(pwszColList, L",");
|
|
wcscat(pwszColList, m_prgColInfo[iCol+ulIndexFirst].pwszName);
|
|
}
|
|
|
|
// Compute memory required for select distinct statement
|
|
// Length of select, 2 parenthesis, table name, table alias name
|
|
cChars+=wcslen(pwszSelectFmt)+wcslen(pwszTableName);
|
|
|
|
// Add space for 'where' clause if needed
|
|
if (pwszRange)
|
|
cChars+=wcslen(pwszRange);
|
|
|
|
// Allocate mem for select
|
|
SAFE_ALLOC(pwszSelect, WCHAR, cChars+1);
|
|
|
|
// select distinct col1,col2 from <table>
|
|
swprintf(pwszSelect, pwszSelectFmt, pwszColList, pwszTableName);
|
|
|
|
// Tack on where clause if needed
|
|
if (pwszRange)
|
|
wcscat(pwszSelect, pwszRange);
|
|
|
|
// Free the range clause
|
|
SAFE_FREE(pwszRange);
|
|
|
|
break;
|
|
case TABLE_CARDINALITY:
|
|
pwszSelectFmt = (LPWSTR)wszSELECT_ALLFROMTBL;
|
|
|
|
cChars+=wcslen(pwszSelectFmt)+wcslen(pwszTableName);
|
|
|
|
// Allocate mem for select
|
|
SAFE_ALLOC(pwszSelect, WCHAR, cChars+1);
|
|
|
|
// Create select stmt
|
|
swprintf(pwszSelect, pwszSelectFmt, pwszTableName);
|
|
|
|
break;
|
|
}
|
|
|
|
// Execute the command
|
|
if (cParams)
|
|
{
|
|
|
|
// Get the command object for the table object
|
|
pICommand = m_pTable->get_ICommandPTR();
|
|
|
|
// Addref the command object so we can release later.
|
|
pICommand->AddRef();
|
|
|
|
// Get accessor interface
|
|
TESTC(VerifyInterface(pICommand, IID_IAccessor, COMMAND_INTERFACE, (IUnknown **)&pICmdAccessor));
|
|
|
|
// Create the parameter accessor
|
|
TESTC_(pICmdAccessor->CreateAccessor(DBACCESSOR_PARAMETERDATA, cParams,
|
|
dbParamBind, cbRowSize, &hParamAcc, rgStatus), S_OK);
|
|
|
|
// Fill DBPARAMS info
|
|
dbParams.pData = pDataRows;
|
|
dbParams.cParamSets = 1;
|
|
dbParams.hAccessor = hParamAcc;
|
|
|
|
}
|
|
|
|
if (!CHECK(m_pTable->BuildCommand(pwszSelect, IID_IRowset,
|
|
EXECUTE_IFNOERROR, 0, NULL, &dbParams, NULL, (IUnknown **)&pIRowset, &pICommand), S_OK))
|
|
goto CLEANUP;
|
|
|
|
// Get accessor and bindings
|
|
dbCountBind.obStatus = offsetof(DATA, sStatus);
|
|
dbCountBind.obLength = offsetof(DATA, ulLength);
|
|
dbCountBind.obValue = offsetof(DATA, bValue);
|
|
dbCountBind.wType = DBTYPE_UI4;
|
|
dbCountBind.iOrdinal = 1;
|
|
dbCountBind.dwPart = DBPART_VALUE | DBPART_LENGTH | DBPART_STATUS;
|
|
|
|
TESTC(VerifyInterface(pIRowset, IID_IAccessor, ROWSET_INTERFACE, (IUnknown **)&pIAccessor));
|
|
TESTC_(pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, 1, &dbCountBind, 0, &hAcc, NULL), S_OK);
|
|
|
|
// Count the rows
|
|
while(hr != DB_S_ENDOFROWSET)
|
|
{
|
|
TEST2C_(hr = pIRowset->GetNextRows(NULL, 0, 10000, &cRowsObtained, &phRows), S_OK, DB_S_ENDOFROWSET);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
TESTC(cRowsObtained);
|
|
}
|
|
|
|
ulCardinality+=cRowsObtained;
|
|
|
|
if (cRowsObtained)
|
|
{
|
|
CHECK(pIRowset->ReleaseRows(cRowsObtained, phRows, NULL, NULL, NULL), S_OK);
|
|
*phRows = DB_NULL_HROW;
|
|
}
|
|
}
|
|
|
|
CLEANUP:
|
|
|
|
// Release rows
|
|
if (pIRowset && phRows && *phRows != DB_NULL_HROW)
|
|
CHECK(pIRowset->ReleaseRows(cRowsObtained, phRows, NULL, NULL, NULL), S_OK);
|
|
|
|
// Release parameter accessor
|
|
if (pICmdAccessor && hParamAcc != DB_NULL_HACCESSOR)
|
|
CHECK(pICmdAccessor->ReleaseAccessor(hParamAcc, NULL), S_OK);
|
|
|
|
SAFE_FREE(phRows);
|
|
SAFE_FREE(pwszColList);
|
|
SAFE_FREE(pwszSelect);
|
|
SAFE_RELEASE(pICommand);
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIAccessor);
|
|
SAFE_RELEASE(pICmdAccessor);
|
|
|
|
return ulCardinality;
|
|
|
|
}
|
|
|
|
void CSchemaTest::SetRowCount(ROW_COUNT eRowCount, DBORDINAL ulRowCount)
|
|
{
|
|
m_eRowCount = eRowCount;
|
|
m_ulRowCount = ulRowCount;
|
|
}
|
|
|
|
HRESULT CSchemaTest::GetNextRows(DBROWOFFSET lOffset, DBROWCOUNT cRows, DBCOUNTITEM* pcRowsObtained, HROW** prghRows)
|
|
{
|
|
ASSERT(prghRows);
|
|
TBEGIN
|
|
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DBCOUNTITEM i=0;
|
|
|
|
//Record if we passed in consumer allocated array...
|
|
HROW* rghRowsInput = *prghRows;
|
|
|
|
//GetNextRows
|
|
HRESULT hr = m_pIRowset->GetNextRows(NULL, lOffset, cRows, &cRowsObtained, prghRows);
|
|
|
|
//Verify Correct values returned
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(hr == S_OK)
|
|
{
|
|
TESTC(cRowsObtained==(DBCOUNTITEM)ABS(cRows));
|
|
}
|
|
else
|
|
{
|
|
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 == 0);
|
|
}
|
|
|
|
//Verify output array, depending upon consumer or provider allocated...
|
|
if(rghRowsInput)
|
|
{
|
|
//This is a users 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);
|
|
}
|
|
|
|
CLEANUP:
|
|
if(pcRowsObtained)
|
|
*pcRowsObtained = cRowsObtained;
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CSchemaTest::GetColumnInfo(LPBYTE pData, DBBINDING * pBinding)
|
|
{
|
|
IOpenRowset * pIOpenRowset = NULL;
|
|
IColumnsInfo * pIColumnsInfo = NULL;
|
|
DBID dbid = DB_NULLID;
|
|
HRESULT hr = E_FAIL;
|
|
ULONG iBind = 0, iFirst = 0;
|
|
LPWSTR pwszCat = NULL;
|
|
LPWSTR pwszSch = NULL;
|
|
LPWSTR pwszTable = NULL;
|
|
LPWSTR pwszQualifiedName = NULL;
|
|
|
|
// pData buffer contains bindings to TABLE_CATALOG, TABLE_SCHEMA, and TABLE_NAME, in that
|
|
// order.
|
|
|
|
// Skip any bookmark
|
|
if (!pBinding[iBind].iOrdinal)
|
|
iFirst++;
|
|
|
|
for (iBind = 0; iBind < 3; iBind++)
|
|
{
|
|
// If value isn't bound then we assume NULL
|
|
if (!VALUE_IS_BOUND(pBinding[iBind+iFirst]))
|
|
continue;
|
|
|
|
// Get a pointer to catalog, schema, and table name
|
|
if (STATUS_IS_BOUND(pBinding[iBind+iFirst]))
|
|
{
|
|
// Check the status, which should always be OK or NULL
|
|
if (STATUS_BINDING(pBinding[iBind+iFirst], pData) != DBSTATUS_S_OK)
|
|
{
|
|
COMPARE(STATUS_BINDING(pBinding[iBind+iFirst], pData), DBSTATUS_S_ISNULL);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// If status wasn't bound we assume OK, and length doesn't matter for null terminated string
|
|
switch(pBinding[iBind+iFirst].iOrdinal)
|
|
{
|
|
case 1:
|
|
pwszCat = (LPWSTR)&VALUE_BINDING(pBinding[iBind+iFirst], pData);
|
|
break;
|
|
case 2:
|
|
pwszSch = (LPWSTR)&VALUE_BINDING(pBinding[iBind+iFirst], pData);
|
|
break;
|
|
case 3:
|
|
pwszTable = (LPWSTR)&VALUE_BINDING(pBinding[iBind+iFirst], pData);
|
|
break;
|
|
default:
|
|
COMPARE(pBinding[iBind+iFirst].iOrdinal < 4, TRUE);
|
|
COMPARE(pBinding[iBind+iFirst].iOrdinal > 0, TRUE);
|
|
}
|
|
}
|
|
|
|
// HACK FOR ORACLE
|
|
if (pwszSch && wcslen(pwszSch) == 0)
|
|
pwszSch = NULL;
|
|
|
|
// Now we have either NULL or valid pointers to catalog, schema, table names
|
|
TESTC_(m_pTable->GetQualifiedName(pwszCat, pwszSch,
|
|
pwszTable,&pwszQualifiedName, TRUE), S_OK);
|
|
|
|
// If we already have information for this table then just don't bother
|
|
if (m_pwszTableName && !wcscmp(pwszQualifiedName, m_pwszTableName))
|
|
{
|
|
m_ulTableOrdinal++;
|
|
|
|
// If we couldn't actually retrieve the colinfo for this table then
|
|
// return S_FALSE
|
|
if (!m_prgColInfo)
|
|
return S_FALSE;
|
|
// Otherwise return success
|
|
else
|
|
return S_OK;
|
|
}
|
|
|
|
// Copy the table name into member var
|
|
SAFE_FREE(m_pwszTableName);
|
|
m_pwszTableName = pwszQualifiedName;
|
|
|
|
// Initialize out params
|
|
m_ulTableOrdinal = 1; // Note that schema rowset never reports bookmarks
|
|
SAFE_FREE(m_prgColInfo);
|
|
SAFE_FREE(m_pwszStringsBuffer);
|
|
|
|
// Get IOpenRowset interface
|
|
TESTC(VerifyInterface(m_pThisTestModule->m_pIUnknown2, IID_IOpenRowset, SESSION_INTERFACE, (IUnknown**)&pIOpenRowset));
|
|
|
|
// Create DBID from table name
|
|
dbid.eKind = DBKIND_NAME;
|
|
dbid.uName.pwszName = m_pwszTableName;
|
|
|
|
// Call OpenRowset
|
|
hr = pIOpenRowset->OpenRowset(NULL, &dbid, NULL, IID_IColumnsInfo,
|
|
0, NULL, (IUnknown **)&pIColumnsInfo);
|
|
|
|
if (FAILED(hr))
|
|
odtLog << m_pwszTableName << L": Unable to open table.\n";
|
|
|
|
// It's possible the table was deleted between the time we called GetRowset and attempting
|
|
// to open the table, so we have to allow DB_E_NOTABLE, but post a warning.
|
|
switch(hr)
|
|
{
|
|
case DB_E_NOTABLE:
|
|
case DB_SEC_E_PERMISSIONDENIED:
|
|
TESTW_(hr, S_OK);
|
|
goto CLEANUP;
|
|
default:
|
|
TESTC_(hr, S_OK);
|
|
}
|
|
|
|
// Make sure we've got a valid interface ptr
|
|
TESTC(pIColumnsInfo != NULL);
|
|
|
|
// Now call GetColumnInfo. We already know cColumns so no need to return in member
|
|
// var.
|
|
TESTC_(hr = pIColumnsInfo->GetColumnInfo(&m_cColInfo, &m_prgColInfo, &m_pwszStringsBuffer), S_OK);
|
|
|
|
CLEANUP:
|
|
|
|
SAFE_RELEASE(pIOpenRowset);
|
|
SAFE_RELEASE(pIColumnsInfo);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Module Values
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// {{ TCW_MODULE_GLOBALS
|
|
DECLARE_MODULE_CLSID = { 0x4ace5741, 0x13bb, 0x11cf, { 0x89, 0x0f, 0x00, 0xaa, 0x00, 0xb5, 0xa9, 0x1b }};
|
|
DECLARE_MODULE_NAME("IDBSchemaRowset");
|
|
DECLARE_MODULE_OWNER("Microsoft");
|
|
DECLARE_MODULE_DESCRIP("test module for IDBSchemaRowset");
|
|
DECLARE_MODULE_VERSION(795921705);
|
|
// TCW_WizardVersion(2)
|
|
// TCW_Automation(True)
|
|
// }} TCW_MODULE_GLOBALS_END
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// @func Initialises up indexes, Primary and Foreign keys on the primary table.
|
|
// Should call TerminateKeysOnTable() upon failure of InitKeysOnTable or completion of test.
|
|
//
|
|
// Global values set. g_fPrimaryKey (TRUE if Primary key is available on the table).
|
|
// g_fForeignKey (TRUE if Foreign key is available on the table).
|
|
// g_fIndexes (TRUE if indexes are available on the table.)
|
|
// g_pExtraTable Creates it.
|
|
//
|
|
BOOL CSchemaTest::InitKeysOnTable()
|
|
{
|
|
CCol TempCol1, TempCol2;
|
|
LONG lrand1 =0;
|
|
LONG lrand2 =0;
|
|
LONG lrand3 =0;
|
|
ULONG i;
|
|
BOOL fSuccess = FALSE;
|
|
ICommand * pICmd = NULL;
|
|
IDBCreateCommand * pIDBCrtCmd = (IDBCreateCommand *)m_pThisTestModule->m_pIUnknown2;
|
|
|
|
// Create the second table.
|
|
g_pKeyTable1 = new CTable(pIDBCrtCmd, (LPWSTR)gwszModuleName, NONULLS);
|
|
|
|
if (!g_pKeyTable1)
|
|
{
|
|
odtLog << wszMemoryAllocationError;
|
|
return FALSE;
|
|
}
|
|
|
|
g_pKeyTable2 = new CTable(pIDBCrtCmd, (LPWSTR)gwszModuleName, NONULLS);
|
|
|
|
if (!g_pKeyTable2)
|
|
{
|
|
odtLog << wszMemoryAllocationError;
|
|
// g_pKeyTable1 will be cleaned up in TerminateKeysOnTable();
|
|
return FALSE;
|
|
}
|
|
|
|
if (FAILED(g_pKeyTable2->CreateTable(0)))
|
|
goto CLEANUP;
|
|
|
|
if (FAILED(g_pKeyTable1->CreateTable(0)))
|
|
goto CLEANUP;
|
|
|
|
// Now alter the tables to create Primary keys and foreign keys.
|
|
for (i = 1; i <= g_pKeyTable1->CountColumnsOnTable(); i++)
|
|
{
|
|
if (FAILED(g_pKeyTable1->GetColInfo(i, TempCol1)))
|
|
goto CLEANUP;
|
|
|
|
// if it is not a long column and is fixed length We found our candidate for Primary and Foreign Key.
|
|
if (!TempCol1.GetIsLong() &&
|
|
!TempCol1.GetNullable()) // Primary keys typically can't be nullable columns
|
|
{
|
|
fSuccess = TRUE;
|
|
break;
|
|
}
|
|
|
|
}
|
|
if (! fSuccess )
|
|
goto CLEANUP;
|
|
|
|
fSuccess = FALSE;
|
|
for (i = 1; i <= g_pKeyTable2->CountColumnsOnTable(); i++)
|
|
{
|
|
if (FAILED(g_pKeyTable2->GetColInfo(i, TempCol2)))
|
|
goto CLEANUP;
|
|
|
|
// if it is not a long column and is fixed length We found our candidate for Primary and Foreign Key.
|
|
if (// (TempCol2.GetProviderType() == DBTYPE_STR) &&
|
|
!(TempCol2.GetIsLong()) &&
|
|
!TempCol2.GetNullable()) // Primary keys typically can't be nullable columns
|
|
{
|
|
fSuccess = TRUE;
|
|
break;
|
|
}
|
|
|
|
}
|
|
if (! fSuccess )
|
|
goto CLEANUP;
|
|
|
|
// Now alloc space for the strings.
|
|
g_pwszAddPrimaryKeyOnTable1 = (WCHAR *)PROVIDER_ALLOC( (wcslen(g_wszAddPrimaryKey)*sizeof (WCHAR)) + sizeof (WCHAR)
|
|
+ (wcslen(g_pKeyTable1->GetTableName())*sizeof (WCHAR))
|
|
+ 2 * (wcslen(TempCol1.GetColName())*sizeof (WCHAR))
|
|
+ 20 // Extra space for the KeyNumber (Random number).
|
|
);
|
|
if (!g_pwszAddPrimaryKeyOnTable1)
|
|
{
|
|
odtLog << wszMemoryAllocationError;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
g_pwszAddPrimaryKeyOnTable2 = (WCHAR *)PROVIDER_ALLOC( (wcslen(g_wszAddPrimaryKey)*sizeof (WCHAR)) + sizeof (WCHAR)
|
|
+ (wcslen(g_pKeyTable2->GetTableName())*sizeof (WCHAR))
|
|
+ 2 * (wcslen(TempCol2.GetColName())*sizeof (WCHAR))
|
|
+ 20 // Extra space for the KeyNumber (Random number).
|
|
);
|
|
if (!g_pwszAddPrimaryKeyOnTable2)
|
|
{
|
|
odtLog << wszMemoryAllocationError;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
|
|
g_pwszAddForeignKeyOnTable1 = (WCHAR *)PROVIDER_ALLOC( (wcslen(g_wszAddForeignKey)*sizeof (WCHAR)) + sizeof (WCHAR)
|
|
+ (wcslen(g_pKeyTable1->GetTableName())*sizeof (WCHAR))
|
|
+ 2 * (wcslen(TempCol1.GetColName())*sizeof (WCHAR))
|
|
+ (wcslen(g_pKeyTable1->GetTableName())*sizeof (WCHAR))
|
|
+ (wcslen(TempCol1.GetColName())*sizeof (WCHAR))
|
|
+ 20 // Extra space for the KeyNumber (Random number).
|
|
);
|
|
if (!g_pwszAddForeignKeyOnTable1)
|
|
{
|
|
odtLog << wszMemoryAllocationError;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
|
|
g_pwszDropPrimaryKeyConstraint1 = (WCHAR *)PROVIDER_ALLOC( (wcslen(g_wszDropPrimaryKeyConstraint)*sizeof (WCHAR)) + sizeof (WCHAR)
|
|
+ (wcslen(g_pKeyTable1->GetTableName())*sizeof (WCHAR))
|
|
+ (wcslen(TempCol1.GetColName())*sizeof (WCHAR))
|
|
+ 20 // Extra space for the KeyNumber (Random number).
|
|
);
|
|
if (!g_pwszDropPrimaryKeyConstraint1)
|
|
{
|
|
odtLog << wszMemoryAllocationError;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
g_pwszDropPrimaryKeyConstraint2 = (WCHAR *)PROVIDER_ALLOC( (wcslen(g_wszDropPrimaryKeyConstraint)*sizeof (WCHAR)) + sizeof (WCHAR)
|
|
+ (wcslen(g_pKeyTable2->GetTableName())*sizeof (WCHAR))
|
|
+ (wcslen(TempCol2.GetColName())*sizeof (WCHAR))
|
|
+ 20 // Extra space for the KeyNumber (Random number).
|
|
);
|
|
if (!g_pwszDropPrimaryKeyConstraint2)
|
|
{
|
|
odtLog << wszMemoryAllocationError;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
g_pwszDropForeignKeyConstraint1 = (WCHAR *)PROVIDER_ALLOC( (wcslen(g_wszDropForeignKeyConstraint)*sizeof (WCHAR)) + sizeof (WCHAR)
|
|
+ (wcslen(g_pKeyTable1->GetTableName())*sizeof (WCHAR))
|
|
+ (wcslen(TempCol1.GetColName())*sizeof (WCHAR))
|
|
+ 20 // Extra space for the KeyNumber (Random number).
|
|
);
|
|
if (!g_pwszDropForeignKeyConstraint1)
|
|
{
|
|
odtLog << wszMemoryAllocationError;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// Add primary key on Table 1.
|
|
swprintf(g_pwszAddPrimaryKeyOnTable1, g_wszAddPrimaryKey,
|
|
g_pKeyTable1->GetTableName(), (lrand1 = GetLongRandomNumber()), TempCol1.GetColName(), TempCol1.GetColName());
|
|
|
|
// Add primary key on table 2.
|
|
swprintf(g_pwszAddPrimaryKeyOnTable2, g_wszAddPrimaryKey,
|
|
g_pKeyTable2->GetTableName(), (lrand2 = GetLongRandomNumber()), TempCol2.GetColName(), TempCol2.GetColName());
|
|
|
|
// Add foriegn key on table 1. (from table 2).
|
|
swprintf(g_pwszAddForeignKeyOnTable1, g_wszAddForeignKey,
|
|
g_pKeyTable1->GetTableName(), (lrand3 = GetLongRandomNumber()), TempCol1.GetColName(), TempCol1.GetColName(),
|
|
g_pKeyTable2->GetTableName(), TempCol2.GetColName() );
|
|
|
|
// Drop primary key on table 1.
|
|
swprintf(g_pwszDropPrimaryKeyConstraint1, g_wszDropPrimaryKeyConstraint,
|
|
g_pKeyTable1->GetTableName(), lrand1, TempCol1.GetColName());
|
|
|
|
// Drop primary key on table 2.
|
|
swprintf(g_pwszDropPrimaryKeyConstraint2, g_wszDropPrimaryKeyConstraint,
|
|
g_pKeyTable2->GetTableName(), lrand2, TempCol2.GetColName());
|
|
|
|
// Drop the foreign key on table 1.
|
|
swprintf(g_pwszDropForeignKeyConstraint1, g_wszDropForeignKeyConstraint,
|
|
g_pKeyTable1->GetTableName(), lrand3, TempCol1.GetColName());
|
|
|
|
pICmd = g_pKeyTable1->get_ICommandPTR();
|
|
|
|
// If we don't already have a primary key on the table
|
|
if (!g_pKeyTable1->GetPrimaryKeyColumn())
|
|
{
|
|
|
|
if( !CHECK(g_pKeyTable1->BuildCommand(g_pwszAddPrimaryKeyOnTable1, // SQL STMT
|
|
IID_NULL, EXECUTE_ALWAYS, NULL, NULL, NULL, NULL, NULL, &pICmd), S_OK) )
|
|
goto CLEANUP;
|
|
|
|
// Set m_fKeyOnTable to Success so that we can drop them.(even if One constraint goes through).
|
|
g_fKeysOnTable = TRUE;
|
|
}
|
|
else
|
|
m_fPrimaryKey = TRUE; // There should be a minimum of one row in PRIMARY_KEYS rowset
|
|
|
|
pICmd = g_pKeyTable2->get_ICommandPTR();
|
|
|
|
// If we don't already have a primary key on the table
|
|
if (!g_pKeyTable2->GetPrimaryKeyColumn())
|
|
{
|
|
TESTC_(g_pKeyTable2->BuildCommand(g_pwszAddPrimaryKeyOnTable2, // SQL STMT
|
|
IID_NULL, EXECUTE_ALWAYS, NULL, NULL, NULL, NULL, NULL, &pICmd), S_OK);
|
|
}
|
|
|
|
m_fPrimaryKey = TRUE; // There should be a minimum of one row in PRIMARY_KEYS rowset
|
|
|
|
pICmd = g_pKeyTable2->get_ICommandPTR();
|
|
TESTC_(g_pKeyTable1->BuildCommand(g_pwszAddForeignKeyOnTable1, // SQL STMT
|
|
IID_NULL, EXECUTE_ALWAYS, NULL, NULL, NULL, NULL, NULL, &pICmd), S_OK);
|
|
|
|
m_fForeignKey = TRUE; // There should be a minimum of one row in FOREIGN_KEYS rowset
|
|
|
|
// Now we add rows.
|
|
// First add rows in 2nd Table and then on 1st table.
|
|
// Start with a table with 1 rows
|
|
if (FAILED(g_pKeyTable2->Insert(1)))
|
|
goto CLEANUP;
|
|
|
|
if (FAILED(g_pKeyTable1->Insert(1)))
|
|
goto CLEANUP;
|
|
|
|
fSuccess = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
if (!fSuccess)
|
|
{
|
|
// CLEANUP memory incase of failure.
|
|
PROVIDER_FREE(g_pwszAddPrimaryKeyOnTable1);
|
|
PROVIDER_FREE(g_pwszAddPrimaryKeyOnTable2);
|
|
PROVIDER_FREE(g_pwszAddForeignKeyOnTable1);
|
|
PROVIDER_FREE(g_pwszDropPrimaryKeyConstraint1);
|
|
PROVIDER_FREE(g_pwszDropPrimaryKeyConstraint2);
|
|
PROVIDER_FREE(g_pwszDropForeignKeyConstraint1);
|
|
}
|
|
|
|
return fSuccess;
|
|
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// @func Drops Key constraintes, indexes etc, created in InitKeysOnTable()
|
|
// Drops the extra table after dropping the constraints.
|
|
BOOL CSchemaTest::TerminateKeysOnTable()
|
|
{
|
|
// Drop the constraints.
|
|
ICommand * pICmd = NULL;
|
|
|
|
if (g_fKeysOnTable)
|
|
{
|
|
// We still need to flag an error if the Drop constraint fails.
|
|
pICmd = g_pKeyTable1->get_ICommandPTR();
|
|
|
|
CHECK(g_pKeyTable1->BuildCommand(g_pwszDropPrimaryKeyConstraint1, // SQL STMT
|
|
IID_NULL, EXECUTE_ALWAYS, NULL, NULL, NULL, NULL, NULL, &pICmd), S_OK);
|
|
|
|
CHECK(g_pKeyTable1->BuildCommand(g_pwszDropForeignKeyConstraint1, // SQL STMT
|
|
IID_NULL, EXECUTE_ALWAYS, NULL, NULL, NULL, NULL, NULL, &pICmd), S_OK);
|
|
|
|
CHECK(g_pKeyTable2->BuildCommand(g_pwszDropPrimaryKeyConstraint2, // SQL STMT
|
|
IID_NULL, EXECUTE_ALWAYS, NULL, NULL, NULL, NULL, NULL, &pICmd), S_OK);
|
|
}
|
|
|
|
if (g_pKeyTable1)
|
|
{
|
|
// remove table from database
|
|
(g_pKeyTable1)->DropTable();
|
|
|
|
// delete CTable object
|
|
delete g_pKeyTable1;
|
|
|
|
g_pKeyTable1 = NULL;
|
|
}
|
|
|
|
if (g_pKeyTable2)
|
|
{
|
|
// remove table from database
|
|
(g_pKeyTable2)->DropTable();
|
|
|
|
// delete CTable object
|
|
delete g_pKeyTable2;
|
|
|
|
g_pKeyTable2 = NULL;
|
|
}
|
|
|
|
// CLEANUP memory incase of failure.
|
|
PROVIDER_FREE(g_pwszAddPrimaryKeyOnTable1);
|
|
PROVIDER_FREE(g_pwszAddPrimaryKeyOnTable2);
|
|
PROVIDER_FREE(g_pwszAddForeignKeyOnTable1);
|
|
PROVIDER_FREE(g_pwszDropPrimaryKeyConstraint1);
|
|
PROVIDER_FREE(g_pwszDropPrimaryKeyConstraint2);
|
|
PROVIDER_FREE(g_pwszDropForeignKeyConstraint1);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// @func Module level initialization routine
|
|
//
|
|
// @rdesc Success or Failure
|
|
// @flag TRUE | Successful initialization
|
|
// @flag FALSE | Initialization problems
|
|
//
|
|
BOOL ModuleInit(CThisTestModule * pThisTestModule)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Need to initialize these in ModuleInit to make sure they get reset if test is
|
|
// run against two providers.
|
|
g_fKeysOnTable=FALSE;
|
|
g_pIDBSchemaRowset=NULL;
|
|
g_fKagera = FALSE;
|
|
g_fSQLServer = FALSE;
|
|
|
|
cSchemas=0;
|
|
rgSchemas=NULL;
|
|
rgRestrictions=NULL;
|
|
|
|
// Get connection and session objects
|
|
if (ModuleCreateDBSession(pThisTestModule))
|
|
{
|
|
LPWSTR pwszName=NULL;
|
|
g_fKagera = IsMSDASQL();
|
|
|
|
// Needed for ExtraLib
|
|
g_pIDBInitialize = (IDBInitialize *)pThisTestModule->m_pIUnknown;
|
|
|
|
// Fail gracefully and quit module if we don't support IDBSchemaRowset
|
|
if (FAILED(hr = pThisTestModule->m_pIUnknown2->QueryInterface(
|
|
IID_IDBSchemaRowset,(void **)&g_pIDBSchemaRowset)))
|
|
{
|
|
// Make sure we returned E_NOINTERFACE if we've failed
|
|
if (pThisTestModule->m_pError->Validate(hr,
|
|
LONGSTRING(__FILE__), __LINE__, E_NOINTERFACE))
|
|
odtLog << L"IDBSchemaRowset is not supported.\n";
|
|
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Get the name of the backend
|
|
GetProperty(DBPROP_DBMSNAME, DBPROPSET_DATASOURCEINFO, pThisTestModule->m_pIUnknown, &pwszName);
|
|
if (pwszName)
|
|
{
|
|
if (!wcscmp(pwszName, L"Microsoft SQL Server"))
|
|
g_fSQLServer = TRUE;
|
|
}
|
|
SAFE_FREE(pwszName);
|
|
|
|
// Just Print out What is Supported
|
|
if (FAILED(g_pIDBSchemaRowset->GetSchemas(&cSchemas,
|
|
&rgSchemas, &rgRestrictions)))
|
|
{
|
|
SAFE_RELEASE(g_pIDBSchemaRowset);
|
|
return FALSE;
|
|
}
|
|
|
|
for(ULONG index=0; index<cSchemas; index++)
|
|
{
|
|
LPWSTR pwszSchemaName = L"Unknown schema";
|
|
// TraceSchemaName(rgSchemas[index],TRUE,TRUE);
|
|
for (ULONG iSchema=0; iSchema < NUMELEM(AllSchemas); iSchema++)
|
|
{
|
|
if (rgSchemas[index] == *AllSchemas[iSchema].pguid)
|
|
pwszSchemaName = AllSchemas[iSchema].pwszName;
|
|
}
|
|
odtLog << pwszSchemaName << L"\n";
|
|
TraceRestrictions(rgRestrictions,index,NULL,FALSE);
|
|
}
|
|
|
|
// Create a table we'll use for the whole test module,
|
|
pThisTestModule->m_pVoid = new CTable(
|
|
(IUnknown *)pThisTestModule->m_pIUnknown2,(LPWSTR)gwszModuleName);
|
|
|
|
if (!pThisTestModule->m_pVoid)
|
|
{
|
|
odtLog << wszMemoryAllocationError;
|
|
return FALSE;
|
|
}
|
|
|
|
// Start with a table with 30 rows
|
|
if (!CHECK(((CTable *)pThisTestModule->m_pVoid)->CreateTable(30), S_OK))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// @func Module level termination routine
|
|
//
|
|
// @rdesc Success or Failure
|
|
// @flag TRUE | Successful initialization
|
|
// @flag FALSE | Initialization problems
|
|
//
|
|
BOOL ModuleTerminate(CThisTestModule * pThisTestModule)
|
|
{
|
|
// We still own the table since all of our testcases
|
|
// have only used it and not deleted it.
|
|
if (pThisTestModule->m_pVoid)
|
|
{
|
|
// Remove table from database
|
|
((CTable *)pThisTestModule->m_pVoid)->DropTable();
|
|
|
|
// Delete CTable object
|
|
delete (CTable*)pThisTestModule->m_pVoid;
|
|
pThisTestModule->m_pVoid = NULL;
|
|
}
|
|
|
|
SAFE_RELEASE(g_pIDBSchemaRowset);
|
|
SAFE_FREE(rgSchemas);
|
|
SAFE_FREE(rgRestrictions);
|
|
|
|
return ModuleReleaseDBSession(pThisTestModule);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Helper classes
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
class CHelper
|
|
{
|
|
|
|
protected:
|
|
|
|
CTable * m_pTable;
|
|
|
|
GUID m_guidSchema;
|
|
|
|
SchemaList * m_pSchemaInfo;
|
|
|
|
CSchemaTest * m_pCSchemaTest;
|
|
|
|
BOOL m_fPassUnsupportedRestrictions;
|
|
|
|
BOOL m_fUseCommonArgumentDefaults;
|
|
|
|
BOOL m_fSupported; // Is this schema supported?
|
|
|
|
ULONG m_ulRestrictionSupport;
|
|
|
|
DBORDINAL m_ulRowCount;
|
|
|
|
ROW_COUNT m_eRowCount;
|
|
|
|
LPWSTR m_pwszCatalogRestriction;
|
|
|
|
LPWSTR m_pwszSchemaName;
|
|
|
|
ULONG_PTR m_ulNullCollation;
|
|
|
|
DBCOUNTITEM m_cTotalRows;
|
|
|
|
// @cmember Count of columns in rowset
|
|
DBORDINAL m_cDBCOLUMNINFO;
|
|
|
|
// @cmember Array of column information in rowset
|
|
DBCOLUMNINFO * m_rgDBCOLUMNINFO;
|
|
|
|
// @cmember String buffer for column info
|
|
LPWSTR m_pStringsBuffer;
|
|
|
|
// @cmember Array of column information in rowset
|
|
DBCOLUMNINFO * m_rgDBCOLUMNINFO_Prev;
|
|
|
|
// @cmember String buffer for column info
|
|
LPWSTR m_pStringsBuffer_Prev;
|
|
|
|
// @cmember Count of columns in rowset
|
|
DBCOUNTITEM m_cDBCOLUMNINFO_Prev;
|
|
|
|
// @cmember Count of Bindings
|
|
DBCOUNTITEM m_cDBBINDING;
|
|
|
|
// @cmember Array of Bindings
|
|
DBBINDING * m_rgDBBINDING;
|
|
|
|
// Bitmask of which restrictions are requested
|
|
RESTRICTIONS m_restrict;
|
|
|
|
// @cmember Count of restrictions
|
|
ULONG m_cRestrict;
|
|
|
|
// All cached restrictions
|
|
VARIANT m_rgRestrict[MAXRESTRICTION];
|
|
|
|
// Valid restrictions for this schema
|
|
VARIANT m_rgRestrictValid[MAXRESTRICTION];
|
|
|
|
// Restrictions for this schema
|
|
VARIANT m_rgRestrictUsed[MAXRESTRICTION];
|
|
|
|
// Track actual restriction array used
|
|
VARIANT * m_prgRestrictUsed;
|
|
ULONG m_cRestrictionsUsed;
|
|
|
|
// @cmember Rowset pointer
|
|
IRowset * m_pIRowset;
|
|
|
|
// Do I want to capture restrictions only
|
|
BOOL m_fCaptureRestrictions;
|
|
BOOL m_fCaptured;
|
|
|
|
// Pointer to current row of schema
|
|
LPBYTE m_pRow;
|
|
|
|
// Pointer to previous row of schema used to verify sorting/ordinals
|
|
LPBYTE m_pRowPrev;
|
|
|
|
// IDBSchemaRowset interface pointer to use
|
|
IDBSchemaRowset * m_pIDBSchemaRowset;
|
|
|
|
// Row to use for restrictions
|
|
DBCOUNTITEM m_ulRestrictRow;
|
|
|
|
// Column ordinal to use for restriction
|
|
ULONG m_iRestrict;
|
|
|
|
enum RESTRICT_ARRAY m_eRestrictArray;
|
|
|
|
LPWSTR m_pwszTableName;
|
|
ULONG m_ulTableOrdinal;
|
|
DBCOLUMNINFO * m_prgColInfo;
|
|
LPWSTR m_pwszStringsBuffer;
|
|
DBORDINAL m_cColInfo;
|
|
|
|
CErrorCache m_ECHelper; // Error cache
|
|
|
|
ULONG m_ulSchemaVersion;
|
|
ULONG m_ulOLEDBVer;
|
|
|
|
// Helper functions
|
|
HRESULT GetColumnInfo(LPBYTE pData, DBBINDING * pBinding);
|
|
BOOL FillRestrictions(DBCOUNTITEM iRow, LPBYTE pData);
|
|
LPWSTR GetRestrictionName(ULONG iRestrict);
|
|
RESTRICT_CAT GetRestrictCat(ULONG iRestrict);
|
|
ULONG GetLiteralMaxSize(DBLITERAL eLiteral);
|
|
|
|
// Function to create at least two rows in schema, so sorting test will actually test something.
|
|
// It's possible this function may just return TRUE if we know the schema already has many rows.
|
|
virtual BOOL InsertRows(void) {return TRUE;}
|
|
|
|
// Function to pick a row from the schema and use values from that row for restrictions
|
|
BOOL GetRestrictions(ULONG iRestrict);
|
|
BOOL IsRestricted(ULONG iRestrict);
|
|
|
|
// Row verification functions
|
|
BOOL CheckAgainstIColumnsInfo(SchemaList * pSchemaInfo);
|
|
BOOL VerifyRowset(IRowset * pIRowset);
|
|
LPBYTE GetValuePtr(DBORDINAL iOrdinal, LPBYTE pData, DBBINDING * pBinding = NULL);
|
|
void GetVersionInfo(IDBInitialize * pIDBInit);
|
|
BOOL VerifyRowCommon(DBCOUNTITEM iRow, BYTE * pData);
|
|
BOOL VerifySort(DBCOUNTITEM iRow, BYTE * pData);
|
|
BOOL VerifyValidTable(DBCOUNTITEM iRow, LPBYTE pData);
|
|
BOOL VerifyColumnCommon(DBORDINAL iOrdinal, DATA * pColumn);
|
|
virtual BOOL VerifyRestriction(DBORDINAL iOrdinal, DATA * pColumn);
|
|
BOOL VerifyLength(DBORDINAL iOrdinal, DATA * pColumn);
|
|
BOOL VerifyTypeSpecific(DBORDINAL iOrdinal, DATA * pColumn);
|
|
virtual BOOL VerifyValue(DBORDINAL iOrdinal, DATA * pColumn);
|
|
BOOL VerifyNull(DBORDINAL iOrdinal, DATA * pColumn);
|
|
BOOL VerifyNonEmptyString(DATA * pColumn, LPWSTR pwszTable, LPWSTR pwszColumn);
|
|
BOOL VerifyColumnMatch(DBORDINAL iOrdinal1, DBORDINAL iOrdinal2);
|
|
|
|
// Schema-specific validation
|
|
virtual BOOL VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn) {return TRUE;}
|
|
virtual BOOL CompareNull(DBORDINAL iOrdinal)
|
|
{
|
|
if (!COMPARE(m_pSchemaInfo->pColList[iOrdinal-1].fAllowNull, TRUE))
|
|
{
|
|
odtLog << L"Column " << m_pSchemaInfo->pColList[iOrdinal-1].pwszName << L" was NULL.\n";
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
public:
|
|
|
|
CHelper(void);
|
|
virtual ~CHelper(void);
|
|
virtual BOOL Init(CSchemaTest * pThis);
|
|
virtual BOOL CreateCheckConstraints(void);
|
|
virtual BOOL CreateStoredProcs(void);
|
|
virtual LPWSTR CreateObject(UINT idsObject, LPWSTR pwszObjectName = NULL);
|
|
virtual BOOL VerifyObject(UINT idsObject);
|
|
virtual BOOL VerifyObjectValue(UINT idsObject, ULONG iOrdinal);
|
|
|
|
BOOL CheckResults(HRESULT hr, REFIID iid, IUnknown * pIUnknown);
|
|
HRESULT GetNextRows(DBROWOFFSET lOffset, DBROWCOUNT cRows, DBCOUNTITEM* pcRowsObtained, HROW** prghRows);
|
|
|
|
BOOL IsSupported(void);
|
|
void UseArgumentDefaults(BOOL fUseDefaults) {m_fUseCommonArgumentDefaults = fUseDefaults;}
|
|
GUID GetSchema(void) {return m_guidSchema;}
|
|
LPWSTR GetCatalogName();
|
|
|
|
HRESULT GetRowsetHelper
|
|
(
|
|
IUnknown * pIUnknown = NULL,
|
|
ULONG cRestrictions = RV_ALL,
|
|
VARIANT * prgRestrictions = NULL,
|
|
REFIID riid = IID_IRowset,
|
|
ULONG cPropertySets = 0,
|
|
DBPROPSET rgPropertySets[] = NULL,
|
|
IUnknown ** ppRowset = NULL,
|
|
GUID guidSchema = GUID_NULL,
|
|
BOOL fFreeRowset = TRUE
|
|
);
|
|
|
|
BOOL HasUnsupportedRestriction(void);
|
|
BOOL IsSupportedRestriction(ULONG iRestrict);
|
|
void ClearRestrictions(VARIANT * prgVariant = NULL);
|
|
BOOL GetValidColumnValues(DBORDINAL iOrdinal, ULONG * pcValidValues, LPVOID * ppValidValues);
|
|
BOOL SetValidColumnValues(DBORDINAL iOrdinal, ULONG cValidValues, LPVOID pValidValues);
|
|
void SetValidRestriction(ULONG iRestrict);
|
|
void SetEmptyRestrict(ULONG iRestrict);
|
|
void SetRestriction(ULONG iRestrict);
|
|
BOOL SetRestriction(ULONG iRestrict, LPVOID pValue);
|
|
BOOL SetRestriction(ULONG iRestrict, LPVOID pValue, DBTYPE wType);
|
|
BOOL SetRestriction(ULONG iRestrict, VARIANT * pVariant);
|
|
BOOL SetInvalidRestriction(ULONG iRestrict, LPVOID pValue, DBTYPE wType);
|
|
void SetRestrictionType(ULONG iRestrict, DBTYPE wType);
|
|
ULONG RestrictionCount(void) {return m_pSchemaInfo->cRestrictions;}
|
|
void SetRestrictionArray(enum RESTRICT_ARRAY eRestrictArray) {m_eRestrictArray = eRestrictArray;}
|
|
VARIANT * GetRestrictPtr(ULONG iRestrict);
|
|
ULONG GetRestrictionMaxLength(ULONG iRestrict);
|
|
|
|
void SetRowCount(ROW_COUNT eRowCount, DBORDINAL ulRowCount);
|
|
|
|
int TestRestriction(ULONG iRestrict);
|
|
|
|
// Obsolete functions
|
|
void SetRestrictions(ULONG ulRestrict) {m_restrict = ulRestrict;}
|
|
|
|
};
|
|
|
|
CHelper::CHelper(void)
|
|
{
|
|
m_pTable = NULL;
|
|
m_guidSchema = GUID_NULL;
|
|
m_pSchemaInfo = NULL;
|
|
m_fPassUnsupportedRestrictions = FALSE;
|
|
m_fUseCommonArgumentDefaults = TRUE;
|
|
m_fSupported = FALSE;
|
|
m_ulRestrictionSupport = 0;
|
|
m_ulRowCount = 1; // By default we will require at least one row back from schema
|
|
m_pwszCatalogRestriction = NULL;
|
|
m_pwszSchemaName = NULL;
|
|
m_ulNullCollation = DBPROPVAL_NC_HIGH;
|
|
m_cTotalRows = 0;
|
|
m_eRowCount = MIN_REQUIRED;
|
|
m_cDBBINDING = 0;
|
|
m_cDBCOLUMNINFO = 0;
|
|
m_cRestrict = 0;
|
|
m_fCaptureRestrictions = FALSE;
|
|
m_iRestrict = 0;
|
|
m_pIDBSchemaRowset = NULL;
|
|
m_ulRestrictRow = 2;
|
|
m_prgRestrictUsed = NULL;
|
|
m_cRestrictionsUsed = 0;
|
|
m_pRow = NULL;
|
|
m_pRowPrev = NULL;
|
|
m_pIRowset = NULL;
|
|
m_rgDBBINDING = NULL;
|
|
m_rgDBCOLUMNINFO = NULL;
|
|
m_pStringsBuffer = NULL;
|
|
m_eRestrictArray = RT_SUPPORTED;
|
|
m_rgDBCOLUMNINFO_Prev = NULL;
|
|
m_pStringsBuffer_Prev = NULL;
|
|
m_cDBCOLUMNINFO_Prev = 0;
|
|
|
|
// Information specific to a given table in a schema
|
|
m_pwszTableName = NULL;
|
|
m_ulTableOrdinal = 0;
|
|
m_prgColInfo = NULL;
|
|
m_pwszStringsBuffer = NULL;
|
|
m_cColInfo = 0;
|
|
|
|
// Init all restrictions variants
|
|
for (ULONG iRestrict = 0; iRestrict < MAXRESTRICTION; iRestrict++)
|
|
{
|
|
VariantInit(&m_rgRestrict[iRestrict]);
|
|
VariantInit(&m_rgRestrictValid[iRestrict]);
|
|
VariantInit(&m_rgRestrictUsed[iRestrict]);
|
|
}
|
|
}
|
|
|
|
CHelper::~CHelper(void)
|
|
{
|
|
ClearRestrictions(m_rgRestrict);
|
|
ClearRestrictions(m_rgRestrictValid);
|
|
ClearRestrictions(m_rgRestrictUsed);
|
|
SAFE_FREE(m_rgDBBINDING);
|
|
SAFE_FREE(m_rgDBCOLUMNINFO);
|
|
SAFE_FREE(m_pStringsBuffer);
|
|
SAFE_RELEASE(m_pIDBSchemaRowset);
|
|
SAFE_RELEASE(m_pIRowset);
|
|
SAFE_FREE(m_pwszTableName);
|
|
SAFE_FREE(m_prgColInfo);
|
|
SAFE_FREE(m_pwszStringsBuffer);
|
|
SAFE_FREE(m_rgDBCOLUMNINFO_Prev);
|
|
SAFE_FREE(m_pStringsBuffer_Prev);
|
|
SAFE_FREE(m_pwszCatalogRestriction);
|
|
SAFE_FREE(m_pwszSchemaName);
|
|
}
|
|
|
|
BOOL CHelper::Init(CSchemaTest * pThis)
|
|
{
|
|
ULONG cSchemas = 0;
|
|
WCHAR * pwszOLEDBVER = NULL;
|
|
GUID * rgSchemas = NULL;
|
|
ULONG * rgRestrictionSupport = NULL;
|
|
BOOL fFoundSchema = FALSE;
|
|
ULONG iSchema;
|
|
BOOL fResult = FALSE;
|
|
IDBInitialize * pIDBInit = NULL;
|
|
|
|
TESTC(pThis != NULL)
|
|
|
|
pIDBInit = pThis->m_pIDBInitialize;
|
|
|
|
m_ECHelper.Init(GetModInfo()->GetDebugMode());
|
|
|
|
// CHelper is a virtual (not pure) base class and m_guidSchema is populated
|
|
// in the derived class with the proper schema, so don't allow users to
|
|
// Init without a valid schema.
|
|
TESTC(m_guidSchema != GUID_NULL)
|
|
|
|
m_pCSchemaTest = pThis;
|
|
m_pTable = pThis->m_pTable;
|
|
m_pIDBSchemaRowset = pThis->m_pIDBSchemaRowset;
|
|
m_pIDBSchemaRowset->AddRef();
|
|
|
|
// Locate this schema in the global schema information array
|
|
for (iSchema = 0; iSchema < NUMELEM(AllSchemas); iSchema++)
|
|
{
|
|
if (*AllSchemas[iSchema].pguid == m_guidSchema)
|
|
{
|
|
m_pSchemaInfo = &AllSchemas[iSchema];
|
|
break;
|
|
}
|
|
}
|
|
|
|
TESTC(m_pSchemaInfo != NULL)
|
|
|
|
// Get Restriction support for this schema
|
|
m_fSupported = FALSE;
|
|
|
|
TESTC_(m_pIDBSchemaRowset->GetSchemas(&cSchemas, &rgSchemas, &rgRestrictionSupport), S_OK)
|
|
|
|
for(iSchema=0; iSchema<cSchemas; iSchema++)
|
|
{
|
|
if(m_guidSchema == rgSchemas[iSchema])
|
|
{
|
|
m_fSupported = TRUE;
|
|
m_ulRestrictionSupport = rgRestrictionSupport[iSchema];
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Insert any rows into this schema that are needed if schema is supported.
|
|
if (m_fSupported)
|
|
{
|
|
TESTC(InsertRows());
|
|
}
|
|
|
|
TESTC(GetRestrictions(0));
|
|
|
|
// Call the GetProperty for the CurrentCatalog
|
|
GetProperty(DBPROP_CURRENTCATALOG, DBPROPSET_DATASOURCE, pIDBInit, &m_pwszCatalogRestriction);
|
|
|
|
// Call the GetProperty for the UserName, which matches the schema name
|
|
GetProperty(DBPROP_USERNAME, DBPROPSET_DATASOURCEINFO, pIDBInit, &m_pwszSchemaName);
|
|
|
|
// Get DBPROP_NULLCOLLATION for use in comparing sort of NULL values
|
|
GetProperty(DBPROP_NULLCOLLATION, DBPROPSET_DATASOURCEINFO, pIDBInit, &m_ulNullCollation);
|
|
|
|
// Figure out what schema version and OLEDB version we're using for verification
|
|
GetVersionInfo(pIDBInit);
|
|
|
|
// Update count of columns if needed.
|
|
if (m_pSchemaInfo->pulColCount)
|
|
{
|
|
m_pSchemaInfo->cColumns = m_pSchemaInfo->pulColCount[0];
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
SAFE_FREE(rgSchemas);
|
|
SAFE_FREE(rgRestrictionSupport);
|
|
|
|
return fResult;
|
|
}
|
|
|
|
// Default implementation does nothing
|
|
LPWSTR CHelper::CreateObject(UINT idsObject, LPWSTR pwszObjectName) {return NULL;}
|
|
BOOL CHelper::VerifyObject(UINT idsObject) {return TRUE;}
|
|
BOOL CHelper::VerifyObjectValue(UINT idsObject, ULONG iOrdinal) {return TRUE;}
|
|
|
|
// Determine the schema version and OLEDB version
|
|
void CHelper::GetVersionInfo(IDBInitialize * pIDBInit)
|
|
{
|
|
LPWSTR pwszOLEDBVER = NULL;
|
|
|
|
// Get DBPROP_PROVIDEROLEDBVER for use in setting correct column count for each schema
|
|
if (GetProperty(DBPROP_PROVIDEROLEDBVER, DBPROPSET_DATASOURCEINFO, pIDBInit, &pwszOLEDBVER))
|
|
{
|
|
if (!wcscmp(pwszOLEDBVER, L"02.00"))
|
|
{
|
|
m_ulSchemaVersion = VER_20;
|
|
m_ulOLEDBVer = VER_20;
|
|
}
|
|
else if (!wcscmp(pwszOLEDBVER, L"02.10"))
|
|
{
|
|
m_ulSchemaVersion = VER_21;
|
|
m_ulOLEDBVer = VER_21;
|
|
}
|
|
else if (!wcscmp(pwszOLEDBVER, L"02.50"))
|
|
{
|
|
m_ulSchemaVersion = VER_25;
|
|
m_ulOLEDBVer = VER_25;
|
|
}
|
|
else if (!wcscmp(pwszOLEDBVER, L"02.60"))
|
|
{
|
|
m_ulSchemaVersion = VER_26;
|
|
m_ulOLEDBVer = VER_26;
|
|
}
|
|
else if (!wcscmp(pwszOLEDBVER, L"02.70"))
|
|
{
|
|
m_ulSchemaVersion = VER_27;
|
|
m_ulOLEDBVer = VER_27;
|
|
}
|
|
else
|
|
{
|
|
odtLog << L"Unexpected provider OLEDB version.\n";
|
|
COMPARE(0,1);
|
|
}
|
|
|
|
SAFE_FREE(pwszOLEDBVER);
|
|
}
|
|
}
|
|
|
|
BOOL CHelper::CreateCheckConstraints(void)
|
|
{
|
|
|
|
// Create at least two check constraints that will not impact other test variations
|
|
// using the test's default table.
|
|
|
|
// alter table slh add constraint slhconstraint check (col1 >= 'bbb' or col1 < 'bbb')
|
|
// %1 tablename, %2 constraintname, %3 columnname, %4 constraintvalue
|
|
|
|
BOOL fRet = FALSE;
|
|
CCol TempCol;
|
|
size_t ccStmt = 0;
|
|
DBORDINAL iCol;
|
|
LPWSTR pwszStmtFormat = L"alter table %s add constraint %s check (%s >= '%s' or %s < '%s')";
|
|
LPWSTR pwszConstraintName = NULL;
|
|
LPWSTR pwszColumnName = NULL;
|
|
LPWSTR pwszTableName = NULL;
|
|
LPWSTR pwszConstraintValue = L"a"; // We use any bogus value because the constriant is not constrained
|
|
LPWSTR pwszStmt = NULL;
|
|
|
|
// This function uses SQL Server syntax. For other DBMS's we assume the check constraints
|
|
// already exist and so just return TRUE;
|
|
if (!g_fSQLServer)
|
|
return TRUE;
|
|
|
|
// Populate the table name
|
|
pwszTableName = m_pTable->GetTableName();
|
|
|
|
for (iCol = 1; iCol <= m_pTable->CountColumnsOnTable(); iCol++)
|
|
{
|
|
// Get the information about the column
|
|
if (!CHECK(m_pTable->GetColInfo(iCol, TempCol), S_OK))
|
|
{
|
|
fRet = FALSE;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// Get a char column name
|
|
if ((TempCol.GetProviderType() != DBTYPE_STR &&
|
|
TempCol.GetProviderType() != DBTYPE_WSTR) ||
|
|
TempCol.GetIsLong())
|
|
continue;
|
|
|
|
// Create a unique constraint name
|
|
pwszConstraintName = MakeObjectName(L"Cnst", 30);
|
|
CHECK_MEMORY(pwszConstraintName);
|
|
|
|
pwszColumnName = TempCol.GetColName();
|
|
|
|
ccStmt = wcslen(pwszStmtFormat) + wcslen(pwszTableName) + wcslen(pwszConstraintName) +
|
|
wcslen(pwszColumnName) + wcslen(pwszConstraintValue) + 1;
|
|
|
|
SAFE_ALLOC(pwszStmt, WCHAR, ccStmt);
|
|
|
|
swprintf(pwszStmt, pwszStmtFormat, pwszTableName, pwszConstraintName, pwszColumnName, pwszConstraintValue, pwszColumnName, pwszConstraintValue);
|
|
|
|
// Execute the command expecting S_OK
|
|
TESTC_(m_pTable->BuildCommand(pwszStmt, IID_IRowset,
|
|
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL), S_OK);
|
|
|
|
SAFE_FREE(pwszConstraintName);
|
|
SAFE_FREE(pwszStmt);
|
|
|
|
fRet = TRUE;
|
|
}
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(pwszConstraintName);
|
|
SAFE_FREE(pwszStmt);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
BOOL CHelper::CreateStoredProcs(void)
|
|
{
|
|
|
|
// Create at least two stored procs using the test's default table.
|
|
|
|
// create proc slhproc(@p1 char(30), @p2 char(30)) as begin select * from <testtable> where charcol > 'aaa' or charcol < 'zzz'; end
|
|
BOOL fRet = FALSE;
|
|
CCol TempCol;
|
|
size_t ccStmt = 0;
|
|
DBORDINAL iCol;
|
|
LPWSTR pwszStmtFormat = L"create procedure %s(@p1 char(30), @p2 char(30)) as begin select * from %s where %s > 'a' or %s < 'z'; end";
|
|
LPWSTR pwszColumnName = NULL;
|
|
LPWSTR pwszSprocName = NULL;
|
|
LPWSTR pwszTableName = NULL;
|
|
LPWSTR pwszStmt = NULL;
|
|
|
|
// This function uses SQL Server syntax. For other DBMS's we assume the procs
|
|
// already exist and so just return TRUE;
|
|
if (!g_fSQLServer)
|
|
return TRUE;
|
|
|
|
// Populate the table name
|
|
pwszTableName = m_pTable->GetTableName();
|
|
|
|
for (iCol = 1; iCol <= m_pTable->CountColumnsOnTable(); iCol++)
|
|
{
|
|
// Get the information about the column
|
|
if (!CHECK(m_pTable->GetColInfo(iCol, TempCol), S_OK))
|
|
{
|
|
fRet = FALSE;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// Get a char column name
|
|
if ((TempCol.GetProviderType() != DBTYPE_STR &&
|
|
TempCol.GetProviderType() != DBTYPE_WSTR) ||
|
|
TempCol.GetIsLong())
|
|
continue;
|
|
|
|
// Create a unique sproc name
|
|
pwszSprocName = MakeObjectName(L"IDBSproc", 30);
|
|
CHECK_MEMORY(pwszSprocName);
|
|
|
|
pwszColumnName = TempCol.GetColName();
|
|
|
|
ccStmt = wcslen(pwszStmtFormat) + wcslen(pwszTableName) + wcslen(pwszSprocName) +
|
|
wcslen(pwszColumnName) + wcslen(pwszColumnName) + 1;
|
|
|
|
SAFE_ALLOC(pwszStmt, WCHAR, ccStmt);
|
|
|
|
swprintf(pwszStmt, pwszStmtFormat, pwszSprocName, pwszTableName, pwszColumnName, pwszColumnName);
|
|
|
|
// Execute the command expecting S_OK
|
|
TESTC_(m_pTable->BuildCommand(pwszStmt, IID_IRowset,
|
|
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL), S_OK);
|
|
|
|
odtLog << L"Created stored proc " << pwszSprocName << L"\n";
|
|
|
|
SAFE_FREE(pwszSprocName);
|
|
SAFE_FREE(pwszStmt);
|
|
|
|
fRet = TRUE;
|
|
}
|
|
|
|
CLEANUP:
|
|
SAFE_FREE(pwszSprocName);
|
|
SAFE_FREE(pwszStmt);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
BOOL CHelper::IsSupported(void)
|
|
{
|
|
return m_fSupported;
|
|
}
|
|
|
|
void CHelper::ClearRestrictions(VARIANT * prgVariant)
|
|
{
|
|
// By default clear the restrictions actually used
|
|
if (!prgVariant)
|
|
prgVariant = m_rgRestrictUsed;
|
|
|
|
for (ULONG iRestrict = 0; iRestrict < MAXRESTRICTION; iRestrict++)
|
|
VariantClear(&prgVariant[iRestrict]);
|
|
}
|
|
|
|
ULONG CHelper::GetLiteralMaxSize(DBLITERAL eLiteral)
|
|
{
|
|
DBLITERALINFO* pLiteralInfo = NULL;
|
|
pLiteralInfo = m_pTable->GetLiteralInfo(eLiteral);
|
|
TESTC(pLiteralInfo != NULL);
|
|
return pLiteralInfo->cchMaxLen;
|
|
|
|
CLEANUP:
|
|
|
|
return CCHMAXLENGTH_UNKNOWN;
|
|
}
|
|
|
|
|
|
ULONG CHelper::GetRestrictionMaxLength(ULONG iRestrict)
|
|
{
|
|
ULONG ulRestrictBit = 1 << (iRestrict-1);
|
|
RESTRICT_CAT eRestrictType = GetRestrictCat(iRestrict);
|
|
|
|
// Restrictions are 1 based
|
|
_ASSERTE(iRestrict > 0);
|
|
|
|
// We don't care about undefined restrictions
|
|
if (eRestrictType == RC_UND)
|
|
return CCHMAXLENGTH_UNKNOWN;
|
|
|
|
switch (eRestrictType)
|
|
{
|
|
case RC_CATALOG:
|
|
// Use max catalog name size
|
|
return GetLiteralMaxSize(DBLITERAL_CATALOG_NAME);
|
|
case RC_SCHEMA:
|
|
// Use max schema name size
|
|
return GetLiteralMaxSize(DBLITERAL_SCHEMA_NAME);
|
|
case RC_TABLE:
|
|
// Use max table name size
|
|
return GetLiteralMaxSize(DBLITERAL_TABLE_NAME);
|
|
case RC_CONSTRAINT:
|
|
// return GetLiteralMaxSize(DBLITERAL_CONSTRAINT_NAME);
|
|
odtLog << L"Missing DBLITERAL_CONSTRAINT_NAME in OLEDB.H, using DBLITERAL_TABLE_NAME\n";
|
|
return GetLiteralMaxSize(DBLITERAL_TABLE_NAME);
|
|
case RC_COLUMN:
|
|
return GetLiteralMaxSize(DBLITERAL_COLUMN_NAME);
|
|
case RC_USER:
|
|
return GetLiteralMaxSize(DBLITERAL_USER_NAME);
|
|
case RC_INDEX:
|
|
return GetLiteralMaxSize(DBLITERAL_INDEX_NAME);
|
|
case RC_PROCEDURE:
|
|
return GetLiteralMaxSize(DBLITERAL_PROCEDURE_NAME);
|
|
case RC_PARAMETER:
|
|
// No literal value for COLUMN NAME, use COLUMN_NAME
|
|
return GetLiteralMaxSize(DBLITERAL_COLUMN_NAME);
|
|
case RC_CONSTRAINT_TYPE:
|
|
return (ULONG)wcslen(L"PRIMARY KEY");
|
|
case RC_STATISTICS:
|
|
// No literal value for STATISTICS NAME, use COLUMN_NAME
|
|
return (ULONG)GetLiteralMaxSize(DBLITERAL_COLUMN_NAME);
|
|
case RC_TABLE_TYPE:
|
|
return (ULONG)wcslen(L"GLOBAL TEMPORARY");
|
|
// Unknown length values
|
|
case RC_SERVER:
|
|
case RC_UND:
|
|
odtLog << L"Unknown restriction length, using DBLITERAL_COLUMN_NAME values.\n";
|
|
return GetLiteralMaxSize(DBLITERAL_COLUMN_NAME);
|
|
default:
|
|
odtLog << L"Unknown restriction length, restriction not tested.\n";
|
|
COMPARE(0, 1);
|
|
return CCHMAXLENGTH_UNKNOWN;
|
|
}
|
|
|
|
}
|
|
|
|
LPWSTR CHelper::GetRestrictionName(ULONG iRestrict)
|
|
{
|
|
// A valid restriction must be within range
|
|
if (COMPARE(iRestrict > 0 && iRestrict <= m_pSchemaInfo->cRestrictions, TRUE))
|
|
{
|
|
DBORDINAL iOrdinal = m_pSchemaInfo->pulRestrictions[iRestrict-1];
|
|
return m_pSchemaInfo->pColList[iOrdinal-1].pwszName;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
LPWSTR CHelper::GetCatalogName()
|
|
{
|
|
return m_pwszCatalogRestriction;
|
|
};
|
|
|
|
RESTRICT_CAT CHelper::GetRestrictCat(ULONG iRestrict)
|
|
{
|
|
// A valid restriction must be within range
|
|
if (COMPARE(iRestrict > 0 && iRestrict <= m_pSchemaInfo->cRestrictions, TRUE))
|
|
return m_pSchemaInfo->peRestrictCat[iRestrict-1];
|
|
|
|
return RC_UND;
|
|
}
|
|
|
|
int CHelper::TestRestriction(ULONG iRestrict)
|
|
{
|
|
HRESULT hrExpected = S_OK;
|
|
HRESULT hr = E_FAIL;
|
|
BOOL fResult = FALSE;
|
|
BOOL fIsOutsideRange = FALSE;
|
|
VARIANT * pVariantFirst = GetRestrictPtr(RV_ONE);
|
|
|
|
if (!IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// If this restriction is > number of spec'd restrictions -> E_INVALIDARG
|
|
if (iRestrict > m_pSchemaInfo->cRestrictions)
|
|
{
|
|
odtLog << L"Restriction " << iRestrict << L" is NOT supported.\n";
|
|
fIsOutsideRange = TRUE;
|
|
hrExpected = E_INVALIDARG;
|
|
}
|
|
else if (IsSupportedRestriction(iRestrict))
|
|
odtLog << L"Restriction on " << GetRestrictionName(iRestrict) << L" is supported.\n";
|
|
else
|
|
{
|
|
odtLog << L"Restriction on " << GetRestrictionName(iRestrict) << L" is NOT supported.\n";
|
|
hrExpected = DB_E_NOTSUPPORTED;
|
|
}
|
|
|
|
SetRestrictionArray(RT_CUSTOM);
|
|
|
|
// If this restrictions is outside the range of valid restrictions
|
|
// just set to the same as the first restriction, since there is
|
|
// no value cached and we don't know which column to cache from anyway
|
|
// or the restriction type
|
|
if (fIsOutsideRange)
|
|
SetRestriction(iRestrict, pVariantFirst);
|
|
else
|
|
SetRestriction(iRestrict);
|
|
|
|
hr = GetRowsetHelper(NULL, iRestrict);
|
|
|
|
// Provider is allowed to return E_INVALIDARG if restriction is not supported.
|
|
if (hrExpected == DB_E_NOTSUPPORTED && hr == E_INVALIDARG)
|
|
hrExpected = hr;
|
|
|
|
TESTC_(hr, hrExpected);
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
ClearRestrictions();
|
|
|
|
SetRestrictionArray(RT_SUPPORTED);
|
|
|
|
return fResult;
|
|
}
|
|
|
|
BOOL CHelper::IsRestricted(ULONG iRestrict)
|
|
{
|
|
// A valid restriction must be within range
|
|
if (COMPARE(iRestrict > 0 && iRestrict <= m_pSchemaInfo->cRestrictions, TRUE))
|
|
{
|
|
return (!m_rgRestrictUsed || m_rgRestrictUsed[iRestrict-1].vt != VT_EMPTY);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void CHelper::SetRestriction(ULONG iRestrict)
|
|
{
|
|
// A valid restriction must be within range
|
|
if (COMPARE(iRestrict > 0 && iRestrict <= m_pSchemaInfo->cRestrictions, TRUE))
|
|
{
|
|
VariantClear(&m_rgRestrictUsed[iRestrict-1]);
|
|
CHECK(VariantCopy(&m_rgRestrictUsed[iRestrict-1], &m_rgRestrict[iRestrict-1]), S_OK);
|
|
}
|
|
}
|
|
|
|
// Set a list of allowed values for this columm
|
|
BOOL CHelper::GetValidColumnValues(DBORDINAL iOrdinal, ULONG * pcValidValues, LPVOID * ppValidValues)
|
|
{
|
|
// Make sure ordinal is valid
|
|
if (!iOrdinal || iOrdinal > m_pSchemaInfo->cColumns)
|
|
return FALSE;
|
|
|
|
// Make sure out params were passed
|
|
if (!pcValidValues || !ppValidValues)
|
|
return FALSE;
|
|
|
|
*pcValidValues = m_pSchemaInfo->pColList[iOrdinal-1].cValidVals;
|
|
*ppValidValues = m_pSchemaInfo->pColList[iOrdinal-1].pValidVals;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Set a list of allowed values for this columm
|
|
BOOL CHelper::SetValidColumnValues(DBORDINAL iOrdinal, ULONG cValidValues, LPVOID pValidValues)
|
|
{
|
|
// Make sure ordinal is valid
|
|
if (!iOrdinal || iOrdinal > m_pSchemaInfo->cColumns)
|
|
return FALSE;
|
|
|
|
m_pSchemaInfo->pColList[iOrdinal-1].cValidVals = cValidValues;
|
|
m_pSchemaInfo->pColList[iOrdinal-1].pValidVals = pValidValues;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CHelper::SetValidRestriction(ULONG iRestrict)
|
|
{
|
|
// A valid restriction must be within range
|
|
if (COMPARE(iRestrict > 0 && iRestrict <= m_pSchemaInfo->cRestrictions, TRUE))
|
|
{
|
|
VariantClear(&m_rgRestrictUsed[iRestrict-1]);
|
|
CHECK(VariantCopy(&m_rgRestrictUsed[iRestrict-1], &m_rgRestrictValid[iRestrict-1]), S_OK);
|
|
}
|
|
}
|
|
|
|
void CHelper::SetEmptyRestrict(ULONG iRestrict)
|
|
{
|
|
// A valid restriction must be within range
|
|
if (COMPARE(iRestrict > 0 && iRestrict <= m_pSchemaInfo->cRestrictions, TRUE))
|
|
{
|
|
VariantClear(&m_rgRestrictUsed[iRestrict-1]);
|
|
V_VT(&m_rgRestrictUsed[iRestrict-1]) = VT_EMPTY;
|
|
}
|
|
}
|
|
|
|
BOOL CHelper::SetRestriction(ULONG iRestrict, VARIANT * pVariant)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
|
|
TESTC(pVariant != NULL);
|
|
|
|
VariantClear(&m_rgRestrictUsed[iRestrict-1]);
|
|
|
|
TESTC_(VariantCopy(&m_rgRestrictUsed[iRestrict-1], pVariant), S_OK);
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
return fResult;
|
|
}
|
|
|
|
|
|
BOOL CHelper::SetRestriction(ULONG iRestrict, LPVOID pValue)
|
|
{
|
|
VARIANT * pVariant = NULL;
|
|
DBTYPE wType;
|
|
DBORDINAL iOrdinal;
|
|
BOOL fResult = FALSE;
|
|
|
|
// Must be within range
|
|
if (COMPARE(iRestrict > 0 && iRestrict <= m_pSchemaInfo->cRestrictions, TRUE))
|
|
{
|
|
iOrdinal = m_pSchemaInfo->pulRestrictions[iRestrict-1];
|
|
wType = m_pSchemaInfo->pColList[iOrdinal-1].wType;
|
|
|
|
VariantClear(&m_rgRestrictUsed[iRestrict-1]);
|
|
pVariant = DBTYPE2VARIANT(pValue, wType);
|
|
TESTC(pVariant != NULL);
|
|
|
|
TESTC_(VariantCopy(&m_rgRestrictUsed[iRestrict-1], pVariant), S_OK);
|
|
|
|
fResult = TRUE;
|
|
}
|
|
|
|
CLEANUP:
|
|
if (pVariant)
|
|
VariantClear(pVariant);
|
|
SAFE_FREE(pVariant);
|
|
|
|
return fResult;
|
|
}
|
|
|
|
BOOL CHelper::SetRestriction(ULONG iRestrict, LPVOID pValue, DBTYPE wType)
|
|
{
|
|
VARIANT * pVariant = NULL;
|
|
BOOL fResult = FALSE;
|
|
|
|
// Must be within range
|
|
if (COMPARE(iRestrict > 0 && iRestrict <= MAXRESTRICTION, TRUE))
|
|
{
|
|
VariantClear(&m_rgRestrictUsed[iRestrict-1]);
|
|
pVariant = DBTYPE2VARIANT(pValue, wType);
|
|
TESTC(pVariant != NULL);
|
|
|
|
TESTC_(VariantCopy(&m_rgRestrictUsed[iRestrict-1], pVariant), S_OK);
|
|
|
|
fResult = TRUE;
|
|
}
|
|
|
|
CLEANUP:
|
|
if (pVariant)
|
|
VariantClear(pVariant);
|
|
SAFE_FREE(pVariant);
|
|
|
|
return fResult;
|
|
}
|
|
|
|
BOOL CHelper::SetInvalidRestriction(ULONG iRestrict, LPVOID pValue, DBTYPE wType)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
|
|
// Must be within range
|
|
if (COMPARE(iRestrict > 0 && iRestrict <= MAXRESTRICTION, TRUE))
|
|
{
|
|
VariantClear(&m_rgRestrictUsed[iRestrict-1]);
|
|
V_VT(&m_rgRestrictUsed[iRestrict-1]) = wType;
|
|
m_rgRestrictUsed[iRestrict-1].punkVal = (struct IUnknown *)pValue;
|
|
|
|
fResult = TRUE;
|
|
}
|
|
|
|
return fResult;
|
|
}
|
|
|
|
|
|
void CHelper::SetRestrictionType(ULONG iRestrict, DBTYPE wType)
|
|
{
|
|
if (COMPARE(iRestrict > 0 && iRestrict <= MAXRESTRICTION, TRUE))
|
|
V_VT(&m_rgRestrictUsed[iRestrict-1]) = wType;
|
|
}
|
|
|
|
VARIANT * CHelper::GetRestrictPtr(ULONG iRestrict)
|
|
{
|
|
VARIANT * prgRestrictions = NULL;
|
|
|
|
if (COMPARE(iRestrict > 0 && iRestrict <= MAXRESTRICTION, TRUE))
|
|
{
|
|
switch(m_eRestrictArray)
|
|
{
|
|
case RT_CACHED:
|
|
prgRestrictions = m_rgRestrict;
|
|
break;
|
|
case RT_SUPPORTED:
|
|
prgRestrictions = m_rgRestrictValid;
|
|
break;
|
|
case RT_CUSTOM:
|
|
prgRestrictions = m_rgRestrictUsed;
|
|
break;
|
|
}
|
|
|
|
_ASSERTE(prgRestrictions);
|
|
|
|
return &prgRestrictions[iRestrict-1];
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
BOOL CHelper::FillRestrictions(DBCOUNTITEM iRow, LPBYTE pData)
|
|
{
|
|
// Fill restrictions with values from this row
|
|
DBTYPE wType;
|
|
ULONG iRestrict = 0;
|
|
ULONG iEnd = m_pSchemaInfo->cRestrictions;
|
|
VARIANT * pVariant = NULL;
|
|
LPBYTE pValue = NULL;
|
|
BOOL fResult = FALSE;
|
|
|
|
// If we're not on the right row, then bail
|
|
if (iRow != m_ulRestrictRow)
|
|
return TRUE;
|
|
|
|
// This is the right row, fill the restriction column(s) desired
|
|
if (m_iRestrict)
|
|
{
|
|
// Only want to restrict this restriction, convert to 0-based
|
|
iRestrict = m_iRestrict-1;
|
|
TESTC(iRestrict < iEnd); // Make sure a bad restriction wasn't passed
|
|
iEnd = m_iRestrict;
|
|
}
|
|
|
|
|
|
for (; iRestrict < iEnd; iRestrict++)
|
|
{
|
|
DBORDINAL iOrdinal = m_pSchemaInfo->pulRestrictions[iRestrict];
|
|
wType = m_pSchemaInfo->pColList[iOrdinal-1].wType;
|
|
pValue = GetValuePtr(iOrdinal, pData, m_rgDBBINDING);
|
|
|
|
// If there is no value, then restriction must be VT_NULL;
|
|
if (!pValue)
|
|
{
|
|
V_VT(&m_rgRestrict[iRestrict]) = VT_NULL;
|
|
continue;
|
|
}
|
|
|
|
// GUID restrictions are mapped to BSTR
|
|
if (wType == DBTYPE_GUID)
|
|
{
|
|
wType = DBTYPE_BSTR;
|
|
// We don't support this yet, need conversionn from GUID->BSTR
|
|
TESTC(FALSE);
|
|
}
|
|
|
|
pVariant = DBTYPE2VARIANT(pValue, wType);
|
|
|
|
TESTC(pVariant != NULL);
|
|
|
|
TESTC_(VariantCopy(&m_rgRestrict[iRestrict], pVariant), S_OK)
|
|
|
|
VariantClear(pVariant);
|
|
SAFE_FREE(pVariant);
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
if (pVariant)
|
|
VariantClear(pVariant);
|
|
SAFE_FREE(pVariant);
|
|
|
|
m_fCaptured = TRUE; // Otherwise we'll loop forever looking for restriction
|
|
|
|
return fResult;
|
|
}
|
|
|
|
BOOL CHelper::GetRestrictions(ULONG iRestrict)
|
|
{
|
|
IRowset * pIRowset = NULL;
|
|
BOOL fResult = FALSE;
|
|
|
|
// Pick a row and use this row's value for restriction iRestrict (1-based)
|
|
// If iRestrict is 0, then all restrictions are filled from this row.
|
|
|
|
// At some later time we will add code to select an interesting restriction such
|
|
// as a NULL value.
|
|
|
|
// For now the row is hard-coded, but later we will use some heuristic to determine
|
|
m_ulRestrictRow = 2;
|
|
m_iRestrict = iRestrict;
|
|
m_fCaptureRestrictions = TRUE;
|
|
m_fCaptured = FALSE;
|
|
|
|
// Clear all cached restrictions
|
|
ClearRestrictions(m_rgRestrict);
|
|
|
|
// Call the GetRowsetHelper to actually do the work of filling the restrictions
|
|
// if the schema is supported, otherwise just leave VT_EMPTY
|
|
if (m_fSupported)
|
|
{
|
|
TESTC_(GetRowsetHelper(NULL, RV_NULL), S_OK);
|
|
|
|
// Now m_rgRestrict is filled with valid known values for each possible restriction,
|
|
// but not all of them may be supported restrictions. Copy supported restrictions to
|
|
// m_rgRestrictValid.
|
|
for (iRestrict = 1; iRestrict <= m_pSchemaInfo->cRestrictions; iRestrict++)
|
|
{
|
|
if (IsSupportedRestriction(iRestrict))
|
|
{
|
|
VariantClear(&m_rgRestrictValid[iRestrict-1]);
|
|
TESTC_(VariantCopy(&m_rgRestrictValid[iRestrict-1], &m_rgRestrict[iRestrict-1]), S_OK)
|
|
}
|
|
}
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
return fResult;
|
|
|
|
}
|
|
|
|
BOOL CHelper::IsSupportedRestriction(ULONG iRestrict)
|
|
{
|
|
if (COMPARE(iRestrict > 0, TRUE))
|
|
return m_ulRestrictionSupport & (1<<(iRestrict-1));
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CHelper::HasUnsupportedRestriction(void)
|
|
{
|
|
for(ULONG iRestrict = 1; iRestrict <= m_pSchemaInfo->cRestrictions; iRestrict++)
|
|
{
|
|
if (!IsSupportedRestriction(iRestrict))
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void CHelper::SetRowCount(ROW_COUNT eRowCount, DBORDINAL ulRowCount)
|
|
{
|
|
m_eRowCount = eRowCount;
|
|
m_ulRowCount = ulRowCount;
|
|
}
|
|
|
|
BOOL CHelper::CheckAgainstIColumnsInfo(SchemaList * pSchemaInfo)
|
|
{
|
|
BOOL fResult = TRUE;
|
|
BOOL fCountNotChecked= FALSE;
|
|
BOOL fBookmark = FALSE;
|
|
ULONG ulIndex = 0;
|
|
ColList * pColList = pSchemaInfo->pColList;
|
|
ULONG cCols = pSchemaInfo->cColumns;
|
|
ULONG iOrdinalExpected = 0;
|
|
ULONG iSchemaInfo = 0;
|
|
|
|
// Make sure the right number of columns were returned for this schema
|
|
COMPARE(cCols <= (m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal), TRUE);
|
|
|
|
// Make sure the rowset is not null
|
|
if((!m_pIRowset) || (!m_cDBCOLUMNINFO) || (!m_rgDBCOLUMNINFO) || (!m_pStringsBuffer)) {
|
|
odtLog << L"CheckAgainstIColumnsInfo:Either rowset or DBCOLUMNINFO variables are null."<<ENDL;
|
|
return FALSE;
|
|
}
|
|
|
|
// Check for the Bookmark
|
|
if(!m_rgDBCOLUMNINFO[0].iOrdinal)
|
|
fBookmark=TRUE;
|
|
|
|
if (fBookmark)
|
|
{
|
|
if (!COMPARE(GetProperty(DBPROP_BOOKMARKS,DBPROPSET_ROWSET,m_pIRowset), TRUE))
|
|
odtLog << m_pSchemaInfo->pwszName << L": Bookmark column was found but the DBPROP_BOOKMARKS was not set.\n";
|
|
}
|
|
|
|
// Check column ordering, column name and data type, skip bookmark column
|
|
for(ulIndex = (0 + fBookmark); ulIndex < m_cDBCOLUMNINFO; ulIndex ++)
|
|
{
|
|
iOrdinalExpected = ulIndex-fBookmark+1;
|
|
iSchemaInfo = ulIndex-fBookmark;
|
|
|
|
// only check spec'd columns, not any provider-specific columns
|
|
if(iSchemaInfo < cCols)
|
|
{
|
|
// Check column ordinal
|
|
if(!COMPARE(m_rgDBCOLUMNINFO[ulIndex].iOrdinal, iOrdinalExpected))
|
|
{
|
|
odtLog << L"ORDINAL [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex
|
|
<< L"]: Expected "<< iOrdinalExpected << L", Received " << m_rgDBCOLUMNINFO[ulIndex].iOrdinal << ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
|
|
// If there is a name in this column, check to make sure it is correct
|
|
if( (m_rgDBCOLUMNINFO[ulIndex].pwszName) &&
|
|
(!COMPARE(0, _wcsicmp(m_rgDBCOLUMNINFO[ulIndex].pwszName,pColList[iSchemaInfo].pwszName))))
|
|
{
|
|
odtLog << L"NAME [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L","
|
|
<< ulIndex << L"]: Expected " << pColList[iSchemaInfo].pwszName << L", Received "
|
|
<< m_rgDBCOLUMNINFO[ulIndex].pwszName << ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
|
|
// Check column type
|
|
if(!COMPARE(m_rgDBCOLUMNINFO[ulIndex].wType, pColList[iSchemaInfo].wType))
|
|
{
|
|
odtLog << L"TYPE [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex << L"]: Expected "
|
|
<< pColList[iSchemaInfo].wType << L", Received " << m_rgDBCOLUMNINFO[ulIndex].wType << ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
|
|
// Check column size
|
|
if((!IsFixedLength(m_rgDBCOLUMNINFO[ulIndex].wType)) && (!m_rgDBCOLUMNINFO[ulIndex].ulColumnSize))
|
|
{
|
|
odtLog << L"COLUMNSIZE [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex << L"]: "
|
|
<< L"Column Size for variable length Column is ZERO, expected non-zero." << ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
else if((IsFixedLength(m_rgDBCOLUMNINFO[ulIndex].wType)) &&
|
|
(!COMPARE((ULONG)GetDBTypeSize(m_rgDBCOLUMNINFO[ulIndex].wType), m_rgDBCOLUMNINFO[ulIndex].ulColumnSize)))
|
|
{
|
|
odtLog << L"COLUMNSIZE [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex << L"]: Expected "
|
|
<< L"Column Size for the Column is incorrect. " << ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
|
|
// Check column precision and scale
|
|
// Note some provider return an alternate precision/scale for
|
|
// DBTYPE_CY
|
|
if(IsNumericType(m_rgDBCOLUMNINFO[ulIndex].wType) &&
|
|
m_rgDBCOLUMNINFO[ulIndex].wType != DBTYPE_CY)
|
|
{
|
|
ULONG MaxPrecision = 0;
|
|
|
|
// Switch on the Type
|
|
switch(m_rgDBCOLUMNINFO[ulIndex].wType)
|
|
{
|
|
case DBTYPE_I1:
|
|
case DBTYPE_UI1:
|
|
MaxPrecision = 3;
|
|
break;
|
|
case DBTYPE_I2:
|
|
case DBTYPE_UI2:
|
|
MaxPrecision = 5;
|
|
break;
|
|
case DBTYPE_R4:
|
|
MaxPrecision = 7;
|
|
break;
|
|
case DBTYPE_I4:
|
|
case DBTYPE_UI4:
|
|
MaxPrecision = 10;
|
|
break;
|
|
case DBTYPE_R8:
|
|
MaxPrecision = 15;
|
|
break;
|
|
case DBTYPE_CY:
|
|
case DBTYPE_I8:
|
|
MaxPrecision = 19;
|
|
break;
|
|
case DBTYPE_UI8:
|
|
MaxPrecision = 20;
|
|
break;
|
|
}
|
|
|
|
// Precision is valid
|
|
if (((m_rgDBCOLUMNINFO[ulIndex].wType != DBTYPE_DECIMAL) &&
|
|
(m_rgDBCOLUMNINFO[ulIndex].wType != DBTYPE_NUMERIC) &&
|
|
(m_rgDBCOLUMNINFO[ulIndex].wType != DBTYPE_VARNUMERIC)) &&
|
|
(MaxPrecision != m_rgDBCOLUMNINFO[ulIndex].bPrecision) )
|
|
{
|
|
odtLog << L"PRECISION [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex << L"]: Expected "
|
|
<< MaxPrecision << L", Received " << m_rgDBCOLUMNINFO[ulIndex].bPrecision << ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
|
|
// Scale is ~0
|
|
if (((m_rgDBCOLUMNINFO[ulIndex].wType != DBTYPE_DECIMAL) &&
|
|
(m_rgDBCOLUMNINFO[ulIndex].wType != DBTYPE_NUMERIC) &&
|
|
(m_rgDBCOLUMNINFO[ulIndex].wType != DBTYPE_VARNUMERIC)) &&
|
|
(!COMPARE((BYTE)(~0), m_rgDBCOLUMNINFO[ulIndex].bScale)))
|
|
{
|
|
odtLog << L"SCALE [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex
|
|
<< L"]: Expected the Scale to be ~0" << L", Received " << m_rgDBCOLUMNINFO[ulIndex].bScale << ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
else if (m_rgDBCOLUMNINFO[ulIndex].wType == DBTYPE_DBTIMESTAMP ||
|
|
m_rgDBCOLUMNINFO[ulIndex].wType == DBTYPE_CY)
|
|
{
|
|
CCol TempCol;
|
|
BYTE bPrecision = 0;
|
|
BYTE bScale = 0;
|
|
|
|
// Get bPrecision and bScale for DBTYPE_DBTIMESTAMP or
|
|
// DBTYPE_CY from CCol object
|
|
for (DBORDINAL iCol = 1; iCol <= m_pTable->CountColumnsOnTable(); iCol++)
|
|
{
|
|
// Get the information about the column
|
|
if (!CHECK(m_pTable->GetColInfo(iCol, TempCol), S_OK))
|
|
{
|
|
fResult = FALSE;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// If this is DBTYPE_DBTIMESTAMP it may be the right one
|
|
if (m_rgDBCOLUMNINFO[ulIndex].wType == TempCol.GetProviderType())
|
|
{
|
|
bPrecision = TempCol.GetPrecision();
|
|
bScale = TempCol.GetScale();
|
|
|
|
if (bPrecision == m_rgDBCOLUMNINFO[ulIndex].bPrecision &&
|
|
bScale == m_rgDBCOLUMNINFO[ulIndex].bScale)
|
|
{
|
|
// We found a matching value for precision and scale
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Precision is defined as length of string representation assuming max
|
|
// allowed precision of fractional seconds component.
|
|
// TODO: Compare against CCol.
|
|
if (!COMPARE(m_rgDBCOLUMNINFO[ulIndex].bPrecision, bPrecision))
|
|
{
|
|
odtLog <<L"PRECISION [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex <<"]:expected valid precision."<<ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
|
|
// Scale is just the maximum length of the string representation of
|
|
// fractional seconds component.
|
|
if (!COMPARE(m_rgDBCOLUMNINFO[ulIndex].bScale, bScale))
|
|
{
|
|
odtLog <<L"SCALE [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex <<"]:expected valid scale."<<ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Precision and scale are ~0
|
|
if (((BYTE)(~0) != m_rgDBCOLUMNINFO[ulIndex].bPrecision) || ((BYTE)(~0) != m_rgDBCOLUMNINFO[ulIndex].bScale))
|
|
{
|
|
COMPARE(0, 1);
|
|
odtLog <<L"PRECISION & SCALE [" << m_rgDBCOLUMNINFO[ulIndex].pwszName << L"," << ulIndex <<"]:non-numeric expect ~0."<<ENDL;
|
|
fResult = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Provider-specific column was found, print warning
|
|
// Since I really don't want to see this warning every time I verify a schema's rowset, but
|
|
// I really do want to see it if there are different provider-specific columns than last
|
|
// time, I guess I have to cache the columns info and compare here before printing the
|
|
// warning - what a pain.
|
|
LPWSTR pwszName = m_rgDBCOLUMNINFO[ulIndex].pwszName;
|
|
LPWSTR pwszPrevName = NULL;
|
|
ULONG ulIndexPrev = 0;
|
|
|
|
if (m_rgDBCOLUMNINFO_Prev)
|
|
{
|
|
ulIndexPrev = ulIndex - !m_rgDBCOLUMNINFO[0].iOrdinal + !m_rgDBCOLUMNINFO_Prev[0].iOrdinal;
|
|
|
|
if (ulIndexPrev < m_cDBCOLUMNINFO_Prev)
|
|
pwszPrevName = m_rgDBCOLUMNINFO_Prev[ulIndexPrev].pwszName;
|
|
}
|
|
|
|
// If we don't know whether the names match print the warning
|
|
if (!pwszName || !pwszPrevName)
|
|
{
|
|
if (!pwszName)
|
|
pwszName = L"<NULL>";
|
|
odtLog << L"Warning - " << m_pSchemaInfo->pwszName << L" provider specific column name: " << pwszName << "\n";
|
|
}
|
|
// If we can tell the names match, don't print the warning
|
|
else if (wcscmp(pwszName, pwszPrevName))
|
|
odtLog << L"Warning - " << m_pSchemaInfo->pwszName << L" provider specific column name: " << pwszName << "\n";
|
|
}
|
|
}
|
|
|
|
CLEANUP:
|
|
|
|
return fResult;
|
|
}
|
|
|
|
HRESULT CHelper::GetNextRows(DBROWOFFSET lOffset, DBROWCOUNT cRows, DBCOUNTITEM* pcRowsObtained, HROW** prghRows)
|
|
{
|
|
ASSERT(prghRows);
|
|
TBEGIN
|
|
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DBCOUNTITEM i=0;
|
|
|
|
//Record if we passed in consumer allocated array...
|
|
HROW* rghRowsInput = *prghRows;
|
|
|
|
//GetNextRows
|
|
HRESULT hr = m_pIRowset->GetNextRows(NULL, lOffset, cRows, &cRowsObtained, prghRows);
|
|
|
|
//Verify Correct values returned
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(hr == S_OK)
|
|
{
|
|
TESTC(cRowsObtained==(DBCOUNTITEM)ABS(cRows));
|
|
}
|
|
else
|
|
{
|
|
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 == 0);
|
|
}
|
|
|
|
//Verify output array, depending upon consumer or provider allocated...
|
|
if(rghRowsInput)
|
|
{
|
|
//This is a users 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);
|
|
}
|
|
|
|
CLEANUP:
|
|
if(pcRowsObtained)
|
|
*pcRowsObtained = cRowsObtained;
|
|
return hr;
|
|
}
|
|
|
|
// GetValuePtr
|
|
// Assumptions: All columns are bound
|
|
LPBYTE CHelper::GetValuePtr(DBORDINAL iOrdinal, LPBYTE pData, DBBINDING * pBinding)
|
|
{
|
|
LPBYTE pValue = NULL;
|
|
DBORDINAL iBind = 0;
|
|
|
|
// If no pData passed in then we can't give the value
|
|
if (!pData)
|
|
return NULL;
|
|
|
|
// If no binding structure passed in assume user wants m_rgDBBINDING
|
|
if (!pBinding)
|
|
pBinding = m_rgDBBINDING;
|
|
|
|
if (pBinding)
|
|
{
|
|
iBind = iOrdinal - pBinding[0].iOrdinal;
|
|
|
|
// We always expect the status to be DBSTATUS_S_OK or DBSTATUS_S_ISNULL, but this is verified
|
|
// earlier in VerifyColumnCommon()
|
|
if (STATUS_BINDING(pBinding[iBind], pData) == DBSTATUS_S_OK)
|
|
pValue = (LPBYTE)&VALUE_BINDING(pBinding[iBind], pData);
|
|
}
|
|
|
|
return pValue;
|
|
}
|
|
|
|
|
|
BOOL CHelper::VerifyRowset(IRowset * pIRowset)
|
|
{
|
|
BOOL fVerifyRow = TRUE;
|
|
HRESULT hr = E_FAIL;
|
|
BOOL fReleaseRowset = FALSE; // whether I should release pIRowset;
|
|
HACCESSOR hAccessor=DB_NULL_HACCESSOR; // handle to accessor
|
|
ULONG iBind = 0; // current binding
|
|
ULONG iRow = 0; // current row
|
|
DBLENGTH cbRowSize = 0; // size of row
|
|
DBCOUNTITEM cRowsObtained = 0; // total rows obtained from getnextrows
|
|
BYTE * pRowBuff = NULL; // row of Data
|
|
HROW * prghRows = NULL; // array of hrows
|
|
IAccessor * pIAccessor = NULL;
|
|
ULONG ulRowsToVerify;
|
|
BOOL fCapturingRestrictions = m_fCaptureRestrictions;
|
|
BOOL fContinue = TRUE;
|
|
GUID guidSchema = *m_pSchemaInfo->pguid;
|
|
|
|
// Reset row count from this schema
|
|
m_cTotalRows = 0;
|
|
|
|
// get bindings and column info
|
|
if(!CHECK(hr=GetAccessorAndBindings(
|
|
pIRowset, // @parmopt [IN] Rowset to create Accessor for
|
|
DBACCESSOR_ROWDATA, // @parmopt [IN] Properties of the Accessor
|
|
&hAccessor, // @parmopt [OUT] Accessor created
|
|
&m_rgDBBINDING, // @parmopt [OUT] Array of DBBINDINGS
|
|
&m_cDBBINDING, // @parmopt [OUT] Count of bindings
|
|
&cbRowSize, // @parmopt [OUT] Length of a row, DATA
|
|
DBPART_VALUE|DBPART_STATUS |DBPART_LENGTH,
|
|
ALL_COLS_BOUND, // @parmopt [IN] Which columns will be used in the bindings
|
|
FORWARD, // @parmopt [IN] Order to bind columns in accessor
|
|
NO_COLS_BY_REF, // @parmopt [IN] Which column types to bind by reference
|
|
&m_rgDBCOLUMNINFO, // @parmopt [OUT] Array of DBCOLUMNINFO
|
|
&m_cDBCOLUMNINFO, // @parmopt [OUT] Count of Columns, also count of ColInfo elements
|
|
&m_pStringsBuffer,
|
|
DBTYPE_EMPTY, // @parmopt [IN] Modifier to be OR'd with each binding type.
|
|
0, // @parmopt [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
|
|
NULL, // @parmopt [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
|
|
NULL, // @parmopt [IN] Corresponds to what ordinals are specified for each binding, if
|
|
NO_COLS_OWNED_BY_PROV, // @parmopt [IN] Which columns' memory is to be owned by the provider
|
|
DBPARAMIO_NOTPARAM, // @parmopt [IN] Parameter kind specified for all bindings
|
|
BLOB_LONG, // @parmopt [IN] how to bind BLOB Columns
|
|
NULL),S_OK)) // @parmopt [OUT] returned status array from CreateAccessor
|
|
goto CLEANUP;
|
|
|
|
// Don't need to check if only capturing restrictions
|
|
if(!m_fCaptureRestrictions)
|
|
{
|
|
fVerifyRow &= CheckAgainstIColumnsInfo(m_pSchemaInfo);
|
|
|
|
// Free any previous columninfo
|
|
SAFE_FREE(m_rgDBCOLUMNINFO_Prev);
|
|
SAFE_FREE(m_pStringsBuffer_Prev);
|
|
|
|
// Save the pointer to the previous columninfo
|
|
m_cDBCOLUMNINFO_Prev = m_cDBCOLUMNINFO;
|
|
m_rgDBCOLUMNINFO_Prev = m_rgDBCOLUMNINFO;
|
|
m_pStringsBuffer_Prev = m_pStringsBuffer;
|
|
}
|
|
|
|
// check if we need to go on
|
|
TESTC(m_cDBBINDING && m_cDBCOLUMNINFO && m_rgDBBINDING && m_rgDBCOLUMNINFO)
|
|
|
|
if(m_fPassUnsupportedRestrictions)
|
|
{
|
|
fVerifyRow = TRUE;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
// create space for two rows of data
|
|
SAFE_ALLOC(pRowBuff, BYTE, cbRowSize*2);
|
|
|
|
m_pRow = pRowBuff; // Start by writing into beginning of buffer
|
|
|
|
if(GetModInfo()->GetDebugMode() & DEBUGMODE_FULL )
|
|
ulRowsToVerify = 90000;
|
|
else
|
|
// This should be larger than NUMROWS_CHUNK to force at least one additional
|
|
// GetNextRows call below.
|
|
ulRowsToVerify = 100;
|
|
|
|
_ASSERTE(m_pRowPrev == NULL);
|
|
|
|
// Process all the rows, NUMROWS_CHUNK rows at a time
|
|
while(fContinue)
|
|
{
|
|
// get rows to process
|
|
hr=GetNextRows(0,30,&cRowsObtained,&prghRows);
|
|
|
|
// odtLog << L"Rows obtained: " << m_cTotalRows + cRowsObtained << L"\n";
|
|
|
|
TEST4C_(hr, S_OK, DB_S_ENDOFROWSET, DB_S_STOPLIMITREACHED, DB_S_ROWLIMITEXCEEDED);
|
|
|
|
// verify that we have rows to process
|
|
if(cRowsObtained==0)
|
|
{
|
|
// Hack for Kagera. Kagera will not return rows from many schemas when unrestricted,
|
|
// so we are unable to capture any restrictions. In this case Kagera will return rows
|
|
// when restricted to a table, and since we know at least one valid table, use that one
|
|
if (g_fKagera && m_fCaptureRestrictions)
|
|
{
|
|
ULONG iRestrict = 0; // 0 based restriction index
|
|
LPWSTR pwszRestrict = NULL;
|
|
|
|
if (guidSchema == DBSCHEMA_COLUMN_PRIVILEGES ||
|
|
guidSchema == DBSCHEMA_COLUMNS ||
|
|
guidSchema == DBSCHEMA_CONSTRAINT_COLUMN_USAGE ||
|
|
guidSchema == DBSCHEMA_CONSTRAINT_TABLE_USAGE ||
|
|
guidSchema == DBSCHEMA_STATISTICS ||
|
|
guidSchema == DBSCHEMA_TABLE_PRIVILEGES ||
|
|
guidSchema == DBSCHEMA_TABLE_STATISTICS ||
|
|
guidSchema == DBSCHEMA_TABLES ||
|
|
guidSchema == DBSCHEMA_TABLES_INFO ||
|
|
guidSchema == DBSCHEMA_VIEWS)
|
|
{
|
|
// Use table name as restriction
|
|
pwszRestrict = m_pTable->GetTableName();
|
|
iRestrict = 2;
|
|
}
|
|
else if (guidSchema == DBSCHEMA_INDEXES)
|
|
{
|
|
// Use table name as restriction
|
|
pwszRestrict = m_pTable->GetTableName();
|
|
iRestrict = 4;
|
|
}
|
|
else if (guidSchema == DBSCHEMA_PRIMARY_KEYS)
|
|
{
|
|
// Use primary/foreign key table name as restriction
|
|
pwszRestrict = g_pKeyTable1->GetTableName();
|
|
iRestrict = 2;
|
|
}
|
|
else if (guidSchema == DBSCHEMA_FOREIGN_KEYS) // This is really FK_TABLE_NAME, but it will suffice
|
|
{
|
|
// Use primary/foreign key table name as restriction
|
|
pwszRestrict = g_pKeyTable1->GetTableName();
|
|
iRestrict = 5;
|
|
}
|
|
else if (guidSchema == DBSCHEMA_KEY_COLUMN_USAGE ||
|
|
guidSchema == DBSCHEMA_TABLE_CONSTRAINTS)
|
|
{
|
|
// Use table name as restriction
|
|
pwszRestrict = m_pTable->GetTableName();
|
|
iRestrict = 5;
|
|
}
|
|
|
|
// Set the restriction to use
|
|
V_VT(&m_rgRestrictValid[iRestrict]) = VT_BSTR;
|
|
V_BSTR(&m_rgRestrictValid[iRestrict]) = SysAllocString(pwszRestrict);
|
|
|
|
// Clean up array binding information and release memory associated with empty rowset
|
|
if (pIAccessor && hAccessor != DB_NULL_HACCESSOR)
|
|
CHECK(pIAccessor->ReleaseAccessor(hAccessor, NULL), S_OK);
|
|
|
|
SAFE_RELEASE(pIAccessor);
|
|
SAFE_RELEASE(m_pIRowset);
|
|
SAFE_FREE(m_rgDBCOLUMNINFO);
|
|
SAFE_FREE(m_pStringsBuffer);
|
|
SAFE_FREE(m_rgDBBINDING);
|
|
SAFE_FREE(prghRows);
|
|
|
|
// Call again with a table name restriction
|
|
hr=m_pIDBSchemaRowset->GetRowset(NULL, guidSchema, m_pSchemaInfo->cRestrictions, m_rgRestrictValid,
|
|
IID_IRowset, 0, NULL, (IUnknown **)&m_pIRowset);
|
|
|
|
TESTC_(hr, S_OK);
|
|
|
|
// get bindings and column info
|
|
if(!CHECK(hr=GetAccessorAndBindings(
|
|
m_pIRowset, // @parmopt [IN] Rowset to create Accessor for
|
|
DBACCESSOR_ROWDATA, // @parmopt [IN] Properties of the Accessor
|
|
&hAccessor, // @parmopt [OUT] Accessor created
|
|
&m_rgDBBINDING, // @parmopt [OUT] Array of DBBINDINGS
|
|
&m_cDBBINDING, // @parmopt [OUT] Count of bindings
|
|
&cbRowSize, // @parmopt [OUT] Length of a row, DATA
|
|
DBPART_VALUE|DBPART_STATUS |DBPART_LENGTH,
|
|
ALL_COLS_BOUND, // @parmopt [IN] Which columns will be used in the bindings
|
|
FORWARD, // @parmopt [IN] Order to bind columns in accessor
|
|
NO_COLS_BY_REF, // @parmopt [IN] Which column types to bind by reference
|
|
&m_rgDBCOLUMNINFO, // @parmopt [OUT] Array of DBCOLUMNINFO
|
|
&m_cDBCOLUMNINFO, // @parmopt [OUT] Count of Columns, also count of ColInfo elements
|
|
&m_pStringsBuffer,
|
|
DBTYPE_EMPTY, // @parmopt [IN] Modifier to be OR'd with each binding type.
|
|
0, // @parmopt [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
|
|
NULL, // @parmopt [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
|
|
NULL, // @parmopt [IN] Corresponds to what ordinals are specified for each binding, if
|
|
NO_COLS_OWNED_BY_PROV, // @parmopt [IN] Which columns' memory is to be owned by the provider
|
|
DBPARAMIO_NOTPARAM, // @parmopt [IN] Parameter kind specified for all bindings
|
|
BLOB_LONG, // @parmopt [IN] how to bind BLOB Columns
|
|
NULL),S_OK)) // @parmopt [OUT] returned status array from CreateAccessor
|
|
goto CLEANUP;
|
|
|
|
// Call GetNextRows again
|
|
hr=GetNextRows(0,30,&cRowsObtained,&prghRows);
|
|
|
|
// Make sure we don't leak the restriction
|
|
VariantClear(&m_rgRestrictValid[iRestrict]);
|
|
|
|
// Theoretically we now have some rows, but if not we're still in the same boat we were before
|
|
}
|
|
|
|
if (cRowsObtained == 0)
|
|
{
|
|
TESTC_(hr, DB_S_ENDOFROWSET);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Only verify required number of rows
|
|
if (m_cTotalRows < ulRowsToVerify)
|
|
{
|
|
// Make sure we don't call verify with no valid restrictions.
|
|
// ASSERT((m_restrict != ALLRES) || (m_currentBitMask == 0));
|
|
|
|
// Loop over rows obtained, getting data for each
|
|
for(iRow=0;iRow<cRowsObtained && fContinue;iRow++)
|
|
{
|
|
m_cTotalRows++;
|
|
|
|
// get row
|
|
TESTC_(m_pIRowset->GetData(prghRows[iRow],hAccessor,m_pRow), S_OK)
|
|
|
|
// If we are just capturing restrictions then don't do verification
|
|
if (m_fCaptureRestrictions)
|
|
{
|
|
// Adjust our restriction row if the rowset doesn't have enough rows
|
|
if (m_cTotalRows - 1 + cRowsObtained < m_ulRestrictRow)
|
|
m_ulRestrictRow = m_cTotalRows - 1 + cRowsObtained;
|
|
|
|
TESTC(FillRestrictions(m_cTotalRows, m_pRow))
|
|
}
|
|
else
|
|
{
|
|
// Verify the row
|
|
fVerifyRow &= VerifyRowCommon(m_cTotalRows,m_pRow);
|
|
|
|
// Reset to point to the next available row location
|
|
m_pRowPrev = m_pRow;
|
|
if (m_pRow == pRowBuff)
|
|
m_pRow += cbRowSize;
|
|
else
|
|
m_pRow = pRowBuff;
|
|
}
|
|
|
|
// If we know we've filled the restriction then break out of loop
|
|
// Otherwise we continue for all rows
|
|
if (m_fCaptureRestrictions && m_fCaptured)
|
|
{
|
|
m_fCaptureRestrictions = FALSE;
|
|
fContinue = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
m_cTotalRows += cRowsObtained;
|
|
|
|
TESTC_(m_pIRowset->ReleaseRows(cRowsObtained,prghRows,NULL,NULL,NULL),S_OK)
|
|
|
|
SAFE_FREE(prghRows);
|
|
}
|
|
|
|
switch (m_eRowCount)
|
|
{
|
|
case MIN_VALUE:
|
|
// Warn if we didn't get any rows but expected some
|
|
if (m_ulRowCount && !m_cTotalRows)
|
|
odtLog << L"Warning - this rowset didn't return any rows so no values were checked.\n";
|
|
|
|
// Fail if we got some rows but less than minimum expected
|
|
if (m_cTotalRows)
|
|
TESTC(m_cTotalRows >= m_ulRowCount);
|
|
break;
|
|
case MIN_REQUIRED:
|
|
// Fail if we got less than minimum expected
|
|
if (!COMPARE(m_cTotalRows >= m_ulRowCount, TRUE))
|
|
odtLog << L"Min row count not retrieved. Expected: >= " << m_ulRowCount << L" Received: " << m_cTotalRows
|
|
<< L"\n";
|
|
break;
|
|
case EXACT_VALUE:
|
|
// ASSERT(m_cTotalRows == m_ulRowCount);
|
|
if (m_cTotalRows != m_ulRowCount)
|
|
odtLog << L"Expected " << m_ulRowCount << " rows, received " << m_cTotalRows << " rows.\n";
|
|
|
|
TESTC(m_cTotalRows == m_ulRowCount);
|
|
break;
|
|
default:
|
|
ASSERT(!L"Unexpected row count value for schema rowset.");
|
|
}
|
|
|
|
|
|
CLEANUP:
|
|
|
|
// If we were capturing restrictions but didn't capture them for some reason
|
|
// then return FALSE
|
|
if (m_fCaptureRestrictions && !m_fCaptured)
|
|
{
|
|
fVerifyRow = FALSE;
|
|
m_fCaptureRestrictions = FALSE; // Don't continue to capture
|
|
COMPARE(TRUE, FALSE);
|
|
}
|
|
|
|
if (pIAccessor && hAccessor != DB_NULL_HACCESSOR)
|
|
CHECK(pIAccessor->ReleaseAccessor(hAccessor, NULL), S_OK);
|
|
|
|
SAFE_RELEASE(pIAccessor);
|
|
SAFE_RELEASE(m_pIRowset);
|
|
|
|
m_cDBCOLUMNINFO = 0;
|
|
m_cDBBINDING = 0;
|
|
|
|
// m_pRowPrev and m_pRow just point into pRowBuff, so don't free them, but
|
|
// set to NULL to avoid using in later variations.
|
|
m_pRow = NULL;
|
|
m_pRowPrev = NULL;
|
|
if(!m_cDBCOLUMNINFO_Prev)
|
|
{
|
|
PROVIDER_FREE(m_rgDBCOLUMNINFO);
|
|
PROVIDER_FREE(m_pStringsBuffer);
|
|
}
|
|
else
|
|
{
|
|
m_rgDBCOLUMNINFO = NULL; // This is not freed, since it's used in m_rgDBCOLUMNINFO_prev
|
|
m_pStringsBuffer = NULL; // ""
|
|
}
|
|
|
|
// Free the memory
|
|
PROVIDER_FREE(m_rgDBBINDING);
|
|
PROVIDER_FREE(pRowBuff);
|
|
|
|
return fVerifyRow;
|
|
}
|
|
|
|
BOOL CHelper::CheckResults(HRESULT hr, REFIID riid, IUnknown * pIUnknown)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Verify the interface requested is usable
|
|
TESTC(DefaultInterfaceTesting(pIUnknown, ROWSET_INTERFACE, riid))
|
|
|
|
// Verify the properties are correct on the rowset
|
|
// TODO:
|
|
|
|
// Get a rowset interface
|
|
TESTC(VerifyInterface(pIUnknown, IID_IRowset,
|
|
ROWSET_INTERFACE, (IUnknown**)&m_pIRowset))
|
|
|
|
// Make sure the rowset is correct
|
|
VerifyRowset(m_pIRowset);
|
|
}
|
|
else
|
|
{
|
|
// Should not be a rowset
|
|
TESTC(pIUnknown == NULL);
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
SAFE_RELEASE(m_pIRowset);
|
|
|
|
return fResult;
|
|
}
|
|
|
|
BOOL CHelper::VerifyRowCommon(DBCOUNTITEM iRow, BYTE * pData)
|
|
{
|
|
|
|
ULONG iBind=0; // Binding Count
|
|
DATA * pColumn=NULL; // Data Structure
|
|
CCol col;
|
|
BOOL fResults=TRUE;
|
|
DBORDINAL iOrdinal = 0;
|
|
|
|
// Perform common checks for each schema
|
|
fResults &= VerifySort(iRow, pData);
|
|
|
|
// Many schemas identify a fully qualified table name. Validate this name is valid
|
|
// by attempting to open the table.
|
|
fResults &= VerifyValidTable(iRow, pData);
|
|
|
|
// check each column we're bound to.
|
|
for (iBind=0; iBind < m_cDBBINDING; iBind++)
|
|
{
|
|
// grab column
|
|
pColumn = (DATA *) (pData + m_rgDBBINDING[iBind].obStatus);
|
|
iOrdinal = m_rgDBCOLUMNINFO[iBind].iOrdinal;
|
|
|
|
// PRVTRACE(L"Row[%lu],Col[%s]:%s:", iRow,m_rgDBCOLUMNINFO[iBind].pwszName,m_pSchemaInfo->pwszName);
|
|
|
|
// Perform common checks for each column
|
|
fResults &= VerifyColumnCommon(iBind, pColumn);
|
|
|
|
}
|
|
return fResults;
|
|
}
|
|
|
|
// Compare each value in order for the sort columns. The
|
|
// current row values must be >= previous row values.
|
|
BOOL CHelper::VerifySort(DBCOUNTITEM iRow, BYTE * pData)
|
|
{
|
|
BOOL fResult = TRUE;
|
|
ULONG cSortCols = m_pSchemaInfo->cSort;
|
|
ULONG iSort;
|
|
BOOL fGreater = TRUE;
|
|
|
|
// If not two rows then we can't determine sort
|
|
if (!m_pRowPrev)
|
|
return TRUE;
|
|
|
|
if (!COMPARE(m_pSchemaInfo->pulSort != NULL, TRUE))
|
|
return FALSE;
|
|
|
|
for (iSort = 0; iSort < cSortCols; iSort++)
|
|
{
|
|
ULONG iSortCol = m_pSchemaInfo->pulSort[iSort];
|
|
DBTYPE wType = m_pSchemaInfo->pColList[iSortCol-1].wType;
|
|
LPBYTE pCurrCol = GetValuePtr(iSortCol, pData, m_rgDBBINDING);
|
|
LPBYTE pPrevCol = GetValuePtr(iSortCol, m_pRowPrev, m_rgDBBINDING);
|
|
LONG fComp;
|
|
|
|
// We assume NULLs are equal
|
|
if (!pCurrCol && !pPrevCol)
|
|
continue;
|
|
|
|
// If one of the values is NULL then we have to use DBPROP_NULLCOLLATION to decide
|
|
// if they're sorted properly
|
|
if ((pCurrCol == NULL) || (pPrevCol == NULL))
|
|
{
|
|
if (pCurrCol == pPrevCol)
|
|
fComp = 0; // Equal
|
|
else if (pPrevCol == NULL &&
|
|
(m_ulNullCollation == DBPROPVAL_NC_LOW ||
|
|
m_ulNullCollation == DBPROPVAL_NC_START))
|
|
fComp = 1; // NULL was less than current value
|
|
else if (pCurrCol == NULL &&
|
|
(m_ulNullCollation == DBPROPVAL_NC_HIGH ||
|
|
m_ulNullCollation == DBPROPVAL_NC_END))
|
|
fComp = 1; // Previous value was less than NULL
|
|
else
|
|
fComp = -1; // NULL was not properly sorted
|
|
}
|
|
else
|
|
{
|
|
// If the values don't compare properly, then it's a failure
|
|
fComp = RelativeCompare(pCurrCol, pPrevCol, wType, 0, 0, 0, 0);
|
|
}
|
|
|
|
if (fComp > 0)
|
|
{
|
|
// We found a larger value
|
|
fGreater = TRUE;
|
|
break;
|
|
}
|
|
else if (fComp == 0)
|
|
continue;
|
|
else
|
|
{
|
|
// We found a smaller value, error
|
|
fGreater = FALSE;
|
|
CCOMPARE(m_ECHelper, fGreater == TRUE,
|
|
EC_INCORRECT_SORT,
|
|
L"Sort is incorrect",
|
|
FALSE);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!fGreater)
|
|
fResult = FALSE;
|
|
|
|
return fResult;
|
|
}
|
|
|
|
BOOL CHelper::VerifyValidTable(DBCOUNTITEM iRow, LPBYTE pData)
|
|
{
|
|
// We will only do this for certain specific schemas
|
|
if (m_guidSchema == DBSCHEMA_TABLES ||
|
|
m_guidSchema == DBSCHEMA_TABLES_INFO ||
|
|
m_guidSchema == DBSCHEMA_COLUMNS)
|
|
{
|
|
// Try to open a rowset on the table. The first 3 bindings contain
|
|
// Catalog, Schema, and Table Name, respectively
|
|
GetColumnInfo(pData, m_rgDBBINDING);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CHelper::VerifyLength(DBORDINAL iBind, DATA * pColumn)
|
|
{
|
|
DBTYPE wType = m_rgDBCOLUMNINFO[iBind].wType;
|
|
size_t ulLength = GetDBTypeSize(wType);
|
|
BOOL fResult = TRUE;
|
|
|
|
// GetDBTypeSize won't return a value for variable length columns
|
|
if (!ulLength)
|
|
{
|
|
switch(wType)
|
|
{
|
|
case DBTYPE_STR:
|
|
ulLength = strlen((LPSTR)&pColumn->bValue);
|
|
break;
|
|
case DBTYPE_WSTR:
|
|
ulLength = wcslen((LPWSTR)&pColumn->bValue)*sizeof(WCHAR);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (wType == DBTYPE_BYTES)
|
|
{
|
|
// We can't get the length of a BYTES column so we will just
|
|
// attempt to access every byte in the hopes of crashing if
|
|
// the length isn't valid.
|
|
BYTE bVal;
|
|
ULONG iByte;
|
|
for (iByte = 0; iByte < pColumn->ulLength; iByte++)
|
|
bVal = pColumn->bValue[iByte];
|
|
fResult = TRUE;
|
|
}
|
|
else
|
|
fResult = COMPARE(pColumn->ulLength, ulLength);
|
|
|
|
// Also, if the length is greater than cbMaxLen in the binding then
|
|
// our status should be DBSTATUS_S_TRUNCATED
|
|
if (pColumn->ulLength > m_rgDBBINDING[iBind].cbMaxLen)
|
|
fResult &= COMPARE(pColumn->sStatus, DBSTATUS_S_TRUNCATED);
|
|
|
|
return fResult;
|
|
}
|
|
|
|
BOOL CHelper::VerifyColumnCommon(DBORDINAL iBind, DATA * pColumn)
|
|
{
|
|
BOOL fResults = TRUE;
|
|
DBORDINAL iOrdinal = m_rgDBBINDING[iBind].iOrdinal;
|
|
|
|
// Can't verify column values if status is not OK
|
|
if(pColumn->sStatus==DBSTATUS_S_OK)
|
|
{
|
|
// If restrictions were specified, validate they were honored
|
|
fResults &= VerifyRestriction(iOrdinal, pColumn);
|
|
|
|
// If the column requires a set of specific values, make sure
|
|
// it's one of the acceptable values.
|
|
fResults &= VerifyValue(iOrdinal, pColumn);
|
|
|
|
// Perform column type-specific verification
|
|
fResults &= VerifyTypeSpecific(iOrdinal, pColumn);
|
|
|
|
// Verify the length
|
|
fResults &= VerifyLength(iBind, pColumn);
|
|
|
|
// Call the specific validation routine for this particular schema
|
|
fResults &= VerifyColumn(iOrdinal, pColumn);
|
|
}
|
|
else if(pColumn->sStatus==DBSTATUS_S_ISNULL)
|
|
{
|
|
// Some columns may not contain a NULL, validate NULL is
|
|
// OK for this column
|
|
fResults &= VerifyNull(iOrdinal,pColumn);
|
|
|
|
// Length should be 0 for NULL
|
|
// COMPARE(pColumn->ulLength, 0); // Per spec, provider ignores length for NULL data
|
|
|
|
// Call the specific validation routine for this particular schema
|
|
// Some schema columns have varying instances where they can be NULL
|
|
fResults &= VerifyColumn(iOrdinal, pColumn);
|
|
}
|
|
else
|
|
{
|
|
// A non-success status was returned, flag this as a failure
|
|
// We don't think truncation is valid here
|
|
PRVTRACE(L"%s=",m_rgDBCOLUMNINFO[iBind].pwszName);
|
|
// Post a failure and print the status if not OK
|
|
fResults &= COMPARE(RowsetBindingStatus((DBSTATUSENUM)pColumn->sStatus), TRUE);
|
|
}
|
|
|
|
return fResults;
|
|
}
|
|
|
|
BOOL CHelper::VerifyNull(DBORDINAL iOrdinal, DATA * pColumn)
|
|
{
|
|
BOOL fNull = FALSE;
|
|
|
|
// The column's status was DBSTATUS_S_ISNULL, make sure this is OK
|
|
// for this column.
|
|
|
|
// If this is a provider-specific column just return TRUE that
|
|
// NULL is allowed.
|
|
if (iOrdinal > m_pSchemaInfo->cColumns)
|
|
return TRUE;
|
|
|
|
// Otherwise return the value from our table
|
|
fNull = CompareNull(iOrdinal);
|
|
|
|
return fNull;
|
|
}
|
|
|
|
BOOL CHelper::VerifyNonEmptyString(DATA * pColumn, LPWSTR pwszTable, LPWSTR pwszColumn)
|
|
{
|
|
DBSTATUS ulStatus = pColumn->sStatus;
|
|
LPBYTE pValue = pColumn->bValue;
|
|
BOOL fReturn = TRUE;
|
|
|
|
if (!pwszTable)
|
|
pwszTable = L"<NoTable>";
|
|
if (!pwszColumn)
|
|
pwszColumn = L"<NoColumn>";
|
|
|
|
if (ulStatus == DBSTATUS_S_OK)
|
|
{
|
|
// For now, just make sure the length is right so we read the value
|
|
if (!COMPARE(wcslen((WCHAR *)pValue)*sizeof(WCHAR), pColumn->ulLength))
|
|
{
|
|
odtLog << pwszTable << L": " << pwszColumn << L": " <<
|
|
L"Length is incorrect.\n";
|
|
fReturn=FALSE;
|
|
}
|
|
|
|
// We really don't expect empty strings for any of these
|
|
if (!COMPARE(wcslen((WCHAR *)pValue) > 0, TRUE))
|
|
{
|
|
odtLog << pwszTable << L": " << pwszColumn << L": " <<
|
|
L"Empty string returned.\n";
|
|
fReturn=FALSE;
|
|
}
|
|
|
|
}
|
|
else if (!COMPARE(ulStatus, DBSTATUS_S_ISNULL))
|
|
{
|
|
odtLog << pwszTable << L": " << pwszColumn << L": " <<
|
|
L"Invalid status returned.\n";
|
|
fReturn=FALSE;
|
|
}
|
|
|
|
return fReturn;
|
|
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CHelper::VerifyColumnMatch
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CHelper::VerifyColumnMatch(DBORDINAL iOrdinal1, DBORDINAL iOrdinal2)
|
|
{
|
|
LPWSTR pwszCol1 = (LPWSTR)GetValuePtr(iOrdinal1, m_pRow);
|
|
LPWSTR pwszCol2 = (LPWSTR)GetValuePtr(iOrdinal2, m_pRow);
|
|
|
|
if (!pwszCol1 && !pwszCol2)
|
|
return TRUE;
|
|
|
|
TESTC(pwszCol1 != NULL && pwszCol2 != NULL);
|
|
|
|
TESTC(!wcscmp(pwszCol1, pwszCol2));
|
|
|
|
return TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CHelper::VerifyTypeSpecific
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CHelper::VerifyTypeSpecific(DBORDINAL iOrdinal, DATA * pColumn)
|
|
{
|
|
DBTYPE wType = m_rgDBCOLUMNINFO[iOrdinal - m_rgDBCOLUMNINFO[0].iOrdinal].wType;
|
|
BOOL fResult = FALSE;
|
|
|
|
switch(wType)
|
|
{
|
|
case DBTYPE_WSTR:
|
|
// We expect DBSTATUS_S_OK columns to have a non-empty string
|
|
|
|
// Actually, we will comment this out, because there is nothing in the spec to prevent a provider
|
|
// returning an empty string for some columns.
|
|
// TESTC(wcslen((LPWSTR)pColumn->bValue) > 0);
|
|
break;
|
|
case DBTYPE_DATE:
|
|
{
|
|
// We expect a valid date, try to convert to bstr
|
|
VARIANT vDate;
|
|
HRESULT hr = E_FAIL;
|
|
VariantInit(&vDate);
|
|
V_VT(&vDate) = VT_DATE;
|
|
V_DATE(&vDate) = *(DOUBLE *)&pColumn->bValue;
|
|
hr = VariantChangeType(&vDate, &vDate, 0, VT_BSTR);
|
|
VariantClear(&vDate);
|
|
TESTC_(hr, S_OK);
|
|
}
|
|
break;
|
|
default:
|
|
// Do nothing
|
|
break;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
return fResult;
|
|
}
|
|
|
|
|
|
BOOL CHelper::VerifyValue(DBORDINAL iOrdinal, DATA * pColumn)
|
|
{
|
|
ULONG cValidVals;
|
|
LPBYTE pValidVals;
|
|
DBTYPE wType;
|
|
ULONG ulTypeSize;
|
|
BOOL fMatch = FALSE;
|
|
|
|
// If this is a bookmark column, just return TRUE
|
|
// If this is a provider-specific column that we do not know about then just return TRUE that
|
|
// the value is allowed.
|
|
if (!iOrdinal || iOrdinal > m_pSchemaInfo->cColumns)
|
|
return TRUE;
|
|
|
|
// If the column doesn't have a set of defined values, just return TRUE
|
|
if (!m_pSchemaInfo->pColList[iOrdinal-1].cValidVals)
|
|
return TRUE;
|
|
|
|
// Get the values from the table
|
|
cValidVals = m_pSchemaInfo->pColList[iOrdinal-1].cValidVals;
|
|
pValidVals = (LPBYTE)m_pSchemaInfo->pColList[iOrdinal-1].pValidVals;
|
|
wType = m_pSchemaInfo->pColList[iOrdinal-1].wType;
|
|
ulTypeSize = GetDBTypeSize(wType);
|
|
|
|
// GetDBTypeSize returns 0 for variable length types
|
|
switch(wType)
|
|
{
|
|
case DBTYPE_STR:
|
|
ulTypeSize = sizeof(LPSTR);
|
|
break;
|
|
case DBTYPE_WSTR:
|
|
ulTypeSize = sizeof(LPWSTR);
|
|
break;
|
|
}
|
|
|
|
// We must have a non-zero type size
|
|
if (!COMPARE(ulTypeSize > 0, TRUE))
|
|
return FALSE;
|
|
|
|
// If there is a count of values, make sure there is a set of values
|
|
// so hopefully we don't crash if the table is bad
|
|
if (!COMPARE(cValidVals && pValidVals, TRUE))
|
|
return FALSE;
|
|
|
|
// Otherwise make sure it matches one of the values in our table
|
|
for (ULONG iVal = 0; iVal < cValidVals; iVal++)
|
|
{
|
|
LPBYTE pValidVal = pValidVals;
|
|
DBLENGTH cbBackEnd = ulTypeSize, cbConsumer = ulTypeSize;
|
|
|
|
switch(wType)
|
|
{
|
|
case DBTYPE_STR:
|
|
pValidVal = *(LPBYTE *)pValidVals;
|
|
cbBackEnd = strlen((LPSTR)pValidVal);
|
|
cbConsumer = strlen((LPSTR)pColumn->bValue);
|
|
case DBTYPE_WSTR:
|
|
pValidVal = *(LPBYTE *)pValidVals;
|
|
cbBackEnd = wcslen((LPWSTR)pValidVal)*sizeof(WCHAR);
|
|
cbConsumer = wcslen((LPWSTR)pColumn->bValue)*sizeof(WCHAR);
|
|
break;
|
|
}
|
|
|
|
if (CompareDBTypeData(&pColumn->bValue, pValidVal, wType, cbBackEnd, 0, 0, NULL, FALSE, DBTYPE_EMPTY, cbConsumer))
|
|
{
|
|
fMatch = TRUE;
|
|
break;
|
|
}
|
|
pValidVals += ulTypeSize;
|
|
}
|
|
|
|
// Post a failure if we didn't find a match.
|
|
// Providers are allowed to return provider
|
|
if (!fMatch)
|
|
{
|
|
if (*(m_pSchemaInfo->pguid) == DBSCHEMA_TABLES &&
|
|
iOrdinal == TABLES_TABLE_TYPE)
|
|
{
|
|
// Providers are allowed to return provider specific values for TABLE_TYPE, so
|
|
// we can only post a warning if the value doesn't match expected TABLE_TYPE's
|
|
COMPAREW(fMatch, TRUE);
|
|
}
|
|
else
|
|
COMPARE(fMatch, TRUE);
|
|
|
|
odtLog << L"The value returned for column " << m_pSchemaInfo->pColList[iOrdinal-1].pwszName <<
|
|
L" was not in the list of valid values.\n";
|
|
}
|
|
|
|
return fMatch;
|
|
}
|
|
|
|
BOOL CHelper::VerifyRestriction(DBORDINAL iOrdinal, DATA * pColumn)
|
|
{
|
|
// If this is a restriction column, make sure it matches expected
|
|
|
|
BOOL fResult = FALSE;
|
|
ULONG iRestrict;
|
|
VARIANT * pVariant = NULL;
|
|
|
|
// If we didn't pass any restrictions, just return TRUE
|
|
if (!m_prgRestrictUsed)
|
|
return TRUE;
|
|
|
|
// If this is the bookmark column just return true
|
|
if (!iOrdinal)
|
|
return TRUE;
|
|
|
|
// If this is not a restriction column for this schema just return TRUE
|
|
for (iRestrict = 0; iRestrict < m_pSchemaInfo->cRestrictions; iRestrict++)
|
|
{
|
|
// Don't check restrictions we didn't actually use
|
|
if (iRestrict >= m_cRestrictionsUsed)
|
|
break;
|
|
|
|
if (iOrdinal == m_pSchemaInfo->pulRestrictions[iRestrict])
|
|
{
|
|
// This is a restriction column, is it restricted?
|
|
if (V_VT(&m_prgRestrictUsed[iRestrict]) == VT_EMPTY)
|
|
return TRUE;
|
|
|
|
// Convert column value to a variant
|
|
pVariant = DBTYPE2VARIANT(&pColumn->bValue, m_pSchemaInfo->pColList[iOrdinal-1].wType);
|
|
|
|
TESTC(pVariant != NULL);
|
|
|
|
// Compare the variants. Use case insensitive compare for BSTR restrictions
|
|
TESTC(CompareVariant(pVariant, &m_prgRestrictUsed[iRestrict], FALSE));
|
|
|
|
// We found the restriction column, break out of the loop
|
|
break;
|
|
}
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
if (pVariant)
|
|
VariantClear(pVariant);
|
|
SAFE_FREE(pVariant);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
HRESULT CHelper::GetColumnInfo(LPBYTE pData, DBBINDING * pBinding)
|
|
{
|
|
IOpenRowset * pIOpenRowset = NULL;
|
|
IColumnsInfo * pIColumnsInfo = NULL;
|
|
DBID dbid = DB_NULLID;
|
|
HRESULT hr = E_FAIL;
|
|
ULONG iBind = 0, iFirst = 0;
|
|
LPWSTR pwszCat = NULL;
|
|
LPWSTR pwszSch = NULL;
|
|
LPWSTR pwszTable = NULL;
|
|
LPWSTR pwszQualifiedName = NULL;
|
|
DBPROPSET * prgPropSets = NULL;
|
|
ULONG cPropSets = 0;
|
|
|
|
|
|
// pData buffer contains bindings to TABLE_CATALOG, TABLE_SCHEMA, and TABLE_NAME, in that
|
|
// order.
|
|
|
|
// Skip any bookmark
|
|
if (!pBinding[iBind].iOrdinal)
|
|
iFirst++;
|
|
|
|
for (iBind = 0; iBind < 3; iBind++)
|
|
{
|
|
// If value isn't bound then we assume NULL
|
|
if (!VALUE_IS_BOUND(pBinding[iBind+iFirst]))
|
|
continue;
|
|
|
|
// Get a pointer to catalog, schema, and table name
|
|
if (STATUS_IS_BOUND(pBinding[iBind+iFirst]))
|
|
{
|
|
// Check the status, which should always be OK or NULL
|
|
if (STATUS_BINDING(pBinding[iBind+iFirst], pData) != DBSTATUS_S_OK)
|
|
{
|
|
COMPARE(STATUS_BINDING(pBinding[iBind+iFirst], pData), DBSTATUS_S_ISNULL);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// If status wasn't bound we assume OK, and length doesn't matter for null terminated string
|
|
switch(pBinding[iBind+iFirst].iOrdinal)
|
|
{
|
|
case 1:
|
|
pwszCat = (LPWSTR)&VALUE_BINDING(pBinding[iBind+iFirst], pData);
|
|
break;
|
|
case 2:
|
|
pwszSch = (LPWSTR)&VALUE_BINDING(pBinding[iBind+iFirst], pData);
|
|
break;
|
|
case 3:
|
|
pwszTable = (LPWSTR)&VALUE_BINDING(pBinding[iBind+iFirst], pData);
|
|
break;
|
|
default:
|
|
COMPARE(pBinding[iBind+iFirst].iOrdinal < 4, TRUE);
|
|
COMPARE(pBinding[iBind+iFirst].iOrdinal > 0, TRUE);
|
|
}
|
|
}
|
|
|
|
// HACK FOR ORACLE
|
|
if (pwszSch && wcslen(pwszSch) == 0)
|
|
pwszSch = NULL;
|
|
|
|
// Now we have either NULL or valid pointers to catalog, schema, table names
|
|
TESTC_(m_pTable->GetQualifiedName(pwszCat, pwszSch,
|
|
pwszTable,&pwszQualifiedName, TRUE), S_OK);
|
|
|
|
// If we already have information for this table then just don't bother
|
|
if (m_pwszTableName && !wcscmp(pwszQualifiedName, m_pwszTableName))
|
|
{
|
|
m_ulTableOrdinal++;
|
|
|
|
// If we couldn't actually retrieve the colinfo for this table then
|
|
// return S_FALSE
|
|
if (!m_prgColInfo)
|
|
return S_FALSE;
|
|
// Otherwise return success
|
|
else
|
|
return S_OK;
|
|
}
|
|
|
|
// Copy the table name into member var
|
|
SAFE_FREE(m_pwszTableName);
|
|
m_pwszTableName = pwszQualifiedName;
|
|
|
|
// Initialize out params
|
|
m_ulTableOrdinal = 1; // Note that schema rowset never reports bookmarks
|
|
SAFE_FREE(m_prgColInfo);
|
|
SAFE_FREE(m_pwszStringsBuffer);
|
|
|
|
// Get IOpenRowset interface
|
|
TESTC(VerifyInterface(m_pIDBSchemaRowset, IID_IOpenRowset, SESSION_INTERFACE, (IUnknown**)&pIOpenRowset));
|
|
|
|
// Create DBID from table name
|
|
dbid.eKind = DBKIND_NAME;
|
|
dbid.uName.pwszName = m_pwszTableName;
|
|
|
|
// When retrieving column information for TABLES_INFO rowset we want a bookmark also
|
|
if (m_guidSchema == DBSCHEMA_TABLES_INFO && SupportedProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET,
|
|
m_pCSchemaTest->m_pIDBInitialize, ROWSET_INTERFACE))
|
|
{
|
|
TESTC_(SetProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET,
|
|
&cPropSets, &prgPropSets, DBTYPE_BOOL, VARIANT_TRUE), S_OK);
|
|
}
|
|
|
|
// Call OpenRowset
|
|
hr = pIOpenRowset->OpenRowset(NULL, &dbid, NULL, IID_IColumnsInfo,
|
|
cPropSets, prgPropSets, (IUnknown **)&pIColumnsInfo);
|
|
|
|
if (FAILED(hr))
|
|
odtLog << m_pwszTableName << L": Unable to open table.\n";
|
|
|
|
// It's possible the table was deleted between the time we called GetRowset and attempting
|
|
// to open the table, so we have to allow DB_E_NOTABLE, but post a warning.
|
|
// It's also possible we don't have permission for the table.
|
|
switch(hr)
|
|
{
|
|
case DB_E_NOTABLE:
|
|
case DB_SEC_E_PERMISSIONDENIED:
|
|
// Only post the warning when debugmode is FULL
|
|
if (GetModInfo()->GetDebugMode() & DEBUGMODE_FULL)
|
|
TESTW_(hr, S_OK);
|
|
goto CLEANUP;
|
|
default:
|
|
TESTC_(hr, S_OK);
|
|
}
|
|
|
|
// Make sure we've got a valid interface ptr
|
|
TESTC(pIColumnsInfo != NULL);
|
|
|
|
// Now call GetColumnInfo. We already know cColumns so no need to return in member
|
|
// var.
|
|
TESTC_(hr = pIColumnsInfo->GetColumnInfo(&m_cColInfo, &m_prgColInfo, &m_pwszStringsBuffer), S_OK);
|
|
|
|
CLEANUP:
|
|
|
|
SAFE_RELEASE(pIOpenRowset);
|
|
SAFE_RELEASE(pIColumnsInfo);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// GetRowset, execute method and check results
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
HRESULT CHelper::GetRowsetHelper
|
|
(
|
|
IUnknown * pIUnknown,
|
|
ULONG cRestrictions,
|
|
VARIANT * prgRestrictions,
|
|
REFIID riid,
|
|
ULONG cPropertySets,
|
|
DBPROPSET rgPropertySets[],
|
|
IUnknown ** ppRowset,
|
|
GUID guidSchema,
|
|
BOOL fFreeRowset
|
|
)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
IUnknown * pIRowsetUnknown = NULL;
|
|
|
|
if (m_fUseCommonArgumentDefaults)
|
|
{
|
|
// If we were not passed a valid schema then
|
|
// just use the one for our helper class.
|
|
if (guidSchema == GUID_NULL)
|
|
guidSchema = m_guidSchema;
|
|
|
|
switch(m_eRestrictArray)
|
|
{
|
|
case RT_CACHED:
|
|
prgRestrictions = m_rgRestrict;
|
|
break;
|
|
case RT_SUPPORTED:
|
|
prgRestrictions = m_rgRestrictValid;
|
|
break;
|
|
case RT_CUSTOM:
|
|
prgRestrictions = m_rgRestrictUsed;
|
|
break;
|
|
default:
|
|
COMPARE(0, 1);
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Set desired restrictions
|
|
switch(cRestrictions)
|
|
{
|
|
// Pass a 0, NULL restriction
|
|
case RV_NULL:
|
|
cRestrictions = 0;
|
|
prgRestrictions = NULL;
|
|
break;
|
|
// Pass all restrictions
|
|
case RV_ALL:
|
|
cRestrictions = m_pSchemaInfo->cRestrictions;
|
|
break;
|
|
// default:
|
|
// COMPARE(cRestrictions <= m_pSchemaInfo->cRestrictions, TRUE);
|
|
}
|
|
|
|
|
|
// If not passed a rowset pointer, just use an internal one
|
|
if (!ppRowset)
|
|
ppRowset = (IUnknown **)&pIRowsetUnknown;
|
|
}
|
|
|
|
// Track which set of restrictions was actually used so we can validate them
|
|
m_prgRestrictUsed = prgRestrictions;
|
|
m_cRestrictionsUsed = cRestrictions;
|
|
|
|
// Now get Schema rowset.
|
|
hr=m_pIDBSchemaRowset->GetRowset(pIUnknown, guidSchema, cRestrictions, prgRestrictions,
|
|
riid, cPropertySets, rgPropertySets, ppRowset);
|
|
|
|
if (ppRowset)
|
|
pIRowsetUnknown = *ppRowset;
|
|
|
|
// Check results of GetRowset
|
|
CheckResults(hr, riid, pIRowsetUnknown);
|
|
|
|
if (fFreeRowset && ppRowset)
|
|
SAFE_RELEASE(*ppRowset);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Assertions schema specific functions
|
|
class CAssertionsHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
BOOL VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn);
|
|
|
|
public:
|
|
|
|
CAssertionsHelper(void) {m_guidSchema = DBSCHEMA_ASSERTIONS;}
|
|
|
|
};
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CAssertionsHelper::VerifyColumn
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CAssertionsHelper::VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn)
|
|
{
|
|
BOOL fResults = FALSE;
|
|
|
|
switch(iOrdinal)
|
|
{
|
|
case 1:// CONSTRAINT CATALOG
|
|
|
|
PRVTRACE(L"= %s\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 2://CONSTRAINT SCHEMA
|
|
|
|
PRVTRACE(L"= %s\n",(TYPE_WSTR)pColumn->bValue);
|
|
break;
|
|
case 3://CONSTRAINT NAME
|
|
PRVTRACE(L"= %s\n",(WCHAR *)pColumn->bValue);
|
|
break;
|
|
case 4: //IS_DEFERRABLE
|
|
case 5: //INITIALLY_DEFERRED
|
|
if(*(TYPE_BOOL *)pColumn->bValue==VARIANT_TRUE)
|
|
PRVTRACE(L"TRUE\n");
|
|
else
|
|
PRVTRACE(L"FALSE\n");
|
|
break;
|
|
case 6: // DESCRIPTION
|
|
PRVTRACE(L"= %s\n",(TYPE_WSTR)pColumn->bValue );
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return fResults;
|
|
|
|
}
|
|
|
|
|
|
// Catalogs schema specific functions
|
|
class CCatalogsHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
public:
|
|
|
|
CCatalogsHelper(void) {m_guidSchema = DBSCHEMA_CATALOGS;}
|
|
};
|
|
|
|
// Catalogs schema specific functions
|
|
class CLargeRestrictionCatalogsHelper : public CCatalogsHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
virtual BOOL VerifyRestriction(DBORDINAL iOrdinal, DATA * pColumn);
|
|
|
|
public:
|
|
|
|
CLargeRestrictionCatalogsHelper(void) {}
|
|
};
|
|
|
|
|
|
BOOL CLargeRestrictionCatalogsHelper::VerifyRestriction(DBORDINAL iOrdinal, DATA * pColumn)
|
|
{
|
|
return CCatalogsHelper::VerifyRestriction(iOrdinal, pColumn);
|
|
}
|
|
|
|
// Character Sets schema specific functions
|
|
class CCharacterSetsHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
public:
|
|
|
|
CCharacterSetsHelper(void) {m_guidSchema = DBSCHEMA_CHARACTER_SETS;}
|
|
};
|
|
|
|
// Check Constraints schema specific functions
|
|
class CCheckConstraintsHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
BOOL InsertRows(void);
|
|
|
|
public:
|
|
|
|
CCheckConstraintsHelper(void) {m_guidSchema = DBSCHEMA_CHECK_CONSTRAINTS;}
|
|
};
|
|
|
|
BOOL CCheckConstraintsHelper::InsertRows(void)
|
|
{
|
|
return CreateCheckConstraints();
|
|
}
|
|
|
|
|
|
// CheckConstraintsByTable schema specific functions
|
|
class CCheckConstraintsByTableHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
BOOL VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn);
|
|
BOOL InsertRows(void);
|
|
|
|
public:
|
|
|
|
CCheckConstraintsByTableHelper(void) {m_guidSchema = DBSCHEMA_CHECK_CONSTRAINTS_BY_TABLE;}
|
|
|
|
};
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CCheckConstraintsByTableHelper::InsertRows
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CCheckConstraintsByTableHelper::InsertRows(void)
|
|
{
|
|
return CreateCheckConstraints();
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CCheckConstraintsByTableHelper::VerifyColumn
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CCheckConstraintsByTableHelper::VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn)
|
|
{
|
|
BOOL fResults = TRUE; // For now
|
|
|
|
switch(iOrdinal)
|
|
{
|
|
case CCBTS_TABLE_CATALOG:
|
|
// Verify matches DBPROPSET_DATASOURCE, DBPROP_CURRENTCATALOG
|
|
break;
|
|
case CCBTS_TABLE_SCHEMA:
|
|
// Verify matches DBPROPSET_DATASOURCEINFO, DBPROP_USERNAME when tablename
|
|
// is automaketable name
|
|
break;
|
|
case CCBTS_TABLE_NAME:
|
|
break;
|
|
case CCBTS_CONSTRAINT_CATALOG:
|
|
// Validate matches TABLE_CATALOG?
|
|
case CCBTS_CONSTRAINT_SCHEMA:
|
|
// Validate matches TABLE_CATALOG?
|
|
case CCBTS_CONSTRAINT_NAME:
|
|
// Validate non-NULL
|
|
case CCBTS_CHECK_CLAUSE:
|
|
// Validate this matches check clause we created for automaketable
|
|
case CCBTS_DESCRIPTION:
|
|
break;
|
|
default:
|
|
// Provider-specific column, can't validate
|
|
break;
|
|
}
|
|
|
|
return fResults;
|
|
|
|
}
|
|
|
|
// Collations schema specific functions
|
|
class CCollationsHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
public:
|
|
|
|
CCollationsHelper(void) {m_guidSchema = DBSCHEMA_COLLATIONS;}
|
|
};
|
|
|
|
// Column Domain Usage schema specific functions
|
|
class CColumnDomainUsageHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
public:
|
|
|
|
CColumnDomainUsageHelper(void) {m_guidSchema = DBSCHEMA_COLUMN_DOMAIN_USAGE;}
|
|
};
|
|
|
|
// Column Privileges schema specific functions
|
|
class CColumnPrivilegesHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
public:
|
|
|
|
CColumnPrivilegesHelper(void) {m_guidSchema = DBSCHEMA_COLUMN_PRIVILEGES;}
|
|
};
|
|
|
|
// Columns schema specific functions
|
|
class CColumnsHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
CErrorCache m_EC; // Columns error cache
|
|
|
|
protected:
|
|
|
|
BOOL VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn);
|
|
|
|
public:
|
|
|
|
CColumnsHelper(void) {m_guidSchema = DBSCHEMA_COLUMNS;}
|
|
BOOL Init(CSchemaTest * pThis);
|
|
};
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CColumnsHelper::Init
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CColumnsHelper::Init(CSchemaTest * pThis)
|
|
{
|
|
if (CHelper::Init(pThis))
|
|
return m_EC.Init(GetModInfo()->GetDebugMode());
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CColumnsHelper::VerifyColumn
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CColumnsHelper::VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn)
|
|
{
|
|
LPWSTR pwszSchemaName = (LPWSTR)GetValuePtr(COLS_TABLE_SCHEMA, m_pRow);
|
|
LPWSTR pwszTableName = (LPWSTR)GetValuePtr(COLS_TABLE_NAME, m_pRow);
|
|
LPWSTR pwszColumnName = (LPWSTR)GetValuePtr(COLS_COLUMN_NAME, m_pRow);
|
|
LPWSTR pwszColumnDefault = (LPWSTR)GetValuePtr(COLS_COLUMN_DEFAULT, m_pRow);
|
|
ULONG * pulOrdinal = (ULONG *)GetValuePtr(COLS_ORDINAL_POSITION, m_pRow);
|
|
LPBYTE pValue = GetValuePtr(iOrdinal, m_pRow);
|
|
BOOL fResult = FALSE;
|
|
ULONG iIndex = 0;
|
|
DBSTATUS ulStatus = pColumn->sStatus;
|
|
DBTYPE wType = 0;
|
|
|
|
// Compute index into colinfo given this ordinal
|
|
if (m_prgColInfo && pulOrdinal)
|
|
iIndex = *pulOrdinal + !m_prgColInfo[0].iOrdinal - 1;
|
|
|
|
// Need the column name to verify
|
|
// Note: We may be able to get by without this by computing the index via
|
|
// counting the rows in this table, but since providers don't have to return
|
|
// rows in ordinal order this is likely to be wrong.
|
|
TESTC(pwszColumnName != NULL);
|
|
|
|
// If we don't have the right index we can't verify
|
|
if (m_prgColInfo && m_prgColInfo[iIndex].pwszName &&
|
|
RelCompareString(pwszColumnName, m_prgColInfo[iIndex].pwszName))
|
|
{
|
|
// Names didn't match, so we have to search for the index
|
|
for (iIndex = 0; iIndex < m_cColInfo; iIndex++)
|
|
if (!RelCompareString(pwszColumnName, m_prgColInfo[iIndex].pwszName))
|
|
break;
|
|
}
|
|
|
|
// Make sure we found the matching index. If we didn't get m_prgColInfo then
|
|
// we don't index into it below.
|
|
if (m_prgColInfo)
|
|
{
|
|
TESTC(iIndex < m_cColInfo);
|
|
|
|
wType = m_prgColInfo[iIndex].wType;
|
|
}
|
|
else
|
|
wType = (DBTYPE)GetValuePtr(COLS_DATA_TYPE, m_pRow);
|
|
|
|
switch(iOrdinal)
|
|
{
|
|
case COLS_TABLE_CATALOG:
|
|
break;
|
|
|
|
case COLS_TABLE_SCHEMA:
|
|
break;
|
|
|
|
case COLS_TABLE_NAME:
|
|
break;
|
|
|
|
case COLS_COLUMN_NAME:
|
|
break;
|
|
|
|
case COLS_COLUMN_GUID:
|
|
break;
|
|
case COLS_TYPE_GUID:
|
|
break;
|
|
case COLS_COLUMN_PROPID:
|
|
break;
|
|
case COLS_ORDINAL_POSITION:
|
|
// Status is OK, warning if ordinals don't match
|
|
// Providers are not required to return results in ordinal order, since
|
|
// sort is only on catalog, schema, and name, so only a warning.
|
|
// If restriction is only on column then the ordinal may not match anyway.
|
|
|
|
// We will assume if the index for the matching ordinal contains
|
|
// the proper column name that it was the right ordinal.
|
|
if (pulOrdinal && m_prgColInfo && !COMPARE(*pulOrdinal, m_prgColInfo[iIndex].iOrdinal))
|
|
odtLog << pwszTableName << L": " << m_prgColInfo[iIndex].pwszName << L": " <<
|
|
L"Ordinal didn't match expected value.\n";
|
|
break;
|
|
case COLS_COLUMN_FLAGS:
|
|
if (m_prgColInfo)
|
|
{
|
|
COMPARE(m_prgColInfo[iIndex].dwFlags, *(DBCOLUMNFLAGS *)pValue);
|
|
}
|
|
break;
|
|
case COLS_CHARACTER_MAXIMUM_LENGTH:
|
|
if (m_prgColInfo)
|
|
{
|
|
switch(m_prgColInfo[iIndex].wType)
|
|
{
|
|
// case DBTYPE_BOOL: // We assume BOOL is not a "bit" column per spec.
|
|
case DBTYPE_UDT:
|
|
case DBTYPE_BYTES:
|
|
case DBTYPE_STR:
|
|
case DBTYPE_WSTR:
|
|
if (COMPARE(ulStatus, DBSTATUS_S_OK))
|
|
{
|
|
if (m_prgColInfo[iIndex].ulColumnSize == ~0)
|
|
{
|
|
if (!COMPARE(*(ULONG *)pValue, 0))
|
|
odtLog << m_pwszTableName << L": " << m_prgColInfo[iIndex].pwszName << L": " <<
|
|
L"Must be 0 for column without defined max length.\n";
|
|
}
|
|
else
|
|
CCOMPARE(m_EC, *(ULONG *)pValue == m_prgColInfo[iIndex].ulColumnSize,
|
|
EC_BAD_CHARACTER_MAXIMUM_LENGTH,
|
|
L"CHARACTER_MAXIMUM_LENGTH value did not match GetColumnInfo",
|
|
FALSE);
|
|
}
|
|
else
|
|
odtLog << pwszTableName << L": " << m_prgColInfo[iIndex].pwszName << L": " <<
|
|
L"Cannot be NULL for variable length column.\n";
|
|
break;
|
|
// NULL for all other data types
|
|
default:
|
|
if (!COMPARE(ulStatus, DBSTATUS_S_ISNULL))
|
|
odtLog << m_pwszTableName << L": " << m_prgColInfo[iIndex].pwszName << L": " <<
|
|
L"Status was not DBSTATUS_S_ISNULL for non-char, binary, or bit column\n";
|
|
}
|
|
}
|
|
break;
|
|
case COLS_CHARACTER_OCTET_LENGTH:
|
|
if (m_prgColInfo)
|
|
{
|
|
switch(m_prgColInfo[iIndex].wType)
|
|
{
|
|
case DBTYPE_UDT:
|
|
case DBTYPE_BYTES:
|
|
case DBTYPE_STR:
|
|
case DBTYPE_WSTR:
|
|
if (COMPARE(ulStatus, DBSTATUS_S_OK))
|
|
{
|
|
if (m_prgColInfo[iIndex].ulColumnSize == ~0)
|
|
{
|
|
if (!COMPARE(*(ULONG *)pValue, 0))
|
|
odtLog << m_pwszTableName << L": " << m_prgColInfo[iIndex].pwszName << L": " <<
|
|
L"Must be 0 for column without defined max length.\n";
|
|
}
|
|
else
|
|
{
|
|
DBLENGTH ulOctetLen = m_prgColInfo[iIndex].ulColumnSize;
|
|
if (m_prgColInfo[iIndex].wType == DBTYPE_WSTR)
|
|
ulOctetLen *= sizeof(WCHAR);
|
|
|
|
CCOMPARE(m_EC, ulOctetLen == *(ULONG *)pValue,
|
|
EC_BAD_CHARACTER_OCTET_LENGTH,
|
|
L"CHARACTER_OCTET_LENGTH value did not match GetColumnInfo",
|
|
FALSE);
|
|
}
|
|
}
|
|
break;
|
|
// NULL for all other data types
|
|
default:
|
|
if (!COMPARE(ulStatus, DBSTATUS_S_ISNULL))
|
|
odtLog << m_pwszTableName << L": " << m_prgColInfo[iIndex].pwszName << L": " <<
|
|
L"Status was not DBSTATUS_S_ISNULL for non-char, binary, or bit column\n";
|
|
}
|
|
}
|
|
break;
|
|
case COLS_DATETIME_PRECISION:
|
|
if (m_prgColInfo)
|
|
{
|
|
switch(m_prgColInfo[iIndex].wType)
|
|
{
|
|
case DBTYPE_DBTIMESTAMP:
|
|
// The following types are new for 9.0 and do support DATETIME_PRECISION per spec
|
|
#ifdef __UTC_
|
|
case DBTYPE_DBUTCDATETIME:
|
|
case DBTYPE_DBTIME_EX:
|
|
case DBTYPE_DBDATE:
|
|
#endif
|
|
// DATETIME_PRECISION matches IColumnsInfo bScale vaue
|
|
if (COMPARE(ulStatus, DBSTATUS_S_OK) &&
|
|
!COMPARE((ULONG)m_prgColInfo[iIndex].bScale, *(ULONG *)pValue))
|
|
/*
|
|
|
|
CCOMPARE(m_EC, *(ULONG *)pValue == (ULONG)m_prgColInfo[iIndex].bScale,
|
|
EC_BAD_DATETIME_PRECISION,
|
|
L"DATETIME_PRECISION value did not match GetColumnInfo",
|
|
FALSE);
|
|
*/
|
|
odtLog << m_pwszTableName << L": " << m_prgColInfo[iIndex].pwszName << L"DATETIME_PRECISION value did not match GetColumnInfo" << L" \n";
|
|
break;
|
|
// NULL for all other data types
|
|
default:
|
|
if (!COMPARE(ulStatus, DBSTATUS_S_ISNULL))
|
|
odtLog << m_pwszTableName << L": " << m_prgColInfo[iIndex].pwszName << L": " <<
|
|
L"Status was not DBSTATUS_S_ISNULL for non-char, binary, or bit column\n";
|
|
}
|
|
}
|
|
break;
|
|
case COLS_COLUMN_HASDEFAULT:
|
|
// We can't actually try the default value except for our test table, so we don't know
|
|
// if it actually would work or not for other tables.
|
|
// Note that COLUMN_DEFAULT may be NULL even if HASDEFAULT is TRUE but the converse
|
|
// is not true.
|
|
|
|
if (COMPARE(ulStatus, DBSTATUS_S_OK))
|
|
{
|
|
// If the COLUMN_DEFAULT is non-NULL, then HASDEFAULT should be TRUE, otherwise
|
|
// we're not sure
|
|
if (pwszColumnDefault && !COMPARE(*(VARIANT_BOOL *)pValue, VARIANT_TRUE))
|
|
odtLog << pwszTableName << L": " << rgwszCOLUMNS[iOrdinal-1] << L": " <<
|
|
L"Invalid value returned.\n";
|
|
|
|
// TODO: If the current table is the automaketable for this test try to use the default
|
|
// value and make sure it matches expected.
|
|
}
|
|
else
|
|
odtLog << pwszTableName << L": " << m_prgColInfo[iIndex].pwszName << L": " <<
|
|
L"Invalid status returned.\n";
|
|
break;
|
|
case COLS_COLUMN_DEFAULT:
|
|
if (ulStatus == DBSTATUS_S_OK)
|
|
{
|
|
// For now, just make sure the length is right so we read the default value
|
|
if (!COMPARE(wcslen(pwszColumnDefault)*sizeof(WCHAR), pColumn->ulLength))
|
|
odtLog << m_pwszTableName << L": " << m_prgColInfo[iIndex].pwszName << L": " <<
|
|
L"Default value has the wrong length.\n";
|
|
|
|
// TODO: If the current table is the automaketable for this test try to use the default
|
|
// value and make sure it matches expected.
|
|
}
|
|
break;
|
|
case COLS_IS_NULLABLE:
|
|
if (m_prgColInfo)
|
|
{
|
|
DBCOLUMNFLAGS dwNullableFlag = m_prgColInfo[iIndex].dwFlags & DBCOLUMNFLAGS_ISNULLABLE;
|
|
DBCOLUMNFLAGS dwISNULLABLEFlag = *(VARIANT_BOOL *)pValue == VARIANT_TRUE ? DBCOLUMNFLAGS_ISNULLABLE : 0;
|
|
if (!COMPARE(dwNullableFlag, dwISNULLABLEFlag))
|
|
odtLog << m_pwszTableName << L": " << m_prgColInfo[iIndex].pwszName << L": " <<
|
|
L"DBCOLUMNFLAGS_ISNULLABLE incorrect value returned.\n";
|
|
/*
|
|
// Turn this column's value into DBCOLUMNFLAGS and use CompareColumnFlags
|
|
|
|
|
|
VARIANT_BOOL fNullable = m_prgColInfo[iIndex].dwFlags & DBCOLUMNFLAGS_ISNULLABLE ? VARIANT_TRUE : VARIANT_FALSE;
|
|
if (!COMPARE(fNullable, *(VARIANT_BOOL *)pValue))
|
|
odtLog << m_pwszTableName << L": " << m_prgColInfo[iIndex].pwszName << L": " <<
|
|
L"DBCOLUMNFLAGS_ISNULLABLE incorrect value returned.\n";
|
|
*/
|
|
}
|
|
break;
|
|
case COLS_DATA_TYPE:
|
|
// This column cannot contain NULL
|
|
if (COMPARE(ulStatus, DBSTATUS_S_OK) && m_prgColInfo &&
|
|
!COMPARE(m_prgColInfo[iIndex].wType, *(DBTYPE *)pValue))
|
|
odtLog << m_pwszTableName << L": " << m_prgColInfo[iIndex].pwszName << L": " <<
|
|
L"Invalid value returned for data type. Expected: " << m_prgColInfo[iIndex].wType <<
|
|
L" Received: " << *(DBTYPE *)pValue << L" \n";
|
|
break;
|
|
case COLS_NUMERIC_PRECISION:
|
|
if (m_prgColInfo)
|
|
{
|
|
if (IsNumericType(m_prgColInfo[iIndex].wType))
|
|
{
|
|
if (COMPARE(ulStatus, DBSTATUS_S_OK))
|
|
{
|
|
CCOMPARE(m_EC, *(USHORT *)pValue == (USHORT)m_prgColInfo[iIndex].bPrecision,
|
|
EC_COLUMNS_BAD_NUMERIC_PRECISION,
|
|
L"NUMERIC_PRECISION is incorrect",
|
|
FALSE);
|
|
}
|
|
}
|
|
// NULL for all other data types
|
|
else if (!COMPARE(ulStatus, DBSTATUS_S_ISNULL))
|
|
odtLog << m_pwszTableName << L": " << m_prgColInfo[iIndex].pwszName << L": " <<
|
|
L"Status was not DBSTATUS_S_ISNULL for non-numeric column\n";
|
|
}
|
|
break;
|
|
case COLS_NUMERIC_SCALE:
|
|
if (m_prgColInfo)
|
|
{
|
|
if (m_prgColInfo[iIndex].wType == DBTYPE_DECIMAL ||
|
|
m_prgColInfo[iIndex].wType == DBTYPE_NUMERIC ||
|
|
m_prgColInfo[iIndex].wType == DBTYPE_VARNUMERIC)
|
|
{
|
|
|
|
CCOMPARE(m_EC, ulStatus == DBSTATUS_S_OK,
|
|
EC_COLUMNS_NULL_NUMERIC_SCALE,
|
|
L"NUMERIC_SCALE cannot be NULL for numeric column",
|
|
FALSE);
|
|
|
|
if (ulStatus==DBSTATUS_S_OK)
|
|
{
|
|
SHORT sScale = (SHORT)m_prgColInfo[iIndex].bScale;
|
|
|
|
// Account for negative scale values
|
|
if (m_prgColInfo[iIndex].dwFlags & DBCOLUMNFLAGS_SCALEISNEGATIVE)
|
|
sScale = -sScale;
|
|
|
|
if (!COMPARE(*(SHORT *)pValue, sScale))
|
|
odtLog << m_pwszTableName << L": " << m_prgColInfo[iIndex].pwszName << L": " <<
|
|
L"Invalid value returned.\n";
|
|
}
|
|
}
|
|
// NULL for all other data types
|
|
else if (!COMPARE(ulStatus, DBSTATUS_S_ISNULL))
|
|
odtLog << m_pwszTableName << L": " << m_prgColInfo[iIndex].pwszName << L": " <<
|
|
L"Status was not DBSTATUS_S_ISNULL for non-DECIMAL, NUMERIC column\n";
|
|
}
|
|
break;
|
|
case COLS_CHARACTER_SET_CATALOG:
|
|
case COLS_CHARACTER_SET_SCHEMA:
|
|
case COLS_CHARACTER_SET_NAME:
|
|
case COLS_COLLATION_CATALOG:
|
|
case COLS_COLLATION_SCHEMA:
|
|
case COLS_COLLATION_NAME:
|
|
case COLS_DOMAIN_CATALOG:
|
|
case COLS_DOMAIN_SCHEMA:
|
|
case COLS_DOMAIN_NAME:
|
|
VerifyNonEmptyString(pColumn, m_pwszTableName, m_prgColInfo ? m_prgColInfo[iIndex].pwszName: L"<Unknown>");
|
|
break;
|
|
case COLS_DESCRIPTION:
|
|
break;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
return fResult;
|
|
|
|
}
|
|
|
|
// Constraint Column Usage schema specific functions
|
|
class CConstraintTableUsageHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
protected:
|
|
|
|
public:
|
|
|
|
CConstraintTableUsageHelper(void) {m_guidSchema = DBSCHEMA_CONSTRAINT_TABLE_USAGE;}
|
|
};
|
|
|
|
// Constraint Column Usage schema specific functions
|
|
class CConstraintColumnUsageHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
BOOL InsertRows(void);
|
|
|
|
public:
|
|
|
|
CConstraintColumnUsageHelper(void) {m_guidSchema = DBSCHEMA_CONSTRAINT_COLUMN_USAGE;}
|
|
};
|
|
|
|
BOOL CConstraintColumnUsageHelper::InsertRows(void)
|
|
{
|
|
return CreateCheckConstraints();
|
|
}
|
|
|
|
// Foreign Keys schema specific functions
|
|
class CForeignKeysHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
public:
|
|
|
|
CForeignKeysHelper(void) {m_guidSchema = DBSCHEMA_FOREIGN_KEYS;}
|
|
};
|
|
|
|
// Indexes schema specific functions
|
|
class CIndexesHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
CErrorCache m_EC; // Indexes error cache
|
|
|
|
protected:
|
|
BOOL CompareNull(DBORDINAL iOrdinal);
|
|
|
|
public:
|
|
|
|
CIndexesHelper(void) {m_guidSchema = DBSCHEMA_INDEXES;}
|
|
BOOL Init(CSchemaTest * pThis);
|
|
};
|
|
|
|
BOOL CIndexesHelper::CompareNull(DBORDINAL iOrdinal)
|
|
{
|
|
switch (iOrdinal)
|
|
{
|
|
case IS_NULLS:
|
|
return CCOMPARE(m_EC, m_pSchemaInfo->pColList[iOrdinal-1].fAllowNull == TRUE,
|
|
EC_INDEXES_NULLS_ISNULL,
|
|
L"NULLS column cannot be DBSTATUS_S_ISNULL",
|
|
FALSE);
|
|
case IS_INDEX_NAME:
|
|
return CCOMPARE(m_EC, m_pSchemaInfo->pColList[iOrdinal-1].fAllowNull == TRUE,
|
|
EC_INDEXES_INDEX_NAME_ISNULL,
|
|
L"INDEX_NAME column cannot be DBSTATUS_S_ISNULL",
|
|
FALSE);
|
|
case IS_UNIQUE:
|
|
return CCOMPARE(m_EC, m_pSchemaInfo->pColList[iOrdinal-1].fAllowNull == TRUE,
|
|
EC_INDEXES_UNIQUE_ISNULL,
|
|
L"UNIQUE column cannot be DBSTATUS_S_ISNULL",
|
|
FALSE);
|
|
case IS_AUTO_UPDATE:
|
|
return CCOMPARE(m_EC, m_pSchemaInfo->pColList[iOrdinal-1].fAllowNull == TRUE,
|
|
EC_INDEXES_AUTO_UPDATE_ISNULL,
|
|
L"AUTO_UPDATE column cannot be DBSTATUS_S_ISNULL",
|
|
FALSE);
|
|
|
|
}
|
|
|
|
return CHelper::CompareNull(iOrdinal);
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CIndexesHelper::Init
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CIndexesHelper::Init(CSchemaTest * pThis)
|
|
{
|
|
if (CHelper::Init(pThis))
|
|
return m_EC.Init(GetModInfo()->GetDebugMode());
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
// Key Column Usage schema specific functions
|
|
class CKeyColumnUsageHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
|
|
public:
|
|
|
|
CKeyColumnUsageHelper(void) {m_guidSchema = DBSCHEMA_KEY_COLUMN_USAGE;}
|
|
};
|
|
|
|
// Primary Keys schema specific functions
|
|
class CPrimaryKeysHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
public:
|
|
|
|
CPrimaryKeysHelper(void) {m_guidSchema = DBSCHEMA_PRIMARY_KEYS;}
|
|
};
|
|
|
|
// Procedures schema specific functions
|
|
class CProceduresHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
CErrorCache m_EC; // Error cache
|
|
|
|
protected:
|
|
BOOL CompareNull(DBORDINAL iOrdinal);
|
|
|
|
public:
|
|
|
|
CProceduresHelper(void) {m_guidSchema = DBSCHEMA_PROCEDURES;}
|
|
BOOL Init(CSchemaTest * pThis);
|
|
};
|
|
|
|
BOOL CProceduresHelper::CompareNull(DBORDINAL iOrdinal)
|
|
{
|
|
if (iOrdinal == PRS_PROCEDURE_DEFINITION)
|
|
return CCOMPARE(m_EC, m_pSchemaInfo->pColList[iOrdinal-1].fAllowNull == TRUE,
|
|
EC_PROCEDURES_PROC_DEF_ISNULL,
|
|
L"PROCEDURE_DEFINITION column cannot be DBSTATUS_S_ISNULL",
|
|
FALSE);
|
|
else
|
|
return CHelper::CompareNull(iOrdinal);
|
|
}
|
|
|
|
BOOL CProceduresHelper::Init(CSchemaTest * pThis)
|
|
{
|
|
if (CHelper::Init(pThis))
|
|
return m_EC.Init(GetModInfo()->GetDebugMode());
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// Procedure Columns schema specific functions
|
|
class CProcedureColumnsHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
CErrorCache m_EC; // Error cache
|
|
|
|
protected:
|
|
BOOL CompareNull(DBORDINAL iOrdinal);
|
|
BOOL VerifyValue(DBORDINAL iOrdinal, DATA * pColumn);
|
|
|
|
public:
|
|
|
|
CProcedureColumnsHelper(void) {m_guidSchema = DBSCHEMA_PROCEDURE_COLUMNS;}
|
|
BOOL Init(CSchemaTest * pThis);
|
|
};
|
|
|
|
BOOL CProcedureColumnsHelper::CompareNull(DBORDINAL iOrdinal)
|
|
{
|
|
if (iOrdinal == PCS_COLS_IS_NULLABLE)
|
|
return CCOMPARE(m_EC, m_pSchemaInfo->pColList[iOrdinal-1].fAllowNull == TRUE,
|
|
EC_PROC_COLS_IS_NULLABLE_ISNULL,
|
|
L"IS_NULLABLE column cannot be DBSTATUS_S_ISNULL",
|
|
FALSE);
|
|
else
|
|
return CHelper::CompareNull(iOrdinal);
|
|
}
|
|
|
|
BOOL CProcedureColumnsHelper::Init(CSchemaTest * pThis)
|
|
{
|
|
if (CHelper::Init(pThis))
|
|
return m_EC.Init(GetModInfo()->GetDebugMode());
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CProcedureColumnsHelper::VerifyValue(DBORDINAL iOrdinal, DATA * pColumn)
|
|
{
|
|
ULONG cValidVals;
|
|
LPBYTE pValidVals;
|
|
DBTYPE wType;
|
|
ULONG ulTypeSize;
|
|
BOOL fMatch = FALSE;
|
|
|
|
// If this is a bookmark column, just return TRUE
|
|
// If this is a provider-specific column just return TRUE that
|
|
// the value is allowed.
|
|
if (!iOrdinal || iOrdinal > m_pSchemaInfo->cColumns)
|
|
return TRUE;
|
|
|
|
// If the column doesn't have a set of defined values, just return TRUE
|
|
if (!m_pSchemaInfo->pColList[iOrdinal-1].cValidVals)
|
|
return TRUE;
|
|
|
|
// Get the values from the table
|
|
cValidVals = m_pSchemaInfo->pColList[iOrdinal-1].cValidVals;
|
|
pValidVals = (LPBYTE)m_pSchemaInfo->pColList[iOrdinal-1].pValidVals;
|
|
wType = m_pSchemaInfo->pColList[iOrdinal-1].wType;
|
|
ulTypeSize = GetDBTypeSize(wType);
|
|
|
|
// GetDBTypeSize returns 0 for variable length types
|
|
switch(wType)
|
|
{
|
|
case DBTYPE_STR:
|
|
ulTypeSize = sizeof(LPSTR);
|
|
break;
|
|
case DBTYPE_WSTR:
|
|
ulTypeSize = sizeof(LPWSTR);
|
|
break;
|
|
}
|
|
|
|
// We must have a non-zero type size
|
|
if (!COMPARE(ulTypeSize > 0, TRUE))
|
|
return FALSE;
|
|
|
|
// If there is a count of values, make sure there is a set of values
|
|
// so hopefully we don't crash if the table is bad
|
|
if (!COMPARE(cValidVals && pValidVals, TRUE))
|
|
return FALSE;
|
|
|
|
// Otherwise make sure it matches one of the values in our table
|
|
for (ULONG iVal = 0; iVal < cValidVals; iVal++)
|
|
{
|
|
LPBYTE pValidVal = pValidVals;
|
|
DBLENGTH cbBackEnd = ulTypeSize, cbConsumer = ulTypeSize;
|
|
|
|
switch(wType)
|
|
{
|
|
case DBTYPE_STR:
|
|
pValidVal = *(LPBYTE *)pValidVals;
|
|
cbBackEnd = strlen((LPSTR)pValidVal);
|
|
cbConsumer = strlen((LPSTR)pColumn->bValue);
|
|
case DBTYPE_WSTR:
|
|
pValidVal = *(LPBYTE *)pValidVals;
|
|
cbBackEnd = wcslen((LPWSTR)pValidVal)*sizeof(WCHAR);
|
|
cbConsumer = wcslen((LPWSTR)pColumn->bValue)*sizeof(WCHAR);
|
|
break;
|
|
}
|
|
|
|
if (CompareDBTypeData(&pColumn->bValue, pValidVal, wType, cbBackEnd, 0, 0, NULL, FALSE, DBTYPE_EMPTY, cbConsumer))
|
|
{
|
|
fMatch = TRUE;
|
|
break;
|
|
}
|
|
pValidVals += ulTypeSize;
|
|
}
|
|
|
|
// Post a failure if we didn't find a match
|
|
if (iOrdinal == PCS_COLS_IS_NULLABLE)
|
|
{
|
|
// Only post this failure once
|
|
CCOMPARE(m_EC, fMatch == TRUE,
|
|
EC_INVALID_IS_NULLABLE,
|
|
L"IS_NULLABLE value was not in list of valid values",
|
|
FALSE);
|
|
}
|
|
else if (!COMPARE(fMatch, TRUE))
|
|
odtLog << L"The value returned for column " << m_pSchemaInfo->pColList[iOrdinal-1].pwszName <<
|
|
L" was not in the list of valid values.\n";
|
|
|
|
return fMatch;
|
|
}
|
|
|
|
|
|
// Procedure Parameters schema specific functions
|
|
class CProcedureParametersHelper : public CHelper
|
|
{
|
|
private:
|
|
LPWSTR m_pwszQualifiedName;
|
|
DB_UPARAMS m_cParams;
|
|
DB_UPARAMS m_cPropParams;
|
|
DBPARAMINFO * m_pParamInfo;
|
|
LPWSTR m_pNamesBuffer;
|
|
SHORT m_iOrdinalPrev;
|
|
UWORD m_iOrdinalStart;
|
|
|
|
protected:
|
|
|
|
BOOL VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn);
|
|
BOOL GetParamInfo(void);
|
|
BOOL InsertRows(void);
|
|
|
|
public:
|
|
CProcedureParametersHelper(void)
|
|
{
|
|
m_guidSchema = DBSCHEMA_PROCEDURE_PARAMETERS;
|
|
m_pwszQualifiedName = NULL;
|
|
m_pParamInfo = NULL;
|
|
m_pNamesBuffer = NULL;
|
|
}
|
|
|
|
~CProcedureParametersHelper(void)
|
|
{
|
|
SAFE_FREE(m_pwszQualifiedName);
|
|
SAFE_FREE(m_pParamInfo);
|
|
SAFE_FREE(m_pNamesBuffer);
|
|
}
|
|
};
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CProcedureParametersHelper::InsertRows
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CProcedureParametersHelper::InsertRows(void)
|
|
{
|
|
return CreateStoredProcs();
|
|
}
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CProcedureParametersHelper::GetParamInfo
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CProcedureParametersHelper::GetParamInfo(void)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
LPWSTR pwszProcCat = (LPWSTR)GetValuePtr(PPS_PROCEDURE_CATALOG, m_pRow);
|
|
LPWSTR pwszProcSchema = (LPWSTR)GetValuePtr(PPS_PROCEDURE_SCHEMA, m_pRow);
|
|
LPWSTR pwszProcName = (LPWSTR)GetValuePtr(PPS_PROCEDURE_NAME, m_pRow);
|
|
DBTYPE * pwType = (DBTYPE *)GetValuePtr(PPS_DATA_TYPE, m_pRow);
|
|
UWORD * piOrdinal = (UWORD *)GetValuePtr(PPS_ORDINAL_POSITION, m_pRow);
|
|
LPWSTR pwszQualifiedName= NULL;
|
|
IDBCreateSession * pIDBCreateSession = NULL;
|
|
IDBCreateCommand * pIDBCreateCommand = NULL;
|
|
ICommand * pICmd = NULL;
|
|
ICommandWithParameters * pICmdWPar = NULL;
|
|
ICommandText * pICmdText = NULL;
|
|
ICommandPrepare * pICmdPrep = NULL;
|
|
LPWSTR pwszCmdFormat1 = L"{call %s}"; // {call procname}
|
|
LPWSTR pwszCmdFormat2 = L"{call %s(%s)}"; // {call procname(procparams)}
|
|
LPWSTR pwszCmdFormat1r = L"{?=call %s}"; // {call procname}
|
|
LPWSTR pwszCmdFormat2r = L"{?=call %s(%s)}"; // {call procname(procparams)}
|
|
LPWSTR pwszProcVersion = NULL;
|
|
ULONG iParam, ccCmdBufSize = 1000;
|
|
HRESULT hr = S_OK;
|
|
LPWSTR pwszCmd = NULL;
|
|
WCHAR wszMarkers[MAX_PARAM_COUNT*2] = L""; // Each parameter requires ",?"
|
|
LPWSTR pwszCmdFmt = pwszCmdFormat1;
|
|
size_t ulValidLen = 0;
|
|
BOOL fFoundParamCount = FALSE;
|
|
|
|
TESTC(pwszProcCat != NULL);
|
|
TESTC(pwszProcSchema && pwszProcName && pwType);
|
|
|
|
// If the proc name contains a semicolon, then we have to build the fully
|
|
// qualified name w/o the ;nn part because those are not really part of the
|
|
// name. This should only occur for SQL Server
|
|
wcstok(pwszProcName, L";");
|
|
|
|
// Create fully qualified name from the 3 values
|
|
TESTC_(m_pTable->GetQualifiedName(
|
|
pwszProcCat,
|
|
pwszProcSchema,
|
|
pwszProcName,
|
|
&pwszQualifiedName, TRUE), S_OK);
|
|
|
|
// Deal with remaining numeric portion of proc version.
|
|
if (pwszProcVersion = wcstok(NULL, L";"))
|
|
{
|
|
// Put back the semicolon in the proc name
|
|
pwszProcVersion[-1] = L';';
|
|
|
|
// Realloc the qualified name to allow space for the version.
|
|
SAFE_REALLOC(pwszQualifiedName, WCHAR, wcslen(pwszQualifiedName)+wcslen(pwszProcVersion-1)+sizeof(WCHAR));
|
|
|
|
// Concat on the version
|
|
wcscat(pwszQualifiedName, pwszProcVersion-1);
|
|
}
|
|
|
|
// Have to assume the ordinal position increments
|
|
if (!piOrdinal)
|
|
{
|
|
m_iOrdinalPrev++;
|
|
}
|
|
|
|
// If this matches the previously obtained fully qualified name then
|
|
// we have the same proc, just exit.
|
|
if (m_pwszQualifiedName && !wcscmp(pwszQualifiedName, m_pwszQualifiedName))
|
|
return TRUE;
|
|
|
|
// Allocate some space for command buffer
|
|
SAFE_ALLOC(pwszCmd, WCHAR, ccCmdBufSize);
|
|
pwszCmd[0] = L'\0'; // Init to empty
|
|
|
|
// This is a different stored proc, get the parameter information
|
|
SAFE_FREE(m_pwszQualifiedName);
|
|
m_pwszQualifiedName = pwszQualifiedName;
|
|
SAFE_FREE(m_pNamesBuffer);
|
|
|
|
// Reset our previous ordinal info and starting ordinal for this proc
|
|
if (piOrdinal)
|
|
{
|
|
m_iOrdinalStart = *piOrdinal;
|
|
m_iOrdinalPrev = *piOrdinal-1;
|
|
}
|
|
else
|
|
{
|
|
// Have to assume the ordinal position starts at 1
|
|
m_iOrdinalPrev = 0;
|
|
m_iOrdinalStart = 1;
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Spawn off an entirely new connection to work around provider bug
|
|
// ----------------------------------------------------------------
|
|
TESTC(VerifyInterface(g_pIDBInitialize, IID_IDBCreateSession, DATASOURCE_INTERFACE, (IUnknown **)&pIDBCreateSession));
|
|
TESTC_(pIDBCreateSession->CreateSession(NULL, IID_IDBCreateCommand, (IUnknown **)&pIDBCreateCommand), S_OK);
|
|
|
|
// Get a fresh command object
|
|
TESTC_(pIDBCreateCommand->CreateCommand(
|
|
NULL,
|
|
IID_ICommand,
|
|
(IUnknown **)&pICmd), S_OK);
|
|
// pICmd = m_pTable->get_ICommandPTR();
|
|
// ----------------------------------------------------------------
|
|
// Remove above block and associated variables when provider bug is fixed.
|
|
// ----------------------------------------------------------------
|
|
|
|
TESTC(VerifyInterface(pICmd, IID_ICommandText, COMMAND_INTERFACE, (IUnknown **)&pICmdText))
|
|
TESTC(VerifyInterface(pICmd, IID_ICommandPrepare, COMMAND_INTERFACE, (IUnknown **)&pICmdPrep))
|
|
|
|
// We should always be able to get ICommandWithParameters if there is PROCEDURE_PARAMETERS rowset
|
|
TESTC(VerifyInterface(pICmd, IID_ICommandWithParameters, COMMAND_INTERFACE, (IUnknown **)&pICmdWPar));
|
|
|
|
m_cParams=0;
|
|
|
|
if (m_cTotalRows == 1)
|
|
{
|
|
odtLog << L"Bug here - can't prepare command on 2nd cmd obj if schema open on first cmd obj?\n";
|
|
// COMPAREW(0,1);
|
|
}
|
|
|
|
// If there is a return param, use that form
|
|
// if (m_iOrdinalStart == 0)
|
|
pwszCmdFmt = pwszCmdFormat1r;
|
|
|
|
// Assume there may be up to 50 params
|
|
for (iParam = 0; iParam < MAX_PARAM_COUNT; iParam++)
|
|
{
|
|
if (wcslen(pwszCmdFmt) + wcslen(m_pwszQualifiedName) + wcslen(wszMarkers) > ccCmdBufSize)
|
|
{
|
|
// Double the command buffer size and reallocate
|
|
ccCmdBufSize *= 2;
|
|
SAFE_REALLOC(pwszCmd, WCHAR, ccCmdBufSize);
|
|
}
|
|
|
|
// Build the command
|
|
swprintf(pwszCmd, pwszCmdFmt, m_pwszQualifiedName, wszMarkers);
|
|
// swprintf(pwszCmd, pwszCmdFmt, pwszProcName, wszMarkers);
|
|
|
|
TESTC_(pICmdText->SetCommandText(DBGUID_DEFAULT, pwszCmd), S_OK);
|
|
|
|
hr = pICmdPrep->Prepare(1);
|
|
|
|
// We expect S_OK or DB_E_ERRORSINCOMMAND here
|
|
if (E_FAIL == hr)
|
|
{
|
|
CHECKW(hr, DB_E_ERRORSINCOMMAND);
|
|
}
|
|
else
|
|
{
|
|
TEST2C_(hr, S_OK, DB_E_ERRORSINCOMMAND);
|
|
}
|
|
|
|
// ODBC drivers are allowed to succeed for Prepare() even if param count
|
|
// is more than actual number of parameters. For ODBC, need to use
|
|
// GetParameterInfo to keep the driver honest.
|
|
if (hr == S_OK)
|
|
{
|
|
// Don't leak previous param info
|
|
SAFE_FREE(m_pParamInfo);
|
|
SAFE_FREE(m_pNamesBuffer);
|
|
|
|
// Temporarily print command executed
|
|
// odtLog << L"Prepared: " << pwszCmd << L"\n";
|
|
|
|
// Get new param info
|
|
hr = pICmdWPar->GetParameterInfo(&m_cParams, &m_pParamInfo, &m_pNamesBuffer);
|
|
TEST2C_(hr, S_OK, E_FAIL);
|
|
}
|
|
|
|
// Some providers will return S_OK for more param markers than required, but
|
|
// m_cParams will be set to the proper number of parameters
|
|
if (FAILED(hr) || m_cParams < iParam)
|
|
{
|
|
// Post failure if provider returns param count less than requested for S_OK
|
|
// COMPARE(hr != S_OK || m_cParams >= iParam+1, TRUE);
|
|
|
|
// Strip off the last param
|
|
if (iParam > 1) // If iParam == 1 then 0 params were allowed
|
|
{
|
|
pwszCmd[ulValidLen-2] = L'\0';
|
|
wcscat(pwszCmd, L")");
|
|
}
|
|
else
|
|
{
|
|
// We can get here if provider specifies there is a return param
|
|
// but fails the prepare if there is a return param present, or if
|
|
// the provider specifies there is no return param but fails prepare
|
|
// w/o params, or if there are no additional params beyond the return
|
|
// param.
|
|
// ASSERT(ulValidLen > 0);
|
|
TESTC(ulValidLen != 0);
|
|
pwszCmd[ulValidLen-1] = L'\0';
|
|
}
|
|
|
|
// Add back the closing bracket
|
|
wcscat(pwszCmd, L"}");
|
|
|
|
// Set and Prepare again
|
|
TESTC_(pICmdText->SetCommandText(DBGUID_DEFAULT, pwszCmd), S_OK);
|
|
TESTC_(pICmdPrep->Prepare(1), S_OK);
|
|
TESTC_(pICmdWPar->GetParameterInfo(&m_cParams, &m_pParamInfo, &m_pNamesBuffer), S_OK);
|
|
fFoundParamCount = TRUE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
TESTC_(hr, S_OK);
|
|
ulValidLen = wcslen(pwszCmd);
|
|
m_cParams = iParam;
|
|
}
|
|
|
|
if (iParam)
|
|
wcscat(wszMarkers, L",");
|
|
|
|
wcscat(wszMarkers, L"?");
|
|
pwszCmdFmt = pwszCmdFormat2;
|
|
if (m_iOrdinalStart == 0)
|
|
pwszCmdFmt = pwszCmdFormat2r;
|
|
else
|
|
pwszCmdFmt = pwszCmdFormat2;
|
|
|
|
}
|
|
|
|
TESTC(fFoundParamCount);
|
|
fRet = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
SAFE_RELEASE(pICmdWPar);
|
|
SAFE_RELEASE(pICmdText);
|
|
SAFE_RELEASE(pICmdPrep);
|
|
SAFE_RELEASE(pICmd);
|
|
SAFE_RELEASE(pIDBCreateCommand);
|
|
SAFE_RELEASE(pIDBCreateSession);
|
|
SAFE_FREE(pwszCmd);
|
|
return fRet;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CProcedureParametersHelper::VerifyColumn
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CProcedureParametersHelper::VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn)
|
|
{
|
|
// At this time there is no schema-specific testing for PROCEDURE_PARAMETERS schema
|
|
|
|
BOOL fResult = FALSE;
|
|
DBSTATUS ulStatus = pColumn->sStatus;
|
|
LPBYTE pValue = GetValuePtr(iOrdinal, m_pRow);
|
|
UWORD * piOrdinal = (UWORD *)GetValuePtr(PPS_ORDINAL_POSITION, m_pRow);
|
|
LPWSTR pwszProcName = (LPWSTR)GetValuePtr(PPS_PROCEDURE_NAME, m_pRow);
|
|
LPWSTR pwszParamName = (LPWSTR)GetValuePtr(PPS_PARAMETER_NAME, m_pRow);
|
|
USHORT * pusParamType = (USHORT *)GetValuePtr(PPS_PARAMETER_TYPE, m_pRow);
|
|
DBTYPE * pwType = (DBTYPE *)GetValuePtr(PPS_DATA_TYPE, m_pRow);
|
|
USHORT usParamType = 0;
|
|
DBORDINAL iParamOrdinal = 0;
|
|
ULONG iParamIndex= 0;
|
|
DBORDINAL ord1, ord2;
|
|
DBTYPE wTypeInfo, wType;
|
|
|
|
wType = *pwType;
|
|
|
|
if (pusParamType)
|
|
usParamType = *pusParamType;
|
|
|
|
if (m_cTotalRows == 1 && ((iOrdinal == 0) || (iOrdinal == 1)))
|
|
{
|
|
// Always reset param info if first row and ordinal in case it's left
|
|
// over from previous test variation.
|
|
SAFE_FREE(m_pwszQualifiedName);
|
|
SAFE_FREE(m_pParamInfo);
|
|
SAFE_FREE(m_pNamesBuffer);
|
|
m_cParams = 0;
|
|
}
|
|
|
|
TESTC(piOrdinal != NULL);
|
|
|
|
TESTC(GetParamInfo());
|
|
// ASSERT(m_pParamInfo != NULL);
|
|
TESTC(m_pParamInfo != NULL); // Should always have param info
|
|
|
|
iParamOrdinal = *piOrdinal;
|
|
|
|
// If we have the right index, then the ordinals will be related
|
|
// If no return param, both ordinals start at one, otherwise not
|
|
// Proc param ordinals are 0-based if return param
|
|
ord2 = (DBORDINAL)(*piOrdinal);
|
|
|
|
// Search for proper ordinal in parameter info
|
|
for (iParamIndex = 0; iParamIndex < m_cParams; iParamIndex++)
|
|
{
|
|
if (!wcscmp(m_pParamInfo[iParamIndex].pwszName, pwszParamName))
|
|
{
|
|
ord1 = m_pParamInfo[iParamIndex].iOrdinal - !(m_iOrdinalStart);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Make sure we found the ordinal
|
|
TESTC(iParamIndex < m_cParams);
|
|
|
|
// If we restricted on the parameter name, then we can't know if the ordinals
|
|
// are correct w/o going out and calling GetSchema w/o param name restriction
|
|
// to find out if there is a return param. So only test ordinals when not
|
|
// restricted on param name.
|
|
if (!m_prgRestrictUsed || V_VT(&m_prgRestrictUsed[3]) == VT_EMPTY)
|
|
{
|
|
TESTC(ord1 == ord2);
|
|
}
|
|
|
|
wTypeInfo = m_pParamInfo[iParamIndex].wType; //wType reported by GetParameterInfo
|
|
|
|
COMPARE(wType, wTypeInfo);
|
|
|
|
// We don't check provider-specific columns
|
|
if (iOrdinal > m_pSchemaInfo->cColumns)
|
|
return TRUE;
|
|
|
|
switch(iOrdinal)
|
|
{
|
|
case PPS_PROCEDURE_CATALOG:
|
|
break;
|
|
case PPS_PROCEDURE_SCHEMA:
|
|
break;
|
|
case PPS_PROCEDURE_NAME:
|
|
break;
|
|
case PPS_PARAMETER_NAME:
|
|
TESTC(ulStatus == DBSTATUS_S_OK);
|
|
TESTC(!wcscmp(m_pParamInfo[iParamIndex].pwszName, pwszParamName));
|
|
break;
|
|
case PPS_ORDINAL_POSITION:
|
|
// Ordinals are always sequential. Ordinals in proc params schema are 0-based if
|
|
// there is a return param, while ordinals in GetParameterInfo are always 1-based.
|
|
TESTC(*piOrdinal - m_iOrdinalPrev == 1);
|
|
m_iOrdinalPrev++;
|
|
break;
|
|
case PPS_PARAMETER_TYPE:
|
|
{
|
|
usParamType = *(USHORT *)pValue;
|
|
DBPARAMFLAGS dwFlags = m_pParamInfo[iParamIndex].dwFlags;
|
|
|
|
// Note we check for at least one of the valid values in the generic
|
|
// CHelper::VerifyValue
|
|
|
|
// If this is the return param, then ordinal is 0
|
|
if (iParamOrdinal == 0)
|
|
{
|
|
TESTC(usParamType == DBPARAMTYPE_RETURNVALUE);
|
|
}
|
|
else if ((dwFlags & DBPARAMFLAGS_ISINPUT) &&
|
|
(dwFlags & DBPARAMFLAGS_ISOUTPUT))
|
|
{
|
|
TESTC(usParamType == DBPARAMTYPE_INPUTOUTPUT);
|
|
}
|
|
else if (dwFlags & DBPARAMFLAGS_ISINPUT)
|
|
{
|
|
TESTC(usParamType == DBPARAMTYPE_INPUT);
|
|
}
|
|
else if (dwFlags & DBPARAMFLAGS_ISOUTPUT)
|
|
{
|
|
TESTC(usParamType == DBPARAMTYPE_OUTPUT);
|
|
}
|
|
}
|
|
break;
|
|
case PPS_PARAMETER_HASDEFAULT:
|
|
break;
|
|
case PPS_PARAMETER_DEFAULT:
|
|
break;
|
|
case PPS_IS_NULLABLE:
|
|
{
|
|
DBPARAMFLAGS dwFlags = m_pParamInfo[iParamIndex].dwFlags;
|
|
VARIANT_BOOL vbIsNullable = VARIANT_TRUE;
|
|
|
|
// Note: Error is posted if value is NULL based on schema info in VerifiyNull
|
|
if (pValue != NULL)
|
|
{
|
|
vbIsNullable = *(VARIANT_BOOL *)pValue;
|
|
|
|
if (dwFlags & DBPARAMFLAGS_ISNULLABLE)
|
|
{
|
|
TESTC(vbIsNullable == VARIANT_TRUE);
|
|
}
|
|
else
|
|
{
|
|
TESTC(vbIsNullable == VARIANT_FALSE);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case PPS_DATA_TYPE:
|
|
TESTC(ulStatus == DBSTATUS_S_OK);
|
|
TESTC(wType == *(DBTYPE *)pValue); // Redundant test, tested above comparing to wTypeInfo
|
|
break;
|
|
case PPS_CHARACTER_MAXIMUM_LENGTH:
|
|
break;
|
|
case PPS_CHARACTER_OCTET_LENGTH:
|
|
break;
|
|
case PPS_NUMERIC_PRECISION:
|
|
if (!IsNumericType(wType) || DBTYPE_VARNUMERIC == wType)
|
|
{
|
|
TESTC(ulStatus == DBSTATUS_S_ISNULL);
|
|
}
|
|
else
|
|
{
|
|
TESTC(ulStatus == DBSTATUS_S_OK);
|
|
TESTC((USHORT)m_pParamInfo[iParamIndex].bPrecision == *(USHORT *)pValue);
|
|
}
|
|
break;
|
|
case PPS_NUMERIC_SCALE:
|
|
switch(wType)
|
|
{
|
|
case DBTYPE_DECIMAL:
|
|
case DBTYPE_NUMERIC:
|
|
case DBTYPE_VARNUMERIC:
|
|
TESTC(ulStatus == DBSTATUS_S_OK);
|
|
TESTC((USHORT)m_pParamInfo[iParamIndex].bScale == *(USHORT *)pValue);
|
|
break;
|
|
default:
|
|
TESTC(ulStatus == DBSTATUS_S_ISNULL);
|
|
}
|
|
break;
|
|
case PPS_DESCRIPTION:
|
|
if (ulStatus != DBSTATUS_S_ISNULL)
|
|
VerifyNonEmptyString(pColumn, pwszProcName, pwszParamName);
|
|
break;
|
|
case PPS_TYPE_NAME:
|
|
// TODO: Make sure the type name is one from PROVIDER_TYPES, and the
|
|
// DBType matches the name.
|
|
// COMPAREW(0, 1);
|
|
VerifyNonEmptyString(pColumn, pwszProcName, pwszParamName);
|
|
VerifyColumnMatch(PPS_TYPE_NAME, PPS_LOCAL_TYPE_NAME);
|
|
break;
|
|
case PPS_LOCAL_TYPE_NAME:
|
|
VerifyNonEmptyString(pColumn, pwszProcName, pwszParamName);
|
|
break;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
return fResult;
|
|
}
|
|
|
|
// Provider Types schema specific functions
|
|
class CProviderTypesHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
DBTYPE m_dbPrevType;
|
|
BOOL m_fBestMatchFound;
|
|
|
|
protected:
|
|
BOOL VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn);
|
|
|
|
public:
|
|
CProviderTypesHelper(void);
|
|
};
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CProviderTypesHelper::CProviderTypesHelper
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
CProviderTypesHelper::CProviderTypesHelper(void)
|
|
{
|
|
m_guidSchema = DBSCHEMA_PROVIDER_TYPES;
|
|
m_dbPrevType = DBTYPE_VECTOR; // DBTYPE_VECTOR by itself is not valid
|
|
m_fBestMatchFound = FALSE;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CProviderTypesHelper::VerifyColumn
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CProviderTypesHelper::VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn)
|
|
{
|
|
DBTYPE * pdbTypeRow = (DBTYPE *)GetValuePtr(PTS_DATA_TYPE, m_pRow);
|
|
VARIANT_BOOL * pvbBestMatch = (VARIANT_BOOL *)GetValuePtr(PTS_BEST_MATCH, m_pRow);
|
|
DBSTATUS ulStatus = pColumn->sStatus;
|
|
BOOL fResult = FALSE;
|
|
|
|
switch(iOrdinal)
|
|
{
|
|
// Currently only have tests for BEST_MATCH. Most PROVIDER_TYPES schema testing is done in
|
|
// ADO Connection test which caches the entire rowset and verifies no changes from previous
|
|
// runs.
|
|
case PTS_BEST_MATCH:
|
|
{
|
|
// PROVIDER_TYPES has only two restrictions. The first is on data type and second on BEST_MATCH.
|
|
// If we are restricted on BEST_MATCH then we will either always get all VARIANT_TRUE or all
|
|
// VARIANT_FALSE, so we cannot test for one and only one BEST_MATCH == VARIANT_TRUE.
|
|
if (m_cRestrictionsUsed > 1)
|
|
break;
|
|
|
|
// MSDASQL does not support BEST_MATCH and always returns NULL. In general, since the column
|
|
// is BOOL and NULL is not a valid value we should disallow this behavior, so only allow for MSDASQL.
|
|
if (IsMSDASQL() && ulStatus == DBSTATUS_S_ISNULL)
|
|
break;
|
|
|
|
TESTC(ulStatus == DBSTATUS_S_OK);
|
|
|
|
// Reset best match found flag if on the first row
|
|
if (m_cTotalRows == 1)
|
|
{
|
|
m_fBestMatchFound = FALSE;
|
|
m_dbPrevType = DBTYPE_VECTOR;
|
|
}
|
|
|
|
if (*pdbTypeRow != m_dbPrevType)
|
|
{
|
|
if (m_dbPrevType != DBTYPE_VECTOR)
|
|
{
|
|
TESTC(m_fBestMatchFound);
|
|
}
|
|
m_fBestMatchFound = FALSE;
|
|
m_dbPrevType = *pdbTypeRow;
|
|
}
|
|
else if (m_fBestMatchFound)
|
|
{
|
|
TESTC(*pvbBestMatch == VARIANT_FALSE);
|
|
}
|
|
|
|
if (*pvbBestMatch == VARIANT_TRUE)
|
|
m_fBestMatchFound = TRUE;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
return fResult;
|
|
}
|
|
|
|
// Table Constraints schema specific functions
|
|
class CTableConstraintsHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
public:
|
|
|
|
CTableConstraintsHelper(void) {m_guidSchema = DBSCHEMA_TABLE_CONSTRAINTS;}
|
|
};
|
|
|
|
// Table Privileges schema specific functions
|
|
class CTablePrivilegesHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
public:
|
|
|
|
CTablePrivilegesHelper(void) {m_guidSchema = DBSCHEMA_TABLE_PRIVILEGES;}
|
|
};
|
|
|
|
|
|
// Tables schema specific functions
|
|
class CTablesHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
BOOL VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn);
|
|
|
|
public:
|
|
|
|
CTablesHelper(void) {m_guidSchema = DBSCHEMA_TABLES;}
|
|
|
|
};
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CTablesHelper::VerifyColumn
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CTablesHelper::VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn)
|
|
{
|
|
BOOL fResults = FALSE;
|
|
|
|
// At this time there is no schema-specific testing for TABLES schema
|
|
|
|
switch(iOrdinal)
|
|
{
|
|
case 0:
|
|
// Bookmarks on and bound
|
|
// TODO: Add code to validate bookmarks are expected and they work.
|
|
break;
|
|
case TABLES_TABLE_CATALOG:
|
|
break;
|
|
|
|
case TABLES_TABLE_SCHEMA:
|
|
break;
|
|
|
|
case TABLES_TABLE_NAME:
|
|
break;
|
|
|
|
case TABLES_TABLE_TYPE:
|
|
break;
|
|
|
|
case TABLES_TABLE_GUID:
|
|
break;
|
|
|
|
case TABLES_DESCRIPTION:
|
|
break;
|
|
|
|
case TABLES_TABLE_PROPID:
|
|
break;
|
|
|
|
case TABLES_DATE_CREATED:
|
|
case TABLES_DATE_MODIFIED:
|
|
break;
|
|
default:
|
|
odtLog << L"Unexpected column in schema rowset.\n";
|
|
TESTC(FALSE);
|
|
}
|
|
|
|
fResults = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
return fResults;
|
|
|
|
}
|
|
|
|
// Tables Info schema specific functions
|
|
class CTablesInfoHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
BOOL VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn);
|
|
|
|
public:
|
|
|
|
CTablesInfoHelper(void) {m_guidSchema = DBSCHEMA_TABLES_INFO;}
|
|
};
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CTablesInfoHelper::VerifyColumn
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CTablesInfoHelper::VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn)
|
|
{
|
|
LPWSTR pwszTableName = (LPWSTR)GetValuePtr(TIS_TABLE_NAME, m_pRow);
|
|
LPWSTR pwszTableType = (LPWSTR)GetValuePtr(TIS_TABLE_TYPE, m_pRow);
|
|
VARIANT_BOOL bBookMarks = (VARIANT_BOOL)GetValuePtr(TIS_BOOKMARKS, m_pRow);
|
|
LPBYTE pValue = GetValuePtr(iOrdinal, m_pRow);
|
|
BOOL fResult = FALSE;
|
|
ULONG iIndex = 0;
|
|
DBSTATUS ulStatus = pColumn->sStatus;
|
|
|
|
switch(iOrdinal)
|
|
{
|
|
case TIS_TABLE_CATALOG:
|
|
break;
|
|
|
|
case TIS_TABLE_SCHEMA:
|
|
break;
|
|
|
|
case TIS_TABLE_NAME:
|
|
break;
|
|
|
|
case TIS_TABLE_TYPE:
|
|
// Note: We already test that the value is one of the valid ones in VerifyValue
|
|
break;
|
|
|
|
case TIS_TABLE_GUID:
|
|
break;
|
|
|
|
case TIS_BOOKMARKS:
|
|
// Note: We already test that the value is one of the valid ones in VerifyValue
|
|
break;
|
|
|
|
case TIS_BOOKMARK_TYPE:
|
|
// This column is NULL if BOOKMARKS column is VARIANT_FALSE
|
|
if (bBookMarks == VARIANT_FALSE)
|
|
{
|
|
TESTC(ulStatus == DBSTATUS_S_ISNULL);
|
|
}
|
|
else
|
|
{
|
|
TESTC(ulStatus == DBSTATUS_S_OK);
|
|
|
|
// Note: We already test that the value is one of the valid ones in VerifyValue
|
|
}
|
|
break;
|
|
|
|
case TIS_BOOKMARK_DATATYPE:
|
|
|
|
if (bBookMarks == VARIANT_FALSE)
|
|
{
|
|
TESTC(ulStatus == DBSTATUS_S_ISNULL);
|
|
}
|
|
else
|
|
{
|
|
TESTC(ulStatus == DBSTATUS_S_OK);
|
|
|
|
if (m_prgColInfo && m_prgColInfo[0].iOrdinal == 0)
|
|
{
|
|
TESTC(m_prgColInfo[0].wType == *(DBTYPE *)pValue);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TIS_BOOKMARK_MAXIMUM_LENGTH:
|
|
if (bBookMarks == VARIANT_FALSE)
|
|
{
|
|
TESTC(ulStatus == DBSTATUS_S_ISNULL);
|
|
}
|
|
else
|
|
{
|
|
TESTC(ulStatus == DBSTATUS_S_OK);
|
|
|
|
if (m_prgColInfo && m_prgColInfo[0].iOrdinal == 0)
|
|
{
|
|
TESTC(m_prgColInfo[0].ulColumnSize == *(ULONG *)pValue);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TIS_BOOKMARK_INFORMATION:
|
|
break;
|
|
|
|
case TIS_TABLE_VERSION:
|
|
break;
|
|
|
|
case TIS_CARDINALITY:
|
|
// Only valid for TABLE types, must be NULL for other types
|
|
|
|
if (pwszTableType && (
|
|
!wcscmp(pwszTableType, L"TABLE") ||
|
|
!wcscmp(pwszTableType, L"SYSTEM TABLE") ||
|
|
!wcscmp(pwszTableType, L"GLOBAL TEMPORARY") ||
|
|
!wcscmp(pwszTableType, L"LOCAL TEMPORARY") ||
|
|
!wcscmp(pwszTableType, L"EXTERNAL TABLE")))
|
|
{
|
|
// We expect a valid non-null cardinality
|
|
TESTC(ulStatus == DBSTATUS_S_OK);
|
|
}
|
|
else
|
|
{
|
|
// This is not a TABLE type, so cardinality must be null
|
|
TESTC(ulStatus == DBSTATUS_S_ISNULL);
|
|
|
|
// TODO: For the base table we created, this should have the right number of rows.
|
|
// For random tables counting the rows could possibly be done but is likely too time intensive.
|
|
|
|
|
|
}
|
|
break;
|
|
|
|
case TIS_DESCRIPTION:
|
|
break;
|
|
|
|
case TIS_TABLE_PROPID:
|
|
break;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
return fResult;
|
|
|
|
}
|
|
|
|
|
|
// Table Statistics schema specific functions
|
|
class CTableStatisticsHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
CErrorCache m_EC; // Table Statistics error cache
|
|
BOOL m_fFoundCardinality;
|
|
BOOL m_fFoundHistogram;
|
|
BOOL m_fCardinalityIncludesBlob;
|
|
LPWSTR m_pwszStatName;
|
|
BOOL m_fDetailCheck;
|
|
ULONG m_iOrdinalExpected;
|
|
IOpenRowset * m_pIOpenRowset;
|
|
ULONG_PTR m_ulTableStatistics;
|
|
LPWSTR * m_ppwszStatCols;
|
|
DBORDINAL m_cStatCols;
|
|
|
|
protected:
|
|
|
|
BOOL VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn);
|
|
BOOL CheckHistogramColInfo(IRowset * pIHistogramRowset, DBTYPE wRangeColType,
|
|
DBORDINAL * pcBinding, DBBINDING ** ppBinding, DBLENGTH * pcbRowSize,
|
|
HACCESSOR * phAccessor);
|
|
|
|
// Returns cardinality (COUNT) information for the given table using ulColIndex index into
|
|
// columns info for table.
|
|
DBCOUNTITEM Cardinality(LPWSTR pwszTableName, ULONG ulColIndex, CARDINALITY eCardinality,
|
|
DBBINDING * pStartBind = NULL, DBBINDING * pEndBind = NULL, LPBYTE pDataHist = NULL,
|
|
DBLENGTH cbRowSize = 0);
|
|
|
|
public:
|
|
CTableStatisticsHelper(void);
|
|
~CTableStatisticsHelper(void);
|
|
BOOL Init(CSchemaTest * pThis);
|
|
};
|
|
|
|
CTableStatisticsHelper::CTableStatisticsHelper(void)
|
|
{
|
|
m_guidSchema = DBSCHEMA_TABLE_STATISTICS;
|
|
m_pIOpenRowset = NULL;
|
|
m_pwszStatName = NULL;
|
|
m_ppwszStatCols = NULL;
|
|
m_cStatCols = 0;
|
|
}
|
|
|
|
// CTableStatisticsHelper destructor
|
|
CTableStatisticsHelper::~CTableStatisticsHelper(void)
|
|
{
|
|
// If a histogram was found then make sure support is indicated.
|
|
// Note that if a histogram was not found we cannot infer lack of support
|
|
// as there may not happen to be any created at this time, so only post
|
|
// a warning
|
|
if (m_fFoundHistogram)
|
|
COMPARE(!!(m_ulTableStatistics & DBPROPVAL_TS_HISTOGRAM), TRUE);
|
|
else
|
|
COMPAREW(!!(m_ulTableStatistics & DBPROPVAL_TS_HISTOGRAM), FALSE);
|
|
|
|
// If a cardinality info was found then make sure support is indicated.
|
|
// Note that if a cardinality was not found we cannot infer lack of support
|
|
// as there may not happen to be any created at this time, so only post
|
|
// a warning
|
|
if (m_fFoundCardinality)
|
|
COMPARE(!!(m_ulTableStatistics & DBPROPVAL_TS_CARDINALITY), TRUE);
|
|
else
|
|
COMPAREW(!!(m_ulTableStatistics & DBPROPVAL_TS_CARDINALITY), FALSE);
|
|
|
|
SAFE_RELEASE(m_pIOpenRowset);
|
|
|
|
if (m_ppwszStatCols)
|
|
{
|
|
for (DBORDINAL iCol = 0; iCol < m_cStatCols; iCol++)
|
|
SAFE_FREE(m_ppwszStatCols[iCol]);
|
|
|
|
SAFE_FREE(m_ppwszStatCols);
|
|
}
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// CTableStatisticsHelper::Init
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
BOOL CTableStatisticsHelper::Init(CSchemaTest * pThis)
|
|
{
|
|
LPWSTR pwszUpdateStats = NULL;
|
|
size_t ccUpdateStats = 0;
|
|
LPWSTR pwszUpdateStatsFormat = pThis->m_pwszUpdateStatsFormat;
|
|
BOOL fSuccess = FALSE;
|
|
|
|
IRowset * pIRowset = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBBINDING * prgDBBINDING = NULL;
|
|
DBCOUNTITEM cDBBINDING = 0;
|
|
DBLENGTH cbRowSize = 0;
|
|
HRESULT hr = S_OK;
|
|
DBCOUNTITEM cRowsObtained;
|
|
HROW * prghRows = NULL; // array of hrows
|
|
LPBYTE pData = NULL;
|
|
LPWSTR pwszQualifiedName = NULL;
|
|
VARIANT rgRestrict[NUMELEM(rgTablesRestrict)];
|
|
ULONG cRestrict = NUMELEM(rgTablesRestrict);
|
|
HRESULT hrUpdate = E_FAIL;
|
|
|
|
// Schema specific vars init
|
|
m_fFoundCardinality = FALSE;
|
|
m_fFoundHistogram = FALSE;
|
|
m_ulTableStatistics = 0;
|
|
m_pwszStatName = NULL;
|
|
m_fDetailCheck = FALSE;
|
|
m_iOrdinalExpected = 0;
|
|
m_pIOpenRowset = pThis->m_pIOpenRowset;
|
|
|
|
// Addref the IOpenRowset so it won't go away while we're using
|
|
m_pIOpenRowset->AddRef();
|
|
|
|
// Initialize the helper
|
|
if (!CHelper::Init(pThis))
|
|
return FALSE;
|
|
|
|
// Get DBPROP_TABLESTATISTICS
|
|
GetProperty(g_propTableStatistics, DBPROPSET_DATASOURCEINFO, pThis->m_pIDBInitialize, &m_ulTableStatistics);
|
|
|
|
// Execute the provider-specific command to update all table statistics so they will
|
|
// be accurate for the test. Both Oracle and SQL Server have a stored proc that can
|
|
// be called to update all table's statistics in the user's schema, but these have
|
|
// problems. On SQL Server, the proc can only be run by admin, and against Oracle,
|
|
// the proc is not supported for older servers (7.x). So brute force method is
|
|
// required (very slow).
|
|
if (pwszUpdateStatsFormat)
|
|
{
|
|
// Get the max size for a table name
|
|
DBLITERALINFO* pTableLiteral = m_pTable->GetLiteralInfo(DBLITERAL_TABLE_NAME);
|
|
TESTC(pTableLiteral != NULL);
|
|
|
|
// Compute max size for a statement that will update a table
|
|
// We assume Catalog Name, Schema Name, and Table Name will have
|
|
// the same max length, and additionally that tables will be fully
|
|
// qualified and quoted, since we don't know if there will be different
|
|
// catalogs, schemas and we don't know there are not table names that
|
|
// require quotes in the TABLES schema.
|
|
// 8 == two quotes for each name portion, plus 2 separators for the portions
|
|
ccUpdateStats = wcslen(pwszUpdateStatsFormat) +
|
|
(pTableLiteral->cchMaxLen * 3 + 8) +1;
|
|
|
|
SAFE_ALLOC(pwszUpdateStats, WCHAR, ccUpdateStats);
|
|
|
|
// Initialize restrictions
|
|
memset(rgRestrict, 0, sizeof(VARIANT) * cRestrict);
|
|
|
|
// Set restriction on table type
|
|
V_VT(&rgRestrict[3]) = VT_BSTR;
|
|
V_BSTR(&rgRestrict[3]) = SysAllocString(L"TABLE");
|
|
|
|
// Get the TABLES schema rowset
|
|
TESTC_(m_pIDBSchemaRowset->GetRowset(NULL, DBSCHEMA_TABLES, cRestrict, rgRestrict,
|
|
IID_IRowset, 0, NULL, (IUnknown **)&pIRowset), S_OK);
|
|
|
|
// Get accessor and bindings for tables schema
|
|
TESTC_(GetAccessorAndBindings(
|
|
pIRowset, // @parmopt [IN] Rowset to create Accessor for
|
|
DBACCESSOR_ROWDATA, // @parmopt [IN] Properties of the Accessor
|
|
&hAccessor, // @parmopt [OUT] Accessor created
|
|
&prgDBBINDING, // @parmopt [OUT] Array of DBBINDINGS
|
|
&cDBBINDING, // @parmopt [OUT] Count of bindings
|
|
&cbRowSize, // @parmopt [OUT] Length of a row, DATA
|
|
DBPART_VALUE|DBPART_STATUS |DBPART_LENGTH,
|
|
ALL_COLS_BOUND, // @parmopt [IN] Which columns will be used in the bindings
|
|
FORWARD, // @parmopt [IN] Order to bind columns in accessor
|
|
NO_COLS_BY_REF, // @parmopt [IN] Which column types to bind by reference
|
|
NULL, // @parmopt [OUT] Array of DBCOLUMNINFO
|
|
NULL, // @parmopt [OUT] Count of Columns, also count of ColInfo elements
|
|
NULL,
|
|
DBTYPE_EMPTY, // @parmopt [IN] Modifier to be OR'd with each binding type.
|
|
0, // @parmopt [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
|
|
NULL, // @parmopt [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
|
|
NULL, // @parmopt [IN] Corresponds to what ordinals are specified for each binding, if
|
|
NO_COLS_OWNED_BY_PROV, // @parmopt [IN] Which columns' memory is to be owned by the provider
|
|
DBPARAMIO_NOTPARAM, // @parmopt [IN] Parameter kind specified for all bindings
|
|
BLOB_LONG, // @parmopt [IN] how to bind BLOB Columns
|
|
NULL),S_OK); // @parmopt [OUT] returned status array from CreateAccessor
|
|
|
|
// Allocate a buffer to hold a row
|
|
SAFE_ALLOC(pData, BYTE, cbRowSize);
|
|
|
|
while (hr == S_OK)
|
|
{
|
|
|
|
// Loop through schema and update stats for each table
|
|
hr=pIRowset->GetNextRows(NULL, 0, 1, &cRowsObtained, &prghRows);
|
|
|
|
if (hr != DB_S_ENDOFROWSET)
|
|
TESTC_(hr, S_OK);
|
|
|
|
if (cRowsObtained)
|
|
{
|
|
// Get data for the row
|
|
TESTC_(pIRowset->GetData(prghRows[0],hAccessor,pData), S_OK)
|
|
|
|
// Create a fully qualified table name
|
|
TESTC_(m_pTable->GetQualifiedName(
|
|
(LPWSTR)GetValuePtr(TABLES_TABLE_CATALOG, pData, prgDBBINDING),
|
|
(LPWSTR)GetValuePtr(TABLES_TABLE_SCHEMA, pData, prgDBBINDING),
|
|
(LPWSTR)GetValuePtr(TABLES_TABLE_NAME, pData, prgDBBINDING),
|
|
&pwszQualifiedName, TRUE), S_OK);
|
|
|
|
swprintf(pwszUpdateStats, pwszUpdateStatsFormat, pwszQualifiedName);
|
|
|
|
hrUpdate = m_pTable->BuildCommand(pwszUpdateStats, IID_IRowset,
|
|
EXECUTE_IFNOERROR, 0, NULL, NULL, NULL, NULL);
|
|
|
|
// Table could have been dropped after schema was retrieved, or we
|
|
// may not have permission.
|
|
if (hrUpdate != DB_E_NOTABLE && hrUpdate != DB_SEC_E_PERMISSIONDENIED)
|
|
CHECK(hrUpdate, S_OK);
|
|
|
|
if (hrUpdate != S_OK)
|
|
odtLog << pwszUpdateStats << L"\n";
|
|
|
|
SAFE_FREE(pwszQualifiedName);
|
|
ReleaseInputBindingsMemory(cDBBINDING, prgDBBINDING, pData, FALSE);
|
|
pIRowset->ReleaseRows(cRowsObtained, prghRows, NULL, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
odtLog << "\n==========================================================\n";
|
|
// odtLog << "Executed command: " << pwszUpdateStats << "\n";
|
|
odtLog << "Statistics for all tables in user's schema were updated.\n";
|
|
odtLog << "==========================================================\n\n";
|
|
}
|
|
|
|
fSuccess = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
VariantClear(&rgRestrict[4]);
|
|
SAFE_FREE(pwszQualifiedName);
|
|
SAFE_FREE(pwszUpdateStats);
|
|
SAFE_FREE(prgDBBINDING);
|
|
if (pIRowset && prghRows && *prghRows)
|
|
pIRowset->ReleaseRows(cRowsObtained, prghRows, NULL, NULL, NULL);
|
|
SAFE_RELEASE(pIRowset);
|
|
|
|
if (fSuccess)
|
|
return m_EC.Init(GetModInfo()->GetDebugMode());
|
|
else
|
|
return TEST_FAIL;
|
|
}
|
|
|
|
// Compare histogram rowset columns info
|
|
BOOL CTableStatisticsHelper::CheckHistogramColInfo(IRowset * pIHistogramRowset, DBTYPE wRangeColType,
|
|
DBORDINAL * pcBinding, DBBINDING ** ppBinding, DBLENGTH * pcbRowSize, HACCESSOR * phAccessor)
|
|
{
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
DBLENGTH cbRowSize = 0;
|
|
BOOL fColInfo = FALSE;
|
|
DBCOUNTITEM cActualCols = 0; // Count of columns returned in histogram rowset
|
|
LPWSTR pwszCmd = NULL;
|
|
IAccessor * pIAcc = NULL;
|
|
ICommand * pICmd = NULL;
|
|
DBBINDING * prgUDTBinding = NULL;
|
|
DB_LORDINAL * pNonUDTOrdinals = NULL;
|
|
|
|
// Save off member vars so we can call CheckAgainstIColumnsInfo()
|
|
DBBINDING * pBinding = m_rgDBBINDING;
|
|
DBCOUNTITEM cBinding = m_cDBBINDING;
|
|
DBCOLUMNINFO * pColInfo = m_rgDBCOLUMNINFO;
|
|
DBCOUNTITEM cColInfo = m_cDBCOLUMNINFO;
|
|
LPWSTR pStringsBuf = m_pStringsBuffer;
|
|
|
|
m_cDBCOLUMNINFO = 0;
|
|
m_rgDBCOLUMNINFO = NULL;
|
|
m_pStringsBuffer = NULL;
|
|
|
|
// Update expected type for RANGE_HI_KEY
|
|
HistogramRowset[0].pColList[0].wType = wRangeColType;
|
|
|
|
// Update count of columns if needed.
|
|
if (HistogramRowset[0].pulColCount)
|
|
{
|
|
HistogramRowset[0].cColumns = HistogramRowset[0].pulColCount[0];
|
|
}
|
|
|
|
// get bindings and column info
|
|
if(!CHECK(GetAccessorAndBindings(
|
|
pIHistogramRowset, // @parmopt [IN] Rowset to create Accessor for
|
|
DBACCESSOR_ROWDATA, // @parmopt [IN] Properties of the Accessor
|
|
&hAccessor, // @parmopt [OUT] Accessor created
|
|
&m_rgDBBINDING, // @parmopt [OUT] Array of DBBINDINGS
|
|
&m_cDBBINDING, // @parmopt [OUT] Count of bindings
|
|
&cbRowSize, // @parmopt [OUT] Length of a row, DATA
|
|
DBPART_VALUE|DBPART_STATUS |DBPART_LENGTH,
|
|
ALL_COLS_BOUND, // @parmopt [IN] Which columns will be used in the bindings
|
|
FORWARD, // @parmopt [IN] Order to bind columns in accessor
|
|
NO_COLS_BY_REF, // @parmopt [IN] Which column types to bind by reference
|
|
&m_rgDBCOLUMNINFO, // @parmopt [OUT] Array of DBCOLUMNINFO
|
|
&m_cDBCOLUMNINFO, // @parmopt [OUT] Count of Columns, also count of ColInfo elements
|
|
&m_pStringsBuffer,
|
|
DBTYPE_EMPTY, // @parmopt [IN] Modifier to be OR'd with each binding type.
|
|
0, // @parmopt [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
|
|
NULL, // @parmopt [IN] Used only if eColsToBind = USE_COLS_TO_BIND_ARRAY
|
|
NULL, // @parmopt [IN] Corresponds to what ordinals are specified for each binding, if
|
|
NO_COLS_OWNED_BY_PROV, // @parmopt [IN] Which columns' memory is to be owned by the provider
|
|
DBPARAMIO_NOTPARAM, // @parmopt [IN] Parameter kind specified for all bindings
|
|
BLOB_LONG, // @parmopt [IN] how to bind BLOB Columns
|
|
NULL),S_OK)) // @parmopt [OUT] returned status array from CreateAccessor
|
|
goto CLEANUP;
|
|
|
|
fColInfo = CheckAgainstIColumnsInfo(&HistogramRowset[0]);
|
|
|
|
// CheckAgainstIColumnsInfo doesn't test for any extra columns, so warn here
|
|
// if there are extras
|
|
cActualCols = m_cDBCOLUMNINFO - !m_rgDBCOLUMNINFO[0].iOrdinal;
|
|
|
|
// Check for extra columns in histogram rowset. This is only a warning
|
|
// since it's allowed to return extra columns. Cache the warning so we don't
|
|
// get it for every histogram over and over.
|
|
CCOMPARE(m_EC, HistogramRowset[0].cColumns == cActualCols, EC_EXTRA_COLUMN,
|
|
L"Extra column in Histogram rowset.", TRUE);
|
|
|
|
CLEANUP:
|
|
|
|
// Populate output params
|
|
if (pcBinding)
|
|
*pcBinding = cActualCols;
|
|
if (ppBinding)
|
|
*ppBinding = m_rgDBBINDING;
|
|
else
|
|
SAFE_FREE(m_rgDBBINDING);
|
|
if (pcbRowSize)
|
|
*pcbRowSize = cbRowSize;
|
|
if (phAccessor)
|
|
*phAccessor = hAccessor;
|
|
else if (pIAcc && (hAccessor != DB_NULL_HACCESSOR))
|
|
CHECK(pIAcc->ReleaseAccessor(hAccessor, NULL), S_OK);
|
|
|
|
SAFE_RELEASE(pIAcc);
|
|
SAFE_RELEASE(pICmd);
|
|
|
|
SAFE_FREE(m_rgDBCOLUMNINFO);
|
|
SAFE_FREE(m_pStringsBuffer);
|
|
SAFE_FREE(pwszCmd);
|
|
SAFE_FREE(prgUDTBinding);
|
|
SAFE_FREE(pNonUDTOrdinals);
|
|
|
|
// Restore member vars to avoid side effects
|
|
m_rgDBBINDING = pBinding;
|
|
m_cDBBINDING = cBinding;
|
|
m_rgDBCOLUMNINFO= pColInfo;
|
|
m_cDBCOLUMNINFO = cColInfo;
|
|
m_pStringsBuffer= pStringsBuf;
|
|
|
|
return fColInfo;
|
|
}
|
|
|
|
DBCOUNTITEM CTableStatisticsHelper::Cardinality(LPWSTR pwszTableName, ULONG ulColIndex, CARDINALITY eCardinality,
|
|
DBBINDING * pStartBind, DBBINDING * pEndBind, LPBYTE pDataRows, DBLENGTH cbRowSize)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG ulIndexFirst = 0;
|
|
size_t cChars = 0;
|
|
LPWSTR pwszColList = NULL;
|
|
LPWSTR pwszSelectFmt = (LPWSTR)wszSELECT_DISTINCTCOLLIST;
|
|
LPWSTR pwszSelect = NULL;
|
|
LPWSTR pwszGreaterFmt = L"%s > ?";
|
|
LPWSTR pwszLessThanEqFmt = L"%s <= ?";
|
|
LPWSTR pwszEqFmt = L"%s = ?";
|
|
LPWSTR pwszRange = NULL;
|
|
DBCOUNTITEM ulCardinality = 0;
|
|
IRowset * pIRowset = NULL;
|
|
IAccessor * pIAccessor = NULL;
|
|
ICommand * pICommand = NULL;
|
|
IAccessor * pICmdAccessor = NULL;
|
|
DBBINDING dbCountBind;
|
|
DBBINDING dbParamBind[2]; // Only two params required for all cases
|
|
ULONG cParams = 0;
|
|
// HACCESSOR hAcc = DB_NULL_HACCESSOR;
|
|
HACCESSOR hParamAcc = DB_NULL_HACCESSOR;
|
|
HROW * phRows = NULL;
|
|
ULONG * pulCardinality = NULL;
|
|
DBORDINAL iCol;
|
|
DBCOUNTITEM cRowsObtained;
|
|
DBPARAMS dbParams;
|
|
DBBINDSTATUS rgStatus[2];
|
|
ULONG * pulOrdinal = (ULONG *)GetValuePtr(TSS_ORDINAL_POSITION, m_pRow);
|
|
ULONG ulOrdinal;
|
|
|
|
if (eCardinality == TUPLE_CARDINALITY)
|
|
{
|
|
if (!COMPARE(pulOrdinal != NULL, TRUE))
|
|
return 0;
|
|
|
|
ulOrdinal = *pulOrdinal;
|
|
}
|
|
|
|
// Previously used the count aggregate function, but that was bad because:
|
|
// 1) Doesn't include NULL rows
|
|
// 2) Fails against GUID column on some providers.
|
|
// select count(*) from (select distinct col1,col2 from <table> where col1 > ? and
|
|
// col1 <= ?) t1
|
|
|
|
// Now we use just the select distinct, but this still will fail for BLOB columns,
|
|
// so we have to avoid calling this function for BLOBS.
|
|
// TODO: If this function is made more sophisticated we can actually call for BLOBS.
|
|
// Possible improvements 1) Use conversion function, 2) actually retrieve data
|
|
// ourselves and count distinct values.
|
|
// select distinct col1,col2 from <table> where col1 > ? and col1 <= ?
|
|
|
|
// Assume no Blob columns are included in cardinality results. Most important
|
|
// for Tuple cardinality
|
|
m_fCardinalityIncludesBlob = FALSE;
|
|
|
|
// Initialize binding structures
|
|
memset(&dbCountBind, 0, sizeof(DBBINDING));
|
|
memset(&dbParamBind, 0, sizeof(DBBINDING)*2);
|
|
|
|
// Initialize dbParams
|
|
memset(&dbParams, 0, sizeof(DBPARAMS));
|
|
|
|
// Note we use params for this to avoid having to convert range limits to strings and
|
|
// obtain the appropriate literal prefix and suffix. I am assuming that any provider
|
|
// that has gone to the trouble to provide extensive support for query processors has
|
|
// also supported parameters.
|
|
|
|
switch (eCardinality)
|
|
{
|
|
// Both range rows and eq rows are non-distinct, and all the cardinalities
|
|
// for histogram are for only one column. But they all need a 'where' clause
|
|
case EQ_ROWS_CARDINALITY:
|
|
// We don't have a range for this cardinality, we're only looking for
|
|
// values equal to RANGE_HIGH_KEY
|
|
ASSERT(!pStartBind);
|
|
// Fall through
|
|
case RANGE_ROWS_CARDINALITY:
|
|
// Both of these counts are non-distinct, so change our select
|
|
// clause to not return distinct counts.
|
|
pwszSelectFmt = (LPWSTR)wszSELECT_COLLISTFROMTBL;
|
|
// Fall through
|
|
case DISTINCT_RANGE_ROWS_CARDINALITY:
|
|
{
|
|
size_t cchWhere = wcslen(wszWHERE); // Length of " where "
|
|
size_t cchColName = wcslen(m_prgColInfo[ulColIndex].pwszName);
|
|
LPWSTR pwszFmt = pwszLessThanEqFmt;
|
|
|
|
if (eCardinality == EQ_ROWS_CARDINALITY)
|
|
pwszFmt = pwszEqFmt;
|
|
|
|
// Fill out param info
|
|
if (pStartBind)
|
|
{
|
|
cchWhere += wcslen(pwszGreaterFmt) -2 + cchColName + wcslen(wszAND);
|
|
|
|
// Set parameter binding info
|
|
memcpy(&dbParamBind[cParams], pStartBind, sizeof(DBBINDING));
|
|
dbParamBind[cParams].eParamIO = DBPARAMIO_INPUT;
|
|
dbParamBind[cParams].iOrdinal = cParams+1;
|
|
|
|
cParams++;
|
|
}
|
|
if (pEndBind)
|
|
{
|
|
cchWhere += wcslen(pwszFmt) -2 + cchColName;
|
|
|
|
// Set parameter binding info
|
|
memcpy(&dbParamBind[cParams], pEndBind, sizeof(DBBINDING));
|
|
dbParamBind[cParams].eParamIO = DBPARAMIO_INPUT;
|
|
dbParamBind[cParams].iOrdinal = cParams+1;
|
|
|
|
cParams++;
|
|
}
|
|
|
|
// Now we know all the pieces for the range clause, allocate memory and create
|
|
SAFE_ALLOC(pwszRange, WCHAR, cchWhere+1);
|
|
|
|
wcscpy(pwszRange, wszWHERE);
|
|
|
|
// Put in the starting range clause
|
|
if (pStartBind)
|
|
{
|
|
swprintf(pwszRange+wcslen(pwszRange), pwszGreaterFmt, m_prgColInfo[ulColIndex].pwszName);
|
|
wcscat(pwszRange, wszAND);
|
|
}
|
|
|
|
// Put in ending range clause (always needed)
|
|
swprintf(pwszRange+wcslen(pwszRange), pwszFmt, m_prgColInfo[ulColIndex].pwszName);
|
|
|
|
}
|
|
// Fall through
|
|
case COLUMN_CARDINALITY:
|
|
ulIndexFirst = ulColIndex;
|
|
// Fall through
|
|
case TUPLE_CARDINALITY:
|
|
// Compute memory for column list (column name plus comma)
|
|
for (iCol = 0; iCol < m_cStatCols; iCol++)
|
|
cChars+=wcslen(m_ppwszStatCols[iCol])+1;
|
|
|
|
// Allocate memory for col list
|
|
SAFE_ALLOC(pwszColList, WCHAR, cChars+1);
|
|
|
|
pwszColList[0] = L'\0';
|
|
// Put non-BLOB columns in final list
|
|
// Note we leave out BLOB cols because providers can't do a
|
|
// select distinct on a BLOB, which may have some impact on
|
|
// the cardinality results.
|
|
for (iCol = 0; iCol < m_cStatCols; iCol++)
|
|
{
|
|
LPWSTR pwszCol = m_ppwszStatCols[iCol];
|
|
ULONG iColInfo;
|
|
|
|
// Locate this stat column in the columns info
|
|
for (iColInfo = 0; iColInfo < m_cColInfo; iColInfo++)
|
|
{
|
|
if (!wcscmp(m_prgColInfo[iColInfo].pwszName, pwszCol))
|
|
break;
|
|
}
|
|
TESTC(iColInfo < m_cColInfo);
|
|
|
|
if (m_prgColInfo[iColInfo].dwFlags & DBCOLUMNFLAGS_ISLONG)
|
|
{
|
|
m_fCardinalityIncludesBlob = TRUE;
|
|
continue;
|
|
}
|
|
|
|
// Put in comma separator if needed
|
|
if (pwszColList[0])
|
|
wcscat(pwszColList, L",");
|
|
wcscat(pwszColList, pwszCol);
|
|
}
|
|
|
|
// Compute memory required for select distinct statement
|
|
// Length of select, 2 parenthesis, table name, table alias name
|
|
cChars+=wcslen(pwszSelectFmt)+wcslen(pwszTableName);
|
|
|
|
// Add space for 'where' clause if needed
|
|
if (pwszRange)
|
|
cChars+=wcslen(pwszRange);
|
|
|
|
// Allocate mem for select
|
|
SAFE_ALLOC(pwszSelect, WCHAR, cChars+1);
|
|
|
|
// select distinct col1,col2 from <table>
|
|
swprintf(pwszSelect, pwszSelectFmt, pwszColList, pwszTableName);
|
|
|
|
// Tack on where clause if needed
|
|
if (pwszRange)
|
|
wcscat(pwszSelect, pwszRange);
|
|
|
|
// Free the range clause
|
|
SAFE_FREE(pwszRange);
|
|
|
|
break;
|
|
case TABLE_CARDINALITY:
|
|
pwszSelectFmt = (LPWSTR)wszSELECT_ALLFROMTBL;
|
|
|
|
cChars+=wcslen(pwszSelectFmt)+wcslen(pwszTableName);
|
|
|
|
// Allocate mem for select
|
|
SAFE_ALLOC(pwszSelect, WCHAR, cChars+1);
|
|
|
|
// Create select stmt
|
|
swprintf(pwszSelect, pwszSelectFmt, pwszTableName);
|
|
|
|
break;
|
|
}
|
|
|
|
// Execute the command
|
|
if (cParams)
|
|
{
|
|
|
|
// Get the command object for the table object
|
|
pICommand = m_pTable->get_ICommandPTR();
|
|
|
|
// Addref the command object so we can release later.
|
|
pICommand->AddRef();
|
|
|
|
// Get accessor interface
|
|
TESTC(VerifyInterface(pICommand, IID_IAccessor, COMMAND_INTERFACE, (IUnknown **)&pICmdAccessor));
|
|
|
|
// Create the parameter accessor
|
|
TESTC_(pICmdAccessor->CreateAccessor(DBACCESSOR_PARAMETERDATA, cParams,
|
|
dbParamBind, cbRowSize, &hParamAcc, rgStatus), S_OK);
|
|
|
|
// Fill DBPARAMS info
|
|
dbParams.pData = pDataRows;
|
|
dbParams.cParamSets = 1;
|
|
dbParams.hAccessor = hParamAcc;
|
|
|
|
}
|
|
|
|
if (!CHECK(m_pTable->BuildCommand(pwszSelect, IID_IRowset,
|
|
EXECUTE_IFNOERROR, 0, NULL, &dbParams, NULL, (IUnknown **)&pIRowset, &pICommand), S_OK))
|
|
goto CLEANUP;
|
|
|
|
// Get accessor and bindings
|
|
// dbCountBind.obStatus = offsetof(DATA, sStatus);
|
|
// dbCountBind.obLength = offsetof(DATA, ulLength);
|
|
// dbCountBind.obValue = offsetof(DATA, bValue);
|
|
// dbCountBind.wType = DBTYPE_UI4;
|
|
// dbCountBind.iOrdinal = 1;
|
|
// dbCountBind.dwPart = DBPART_VALUE | DBPART_LENGTH | DBPART_STATUS;
|
|
|
|
// TESTC(VerifyInterface(pIRowset, IID_IAccessor, ROWSET_INTERFACE, (IUnknown **)&pIAccessor));
|
|
// TESTC_(pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, 1, &dbCountBind, 0, &hAcc, NULL), S_OK);
|
|
// hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, 1, &dbCountBind, 0, &hAcc, NULL);
|
|
|
|
// TESTC_(hr, S_OK);
|
|
|
|
// Count the rows
|
|
while(hr != DB_S_ENDOFROWSET)
|
|
{
|
|
TEST3C_(hr = pIRowset->GetNextRows(NULL, 0, 10000, &cRowsObtained, &phRows), S_OK, DB_S_ENDOFROWSET, DB_S_ROWLIMITEXCEEDED);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
TESTC(cRowsObtained);
|
|
}
|
|
|
|
ulCardinality+=cRowsObtained;
|
|
|
|
if (cRowsObtained)
|
|
{
|
|
CHECK(pIRowset->ReleaseRows(cRowsObtained, phRows, NULL, NULL, NULL), S_OK);
|
|
*phRows = DB_NULL_HROW;
|
|
}
|
|
}
|
|
|
|
CLEANUP:
|
|
|
|
// Release rows
|
|
if (pIRowset && phRows && *phRows != DB_NULL_HROW)
|
|
CHECK(pIRowset->ReleaseRows(cRowsObtained, phRows, NULL, NULL, NULL), S_OK);
|
|
|
|
// Release parameter accessor
|
|
if (pICmdAccessor && hParamAcc != DB_NULL_HACCESSOR)
|
|
CHECK(pICmdAccessor->ReleaseAccessor(hParamAcc, NULL), S_OK);
|
|
|
|
SAFE_FREE(phRows);
|
|
SAFE_FREE(pwszColList);
|
|
SAFE_FREE(pwszSelect);
|
|
SAFE_RELEASE(pICommand);
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIAccessor);
|
|
SAFE_RELEASE(pICmdAccessor);
|
|
|
|
return ulCardinality;
|
|
|
|
}
|
|
|
|
|
|
BOOL CTableStatisticsHelper::VerifyColumn(DBORDINAL iOrdinal, DATA * pColumn)
|
|
{
|
|
|
|
CCol col;
|
|
BOOL fResults = TRUE;
|
|
HRESULT hrOpenTable = E_FAIL;
|
|
LPWSTR pwszTableName = (LPWSTR)GetValuePtr(TSS_TABLE_NAME, m_pRow);
|
|
LPWSTR pwszStatName = (LPWSTR)GetValuePtr(TSS_STATISTICS_NAME, m_pRow);
|
|
LPWSTR pwszColumnName = (LPWSTR)GetValuePtr(TSS_COLUMN_NAME, m_pRow);
|
|
ULONG * pulTableCardinality = (ULONG *)GetValuePtr(TSS_TABLE_CARDINALITY, m_pRow);
|
|
ULONG * pulOrdinal = (ULONG *)GetValuePtr(TSS_ORDINAL_POSITION, m_pRow);
|
|
ULONG ulStatType = 0;
|
|
ULONG ulIndex = 0;
|
|
DBID dbidTable = DB_NULLID;
|
|
BOOL fNewTable = (!m_pwszTableName || !pwszTableName || (pwszTableName && RelCompareString(pwszTableName, m_pwszTableName)));
|
|
BOOL fNewStat = fNewTable | (!m_pwszStatName || !pwszStatName || (pwszStatName && RelCompareString(pwszStatName, m_pwszStatName)));
|
|
CARDINALITY eCardinality = TUPLE_CARDINALITY;
|
|
LPWSTR pwszCat = (LPWSTR)GetValuePtr(TSS_TABLE_CATALOG, m_pRow);
|
|
LPWSTR pwszSch = (LPWSTR)GetValuePtr(TSS_TABLE_SCHEMA, m_pRow);
|
|
LPWSTR pwszQualifiedName = NULL;
|
|
LPWSTR pwszQualifiedStatName = NULL;
|
|
|
|
// Reset any previous table or stat name saved
|
|
if (m_cTotalRows == 1)
|
|
{
|
|
fNewTable = TRUE;
|
|
fNewStat = TRUE;
|
|
}
|
|
|
|
if (iOrdinal == 1)
|
|
{
|
|
// Initial allocation
|
|
if (!m_ppwszStatCols)
|
|
{
|
|
m_cStatCols = 0;
|
|
SAFE_ALLOC(m_ppwszStatCols, LPWSTR, MAX_STATS_COLS);
|
|
memset(m_ppwszStatCols, 0, MAX_STATS_COLS * sizeof(LPWSTR *));
|
|
}
|
|
|
|
TESTC(m_cStatCols < MAX_STATS_COLS-1);
|
|
|
|
// Reset list of stats columns for each new statistic
|
|
if (fNewStat)
|
|
{
|
|
for (DBORDINAL iCol = 0; iCol < m_cStatCols; iCol++)
|
|
SAFE_FREE(m_ppwszStatCols[iCol]);
|
|
m_cStatCols = 0; // No columns currently in this new statistic
|
|
}
|
|
|
|
// Add this stat column to the list of statistics columns
|
|
m_ppwszStatCols[m_cStatCols++] = wcsDuplicate(pwszColumnName);
|
|
}
|
|
|
|
TESTC_(m_pTable->GetQualifiedName(pwszCat, pwszSch,
|
|
pwszTableName,&pwszQualifiedName, TRUE), S_OK);
|
|
TESTC_(m_pTable->GetQualifiedName(
|
|
(LPWSTR)GetValuePtr(TSS_STATISTICS_CATALOG, m_pRow),
|
|
(LPWSTR)GetValuePtr(TSS_STATISTICS_SCHEMA, m_pRow),
|
|
pwszStatName,
|
|
&pwszQualifiedStatName, TRUE), S_OK);
|
|
|
|
// *********************************************************************
|
|
// For current time, set this on for debugging test code.
|
|
// *********************************************************************
|
|
m_fDetailCheck = TRUE;
|
|
|
|
if (m_fDetailCheck)
|
|
{
|
|
ULONG * pulStatType = (ULONG *)GetValuePtr(TSS_STATISTICS_TYPE, m_pRow);
|
|
|
|
// Attempt to open table and get columns info
|
|
if (fNewTable)
|
|
{
|
|
hrOpenTable = GetColumnInfo(m_pRow, m_rgDBBINDING);
|
|
|
|
// Should be S_OK, or perhaps DB_E_NOTABLE
|
|
if (DB_E_NOTABLE != hrOpenTable)
|
|
{
|
|
// The first time we attempt to open the table we get the appropriate error,
|
|
// and from then on for the same table we get S_FALSE. We can't test much w/o
|
|
// columnsinfo, so just skip.
|
|
if (S_FALSE == hrOpenTable)
|
|
goto CLEANUP;
|
|
|
|
CHECK(hrOpenTable, S_OK);
|
|
}
|
|
else
|
|
// We warn here because it's possible the table name is
|
|
// bogus, or just deleted.
|
|
CHECKW(hrOpenTable, S_OK);
|
|
}
|
|
else
|
|
// If we obtained col info for the table we successfully opened it.
|
|
hrOpenTable = (m_prgColInfo) ? S_OK : E_FAIL;
|
|
|
|
// Set index into columns info given column name
|
|
if (m_prgColInfo && pwszColumnName)
|
|
{
|
|
for (ulIndex = 0; ulIndex < m_cColInfo; ulIndex++)
|
|
{
|
|
if (!wcscmp(m_prgColInfo[ulIndex].pwszName, pwszColumnName))
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Set up table dbid
|
|
dbidTable.eKind = DBKIND_NAME;
|
|
// dbidTable.uName.pwszName = pwszTableName;
|
|
dbidTable.uName.pwszName = pwszQualifiedName;
|
|
|
|
// Get statistic type
|
|
if (pulStatType)
|
|
ulStatType = *pulStatType;
|
|
|
|
}
|
|
|
|
// Set cardinality
|
|
eCardinality = TUPLE_CARDINALITY;
|
|
|
|
switch(iOrdinal)
|
|
{
|
|
case TSS_TABLE_CATALOG:
|
|
break;
|
|
case TSS_TABLE_SCHEMA:
|
|
break;
|
|
case TSS_TABLE_NAME:
|
|
break;
|
|
case TSS_STATISTICS_CATALOG:
|
|
break;
|
|
case TSS_STATISTICS_SCHEMA:
|
|
break;
|
|
case TSS_STATISTICS_NAME:
|
|
break;
|
|
case TSS_STATISTICS_TYPE:
|
|
{
|
|
TYPE_UI2 ulStatType = 0;
|
|
|
|
// Column cannot be NULL
|
|
if (COMPARE(pColumn->sStatus, DBSTATUS_S_OK))
|
|
{
|
|
ulStatType = *(TYPE_UI2 *)pColumn->bValue;
|
|
|
|
// Make sure no other bits are set than those spec'd
|
|
COMPARE(0, ulStatType & (~(DBSTAT_HISTOGRAM | DBSTAT_COLUMN_CARDINALITY |
|
|
DBSTAT_TUPLE_CARDINALITY)));
|
|
|
|
// If we claim histogram support then NO_OF_RANGES cannot be null
|
|
// but may be 0 if the table is empty.
|
|
if (ulStatType & DBSTAT_HISTOGRAM)
|
|
COMPARE(GetValuePtr(TSS_NO_OF_RANGES, m_pRow) != NULL, TRUE);
|
|
else
|
|
{
|
|
CCOMPARE(m_EC, GetValuePtr(TSS_NO_OF_RANGES, m_pRow) == NULL,
|
|
EC_NULL_RANGE_COUNT,
|
|
L"DBSTAT_HISTOGRAM not set but NO_OF_RANGES is non-NULL",
|
|
FALSE);
|
|
}
|
|
|
|
// If we claim column cardinality support then it must not be null
|
|
if (ulStatType & DBSTAT_COLUMN_CARDINALITY)
|
|
{
|
|
m_fFoundCardinality = TRUE;
|
|
COMPARE(GetValuePtr(TSS_COLUMN_CARDINALITY, m_pRow) != NULL, TRUE);
|
|
}
|
|
else
|
|
COMPARE(GetValuePtr(TSS_COLUMN_CARDINALITY, m_pRow) == NULL, TRUE);
|
|
|
|
// If we claim tuple cardinality support then not be null
|
|
if (ulStatType & DBSTAT_TUPLE_CARDINALITY)
|
|
{
|
|
m_fFoundCardinality = TRUE;
|
|
COMPARE(GetValuePtr(TSS_TUPLE_CARDINALITY, m_pRow) != NULL, TRUE);
|
|
}
|
|
else
|
|
COMPARE(GetValuePtr(TSS_TUPLE_CARDINALITY, m_pRow) == NULL, TRUE);
|
|
|
|
// DetailCheckStatType(ulStatType, m_pRow);
|
|
|
|
// Detail check
|
|
if (m_fDetailCheck)
|
|
{
|
|
IRowset * pIRowset = NULL;
|
|
DBID dbidStat;
|
|
LPWSTR pwszStatName = (LPWSTR)GetValuePtr(TSS_STATISTICS_NAME, m_pRow);
|
|
HRESULT hrOpenHistogram = E_FAIL;
|
|
|
|
dbidStat.eKind = DBKIND_GUID_NAME;
|
|
// dbidStat.uName.pwszName = pwszStatName;
|
|
dbidStat.uName.pwszName = pwszQualifiedStatName;
|
|
dbidStat.uGuid.guid = g_guidHistogramRowset;
|
|
|
|
// Attempt to open histogram rowset
|
|
hrOpenHistogram = m_pIOpenRowset->OpenRowset(NULL,
|
|
&dbidTable,
|
|
&dbidStat,
|
|
IID_IRowset,
|
|
0,
|
|
NULL,
|
|
(IUnknown **)&pIRowset);
|
|
|
|
// If there's a histogram then validate values
|
|
if (ulStatType & DBSTAT_HISTOGRAM)
|
|
{
|
|
// Histograms are only supported on first column
|
|
// of a multicolumn statistic.
|
|
if (pulOrdinal && *pulOrdinal == 1)
|
|
{
|
|
// Record we found at least one histogram.
|
|
m_fFoundHistogram = TRUE;
|
|
|
|
ULONG * pcRanges = (ULONG *)GetValuePtr(TSS_NO_OF_RANGES, m_pRow);
|
|
|
|
// It's possible the table was deleted after we opened
|
|
// the schema rowset
|
|
if (S_OK == hrOpenHistogram)
|
|
{
|
|
// odtLog << L"Opened histogram rowset for table: " << pwszTableName << L" statistic: "
|
|
// << pwszStatName << L"\n";
|
|
|
|
if (CHECK(pIRowset != NULL, TRUE))
|
|
{
|
|
HRESULT hrGetNextRows = S_OK;
|
|
ULONG cRows = 0;
|
|
HROW * phRows = NULL;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
DBCOUNTITEM cBinding = 0, iBind;
|
|
DBLENGTH cbRowSize = 0;
|
|
DBBINDING * pBinding = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
LPBYTE pDataRows = NULL;
|
|
|
|
// Check histogram rowset columns info
|
|
if (m_prgColInfo && !COMPARE(CheckHistogramColInfo(
|
|
pIRowset,
|
|
m_prgColInfo[ulIndex].wType,
|
|
&cBinding,
|
|
&pBinding,
|
|
&cbRowSize,
|
|
&hAccessor
|
|
), TRUE))
|
|
odtLog << L"Histogram colinfo doesn't match.\n";
|
|
|
|
// Make sure the provider returned valid info
|
|
if (cBinding > 0 &&
|
|
pBinding &&
|
|
cbRowSize > 0 &&
|
|
hAccessor != DB_NULL_HACCESSOR)
|
|
{
|
|
LPBYTE pDataHist = NULL;
|
|
DBBINDING dbBind;
|
|
DBCOUNTITEM ulRangeCount = 0;
|
|
DBCOUNTITEM ulTotal = 0;
|
|
|
|
// We need the table cardinality so if not available
|
|
// we must compute ourselves
|
|
if (pulTableCardinality)
|
|
ulTotal = *pulTableCardinality;
|
|
else
|
|
ulTotal = Cardinality(pwszQualifiedName, 0, TABLE_CARDINALITY);
|
|
|
|
// Create a binding structure for the other row
|
|
// data
|
|
memcpy(&dbBind, pBinding, sizeof(DBBINDING));
|
|
dbBind.obStatus+=cbRowSize;
|
|
dbBind.obLength+=cbRowSize;
|
|
dbBind.obValue+=cbRowSize;
|
|
|
|
// Allocate memory for two rows of histogram
|
|
SAFE_ALLOC(pDataRows, BYTE, cbRowSize*2);
|
|
|
|
pDataHist = pDataRows;
|
|
|
|
while ((hrGetNextRows = pIRowset->GetNextRows(
|
|
NULL,
|
|
0,
|
|
1,
|
|
&cRowsObtained,
|
|
&phRows)) == S_OK)
|
|
{
|
|
|
|
cRows++;
|
|
|
|
if (COMPARE(cRowsObtained, 1) &&
|
|
COMPARE(phRows != NULL, TRUE) &&
|
|
CHECK(pIRowset->GetData(phRows[0], hAccessor, pDataHist), S_OK))
|
|
{
|
|
LPBYTE pRANGE_HI_KEY = GetValuePtr(HR_RANGE_HI_KEY, pDataHist, pBinding);
|
|
TYPE_R8 * pRANGE_ROWS = (TYPE_R8 *)GetValuePtr(HR_RANGE_ROWS, pDataHist, pBinding);
|
|
TYPE_R8 * pEQ_ROWS = (TYPE_R8 *)GetValuePtr(HR_EQ_ROWS, pDataHist, pBinding);
|
|
TYPE_I8 * pDISTINCT_RANGE_ROWS =
|
|
(TYPE_I8 *)GetValuePtr(HR_DISTINCT_RANGE_ROWS, pDataHist, pBinding);
|
|
DBBINDING * pPrevBind=NULL;
|
|
DBBINDING * pCurrentBind = pBinding;
|
|
double fFraction, fPercent;
|
|
|
|
// Set pointers to previous and current bindings for RANGE_HIGH_KEY
|
|
if (cRows > 1)
|
|
{
|
|
if (pDataHist == pDataRows)
|
|
{
|
|
pCurrentBind = pBinding;
|
|
pPrevBind = &dbBind;
|
|
}
|
|
else
|
|
{
|
|
pCurrentBind = &dbBind;
|
|
pPrevBind = pBinding;
|
|
}
|
|
}
|
|
|
|
|
|
// Validate this row
|
|
|
|
// Check each status for unexpected values
|
|
for (iBind = 0; iBind < cBinding; iBind++)
|
|
{
|
|
if (STATUS_BINDING(pBinding[iBind], pDataHist) != DBSTATUS_S_OK &&
|
|
STATUS_BINDING(pBinding[iBind], pDataHist) != DBSTATUS_S_ISNULL &&
|
|
!COMPARE(STATUS_BINDING(pBinding[iBind], pDataHist), DBSTATUS_S_OK))
|
|
odtLog << L"Histogram rowset column " << iBind << L" returned an unexpected status: "
|
|
<< STATUS_BINDING(pBinding[iBind], pDataHist) << L"\n";
|
|
}
|
|
|
|
// RANGE_HI_KEY is mandatory
|
|
if (!COMPARE(pRANGE_HI_KEY != NULL, TRUE))
|
|
odtLog << L"Table: " << pwszQualifiedName <<
|
|
L" Statistic: " << pwszQualifiedStatName <<
|
|
L" returned NULL for mandatory RANGE_HI_KEY\n";
|
|
|
|
// One of RANGE_ROWS or EQ_ROWS is required
|
|
COMPARE(pRANGE_ROWS != NULL ||
|
|
pEQ_ROWS != NULL, TRUE);
|
|
|
|
// Validate sort is by RANGE_HI_KEY, ascending order
|
|
|
|
// Validate data for each returned column
|
|
// RANGE_HI_KEY
|
|
|
|
/* Actually, this may not necessarily be a value in the column
|
|
It may not even be within the range of values in the table, so we
|
|
really can't test this.
|
|
|
|
// Must be a value in the column
|
|
if (pRANGE_HI_KEY)
|
|
{
|
|
ulRangeCount = Cardinality(pwszQualifiedName, ulIndex, EQ_ROWS_CARDINALITY,
|
|
NULL, pCurrentBind, pDataRows, cbRowSize*2);
|
|
|
|
// Fail if no value in table == RANGE_HIGH_KEY
|
|
if (!COMPARE(ulRangeCount > 0, TRUE))
|
|
odtLog << pwszTableName << L": RANGE_HI_KEY not in base table.\n";
|
|
}
|
|
*/
|
|
|
|
// RANGE_ROWS
|
|
// Fraction of number of rows that fall in this histogram
|
|
// range. Select rows in this range and
|
|
// divide by table cardinality.
|
|
if (pRANGE_ROWS)
|
|
{
|
|
// Can't compute cardinality for BLOB at this time
|
|
if (m_prgColInfo[ulIndex].dwFlags & DBCOLUMNFLAGS_ISLONG)
|
|
{
|
|
odtLog << L"Test cannot compute cardinality for LONG columns.\n";
|
|
odtLog << L"Comparison skipped.\n";
|
|
}
|
|
else
|
|
{
|
|
ulRangeCount = Cardinality(pwszQualifiedName, ulIndex, RANGE_ROWS_CARDINALITY,
|
|
pPrevBind, pCurrentBind, pDataRows, cbRowSize*2);
|
|
fFraction = (float)(DB_LORDINAL)ulRangeCount/(float)(DB_LORDINAL)ulTotal;
|
|
|
|
// Compute percentage error in result, avoid division by 0
|
|
if (fFraction > 0.0)
|
|
fPercent = fabs((*(double *)pRANGE_ROWS - fFraction)/fFraction);
|
|
else
|
|
fPercent = 0.0;
|
|
|
|
// Fail if off by more than 10%
|
|
CCOMPARE(m_EC, fPercent < MAX_STATISTIC_ERROR,
|
|
EC_BAD_RANGE_ROWS,
|
|
L"RANGE_ROWS not within 10%",
|
|
FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
// EQ_ROWS
|
|
// Fraction of rows equal to RANGE_HIGH_KEY.
|
|
// Select rows equal and divide by table cardinality.
|
|
if (pEQ_ROWS)
|
|
{
|
|
ulRangeCount = Cardinality(pwszQualifiedName, ulIndex, EQ_ROWS_CARDINALITY,
|
|
NULL, pCurrentBind, pDataRows, cbRowSize*2);
|
|
fFraction = (float)(DB_LORDINAL)ulRangeCount/(float)(DB_LORDINAL)ulTotal;
|
|
|
|
// Compute percentage error in result, avoid division by 0
|
|
if (fFraction > 0.0)
|
|
fPercent = fabs((*(double *)pEQ_ROWS - fFraction)/fFraction);
|
|
else
|
|
fPercent = 0.0;
|
|
|
|
// Fail if off by more than 10%
|
|
CCOMPARE(m_EC, fPercent < MAX_STATISTIC_ERROR,
|
|
EC_BAD_EQ_ROWS,
|
|
L"EQ_ROWS not within 10%",
|
|
FALSE);
|
|
}
|
|
|
|
// DISTINCT_RANGE_ROWS
|
|
// Number of distinct values in this range.
|
|
// Select distinct rows in this range.
|
|
if (pDISTINCT_RANGE_ROWS)
|
|
{
|
|
ulRangeCount = Cardinality(pwszQualifiedName, ulIndex, DISTINCT_RANGE_ROWS_CARDINALITY,
|
|
pPrevBind, pCurrentBind, pDataRows, cbRowSize*2);
|
|
|
|
// Compute percentage error in result, avoid division by 0
|
|
if (ulRangeCount)
|
|
fPercent = fabs(float((*(LONGLONG *)pDISTINCT_RANGE_ROWS - (LONGLONG)ulRangeCount))/(float)(DB_LORDINAL)ulRangeCount);
|
|
else
|
|
fPercent = 0.0;
|
|
|
|
// Fail if off by more than 10%
|
|
CCOMPARE(m_EC, fPercent < MAX_STATISTIC_ERROR,
|
|
EC_BAD_DISTINCT_RANGE_ROWS,
|
|
L"DISTINCT_RANGE_ROWS not within 10%",
|
|
FALSE);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
odtLog << L"Unable to retrieve data from Histogram for column: " <<
|
|
(m_prgColInfo[ulIndex]).pwszName << ".\n";
|
|
}
|
|
|
|
// Release the row
|
|
CHECK(pIRowset->ReleaseRows(1, phRows, NULL, NULL, NULL), S_OK);
|
|
|
|
// Point the pDataHist buffer to other half of total buffer
|
|
pDataHist = pDataRows+cbRowSize*(cRows % 2);
|
|
ReleaseInputBindingsMemory(cBinding, pBinding, pDataHist, FALSE);
|
|
}
|
|
|
|
// Free the row handles
|
|
SAFE_FREE(phRows);
|
|
|
|
// Release memory for the previous row we retrieved
|
|
if (cRows)
|
|
ReleaseInputBindingsMemory(cBinding, pBinding, pDataRows+cbRowSize*((cRows-1) % 2), FALSE);
|
|
|
|
SAFE_FREE(pDataRows);
|
|
|
|
// Make sure we got DB_S_ENDOFROWSET
|
|
CHECK(hrGetNextRows, DB_S_ENDOFROWSET);
|
|
|
|
// Make sure row count matches NO_OF_RANGES
|
|
if (pcRanges && !COMPARE(cRows, *pcRanges))
|
|
{
|
|
odtLog << L"NO_OF_RANGES did not match count of rows in Histogram rowset.\n";
|
|
odtLog << L"NO_OF_RANGES: " << *pcRanges << L" Row count: " << cRows << "\n";
|
|
odtLog << L"TABLE: " << pwszQualifiedName << L"\n";
|
|
odtLog << L"STATISTIC: " << pwszQualifiedStatName << L"\n";
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
CHECK(pIRowset == NULL, TRUE);
|
|
// We allow the histogram failure if the table no longer
|
|
// exists.
|
|
if (!CHECK(hrOpenHistogram, DB_E_NOTABLE) ||
|
|
!COMPARE(FAILED(hrOpenTable), TRUE))
|
|
odtLog << L"Histogram rowset not returned.\n";
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// If the table was deleted the provider may return
|
|
// DB_E_NOTABLE instead of DB_E_NOSTATISTIC
|
|
if (hrOpenHistogram != DB_E_NOTABLE)
|
|
{
|
|
HRESULT hrExp = DB_E_NOSTATISTIC;
|
|
|
|
CCHECK(m_EC, hrOpenHistogram, hrExp,
|
|
EC_BAD_HR_OPENHISTOGRAM,
|
|
L"Unexpected return code from OpenRowset on histogram.",
|
|
FALSE);
|
|
}
|
|
}
|
|
|
|
SAFE_RELEASE(pIRowset);
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
}
|
|
case TSS_COLUMN_NAME:
|
|
// Sanity check
|
|
|
|
// Column must have non-empty string and cannot be NULL
|
|
if (COMPARE(pColumn->sStatus, DBSTATUS_S_OK))
|
|
{
|
|
// Detail check
|
|
if (m_fDetailCheck && SUCCEEDED(hrOpenTable) && m_prgColInfo)
|
|
// Column name must match columns info for this ordinal
|
|
COMPARE(RelCompareString(m_prgColInfo[ulIndex].pwszName, (TYPE_WSTR)pColumn->bValue), 0);
|
|
}
|
|
break;
|
|
case TSS_COLUMN_GUID:
|
|
// Sanity check: none
|
|
|
|
// Detail check
|
|
if (m_fDetailCheck && SUCCEEDED(hrOpenTable))
|
|
{
|
|
// Column guid must match columns info
|
|
if (S_OK == pColumn->sStatus)
|
|
{
|
|
COMPARE(m_prgColInfo[ulIndex].columnid.uGuid.guid == *(GUID *)pColumn->bValue, TRUE);
|
|
}
|
|
else
|
|
{
|
|
// Must be NULL
|
|
// COMPARE(m_prgColInfo[ulIndex].columnid.uGuid.guid == DB_NULLGUID, TRUE);
|
|
}
|
|
}
|
|
break;
|
|
case TSS_COLUMN_PROPID:
|
|
// Sanity check: none
|
|
|
|
// Detail check
|
|
if (m_fDetailCheck && SUCCEEDED(hrOpenTable))
|
|
{
|
|
// Column propid must match columns info
|
|
if (S_OK == pColumn->sStatus)
|
|
COMPARE(m_prgColInfo[ulIndex].columnid.uName.ulPropid == *(ULONG *)pColumn->bValue, TRUE);
|
|
|
|
// If status == DBSTATUS_S_ISNULL, then value is undefined and can't be
|
|
// compared. And it appears ulPropid in columnsinfo is uninitialized.
|
|
}
|
|
break;
|
|
case TSS_ORDINAL_POSITION:
|
|
// The ordinal position must be sequential within the table
|
|
{
|
|
// Column cannot be null
|
|
if (COMPARE(pColumn->sStatus, DBSTATUS_S_OK))
|
|
{
|
|
// If we have a valid column name
|
|
if (pwszTableName && pwszStatName)
|
|
{
|
|
if (fNewStat)
|
|
{
|
|
// This is a new statistic, ordinal must be 1
|
|
m_iOrdinalExpected = 1;
|
|
SAFE_FREE(m_pwszTableName);
|
|
SAFE_FREE(m_pwszStatName);
|
|
m_pwszTableName = wcsDuplicate(pwszTableName);
|
|
m_pwszStatName = wcsDuplicate(pwszStatName);
|
|
}
|
|
else
|
|
m_iOrdinalExpected++;
|
|
|
|
// Compare Ordinal returned with expected
|
|
if (!COMPARE(m_iOrdinalExpected, *(TYPE_UI4 *)pColumn->bValue))
|
|
odtLog << pwszTableName << L": Invalid ordinal value returned.\n";
|
|
}
|
|
|
|
}
|
|
break;
|
|
}
|
|
case TSS_SAMPLE_PCT:
|
|
case TSS_LAST_UPDATE_TIME:
|
|
case TSS_NO_OF_RANGES:
|
|
// This is tested for accuracy by counting rows in histogram rowset.
|
|
break;
|
|
case TSS_COLUMN_CARDINALITY:
|
|
eCardinality = COLUMN_CARDINALITY;
|
|
// Fall through
|
|
case TSS_TUPLE_CARDINALITY:
|
|
// This should equal number distinct rows in table for this column
|
|
if (m_fDetailCheck && SUCCEEDED(hrOpenTable) &&
|
|
pColumn->sStatus == DBSTATUS_S_OK)
|
|
{
|
|
LPWSTR pwszCardinality = L"COLUMN_CARDINALITY";
|
|
|
|
if (eCardinality == TUPLE_CARDINALITY)
|
|
pwszCardinality = L"TUPLE_CARDINALITY";
|
|
|
|
if (m_prgColInfo)
|
|
{
|
|
// Can't compute cardinality for BLOB at this time
|
|
if (m_prgColInfo[ulIndex].dwFlags & DBCOLUMNFLAGS_ISLONG)
|
|
{
|
|
odtLog << L"Test cannot compute cardinality for LONG columns.\n";
|
|
odtLog << L"Comparison skipped.\n";
|
|
}
|
|
else
|
|
{
|
|
DBCOUNTITEM cRows = Cardinality(pwszQualifiedName, ulIndex, eCardinality);
|
|
WCHAR wszMessage[MAX_MSG_BUF] = L"";
|
|
|
|
swprintf(wszMessage,
|
|
L"%s is incorrect\nTable: %s Statistic: %s %s expected: %d received: %d\n",
|
|
pwszCardinality, pwszQualifiedName, pwszQualifiedStatName, pwszCardinality, cRows, *(ULONG *)pColumn->bValue);
|
|
|
|
// Note test bug here Cardinality() doesn't include BLOB columns, so if the
|
|
// statistic includes BLOBs we skip the comparison.
|
|
if (!m_fCardinalityIncludesBlob)
|
|
{
|
|
if(!CCOMPARE(m_EC, cRows == *(ULONG *)pColumn->bValue,
|
|
EC_BAD_COL_OR_TUPLE_CARD,
|
|
wszMessage, FALSE))
|
|
odtLog << L"";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case TSS_TABLE_CARDINALITY:
|
|
|
|
// Detail check
|
|
|
|
// This should equal number of rows in table
|
|
if (m_fDetailCheck && SUCCEEDED(hrOpenTable) &&
|
|
pColumn->sStatus == DBSTATUS_S_OK)
|
|
{
|
|
DBCOUNTITEM cRows = Cardinality(pwszQualifiedName, ulIndex, TABLE_CARDINALITY);
|
|
|
|
CCOMPARE(m_EC, cRows == *(ULONG *)pColumn->bValue,
|
|
EC_BAD_TABLE_CARDINALITY,
|
|
L"Table cardinality is incorrect",
|
|
FALSE);
|
|
}
|
|
break;
|
|
case TSS_AVG_COLUMN_LENGTH:
|
|
break;
|
|
}
|
|
|
|
CLEANUP:
|
|
|
|
SAFE_FREE(pwszQualifiedName);
|
|
SAFE_FREE(pwszQualifiedStatName);
|
|
|
|
return fResults;
|
|
}
|
|
|
|
// Referential Constraints schema specific functions
|
|
class CReferentialConstraintsHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
public:
|
|
|
|
CReferentialConstraintsHelper(void) {m_guidSchema = DBSCHEMA_REFERENTIAL_CONSTRAINTS;}
|
|
};
|
|
|
|
// Schemata schema specific functions
|
|
class CSchemataHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
public:
|
|
|
|
CSchemataHelper(void) {m_guidSchema = DBSCHEMA_SCHEMATA;}
|
|
};
|
|
|
|
// Statistics schema specific functions
|
|
class CStatisticsHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
public:
|
|
|
|
CStatisticsHelper(void) {m_guidSchema = DBSCHEMA_STATISTICS;}
|
|
};
|
|
|
|
// Trustee schema specific functions
|
|
class CTrusteeHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
public:
|
|
|
|
CTrusteeHelper(void) {m_guidSchema = DBSCHEMA_TRUSTEE;}
|
|
};
|
|
|
|
// Views schema specific functions
|
|
class CViewsHelper : public CHelper
|
|
{
|
|
|
|
private:
|
|
|
|
|
|
protected:
|
|
|
|
public:
|
|
|
|
CViewsHelper(void) {m_guidSchema = DBSCHEMA_VIEWS;}
|
|
};
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
// Test Case Section
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(CCommon)
|
|
//--------------------------------------------------------------------
|
|
// @class test IDBSchemaRowset::GetRowset
|
|
//
|
|
class CCommon : public CSchemaTest {
|
|
protected:
|
|
CHelper * m_pCHelper;
|
|
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(CCommon,CSchemaTest);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
CCommon(void) {m_pCHelper = NULL;}
|
|
|
|
void SetHelper(CHelper * pCHelper) {m_pCHelper = pCHelper;}
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember S_OK: No restrictions, no props
|
|
int Variation_1();
|
|
// @cmember E_INVALIDARG: rguidSchema = DBPROPSET_ROWSET
|
|
int Variation_2();
|
|
// @cmember E_INVALIDARG: rguidSchema = GUID_NULL
|
|
int Variation_3();
|
|
// @cmember DB_E_NOTSUPPORTED: provider does not support restrictions
|
|
int Variation_4();
|
|
// @cmember S_OK: pass all supported restrictions
|
|
int Variation_5();
|
|
// @cmember S_OK: less than max restrictions
|
|
int Variation_6();
|
|
// @cmember E_INVALIDARG: more than max restrictions
|
|
int Variation_7();
|
|
// @cmember E_NOINTERFACE: riid is not initialized
|
|
int Variation_8();
|
|
// @cmember S_OK: restrictions valid for 1st and 3rd restrictions
|
|
int Variation_9();
|
|
// @cmember S_OK: 2 cmd objects open on session
|
|
int Variation_10();
|
|
// @cmember DB_E_ERRORSOCCURED: update properties on read-only rowset
|
|
int Variation_11();
|
|
// @cmember DB_S_ERRORSOCCURED: DBPROP_IRowsetInfo & DBPROP_IRowsetChange
|
|
int Variation_12();
|
|
// @cmember S_OK: DBPROP_BOOKMARKS
|
|
int Variation_13();
|
|
// @cmember S_OK: empty variants = no restricions passed
|
|
int Variation_14();
|
|
// @cmember S_OK or E_NOINTERFACE: all rowset riids
|
|
int Variation_15();
|
|
// @cmember E_NOINTERFACE: riid = IID_IDBProperties
|
|
int Variation_16();
|
|
// @cmember E_INVALIDARG: ppRowset = NULL
|
|
int Variation_17();
|
|
// @cmember E_INVALIDARG: cRestrictions > 0, rgRestrictions = NULL
|
|
int Variation_18();
|
|
// @cmember E_INVALIDARG: cProperty != 0, rgProperties = NULL
|
|
int Variation_19();
|
|
// @cmember E_INVALIDARG: cPropertySets > 0, rgPropertySets = NULL
|
|
int Variation_20();
|
|
// @cmember E_INVALIDARG: invalid restriction with wrong VT type
|
|
int Variation_21();
|
|
// @cmember S_OK: request DBPROP_IColumnsRowset and, iid = IID_IColumnsRowset
|
|
int Variation_22();
|
|
// @cmember S_OK: riid = IID_IRowsetInfo, call IRowset::GetSpecification
|
|
int Variation_23();
|
|
// @cmember S_OK: riid = IID_IUnknown, get IRowset from IUnknown
|
|
int Variation_24();
|
|
// @cmember S_OK: open rowset from schema, try to open rowset on command
|
|
int Variation_25();
|
|
// @cmember S_OK: IRowsetScroll
|
|
int Variation_26();
|
|
// @cmember E_INVALIDARG: Schema not supported
|
|
int Variation_27();
|
|
// @cmember S_OK: Empty result set, pass first restriction that matches second restriction
|
|
int Variation_28();
|
|
// @cmember S_OK: Empty result set, pass non-matching value for each restriction
|
|
int Variation_29();
|
|
// @cmember First restriction
|
|
int Variation_30();
|
|
// @cmember Second restriction
|
|
int Variation_31();
|
|
// @cmember Third restriction
|
|
int Variation_32();
|
|
// @cmember Fourth restriction
|
|
int Variation_33();
|
|
// @cmember Fifth restriction
|
|
int Variation_34();
|
|
// @cmember Sixth restriction
|
|
int Variation_35();
|
|
// @cmember Seventh restriction
|
|
int Variation_36();
|
|
// @cmember S_OK: all rowset properties as required
|
|
int Variation_37();
|
|
// @cmember S_OK: all rowset properties as optional
|
|
int Variation_38();
|
|
// @cmember S_OK: all rowset properties, 2 at time, 1 optional, 1 required
|
|
int Variation_39();
|
|
// @cmember DB_E_ERRORSOCCURRED: non-rowset property sets, all properties in that set
|
|
int Variation_40();
|
|
// @cmember Security: Maximum sized string restriction
|
|
int Variation_41();
|
|
// @cmember Security: Max size plus one string restriction
|
|
int Variation_42();
|
|
// @cmember Security: Extremely large string restriction
|
|
int Variation_43();
|
|
// @cmember Security: Use %s in string restriction
|
|
int Variation_44();
|
|
// @cmember Security: Use recursive variant in restriction
|
|
int Variation_45();
|
|
// @cmember Security: Use unclosed quote in restriction
|
|
int Variation_46();
|
|
// @cmember Synonyms: Use table synonym in table restriction
|
|
int Variation_47();
|
|
// @cmember Synonyms: Use SYNONYM in table type restriction
|
|
int Variation_48();
|
|
// @cmember Synonyms: Use synonym for table name restriction and SYNONYM in table type restriction.
|
|
int Variation_49();
|
|
// @cmember Security: SQLBU #363546: Use max size string restriction of closing square brackets
|
|
int Variation_50();
|
|
// @cmember Security: SQLBU #363546: Use extremely large string restriction of closing square brackets
|
|
int Variation_51();
|
|
// @cmember SQLBU #395368: Use a sortid that does not have a SQL collation
|
|
int Variation_52();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
|
|
// {{ TCW_TESTCASE(CCommon)
|
|
#define THE_CLASS CCommon
|
|
BEG_TEST_CASE(CCommon, CSchemaTest, L"test IDBSchemaRowset::GetRowset")
|
|
TEST_VARIATION(1, L"S_OK: No restrictions, no props")
|
|
TEST_VARIATION(2, L"E_INVALIDARG: rguidSchema = DBPROPSET_ROWSET")
|
|
TEST_VARIATION(3, L"E_INVALIDARG: rguidSchema = GUID_NULL")
|
|
TEST_VARIATION(4, L"DB_E_NOTSUPPORTED: provider does not support restrictions")
|
|
TEST_VARIATION(5, L"S_OK: pass all supported restrictions")
|
|
TEST_VARIATION(6, L"S_OK: less than max restrictions")
|
|
TEST_VARIATION(7, L"E_INVALIDARG: more than max restrictions")
|
|
TEST_VARIATION(8, L"E_NOINTERFACE: riid is not initialized")
|
|
TEST_VARIATION(9, L"S_OK: restrictions valid for 1st and 3rd restrictions")
|
|
TEST_VARIATION(10, L"S_OK: 2 cmd objects open on session")
|
|
TEST_VARIATION(11, L"DB_E_ERRORSOCCURED: update properties on read-only rowset")
|
|
TEST_VARIATION(12, L"DB_S_ERRORSOCCURED: DBPROP_IRowsetInfo & DBPROP_IRowsetChange")
|
|
TEST_VARIATION(13, L"S_OK: DBPROP_BOOKMARKS")
|
|
TEST_VARIATION(14, L"S_OK: empty variants = no restricions passed")
|
|
TEST_VARIATION(15, L"S_OK or E_NOINTERFACE: all rowset riids")
|
|
TEST_VARIATION(16, L"E_NOINTERFACE: riid = IID_IDBProperties")
|
|
TEST_VARIATION(17, L"E_INVALIDARG: ppRowset = NULL")
|
|
TEST_VARIATION(18, L"E_INVALIDARG: cRestrictions > 0, rgRestrictions = NULL")
|
|
TEST_VARIATION(19, L"E_INVALIDARG: cProperty != 0, rgProperties = NULL")
|
|
TEST_VARIATION(20, L"E_INVALIDARG: cPropertySets > 0, rgPropertySets = NULL")
|
|
TEST_VARIATION(21, L"E_INVALIDARG: invalid restriction with wrong VT type")
|
|
TEST_VARIATION(22, L"S_OK: request DBPROP_IColumnsRowset and, iid = IID_IColumnsRowset")
|
|
TEST_VARIATION(23, L"S_OK: riid = IID_IRowsetInfo, call IRowset::GetSpecification")
|
|
TEST_VARIATION(24, L"S_OK: riid = IID_IUnknown, get IRowset from IUnknown")
|
|
TEST_VARIATION(25, L"S_OK: open rowset from schema, try to open rowset on command")
|
|
TEST_VARIATION(26, L"S_OK: IRowsetScroll")
|
|
TEST_VARIATION(27, L"E_INVALIDARG: Schema not supported")
|
|
TEST_VARIATION(28, L"S_OK: Empty result set, pass first restriction that matches second restriction")
|
|
TEST_VARIATION(29, L"S_OK: Empty result set, pass non-matching value for each restriction")
|
|
TEST_VARIATION(30, L"First restriction")
|
|
TEST_VARIATION(31, L"Second restriction")
|
|
TEST_VARIATION(32, L"Third restriction")
|
|
TEST_VARIATION(33, L"Fourth restriction")
|
|
TEST_VARIATION(34, L"Fifth restriction")
|
|
TEST_VARIATION(35, L"Sixth restriction")
|
|
TEST_VARIATION(36, L"Seventh restriction")
|
|
TEST_VARIATION(37, L"S_OK: all rowset properties as required")
|
|
TEST_VARIATION(38, L"S_OK: all rowset properties as optional")
|
|
TEST_VARIATION(39, L"S_OK: all rowset properties, 2 at time, 1 optional, 1 required")
|
|
TEST_VARIATION(40, L"DB_E_ERRORSOCCURRED: non-rowset property sets, all properties in that set")
|
|
TEST_VARIATION(41, L"Security: Maximum sized string restriction")
|
|
TEST_VARIATION(42, L"Security: Max size plus one string restriction")
|
|
TEST_VARIATION(43, L"Security: Extremely large string restriction")
|
|
TEST_VARIATION(44, L"Security: Use %s in string restriction")
|
|
TEST_VARIATION(45, L"Security: Use recursive variant in restriction")
|
|
TEST_VARIATION(46, L"Security: Use unclosed quote in restriction")
|
|
TEST_VARIATION(47, L"Synonyms: Use table synonym in table restriction")
|
|
TEST_VARIATION(48, L"Synonyms: Use SYNONYM in table type restriction")
|
|
TEST_VARIATION(49, L"Synonyms: Use synonym for table name restriction and SYNONYM in table type restriction.")
|
|
TEST_VARIATION(50, L"Security: SQLBU #363546: Use max size string restriction of closing square brackets")
|
|
TEST_VARIATION(51, L"Security: SQLBU #363546: Use extremely large string restriction of closing square brackets")
|
|
TEST_VARIATION(52, L"SQLBU #395368: Use a sortid that does not have a SQL collation")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(CGetSchema)
|
|
//--------------------------------------------------------------------
|
|
// @class test IDBSchemaRowset::GetSchemas
|
|
//
|
|
class CGetSchema : public CSchemaTest {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(CGetSchema,CSchemaTest);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember E_INVALIDARG: pcSchemas = NULL
|
|
int Variation_1();
|
|
// @cmember S_OK: *prgSchemas = NULL, pcSchemas = 0
|
|
int Variation_2();
|
|
// @cmember S_OK: prgRestrictionSupported = NULL
|
|
int Variation_3();
|
|
// @cmember E_INVALIDARG: prgSchemas = NULL
|
|
int Variation_4();
|
|
// @cmember S_OK: open schema rowset, try to open rowset from command object
|
|
int Variation_5();
|
|
// @cmember S_OK: don't initialize variables before sending
|
|
int Variation_6();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(CGetSchema)
|
|
#define THE_CLASS CGetSchema
|
|
BEG_TEST_CASE(CGetSchema, CSchemaTest, L"test IDBSchemaRowset::GetSchemas")
|
|
TEST_VARIATION(1, L"E_INVALIDARG: pcSchemas = NULL")
|
|
TEST_VARIATION(2, L"S_OK: *prgSchemas = NULL, pcSchemas = 0")
|
|
TEST_VARIATION(3, L"S_OK: prgRestrictionSupported = NULL")
|
|
TEST_VARIATION(4, L"E_INVALIDARG: prgSchemas = NULL")
|
|
TEST_VARIATION(5, L"S_OK: open schema rowset, try to open rowset from command object")
|
|
TEST_VARIATION(6, L"S_OK: don't initialize variables before sending")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(CZombie)
|
|
//--------------------------------------------------------------------
|
|
// @class testing IDBSchemaRowset in zombie situation
|
|
//
|
|
class CZombie : public CTransaction {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(CZombie,CTransaction);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
int TestTxnGetRowset(ETXN eTxn,BOOL fRetaining, GUID schema);
|
|
int TestTxnGetSchemas(ETXN eTxn,BOOL fRetaining);
|
|
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember GetRowset: Commit with fRetaining set to TRUE
|
|
int Variation_1();
|
|
// @cmember GetRowset: Commit with fRetaining set to FALSE
|
|
int Variation_2();
|
|
// @cmember GetRowset: Abort with fRetaining set to TRUE
|
|
int Variation_3();
|
|
// @cmember GetRowset: Abort with fRetaining set to FALSE
|
|
int Variation_4();
|
|
// @cmember GetSchemas: Commit with fRetaining set to TRUE
|
|
int Variation_5();
|
|
// @cmember GetSchemas: Commit with fRetaining set to FALSE
|
|
int Variation_6();
|
|
// @cmember GetSchemas: Abort with fRetaining set to TRUE
|
|
int Variation_7();
|
|
// @cmember GetSchemas: Abort with fRetaining set to FALSE
|
|
int Variation_8();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(CZombie)
|
|
#define THE_CLASS CZombie
|
|
BEG_TEST_CASE(CZombie, CTransaction, L"testing IDBSchemaRowset in zombie situation")
|
|
TEST_VARIATION(1, L"GetRowset: Commit with fRetaining set to TRUE")
|
|
TEST_VARIATION(2, L"GetRowset: Commit with fRetaining set to FALSE")
|
|
TEST_VARIATION(3, L"GetRowset: Abort with fRetaining set to TRUE")
|
|
TEST_VARIATION(4, L"GetRowset: Abort with fRetaining set to FALSE")
|
|
TEST_VARIATION(5, L"GetSchemas: Commit with fRetaining set to TRUE")
|
|
TEST_VARIATION(6, L"GetSchemas: Commit with fRetaining set to FALSE")
|
|
TEST_VARIATION(7, L"GetSchemas: Abort with fRetaining set to TRUE")
|
|
TEST_VARIATION(8, L"GetSchemas: Abort with fRetaining set to FALSE")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
|
|
// {{ TCW_TEST_CASE_MAP(ExtendedErrors)
|
|
//--------------------------------------------------------------------
|
|
// @class testing extended errors on IDBSchemaRowset
|
|
//
|
|
class ExtendedErrors : public CSchemaTest {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
CHelper * GetSchemaHelper(GUID guidSchema);
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(ExtendedErrors,CSchemaTest);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Valid GetSchemas Call with previous error object existing
|
|
int Variation_1();
|
|
// @cmember Valid GetRowset call with previous error object existing
|
|
int Variation_2();
|
|
// @cmember Valid GetSchemas call with previous error object existing
|
|
int Variation_3();
|
|
// @cmember Invalid GetRowset call with previous error object existing
|
|
int Variation_4();
|
|
// @cmember Invalid GetSchemas call with previous error object existing
|
|
int Variation_5();
|
|
// @cmember Invalid GetRowset call with previous error object existing
|
|
int Variation_6();
|
|
// @cmember Open schema rowset DBSCHEMA_ASSERTIONS -- E_INVALIDARG
|
|
int Variation_7();
|
|
// }} TCW_TESTVARS_END
|
|
};
|
|
// {{ TCW_TESTCASE(ExtendedErrors)
|
|
#define THE_CLASS ExtendedErrors
|
|
BEG_TEST_CASE(ExtendedErrors, CSchemaTest, L"testing extended errors on IDBSchemaRowset")
|
|
TEST_VARIATION(1, L"Valid GetSchemas Call with previous error object existing")
|
|
TEST_VARIATION(2, L"Valid GetRowset call with previous error object existing")
|
|
TEST_VARIATION(3, L"Valid GetSchemas call with previous error object existing")
|
|
TEST_VARIATION(4, L"Invalid GetRowset call with previous error object existing")
|
|
TEST_VARIATION(5, L"Invalid GetSchemas call with previous error object existing")
|
|
TEST_VARIATION(6, L"Invalid GetRowset call with previous error object existing")
|
|
TEST_VARIATION(7, L"Open schema rowset DBSCHEMA_ASSERTIONS -- E_INVALIDARG")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(CBugRegressions)
|
|
//*-----------------------------------------------------------------------
|
|
// @class Test case for bug regressions
|
|
//
|
|
class CBugRegressions : public CSchemaTest {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(CBugRegressions,CSchemaTest);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember GetRowset on schema TABLES after executing RETURN statement
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(CBugRegressions)
|
|
#define THE_CLASS CBugRegressions
|
|
BEG_TEST_CASE(CBugRegressions, CSchemaTest, L"Test case for bug regressions")
|
|
TEST_VARIATION(1, L"GetRowset on schema TABLES after executing RETURN statement")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// {{ TCW_TEST_CASE_MAP(CTableStatistics)
|
|
//*-----------------------------------------------------------------------
|
|
// @class Test DBSCHEMA_TABLE_STATISTICS
|
|
//
|
|
class CTableStatistics : public CSchemaTest {
|
|
private:
|
|
// @cmember Static array of variations
|
|
DECLARE_TEST_CASE_DATA();
|
|
|
|
public:
|
|
// {{ TCW_DECLARE_FUNCS
|
|
// @cmember Execution Routine
|
|
DECLARE_TEST_CASE_FUNCS(CTableStatistics,CSchemaTest);
|
|
// }} TCW_DECLARE_FUNCS_END
|
|
|
|
// @cmember Initialization Routine
|
|
virtual BOOL Init();
|
|
// @cmember Termination Routine
|
|
virtual BOOL Terminate();
|
|
|
|
// {{ TCW_TESTVARS()
|
|
// @cmember Validate DBPROP_OPENROWSETSUPPORT, DBPROPVAL_ORS_HISTOGRAM
|
|
int Variation_1();
|
|
// }} TCW_TESTVARS_END
|
|
} ;
|
|
// {{ TCW_TESTCASE(CTableStatistics)
|
|
#define THE_CLASS CTableStatistics
|
|
BEG_TEST_CASE(CTableStatistics, CSchemaTest, L"Test DBSCHEMA_TABLE_STATISTICS")
|
|
TEST_VARIATION(1, L"Validate DBPROP_OPENROWSETSUPPORT, DBPROPVAL_ORS_HISTOGRAM")
|
|
END_TEST_CASE()
|
|
#undef THE_CLASS
|
|
// }} TCW_TESTCASE_END
|
|
// }} TCW_TEST_CASE_MAP_END
|
|
|
|
// }} END_DECLARE_TEST_CASES()
|
|
|
|
|
|
#define COPY_TEST_CASE(theClass, baseClass) \
|
|
class theClass : public baseClass \
|
|
{ \
|
|
public: \
|
|
static const WCHAR m_wszTestCaseName[]; \
|
|
DECLARE_TEST_CASE_FUNCS(theClass, baseClass); \
|
|
}; \
|
|
const WCHAR theClass::m_wszTestCaseName[] = { L#theClass }; \
|
|
|
|
#define TEST_CASE_WITH_HELPER(iCase, theClass, helperClass) \
|
|
case iCase: \
|
|
pCTestCase = new theClass(NULL); \
|
|
((theClass*)pCTestCase)->SetHelper(new helperClass()); \
|
|
pCTestCase->SetOwningMod(iCase-1, pCThisTestModule); \
|
|
return pCTestCase;
|
|
|
|
|
|
COPY_TEST_CASE(CAssertionsCommon, CCommon)
|
|
COPY_TEST_CASE(CCatalogsCommon, CCommon)
|
|
COPY_TEST_CASE(CCharacterSetsCommon, CCommon)
|
|
COPY_TEST_CASE(CCheckConstraintsCommon, CCommon)
|
|
COPY_TEST_CASE(CCheckConstraintsByTableCommon, CCommon)
|
|
COPY_TEST_CASE(CCollationsCommon, CCommon)
|
|
COPY_TEST_CASE(CColumnDomainUsageCommon, CCommon)
|
|
COPY_TEST_CASE(CColumnPrivilegesCommon, CCommon)
|
|
COPY_TEST_CASE(CColumnsCommon, CCommon)
|
|
COPY_TEST_CASE(CConstraintColumnUsageCommon, CCommon)
|
|
COPY_TEST_CASE(CForeignKeysCommon, CCommon)
|
|
COPY_TEST_CASE(CIndexesCommon, CCommon)
|
|
COPY_TEST_CASE(CKeyColumnUsageCommon, CCommon)
|
|
COPY_TEST_CASE(CPrimaryKeysCommon, CCommon)
|
|
COPY_TEST_CASE(CProceduresCommon, CCommon)
|
|
COPY_TEST_CASE(CProcedureColumnsCommon, CCommon)
|
|
COPY_TEST_CASE(CProcedureParametersCommon, CCommon)
|
|
COPY_TEST_CASE(CProviderTypesCommon, CCommon)
|
|
COPY_TEST_CASE(CReferentialConstraintsCommon, CCommon)
|
|
COPY_TEST_CASE(CSchemataCommon, CCommon)
|
|
COPY_TEST_CASE(CStatisticsCommon, CCommon)
|
|
COPY_TEST_CASE(CTableConstraintsCommon, CCommon)
|
|
COPY_TEST_CASE(CTablePrivilegesCommon, CCommon)
|
|
COPY_TEST_CASE(CTablesInfoCommon, CCommon)
|
|
COPY_TEST_CASE(CTablesCommon, CCommon)
|
|
COPY_TEST_CASE(CTableStatisticsCommon, CCommon)
|
|
COPY_TEST_CASE(CTrusteeCommon, CCommon)
|
|
COPY_TEST_CASE(CViewsCommon, CCommon)
|
|
|
|
|
|
#if 0
|
|
// {{ TCW_TESTMODULE(ThisModule)
|
|
TEST_MODULE(6, ThisModule, gwszModuleDescrip)
|
|
TEST_CASE(1, CCommon)
|
|
TEST_CASE(2, CGetSchema)
|
|
TEST_CASE(3, CZombie)
|
|
TEST_CASE(4, ExtendedErrors)
|
|
TEST_CASE(5, CBugRegressions)
|
|
TEST_CASE(6, CTableStatistics)
|
|
END_TEST_MODULE()
|
|
// }} TCW_TESTMODULE_END
|
|
#else
|
|
TEST_MODULE(33, ThisModule, gwszModuleDescrip)
|
|
TEST_CASE(1, CGetSchema)
|
|
TEST_CASE_WITH_HELPER(2, CAssertionsCommon, CAssertionsHelper)
|
|
TEST_CASE_WITH_HELPER(3, CCatalogsCommon, CCatalogsHelper)
|
|
TEST_CASE_WITH_HELPER(4, CCharacterSetsCommon, CCharacterSetsHelper)
|
|
TEST_CASE_WITH_HELPER(5, CCheckConstraintsCommon, CCheckConstraintsHelper)
|
|
TEST_CASE_WITH_HELPER(6, CCheckConstraintsByTableCommon, CCheckConstraintsByTableHelper)
|
|
TEST_CASE_WITH_HELPER(7, CCollationsCommon, CCollationsHelper)
|
|
TEST_CASE_WITH_HELPER(8, CColumnDomainUsageCommon, CColumnDomainUsageHelper)
|
|
TEST_CASE_WITH_HELPER(9, CColumnPrivilegesCommon, CColumnPrivilegesHelper)
|
|
TEST_CASE_WITH_HELPER(10, CColumnsCommon, CColumnsHelper)
|
|
TEST_CASE_WITH_HELPER(11, CConstraintColumnUsageCommon, CConstraintColumnUsageHelper)
|
|
TEST_CASE_WITH_HELPER(12, CForeignKeysCommon, CForeignKeysHelper)
|
|
TEST_CASE_WITH_HELPER(13, CIndexesCommon, CIndexesHelper)
|
|
TEST_CASE_WITH_HELPER(14, CKeyColumnUsageCommon, CKeyColumnUsageHelper)
|
|
TEST_CASE_WITH_HELPER(15, CPrimaryKeysCommon, CPrimaryKeysHelper)
|
|
TEST_CASE_WITH_HELPER(16, CProceduresCommon, CProceduresHelper)
|
|
TEST_CASE_WITH_HELPER(17, CProcedureColumnsCommon, CProcedureColumnsHelper)
|
|
TEST_CASE_WITH_HELPER(18, CProcedureParametersCommon, CProcedureParametersHelper)
|
|
TEST_CASE_WITH_HELPER(19, CProviderTypesCommon, CProviderTypesHelper)
|
|
TEST_CASE_WITH_HELPER(20, CReferentialConstraintsCommon, CReferentialConstraintsHelper)
|
|
TEST_CASE_WITH_HELPER(21, CSchemataCommon, CSchemataHelper)
|
|
TEST_CASE_WITH_HELPER(22, CStatisticsCommon, CStatisticsHelper)
|
|
TEST_CASE_WITH_HELPER(23, CTableConstraintsCommon, CTableConstraintsHelper)
|
|
TEST_CASE_WITH_HELPER(24, CTablePrivilegesCommon, CTablePrivilegesHelper)
|
|
TEST_CASE_WITH_HELPER(25, CTablesInfoCommon, CTablesInfoHelper)
|
|
TEST_CASE_WITH_HELPER(26, CTablesCommon, CTablesHelper)
|
|
TEST_CASE_WITH_HELPER(27, CTableStatisticsCommon, CTableStatisticsHelper)
|
|
TEST_CASE_WITH_HELPER(28, CTrusteeCommon, CTrusteeHelper)
|
|
TEST_CASE_WITH_HELPER(29, CViewsCommon, CViewsHelper)
|
|
TEST_CASE(30, CZombie)
|
|
TEST_CASE(31, ExtendedErrors)
|
|
TEST_CASE(32, CBugRegressions)
|
|
TEST_CASE(33, CTableStatistics)
|
|
END_TEST_MODULE()
|
|
#endif
|
|
|
|
// {{ TCW_TC_PROTOTYPE(CCommon)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: CCommon - test IDBSchemaRowset::GetRowset
|
|
//| Created: 09/23/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL CCommon::Init()
|
|
{
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
if(CSchemaTest::Init())
|
|
// }}
|
|
{
|
|
if (COMPARE(m_pCHelper != NULL, TRUE))
|
|
return m_pCHelper->Init(this);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: No restrictions, no props
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_1()
|
|
{
|
|
HRESULT hrExp = S_OK;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Test method
|
|
CHECK(m_pCHelper->GetRowsetHelper(NULL, RV_NULL), hrExp);
|
|
|
|
m_pCHelper->SetRowCount(MIN_VALUE, 1);
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc E_INVALIDARG: rguidSchema = DBPROPSET_ROWSET
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_2()
|
|
{
|
|
// Test method
|
|
CHECK(m_pCHelper->GetRowsetHelper(NULL, RV_NULL, NULL, IID_IRowset, 0, NULL,
|
|
NULL, DBPROPSET_ROWSET), E_INVALIDARG);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc E_INVALIDARG: rguidSchema = GUID_NULL
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_3()
|
|
{
|
|
IRowset * pIRowset = NULL;
|
|
|
|
// Have to turn off setting of default arguments
|
|
m_pCHelper->UseArgumentDefaults(FALSE);
|
|
|
|
// Test method
|
|
CHECK(m_pCHelper->GetRowsetHelper(NULL, 0, NULL, IID_IRowset, 0, NULL,
|
|
(IUnknown **)&pIRowset, GUID_NULL), E_INVALIDARG);
|
|
|
|
// Set default args back on
|
|
m_pCHelper->UseArgumentDefaults(TRUE);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc DB_E_NOTSUPPORTED: provider does not support restrictions
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_4()
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
if (!m_pCHelper->HasUnsupportedRestriction())
|
|
{
|
|
odtLog << L"No unsupported restrictions.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Set to use all cached restrictions, supported or not
|
|
m_pCHelper->SetRestrictionArray(RT_CACHED);
|
|
|
|
// Test method
|
|
hr = m_pCHelper->GetRowsetHelper(NULL, RV_ALL);
|
|
|
|
// Provider may return E_INVALIDARG here, but we prefer DB_E_NOTSUPPORTED
|
|
if (hr != E_INVALIDARG)
|
|
CHECK(hr, DB_E_NOTSUPPORTED);
|
|
|
|
// Set back to use supported restrictions
|
|
m_pCHelper->SetRestrictionArray(RT_SUPPORTED);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: pass all supported restrictions
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_5()
|
|
{
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Test method
|
|
CHECK(m_pCHelper->GetRowsetHelper(), S_OK);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(6)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: less than max restrictions
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_6()
|
|
{
|
|
ULONG cRestrictions = m_pCHelper->RestrictionCount();
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Test method
|
|
CHECK(m_pCHelper->GetRowsetHelper(NULL, cRestrictions-1), S_OK);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(7)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc E_INVALIDARG: more than max restrictions
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_7()
|
|
{
|
|
ULONG cRestrictions = m_pCHelper->RestrictionCount();
|
|
|
|
// Test method. Note spec change that providers may return E_INVALIDARG or
|
|
// DB_E_NOTSUPPORTED for this case.
|
|
TEST2C_(m_pCHelper->GetRowsetHelper(NULL, cRestrictions+1), DB_E_NOTSUPPORTED, E_INVALIDARG);
|
|
|
|
CLEANUP:
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(8)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc E_NOINTERFACE: riid is not initialized
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_8()
|
|
{
|
|
GUID iid;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
memset(&iid, 0x0c, sizeof(GUID));
|
|
|
|
// Test method
|
|
CHECK(m_pCHelper->GetRowsetHelper(NULL, 0, NULL, iid), E_NOINTERFACE);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(9)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: restrictions valid for 1st and 3rd restrictions
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_9()
|
|
{
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
if (!m_pCHelper->IsSupportedRestriction(RV_ONE) &&
|
|
!m_pCHelper->IsSupportedRestriction(RV_THREE))
|
|
{
|
|
odtLog << L"1st and 3rd restrictions not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
m_pCHelper->SetRestrictionArray(RT_CUSTOM);
|
|
|
|
m_pCHelper->ClearRestrictions();
|
|
|
|
if (m_pCHelper->IsSupportedRestriction(RV_ONE))
|
|
m_pCHelper->SetValidRestriction(RV_ONE);
|
|
else
|
|
odtLog << L"1st retriction not supported, setting only 3rd.\n";
|
|
|
|
if (m_pCHelper->IsSupportedRestriction(RV_THREE))
|
|
m_pCHelper->SetValidRestriction(RV_THREE);
|
|
else
|
|
odtLog << L"3rd retriction not supported, setting only 1st.\n";
|
|
|
|
// Test method
|
|
CHECK(m_pCHelper->GetRowsetHelper(), S_OK);
|
|
|
|
m_pCHelper->SetRestrictionArray(RT_SUPPORTED);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(10)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: 2 cmd objects open on session
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_10()
|
|
{
|
|
ICommand * pICommand = NULL;
|
|
BOOL fResult = FALSE;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// If the provider doesn't support commands then
|
|
// m_pIDBCreateCommand is NULL
|
|
if (!m_pIDBCreateCommand)
|
|
{
|
|
odtLog << L"Commands not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// create a second object open on the session object
|
|
TESTC_(m_pIDBCreateCommand->CreateCommand(
|
|
NULL,
|
|
IID_ICommand,
|
|
(IUnknown **)&pICommand), S_OK);
|
|
|
|
// test method
|
|
CHECK(m_pCHelper->GetRowsetHelper(), S_OK);
|
|
|
|
fResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
SAFE_RELEASE(pICommand);
|
|
|
|
return fResult;
|
|
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(11)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc DB_E_ERRORSOCCURED: update properties on read-only rowset
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_11()
|
|
{
|
|
ULONG ulIndex=0;
|
|
ULONG ulIndexProperties=0;
|
|
ULONG ulprop=0;
|
|
DBPROPSET * pPropSet = NULL;
|
|
ULONG cPropSet = 0;
|
|
DBTYPE wPropType;
|
|
LPVOID lpvPropVal;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// for each invalid property
|
|
for(ulIndexProperties=0;ulIndexProperties<cUPDATE_PROPERTIES;ulIndexProperties++)
|
|
{
|
|
if( (IsRowsetPropertySupported(rgUpdateProperties[ulIndexProperties])) ||
|
|
(m_pTable->get_ICommandPTR() &&
|
|
(GetProperty(rgUpdateProperties[ulIndexProperties],DBPROPSET_ROWSET,m_pTable->get_ICommandPTR()))))
|
|
{
|
|
odtLog << L"---" << rgwszUpdateProperties[ulIndexProperties] << L"-\n" ;
|
|
|
|
// Most props are BOOL, but DBPROP_UPDATABILITY is I4
|
|
if (rgUpdateProperties[ulIndexProperties] == DBPROP_UPDATABILITY)
|
|
{
|
|
wPropType = DBTYPE_I4;
|
|
lpvPropVal = (LPVOID)(DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE);
|
|
}
|
|
else
|
|
{
|
|
wPropType = DBTYPE_BOOL;
|
|
lpvPropVal = (LPVOID)VARIANT_TRUE;
|
|
}
|
|
|
|
|
|
TESTC_(SetProperty(rgUpdateProperties[ulIndexProperties], DBPROPSET_ROWSET,
|
|
&cPropSet, &pPropSet, wPropType, &lpvPropVal), S_OK);
|
|
|
|
// test method
|
|
CHECK(m_pCHelper->GetRowsetHelper(NULL, RV_ALL, NULL, IID_IRowset, cPropSet, pPropSet), DB_E_ERRORSOCCURRED);
|
|
|
|
// There is some ambiguity on what DBPROPSTATUS to allow for schema rowsets since they are
|
|
// r/o and therefore don't support some rowset props. We prefer DBPROPSTATUS_CONFLICTING
|
|
// since that conflicts with DBPROP_UPDATABILITY, but we will allow others here such
|
|
// as DBPROPSTATUS_NOTSETTABLE.
|
|
if (pPropSet[0].rgProperties[0].dwStatus != DBPROPSTATUS_NOTSETTABLE)
|
|
{
|
|
VerifyPropStatus(cPropSet, pPropSet, rgUpdateProperties[ulIndexProperties],
|
|
DBPROPSET_ROWSET, DBPROPSTATUS_CONFLICTING);
|
|
}
|
|
|
|
// Free the property info for next iteration
|
|
FreeProperties(&cPropSet, &pPropSet);
|
|
|
|
}
|
|
else
|
|
odtLog << L"Property not supported or not writable, "
|
|
<< rgwszUpdateProperties[ulIndexProperties]
|
|
<< ENDL;
|
|
}
|
|
|
|
CLEANUP:
|
|
|
|
FreeProperties(&cPropSet, &pPropSet);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(12)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc DB_S_ERRORSOCCURED: DBPROP_IRowsetInfo & DBPROP_IRowsetChange
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_12()
|
|
{
|
|
BOOL fResult = TRUE;
|
|
DBPROPSET * pPropSet = NULL;
|
|
ULONG cPropSet = 0;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
if(!IsRowsetPropertySupported(DBPROP_IRowsetInfo))
|
|
{
|
|
odtLog << L"Mandatory interface IRowsetInfo is not supported or not writable\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
if(!IsRowsetPropertySupported(DBPROP_IRowsetChange))
|
|
{
|
|
odtLog << L"IRowsetChange is not supported or not writable\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
TESTC_(SetProperty(DBPROP_IRowsetInfo, DBPROPSET_ROWSET,
|
|
&cPropSet, &pPropSet, DBTYPE_BOOL, VARIANT_TRUE), S_OK);
|
|
|
|
TESTC_(SetProperty(DBPROP_IRowsetChange, DBPROPSET_ROWSET,
|
|
&cPropSet, &pPropSet, DBTYPE_BOOL, VARIANT_TRUE), S_OK);
|
|
|
|
// test method
|
|
TESTC_(m_pCHelper->GetRowsetHelper(NULL, RV_ALL, NULL, IID_IRowset, cPropSet, pPropSet), DB_S_ERRORSOCCURRED);
|
|
|
|
if (!VerifyPropStatus(cPropSet, pPropSet, DBPROP_IRowsetInfo, DBPROPSET_ROWSET, DBPROPSTATUS_CONFLICTING))
|
|
goto CLEANUP;
|
|
if (!VerifyPropStatus(cPropSet, pPropSet, DBPROP_IRowsetChange, DBPROPSET_ROWSET, DBPROPSTATUS_CONFLICTING))
|
|
goto CLEANUP;
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
FreeProperties(&cPropSet, &pPropSet);
|
|
|
|
return fResult;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(13)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: DBPROP_BOOKMARKS
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_13()
|
|
{
|
|
BOOL fResult = TRUE;
|
|
DBPROPSET * pPropSet = NULL;
|
|
ULONG cPropSet = 0;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
if(!IsRowsetPropertySupported(DBPROP_BOOKMARKS))
|
|
{
|
|
odtLog << L"Bookmark not supported\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
TESTC_(SetProperty(DBPROP_BOOKMARKS, DBPROPSET_ROWSET,
|
|
&cPropSet, &pPropSet, DBTYPE_BOOL, VARIANT_TRUE), S_OK);
|
|
|
|
// test method
|
|
hr = m_pCHelper->GetRowsetHelper(NULL, RV_ALL, NULL, IID_IRowset, cPropSet, pPropSet);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
if (!VerifyPropStatus(cPropSet, pPropSet, DBPROP_BOOKMARKS, DBPROPSET_ROWSET, DBPROPSTATUS_OK))
|
|
goto CLEANUP;
|
|
}
|
|
else
|
|
{
|
|
TESTC_(hr, DB_E_ERRORSOCCURRED);
|
|
if (!VerifyPropStatus(cPropSet, pPropSet, DBPROP_BOOKMARKS, DBPROPSET_ROWSET, DBPROPSTATUS_CONFLICTING))
|
|
goto CLEANUP;
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
FreeProperties(&cPropSet, &pPropSet);
|
|
|
|
return fResult;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(14)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: empty variants = no restricions passed
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_14()
|
|
{
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Use our custom restriction array
|
|
m_pCHelper->SetRestrictionArray(RT_CUSTOM);
|
|
|
|
// Set them all to VT_EMPTY
|
|
m_pCHelper->ClearRestrictions();
|
|
|
|
// Test method
|
|
CHECK(m_pCHelper->GetRowsetHelper(), S_OK);
|
|
|
|
// Set back to supported restrictions
|
|
m_pCHelper->SetRestrictionArray(RT_SUPPORTED);
|
|
m_pCHelper->SetRowCount(MIN_VALUE, 1);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(15)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK or E_NOINTERFACE: all rowset riids
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_15()
|
|
{
|
|
ULONG i, cRowsetIIDs = 0;
|
|
INTERFACEMAP* rgRowsetIIDs = NULL;
|
|
IUnknown * pIUnknown = NULL;
|
|
HRESULT hr = E_FAIL;
|
|
BOOL fResult = FALSE;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
//Obtain the Rowset IIDs
|
|
TESTC(GetInterfaceArray(ROWSET_INTERFACE, &cRowsetIIDs, &rgRowsetIIDs));
|
|
|
|
//Loop through all rowset IIDs...
|
|
for(i=0; i<cRowsetIIDs; i++)
|
|
{
|
|
odtLog << rgRowsetIIDs[i].pwszName << L"\n";
|
|
|
|
//Asking for IID_I* is requesting a rowset that supports this interface
|
|
//This is implicilty like requesting DBPROP_I* ahead of time...
|
|
hr = m_pCHelper->GetRowsetHelper(NULL, RV_ALL, NULL, *rgRowsetIIDs[i].pIID,
|
|
0, NULL, &pIUnknown, GUID_NULL, FALSE);
|
|
|
|
// Allow S_OK or E_NOINTERFACE
|
|
if (S_OK != hr)
|
|
{
|
|
CHECK(hr, E_NOINTERFACE);
|
|
}
|
|
|
|
//Success, verify this interface...
|
|
if(hr == S_OK)
|
|
{
|
|
if(!ValidInterface(*rgRowsetIIDs[i].pIID, pIUnknown))
|
|
TERROR(L"Interface Incorrect for " << GetInterfaceName(*rgRowsetIIDs[i].pIID) << "\n");
|
|
|
|
TESTC(DefaultObjectTesting(pIUnknown, ROWSET_INTERFACE));
|
|
}
|
|
else
|
|
{
|
|
//Make sure this is allowed to not be required
|
|
TCOMPARE_(!rgRowsetIIDs[i].fMandatory);
|
|
}
|
|
|
|
SAFE_RELEASE(pIUnknown);
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
return fResult;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(16)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc E_NOINTERFACE: riid = IID_IDBProperties
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_16()
|
|
{
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Test method
|
|
CHECK(m_pCHelper->GetRowsetHelper(NULL, 0, NULL, IID_IDBProperties), E_NOINTERFACE);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(17)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc E_INVALIDARG: ppRowset = NULL
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_17()
|
|
{
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Have to turn off setting of default arguments
|
|
m_pCHelper->UseArgumentDefaults(FALSE);
|
|
|
|
// Test method
|
|
CHECK(m_pCHelper->GetRowsetHelper(NULL, 0, NULL, IID_IRowset, 0, NULL,
|
|
NULL, m_pCHelper->GetSchema()), E_INVALIDARG);
|
|
|
|
// Set default args back on
|
|
m_pCHelper->UseArgumentDefaults(TRUE);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(18)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc E_INVALIDARG: cRestrictions > 0, rgRestrictions = NULL
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_18()
|
|
{
|
|
IRowset * pIRowset = NULL;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Have to turn off setting of default arguments
|
|
m_pCHelper->UseArgumentDefaults(FALSE);
|
|
|
|
// Test method
|
|
CHECK(m_pCHelper->GetRowsetHelper(NULL, 1, NULL, IID_IRowset, 0, NULL,
|
|
(IUnknown **)&pIRowset, m_pCHelper->GetSchema()), E_INVALIDARG);
|
|
|
|
// Set default args back on
|
|
m_pCHelper->UseArgumentDefaults(TRUE);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(19)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc E_INVALIDARG: cProperty != 0, rgProperties = NULL
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_19()
|
|
{
|
|
DBPROPSET rgPropSet[1];
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
rgPropSet[0].cProperties = 1;
|
|
rgPropSet[0].guidPropertySet = DBPROPSET_ROWSET;
|
|
rgPropSet[0].rgProperties = NULL;
|
|
|
|
// Test method
|
|
CHECK(m_pCHelper->GetRowsetHelper(NULL, RV_ALL, NULL, IID_IRowset, 1,
|
|
rgPropSet), E_INVALIDARG);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(20)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc E_INVALIDARG: cPropertySets > 0, rgPropertySets = NULL
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_20()
|
|
{
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Test method
|
|
CHECK(m_pCHelper->GetRowsetHelper(NULL, RV_ALL, NULL, IID_IRowset, 1,
|
|
NULL), E_INVALIDARG);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(21)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc E_INVALIDARG: invalid restriction with wrong VT type
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_21()
|
|
{
|
|
ULONG ulIndex=0;
|
|
HRESULT hrTemp = E_FAIL;
|
|
IDispatch * pIDispatch = new CDispatch;
|
|
BOOL fSetInvalidRestriction = FALSE;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
m_pCHelper->SetRestrictionArray(RT_CUSTOM);
|
|
|
|
m_pCHelper->ClearRestrictions();
|
|
|
|
if (m_pCHelper->IsSupportedRestriction(RV_ONE))
|
|
{
|
|
m_pIDBSchemaRowset->AddRef();
|
|
m_pCHelper->SetInvalidRestriction(RV_ONE, (LPVOID)m_pIDBSchemaRowset, VT_UNKNOWN);
|
|
fSetInvalidRestriction = TRUE;
|
|
}
|
|
|
|
if (m_pCHelper->IsSupportedRestriction(RV_TWO))
|
|
{
|
|
pIDispatch->AddRef();
|
|
m_pCHelper->SetInvalidRestriction(RV_TWO, (LPVOID)pIDispatch, VT_DISPATCH);
|
|
fSetInvalidRestriction = TRUE;
|
|
}
|
|
|
|
if (m_pCHelper->IsSupportedRestriction(RV_THREE))
|
|
{
|
|
m_pCHelper->SetInvalidRestriction(RV_THREE, (LPVOID)(LONG_PTR)hrTemp, VT_ERROR);
|
|
fSetInvalidRestriction = TRUE;
|
|
}
|
|
|
|
if (m_pCHelper->IsSupportedRestriction(RV_FOUR))
|
|
{
|
|
m_pCHelper->SetInvalidRestriction(RV_FOUR, (LPVOID)(IUnknown **)&(m_pIDBSchemaRowset),
|
|
VT_BYREF|VT_UNKNOWN);
|
|
fSetInvalidRestriction = TRUE;
|
|
}
|
|
|
|
if (m_pCHelper->IsSupportedRestriction(RV_FIVE))
|
|
{
|
|
m_pCHelper->SetInvalidRestriction(RV_FIVE, (LPVOID)&pIDispatch,
|
|
VT_BYREF|VT_DISPATCH);
|
|
fSetInvalidRestriction = TRUE;
|
|
}
|
|
|
|
if (m_pCHelper->IsSupportedRestriction(RV_SIX))
|
|
{
|
|
m_pCHelper->SetInvalidRestriction(RV_SIX, (LPVOID)&hrTemp,
|
|
VT_BYREF|VT_ERROR);
|
|
fSetInvalidRestriction = TRUE;
|
|
}
|
|
|
|
if (m_pCHelper->IsSupportedRestriction(RV_SEVEN))
|
|
{
|
|
m_pCHelper->SetInvalidRestriction(RV_SEVEN, (LPVOID)&hrTemp,
|
|
VT_BYREF|VT_ERROR);
|
|
fSetInvalidRestriction = TRUE;
|
|
}
|
|
|
|
if (!fSetInvalidRestriction)
|
|
{
|
|
odtLog << L"No restrictions supported.\n";
|
|
goto CLEANUP;
|
|
}
|
|
|
|
CHECK(m_pCHelper->GetRowsetHelper(), E_INVALIDARG);
|
|
|
|
CLEANUP:
|
|
|
|
// Clear the bogus restrictions
|
|
m_pCHelper->ClearRestrictions();
|
|
|
|
m_pCHelper->SetRestrictionArray(RT_SUPPORTED);
|
|
|
|
SAFE_RELEASE(pIDispatch);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(22)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: request DBPROP_IColumnsRowset and, iid = IID_IColumnsRowset
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_22()
|
|
{
|
|
BOOL fResult = TRUE;
|
|
DBPROPSET * pPropSet = NULL;
|
|
ULONG cPropSet = 0;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
if(!IsRowsetPropertySupported(DBPROP_IColumnsRowset))
|
|
{
|
|
odtLog << L"IColumnsRowset is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
TESTC_(SetProperty(DBPROP_IColumnsRowset, DBPROPSET_ROWSET,
|
|
&cPropSet, &pPropSet, DBTYPE_BOOL, VARIANT_TRUE), S_OK);
|
|
|
|
// test method
|
|
TESTC_(m_pCHelper->GetRowsetHelper(NULL, RV_ALL, NULL, IID_IColumnsRowset, cPropSet, pPropSet), S_OK);
|
|
|
|
if (!VerifyPropStatus(cPropSet, pPropSet, DBPROP_IColumnsRowset, DBPROPSET_ROWSET, DBPROPSTATUS_OK))
|
|
goto CLEANUP;
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
FreeProperties(&cPropSet, &pPropSet);
|
|
|
|
return fResult;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(23)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: riid = IID_IRowsetInfo, call IRowset::GetSpecification
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_23()
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
IUnknown * pIUnknown = NULL;
|
|
IRowsetInfo * pIRowsetInfo = NULL;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Test method
|
|
TESTC_(m_pCHelper->GetRowsetHelper(NULL, RV_ALL, NULL, IID_IRowsetInfo, 0,
|
|
NULL, (IUnknown **)&pIRowsetInfo, GUID_NULL, FALSE), S_OK);
|
|
|
|
TESTC(pIRowsetInfo != NULL);
|
|
|
|
// GetSpecification should succeed
|
|
hr = pIRowsetInfo->GetSpecification(IID_IDBSchemaRowset,&pIUnknown);
|
|
|
|
if (hr == S_FALSE)
|
|
{
|
|
// Kagera - Temp table has no way of getting back to kagera's objects so it
|
|
// returns S_FALSE
|
|
|
|
// While this is allowed it's certainly unusual, print warning
|
|
odtLog << L"WARNING - GetSpecification returned S_FALSE.\n";
|
|
odtLog << L"This is allowed but may signify a failure for this provider.\n";
|
|
|
|
// If we claim we didn't return an object make sure
|
|
COMPARE(pIUnknown, NULL);
|
|
}
|
|
else
|
|
{
|
|
// We should have succeeded and returned a valid object pointer
|
|
if (CHECK(hr, S_OK) && COMPARE(pIUnknown != NULL, TRUE))
|
|
{
|
|
IOpenRowset * pIOpenRowset = NULL;
|
|
|
|
// Schema rowsets are always opened via IDBSchemaRowset, therefore GetSpecification
|
|
// should return a session interface.
|
|
if (COMPARE(VerifyInterface(pIUnknown, IID_IOpenRowset, SESSION_INTERFACE, (IUnknown**)&pIOpenRowset),TRUE))
|
|
{
|
|
SAFE_RELEASE(pIOpenRowset);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
CLEANUP:
|
|
|
|
SAFE_RELEASE(pIRowsetInfo);
|
|
SAFE_RELEASE(pIUnknown);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(24)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: riid = IID_IUnknown, get IRowset from IUnknown
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_24()
|
|
{
|
|
IUnknown * pIUnknown = NULL;
|
|
IRowset * pIRowset = NULL;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Test method
|
|
TESTC_(m_pCHelper->GetRowsetHelper(NULL, RV_ALL, NULL, IID_IUnknown, 0,
|
|
NULL, &pIUnknown, GUID_NULL, FALSE), S_OK);
|
|
|
|
TESTC(pIUnknown != NULL);
|
|
|
|
TESTC(VerifyInterface(pIUnknown, IID_IRowset,
|
|
ROWSET_INTERFACE, (IUnknown**)&pIRowset))
|
|
|
|
// RestartPosition should succeed
|
|
TEST2C_(pIRowset->RestartPosition(NULL), S_OK, DB_S_COMMANDREEXECUTED);
|
|
|
|
CLEANUP:
|
|
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIUnknown);
|
|
|
|
return TRUE;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(25)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: open rowset from schema, try to open rowset on command
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_25()
|
|
{
|
|
ULONG ulIndex=0;
|
|
IRowset * pICommandRowset=NULL;
|
|
ICommandText * pICommandText=NULL;
|
|
WCHAR * pSQLText=NULL;
|
|
IDBCreateCommand * pIDBCreateCommand=NULL;
|
|
IRowset * pIRowset = NULL;
|
|
BOOL fResult = FALSE;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
if(m_pIDBCreateCommand)
|
|
{
|
|
TESTC_(m_pIDBCreateCommand->CreateCommand(NULL,IID_ICommandText,(IUnknown**)&pICommandText),S_OK);
|
|
}
|
|
else
|
|
{
|
|
// Check to see if commands are supported
|
|
TESTC_PROVIDER(VerifyInterface(m_pIOpenRowset, IID_IDBCreateCommand,
|
|
SESSION_INTERFACE, (IUnknown**)&pIDBCreateCommand))
|
|
|
|
TESTC_(pIDBCreateCommand->CreateCommand(NULL,IID_ICommandText,(IUnknown**)&pICommandText),S_OK);
|
|
}
|
|
|
|
TESTC_(m_pTable->CreateSQLStmt(SELECT_ALLFROMTBL,m_pTable->GetTableName(),&pSQLText,NULL,NULL),S_OK);
|
|
|
|
TESTC_(pICommandText->SetCommandText(DBGUID_DBSQL,pSQLText),S_OK);
|
|
|
|
// Test method
|
|
TESTC_(m_pCHelper->GetRowsetHelper(NULL, RV_ALL, NULL, IID_IRowset, 0,
|
|
NULL, (IUnknown **)&pIRowset, GUID_NULL, FALSE), S_OK);
|
|
|
|
TESTC(pIRowset != NULL);
|
|
|
|
TESTC_(pICommandText->Execute(NULL,IID_IRowset,NULL,NULL,(IUnknown **)&pICommandRowset),S_OK);
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
SAFE_RELEASE(pICommandText);
|
|
SAFE_RELEASE(pIDBCreateCommand);
|
|
SAFE_RELEASE(pICommandRowset);
|
|
SAFE_RELEASE(pIRowset);
|
|
|
|
// Free the memory
|
|
SAFE_FREE(pSQLText);
|
|
|
|
return fResult;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(26)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: IRowsetScroll
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_26()
|
|
{
|
|
BOOL fResult = TRUE;
|
|
IRowsetScroll * pIRowsetScroll = NULL;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
HROW * phRow = NULL;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
if(!IsRowsetPropertySupported(DBPROP_IRowsetScroll))
|
|
{
|
|
odtLog << L"IRowsetScroll is not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// test method
|
|
TESTC_(m_pCHelper->GetRowsetHelper(NULL, RV_ALL, NULL, IID_IRowsetScroll, 0,
|
|
NULL, (IUnknown **)&pIRowsetScroll, GUID_NULL, FALSE), S_OK);
|
|
|
|
TESTC(pIRowsetScroll != NULL);
|
|
|
|
TESTC_(pIRowsetScroll->GetRowsAtRatio(NULL, NULL, 1, 2, 1, &cRowsObtained, &phRow), S_OK);
|
|
|
|
TESTC(cRowsObtained);
|
|
|
|
TESTC(phRow != NULL);
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
if (phRow && pIRowsetScroll)
|
|
CHECK(pIRowsetScroll->ReleaseRows(cRowsObtained, phRow, NULL, NULL, NULL), S_OK);
|
|
SAFE_FREE(phRow);
|
|
SAFE_RELEASE(pIRowsetScroll);
|
|
|
|
return fResult;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(27)
|
|
//--------------------------------------------------------------------
|
|
// @mfunc E_INVALIDARG: Schema not supported
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_27()
|
|
{
|
|
HRESULT hrExp = S_OK;
|
|
|
|
if (m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema is supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
CHECK(m_pCHelper->GetRowsetHelper(NULL, RV_NULL), E_INVALIDARG);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
|
|
|
|
// }}
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(28)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: Empty result set, pass first restriction that matches second restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_28()
|
|
{
|
|
BOOL fResult = FALSE;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Must support both restrictions
|
|
if (!m_pCHelper->IsSupportedRestriction(RV_ONE) ||
|
|
!m_pCHelper->IsSupportedRestriction(RV_TWO))
|
|
{
|
|
odtLog << L"First or second restriction not suported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// The VT must match between first and second restriction
|
|
if (V_VT(m_pCHelper->GetRestrictPtr(RV_ONE)) !=
|
|
V_VT(m_pCHelper->GetRestrictPtr(RV_TWO)))
|
|
{
|
|
odtLog << L"First and second restriction are different types.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
m_pCHelper->SetRestrictionArray(RT_CUSTOM);
|
|
|
|
m_pCHelper->ClearRestrictions();
|
|
|
|
// Set first restriction to a valid value
|
|
m_pCHelper->SetValidRestriction(RV_ONE);
|
|
|
|
// Set second restriction to first restriction's value
|
|
TESTC(m_pCHelper->SetRestriction(RV_TWO, m_pCHelper->GetRestrictPtr(RV_ONE)));
|
|
|
|
// Tell helper to expect 0 rows
|
|
m_pCHelper->SetRowCount(EXACT_VALUE, 0);
|
|
|
|
// Get the rowset
|
|
TESTC_(m_pCHelper->GetRowsetHelper(), S_OK);
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
m_pCHelper->SetRowCount(MIN_VALUE, 1);
|
|
m_pCHelper->SetRestrictionArray(RT_SUPPORTED);
|
|
|
|
return fResult;
|
|
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(29)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: Empty result set, pass non-matching value for each restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_29()
|
|
{
|
|
BOOL fResult = FALSE;
|
|
ULONG iRestrict;
|
|
VARIANT * pVariant = NULL;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Use custom restrictions
|
|
m_pCHelper->SetRestrictionArray(RT_CUSTOM);
|
|
|
|
// Clear all
|
|
m_pCHelper->ClearRestrictions();
|
|
|
|
// for all possible restrictions
|
|
for (iRestrict = 1; iRestrict <= m_pCHelper->RestrictionCount(); iRestrict++)
|
|
{
|
|
// If this restriction isn't supported then don't test it
|
|
if (!m_pCHelper->IsSupportedRestriction(iRestrict))
|
|
continue;
|
|
|
|
// Set restriction to a valid value
|
|
m_pCHelper->SetValidRestriction(iRestrict);
|
|
|
|
pVariant = m_pCHelper->GetRestrictPtr(iRestrict);
|
|
|
|
TESTC(pVariant != NULL);
|
|
|
|
// It's impossible to come up with a nonmatching
|
|
// value for boolean restrictions without first going
|
|
// the entire rowset, so we'll skip boolean (VARIANT_BOOL)
|
|
// restrictions.
|
|
if (V_VT(pVariant) == VT_BOOL)
|
|
continue;
|
|
|
|
// Now reset to a bogus nonmatching value. We assume all available
|
|
// bits set on will not match any restriction.
|
|
if (V_VT(pVariant) == VT_BSTR)
|
|
V_BSTR(pVariant)[0] = L'z';
|
|
// memset(V_BSTR(pVariant), 0x55,
|
|
// wcslen(V_BSTR(pVariant))*sizeof(WCHAR));
|
|
else
|
|
// For all other types just set all bits on. At this time there
|
|
// are no BYREF restrictions.
|
|
memset(&(pVariant->bVal), 0xF,
|
|
sizeof(VARIANT)-sizeof(VARTYPE)-sizeof(USHORT)*3);
|
|
|
|
|
|
// Over-ride the row count expected, we MUST get 0 rows
|
|
m_pCHelper->SetRowCount(EXACT_VALUE, 0);
|
|
|
|
// Get the rowset
|
|
TESTC_(m_pCHelper->GetRowsetHelper(), S_OK);
|
|
|
|
// Clear the bogus restriction
|
|
m_pCHelper->ClearRestrictions();
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
m_pCHelper->SetRowCount(MIN_VALUE, 1);
|
|
m_pCHelper->SetRestrictionArray(RT_SUPPORTED);
|
|
|
|
return fResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(30)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc First restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_30()
|
|
{
|
|
return m_pCHelper->TestRestriction(RV_ONE);
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(31)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Second restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_31()
|
|
{
|
|
return m_pCHelper->TestRestriction(RV_TWO);
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(32)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Third restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_32()
|
|
{
|
|
return m_pCHelper->TestRestriction(RV_THREE);
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(33)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Fourth restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_33()
|
|
{
|
|
return m_pCHelper->TestRestriction(RV_FOUR);
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(34)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Fifth restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_34()
|
|
{
|
|
return m_pCHelper->TestRestriction(RV_FIVE);
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(35)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Sixth restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_35()
|
|
{
|
|
return m_pCHelper->TestRestriction(RV_SIX);
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(36)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Seventh restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_36()
|
|
{
|
|
return m_pCHelper->TestRestriction(RV_SEVEN);
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(37)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: all rowset properties as required
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_37()
|
|
{
|
|
// TODO: Consolidate vars 37, 38, and 39.
|
|
|
|
BOOL fResult = FALSE;
|
|
ULONG cPropInfos = 0;
|
|
DBPROPINFO * pPropInfos = NULL;
|
|
DBPROPSET * pPropSet = NULL;
|
|
ULONG cPropSet = 0;
|
|
LPVOID lpvPropVal;
|
|
HRESULT hr = E_FAIL;
|
|
DBPROPSTATUS dwPropStatusExpected;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
cPropInfos = m_rgRowsetDBPROPINFOSET[0].cPropertyInfos;
|
|
pPropInfos = m_rgRowsetDBPROPINFOSET[0].rgPropertyInfos;
|
|
|
|
// Spin through each rowset prop
|
|
for(ULONG iProp=0; iProp < cPropInfos; iProp++)
|
|
{
|
|
DBPROPID dwPropertyID = pPropInfos[iProp].dwPropertyID;
|
|
VARTYPE vt = pPropInfos[iProp].vtType;
|
|
|
|
odtLog << pPropInfos[iProp].pwszDescription << L"\n";
|
|
|
|
// If this is a BOOLEAN property set on
|
|
if (vt == VT_BOOL)
|
|
lpvPropVal = (LPVOID)VARIANT_TRUE;
|
|
else
|
|
{
|
|
// Value has to be specifically set for each property
|
|
switch(dwPropertyID)
|
|
{
|
|
case DBPROP_ACCESSORDER:
|
|
lpvPropVal = (LPVOID)(DBPROPVAL_AO_RANDOM);
|
|
break;
|
|
case DBPROP_UPDATABILITY:
|
|
lpvPropVal = (LPVOID)(DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE);
|
|
break;
|
|
default:
|
|
odtLog << L"\tProperty not yet tested.\n";
|
|
continue;
|
|
}
|
|
}
|
|
|
|
TESTC_(SetProperty(dwPropertyID, DBPROPSET_ROWSET,
|
|
&cPropSet, &pPropSet, vt, &lpvPropVal), S_OK);
|
|
|
|
TEST2C_(hr = m_pCHelper->GetRowsetHelper(NULL, RV_ALL, NULL, IID_IRowset, cPropSet, pPropSet),
|
|
S_OK, DB_E_ERRORSOCCURRED);
|
|
|
|
if (S_OK == hr)
|
|
dwPropStatusExpected = DBPROPSTATUS_OK;
|
|
else if (!(pPropInfos[iProp].dwFlags & DBPROPFLAGS_WRITE))
|
|
{
|
|
dwPropStatusExpected = DBPROPSTATUS_NOTSETTABLE;
|
|
}
|
|
else
|
|
{
|
|
// It has been determined that the proper status here is DBPROPSTATUS_CONFLICTING
|
|
// if the provider does not support a given update property on a schema rowset.
|
|
|
|
// We will cheat a little on the spec here since schema rowsets don't generally
|
|
// support all the props other rowsets do and we will allow DBPROPSTATUS_NOTSETTABLE
|
|
// even though GetPropertyInfo returns supported and settable.
|
|
if (pPropSet[0].rgProperties[0].dwStatus == DBPROPSTATUS_NOTSETTABLE)
|
|
dwPropStatusExpected = DBPROPSTATUS_NOTSETTABLE;
|
|
else
|
|
dwPropStatusExpected = DBPROPSTATUS_CONFLICTING;
|
|
|
|
// If this is an update prop or the prop can't be supported on a schema rowset the
|
|
// provider may return DBPROPSTATUS_NOTSUPPORTED. Since we don't have any way
|
|
// to know what props the provider actually does support against a schema rowset
|
|
// we have to allow this.
|
|
if (pPropSet[0].rgProperties[0].dwStatus == DBPROPSTATUS_NOTSUPPORTED)
|
|
dwPropStatusExpected = DBPROPSTATUS_NOTSUPPORTED;
|
|
|
|
// If this is DBPROP_UPDATABILITY itself, we need to allow
|
|
// DBPROPSTATUS_BADVALUE if the user attempts to set non-zero
|
|
if (pPropSet[0].rgProperties[0].dwPropertyID == DBPROP_UPDATABILITY &&
|
|
V_I4(&pPropSet[0].rgProperties[0].vValue) != 0 &&
|
|
pPropSet[0].rgProperties[0].dwStatus == DBPROPSTATUS_BADVALUE)
|
|
dwPropStatusExpected = DBPROPSTATUS_BADVALUE;
|
|
|
|
}
|
|
|
|
// VerifyPropStatus posts its own errors, don't check return.
|
|
VerifyPropStatus(cPropSet, pPropSet, dwPropertyID,
|
|
DBPROPSET_ROWSET, dwPropStatusExpected);
|
|
|
|
// Free the property info for next iteration
|
|
FreeProperties(&cPropSet, &pPropSet);
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
FreeProperties(&cPropSet, &pPropSet);
|
|
|
|
return fResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(38)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: all rowset properties as optional
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_38()
|
|
{
|
|
BOOL fResult = FALSE;
|
|
ULONG cPropInfos = 0;
|
|
DBPROPINFO * pPropInfos = NULL;
|
|
DBPROPSET * pPropSet = NULL;
|
|
ULONG cPropSet = 0;
|
|
LPVOID lpvPropVal;
|
|
HRESULT hr = E_FAIL;
|
|
DBPROPSTATUS dwPropStatusExpected;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
cPropInfos = m_rgRowsetDBPROPINFOSET[0].cPropertyInfos;
|
|
pPropInfos = m_rgRowsetDBPROPINFOSET[0].rgPropertyInfos;
|
|
|
|
// Spin through each rowset prop
|
|
for(ULONG iProp=0; iProp < cPropInfos; iProp++)
|
|
{
|
|
DBPROPID dwPropertyID = pPropInfos[iProp].dwPropertyID;
|
|
VARTYPE vt = pPropInfos[iProp].vtType;
|
|
|
|
odtLog << pPropInfos[iProp].pwszDescription << L"\n";
|
|
|
|
// If this is a BOOLEAN property set on
|
|
if (vt == VT_BOOL)
|
|
lpvPropVal = (LPVOID)VARIANT_TRUE;
|
|
else
|
|
{
|
|
// Value has to be specifically set for each property
|
|
switch(dwPropertyID)
|
|
{
|
|
case DBPROP_ACCESSORDER:
|
|
lpvPropVal = (LPVOID)(DBPROPVAL_AO_RANDOM);
|
|
break;
|
|
case DBPROP_UPDATABILITY:
|
|
lpvPropVal = (LPVOID)(DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE);
|
|
break;
|
|
default:
|
|
odtLog << L"\tProperty not yet tested.\n";
|
|
continue;
|
|
}
|
|
}
|
|
|
|
TESTC_(SetProperty(dwPropertyID, DBPROPSET_ROWSET,
|
|
&cPropSet, &pPropSet, vt, &lpvPropVal, DBPROPOPTIONS_OPTIONAL), S_OK);
|
|
|
|
hr = m_pCHelper->GetRowsetHelper(NULL, RV_ALL, NULL, IID_IRowset, cPropSet, pPropSet);
|
|
|
|
// Allow S_OK or DB_S_ERRORSOCCURRED. Don't use TESTC_ macro because we really don't
|
|
// want to bail from our loop.
|
|
if (hr != S_OK)
|
|
CHECK(hr, DB_S_ERRORSOCCURRED);
|
|
|
|
if (S_OK == hr)
|
|
dwPropStatusExpected = DBPROPSTATUS_OK;
|
|
else
|
|
{
|
|
dwPropStatusExpected = DBPROPSTATUS_NOTSET;
|
|
|
|
// Since the property may not be settable for schema rowset we need to allow
|
|
// DBPROPSTATUS_NOTSETTABLE here also.
|
|
if (pPropSet[0].rgProperties[0].dwStatus == DBPROPSTATUS_NOTSETTABLE)
|
|
dwPropStatusExpected = DBPROPSTATUS_NOTSETTABLE;
|
|
|
|
// Since the property may not be supported for schema rowset we need to allow
|
|
// DBPROPSTATUS_NOTSUPPORTED here also. Unlike regular rowsets we can't depend
|
|
// on GetPropertyInfo to tell us whether it's supported.
|
|
if (pPropSet[0].rgProperties[0].dwStatus == DBPROPSTATUS_NOTSUPPORTED)
|
|
dwPropStatusExpected = DBPROPSTATUS_NOTSUPPORTED;
|
|
|
|
// Since the property may require other properties to be set (example: sqlncli can not set DBPROP_IDBAsynchStatus until DBPROP_ROWSET_ASYNCH is set),
|
|
// some providers may return DBPROPSTATUS_CONFLICTING
|
|
if (pPropSet[0].rgProperties[0].dwStatus == DBPROPSTATUS_CONFLICTING)
|
|
dwPropStatusExpected = DBPROPSTATUS_CONFLICTING;
|
|
|
|
// And, finally, since we don't support updatability for schema rowsets,
|
|
// some providers may return DBPROPSTATUS_BADVALUE when requesting update support
|
|
if (pPropSet[0].rgProperties[0].dwStatus == DBPROPSTATUS_BADVALUE)
|
|
dwPropStatusExpected = DBPROPSTATUS_BADVALUE;
|
|
}
|
|
|
|
// VerifyPropStatus posts its own errors, don't check return.
|
|
VerifyPropStatus(cPropSet, pPropSet, dwPropertyID,
|
|
DBPROPSET_ROWSET, dwPropStatusExpected);
|
|
|
|
// Free the property info for next iteration
|
|
FreeProperties(&cPropSet, &pPropSet);
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
FreeProperties(&cPropSet, &pPropSet);
|
|
|
|
return fResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(39)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: all rowset properties, 2 at time, 1 optional, 1 required
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_39()
|
|
{
|
|
BOOL fResult = FALSE;
|
|
ULONG cPropInfos = 0;
|
|
DBPROPINFO * pPropInfos = NULL;
|
|
DBPROPSET * pPropSet = NULL;
|
|
ULONG cPropSet = 0;
|
|
LPVOID lpvPropVal;
|
|
LPVOID lpvPropValOpt;
|
|
HRESULT hr = E_FAIL;
|
|
BOOL fStatusOK;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
odtLog << L"This testing is too time consuming and has been removed.\n";
|
|
return TEST_SKIPPED;
|
|
|
|
cPropInfos = m_rgRowsetDBPROPINFOSET[0].cPropertyInfos;
|
|
pPropInfos = m_rgRowsetDBPROPINFOSET[0].rgPropertyInfos;
|
|
|
|
// Spin through each rowset prop
|
|
for(ULONG iProp=0; iProp < cPropInfos; iProp++)
|
|
{
|
|
for (ULONG jProp = 0; jProp < cPropInfos; jProp++)
|
|
{
|
|
// Don't set same prop both optional and required
|
|
if (iProp == jProp)
|
|
continue;
|
|
|
|
DBPROPID dwPropertyID = pPropInfos[iProp].dwPropertyID;
|
|
VARTYPE vt = pPropInfos[iProp].vtType;
|
|
DBPROPID dwPropIDOpt = pPropInfos[jProp].dwPropertyID;
|
|
VARTYPE vtOpt = pPropInfos[jProp].vtType;
|
|
|
|
// If this is a BOOLEAN property set on
|
|
if (vt == VT_BOOL)
|
|
lpvPropVal = (LPVOID)VARIANT_TRUE;
|
|
else
|
|
{
|
|
// Value has to be specifically set for each property
|
|
switch(dwPropertyID)
|
|
{
|
|
case DBPROP_ACCESSORDER:
|
|
lpvPropVal = (LPVOID)(DBPROPVAL_AO_RANDOM);
|
|
break;
|
|
case DBPROP_UPDATABILITY:
|
|
lpvPropVal = (LPVOID)(DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE);
|
|
break;
|
|
default:
|
|
continue;
|
|
}
|
|
}
|
|
|
|
TESTC_(SetProperty(dwPropertyID, DBPROPSET_ROWSET,
|
|
&cPropSet, &pPropSet, vt, &lpvPropVal), S_OK);
|
|
|
|
// If this is a BOOLEAN property set on
|
|
if (vtOpt == VT_BOOL)
|
|
lpvPropValOpt = (LPVOID)VARIANT_TRUE;
|
|
else
|
|
{
|
|
// Value has to be specifically set for each property
|
|
switch(dwPropIDOpt)
|
|
{
|
|
case DBPROP_ACCESSORDER:
|
|
lpvPropValOpt = (LPVOID)(DBPROPVAL_AO_RANDOM);
|
|
break;
|
|
case DBPROP_UPDATABILITY:
|
|
lpvPropValOpt = (LPVOID)(DBPROPVAL_UP_CHANGE|DBPROPVAL_UP_INSERT|DBPROPVAL_UP_DELETE);
|
|
break;
|
|
default:
|
|
FreeProperties(&cPropSet, &pPropSet);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
TESTC_(SetProperty(dwPropIDOpt, DBPROPSET_ROWSET,
|
|
&cPropSet, &pPropSet, vtOpt, &lpvPropValOpt, DBPROPOPTIONS_OPTIONAL), S_OK);
|
|
|
|
TEST3C_(hr = m_pCHelper->GetRowsetHelper(NULL, RV_ALL, NULL, IID_IRowset, cPropSet, pPropSet),
|
|
S_OK, DB_S_ERRORSOCCURRED, DB_E_ERRORSOCCURRED);
|
|
|
|
fStatusOK = TRUE;
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
// Both properties were set, verify status
|
|
fStatusOK &= VerifyPropStatus(cPropSet, pPropSet, dwPropertyID,
|
|
DBPROPSET_ROWSET, DBPROPSTATUS_OK);
|
|
fStatusOK &= VerifyPropStatus(cPropSet, pPropSet, dwPropIDOpt,
|
|
DBPROPSET_ROWSET, DBPROPSTATUS_OK);
|
|
}
|
|
else if (DB_S_ERRORSOCCURRED == hr)
|
|
{
|
|
// First prop must have been set
|
|
fStatusOK &= VerifyPropStatus(cPropSet, pPropSet, dwPropertyID,
|
|
DBPROPSET_ROWSET, DBPROPSTATUS_OK);
|
|
|
|
// Due to ambiguities in the spec the provider may return DBPROPSTATUS_NOTSETTABLE
|
|
// or DBPROPSTATUS_NOTSUPPORTED here, but we prefer DBPROPSTATUS_NOTSET.
|
|
if (pPropSet[0].rgProperties[1].dwStatus != DBPROPSTATUS_NOTSUPPORTED &&
|
|
pPropSet[0].rgProperties[1].dwStatus != DBPROPSTATUS_NOTSETTABLE)
|
|
fStatusOK &= VerifyPropStatus(cPropSet, pPropSet, dwPropIDOpt,
|
|
DBPROPSET_ROWSET, DBPROPSTATUS_NOTSET);
|
|
}
|
|
else
|
|
{
|
|
DBPROPSTATUS dwStatusExpected = DBPROPSTATUS_CONFLICTING;
|
|
// First prop must be NOTSETTABLE or CONFLICTING since it was REQUIRED
|
|
if (pPropSet[0].rgProperties[0].dwStatus == DBPROPSTATUS_NOTSETTABLE)
|
|
dwStatusExpected = DBPROPSTATUS_NOTSETTABLE; // We will allow this
|
|
if (pPropSet[0].rgProperties[0].dwStatus == DBPROPSTATUS_NOTSUPPORTED)
|
|
dwStatusExpected = DBPROPSTATUS_NOTSUPPORTED; // We will allow this
|
|
fStatusOK &= VerifyPropStatus(cPropSet, pPropSet, dwPropertyID,
|
|
DBPROPSET_ROWSET, dwStatusExpected);
|
|
// Other may have errored also, but may have succeeded
|
|
if (pPropSet[0].rgProperties[1].dwStatus != DBPROPSTATUS_NOTSUPPORTED &&
|
|
pPropSet[0].rgProperties[1].dwStatus != DBPROPSTATUS_NOTSETTABLE)
|
|
fStatusOK &= VerifyPropStatus(cPropSet, pPropSet, dwPropIDOpt,
|
|
DBPROPSET_ROWSET, DBPROPSTATUS_OK);
|
|
}
|
|
|
|
if (!fStatusOK)
|
|
odtLog << L"For property combination: " << pPropInfos[iProp].pwszDescription <<
|
|
L" and " << pPropInfos[jProp].pwszDescription << L"\n\n";
|
|
|
|
// Free the property info for next iteration
|
|
FreeProperties(&cPropSet, &pPropSet);
|
|
}
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
FreeProperties(&cPropSet, &pPropSet);
|
|
|
|
return fResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(40)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc DB_E_ERRORSOCCURRED: non-rowset property sets, all properties in that set
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_40()
|
|
{
|
|
// TODO: Consolidate vars 37, 38, and 39.
|
|
|
|
BOOL fResult = FALSE;
|
|
ULONG cPropInfos = 0;
|
|
DBPROPINFO * pPropInfos = NULL;
|
|
DBPROPSET * pPropSet = NULL;
|
|
ULONG cPropSet = 0;
|
|
LPVOID lpvPropVal;
|
|
HRESULT hr = E_FAIL;
|
|
DBPROPSTATUS dwPropStatusExpected;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
cPropInfos = m_rgDBPROPINFOSET[0].cPropertyInfos;
|
|
pPropInfos = m_rgDBPROPINFOSET[0].rgPropertyInfos;
|
|
|
|
|
|
for(ULONG iInfoSet=0; iInfoSet < m_cDBPROPINFOSET; iInfoSet++)
|
|
{
|
|
BOOL fRowsetPropSet = FALSE;
|
|
|
|
// We only want the non-rowset props
|
|
for (ULONG iRowsetInfoSet = 0; iRowsetInfoSet < m_cRowsetDBPROPINFOSET; iRowsetInfoSet++)
|
|
{
|
|
if (m_rgDBPROPINFOSET[iInfoSet].guidPropertySet == m_rgRowsetDBPROPINFOSET[iRowsetInfoSet].guidPropertySet)
|
|
{
|
|
fRowsetPropSet = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (fRowsetPropSet)
|
|
continue;
|
|
|
|
// Spin through each non-rowset prop
|
|
for(ULONG iProp=0; iProp < cPropInfos; iProp++)
|
|
{
|
|
DBPROPID dwPropertyID = pPropInfos[iProp].dwPropertyID;
|
|
VARTYPE vt = pPropInfos[iProp].vtType;
|
|
|
|
// odtLog << pPropInfos[iProp].pwszDescription << L"\n";
|
|
|
|
lpvPropVal = (LPVOID)VARIANT_TRUE;
|
|
TESTC_(SetProperty(dwPropertyID, m_rgDBPROPINFOSET[iInfoSet].guidPropertySet,
|
|
&cPropSet, &pPropSet, vt, &lpvPropVal), S_OK);
|
|
|
|
TESTC_(hr = m_pCHelper->GetRowsetHelper(NULL, RV_ALL, NULL, IID_IRowset, cPropSet, pPropSet),
|
|
DB_E_ERRORSOCCURRED);
|
|
|
|
dwPropStatusExpected = DBPROPSTATUS_NOTSUPPORTED;
|
|
VerifyPropStatus(cPropSet, pPropSet, dwPropertyID,
|
|
m_rgDBPROPINFOSET[iInfoSet].guidPropertySet, dwPropStatusExpected);
|
|
|
|
// Free the property info for next iteration
|
|
FreeProperties(&cPropSet, &pPropSet);
|
|
}
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
FreeProperties(&cPropSet, &pPropSet);
|
|
|
|
return fResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(41)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Security: Maximum sized string restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_41()
|
|
{
|
|
BOOL fResult = FALSE;
|
|
ULONG iRestrict;
|
|
VARIANT * pVariant = NULL;
|
|
ULONG cchRestrictionMax = 0;
|
|
BSTR bstrMaxRestriction = NULL;
|
|
LPWSTR pwszMaxRestriction = NULL;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Use custom restrictions
|
|
m_pCHelper->SetRestrictionArray(RT_CUSTOM);
|
|
|
|
// Clear all
|
|
m_pCHelper->ClearRestrictions();
|
|
|
|
// for all possible restrictions
|
|
for (iRestrict = 1; iRestrict <= m_pCHelper->RestrictionCount(); iRestrict++)
|
|
{
|
|
// If this restriction isn't supported then don't test it
|
|
if (!m_pCHelper->IsSupportedRestriction(iRestrict))
|
|
continue;
|
|
|
|
// Get the max length for this restriction
|
|
cchRestrictionMax = m_pCHelper->GetRestrictionMaxLength(iRestrict);
|
|
|
|
// If the length is CCHMAXLENGTH_UNKNOWN, then the restriction does not have a max length OR
|
|
// the max length is unknown
|
|
if (cchRestrictionMax == CCHMAXLENGTH_UNKNOWN)
|
|
continue;
|
|
|
|
// Set restriction to a valid value
|
|
m_pCHelper->SetValidRestriction(iRestrict);
|
|
|
|
pVariant = m_pCHelper->GetRestrictPtr(iRestrict);
|
|
|
|
TESTC(pVariant != NULL);
|
|
|
|
// We don't care about non-BSTR restrictions
|
|
if (V_VT(pVariant) != VT_BSTR)
|
|
continue;
|
|
|
|
// Now reset to a maximum value. Note this value likely does not
|
|
// match any rows, so there should be an empty rowset.
|
|
|
|
// Create a restriction value of the appropriate size
|
|
bstrMaxRestriction = SysAllocStringLen(NULL, cchRestrictionMax+1);
|
|
TESTC(bstrMaxRestriction != NULL);
|
|
|
|
memset(bstrMaxRestriction, 1, cchRestrictionMax*sizeof(WCHAR));
|
|
bstrMaxRestriction[cchRestrictionMax] = L'\0';
|
|
|
|
VariantClear(pVariant);
|
|
|
|
V_VT(pVariant) = VT_BSTR;
|
|
V_BSTR(pVariant) = bstrMaxRestriction;
|
|
bstrMaxRestriction = NULL; // Because the Variant now owns the BSTR.
|
|
|
|
// Over-ride the row count expected, we MUST get 0 rows
|
|
m_pCHelper->SetRowCount(EXACT_VALUE, 0);
|
|
|
|
// Get the rowset
|
|
TESTC_(m_pCHelper->GetRowsetHelper(), S_OK);
|
|
|
|
// Clear the bogus restriction
|
|
m_pCHelper->ClearRestrictions();
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
// VariantClear(pVariant); Don't need to clear the variant as it's owned by the helper class
|
|
m_pCHelper->SetRowCount(MIN_VALUE, 1);
|
|
m_pCHelper->SetRestrictionArray(RT_SUPPORTED);
|
|
|
|
return fResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(42)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Security: Max size plus one string restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_42()
|
|
{
|
|
BOOL fResult = FALSE;
|
|
ULONG iRestrict;
|
|
VARIANT * pVariant = NULL;
|
|
ULONG cchRestrictionMax = 0;
|
|
BSTR bstrMaxRestriction = NULL;
|
|
LPWSTR pwszMaxRestriction = NULL;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Use custom restrictions
|
|
m_pCHelper->SetRestrictionArray(RT_CUSTOM);
|
|
|
|
// Clear all
|
|
m_pCHelper->ClearRestrictions();
|
|
|
|
// for all possible restrictions
|
|
for (iRestrict = 1; iRestrict <= m_pCHelper->RestrictionCount(); iRestrict++)
|
|
{
|
|
// If this restriction isn't supported then don't test it
|
|
if (!m_pCHelper->IsSupportedRestriction(iRestrict))
|
|
continue;
|
|
|
|
// Get the max length for this restriction
|
|
cchRestrictionMax = m_pCHelper->GetRestrictionMaxLength(iRestrict);
|
|
|
|
// If the length is CCHMAXLENGTH_UNKNOWN, then the restriction does not have a max length OR
|
|
// the max length is unknown
|
|
if (cchRestrictionMax == CCHMAXLENGTH_UNKNOWN)
|
|
continue;
|
|
|
|
// Set restriction to a valid value
|
|
m_pCHelper->SetValidRestriction(iRestrict);
|
|
|
|
pVariant = m_pCHelper->GetRestrictPtr(iRestrict);
|
|
|
|
TESTC(pVariant != NULL);
|
|
|
|
// We don't care about non-BSTR restrictions
|
|
if (V_VT(pVariant) != VT_BSTR)
|
|
continue;
|
|
|
|
// Now reset to a maximum plus 1 value. Note this value likely does not
|
|
// match any rows, so there should be an empty rowset.
|
|
cchRestrictionMax++;
|
|
|
|
// Create a restriction value of the appropriate size. Use max size
|
|
// plus null terminator.
|
|
bstrMaxRestriction = SysAllocStringLen(NULL, cchRestrictionMax+1);
|
|
TESTC(bstrMaxRestriction != NULL);
|
|
|
|
memset(bstrMaxRestriction, 1, cchRestrictionMax*sizeof(WCHAR));
|
|
bstrMaxRestriction[cchRestrictionMax] = L'\0';
|
|
|
|
VariantClear(pVariant);
|
|
|
|
V_VT(pVariant) = VT_BSTR;
|
|
V_BSTR(pVariant) = bstrMaxRestriction;
|
|
bstrMaxRestriction = NULL; // Because the Variant now owns the BSTR.
|
|
|
|
// Over-ride the row count expected, we MUST get 0 rows
|
|
m_pCHelper->SetRowCount(EXACT_VALUE, 0);
|
|
|
|
// Get the rowset. Expect empty rowset (S_OK) or provider specific error (E_FAIL)
|
|
TEST2C_(m_pCHelper->GetRowsetHelper(), S_OK, E_FAIL);
|
|
|
|
// Clear the bogus restriction
|
|
m_pCHelper->ClearRestrictions();
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
// VariantClear(pVariant); Don't need to clear the variant as it's owned by the helper class
|
|
m_pCHelper->SetRowCount(MIN_VALUE, 1);
|
|
m_pCHelper->SetRestrictionArray(RT_SUPPORTED);
|
|
|
|
return fResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(43)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Security: Extremely large string restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_43()
|
|
{
|
|
BOOL fResult = FALSE;
|
|
ULONG iRestrict;
|
|
VARIANT * pVariant = NULL;
|
|
ULONG cchRestrictionMax = 0;
|
|
BSTR bstrMaxRestriction = NULL;
|
|
LPWSTR pwszMaxRestriction = NULL;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Use custom restrictions
|
|
m_pCHelper->SetRestrictionArray(RT_CUSTOM);
|
|
|
|
// Clear all
|
|
m_pCHelper->ClearRestrictions();
|
|
|
|
// for all possible restrictions
|
|
for (iRestrict = 1; iRestrict <= m_pCHelper->RestrictionCount(); iRestrict++)
|
|
{
|
|
// If this restriction isn't supported then don't test it
|
|
if (!m_pCHelper->IsSupportedRestriction(iRestrict))
|
|
continue;
|
|
|
|
// Get the max length for this restriction
|
|
cchRestrictionMax = m_pCHelper->GetRestrictionMaxLength(iRestrict);
|
|
|
|
// If the length is CCHMAXLENGTH_UNKNOWN, then the restriction does not have a max length OR
|
|
// the max length is unknown
|
|
if (cchRestrictionMax == CCHMAXLENGTH_UNKNOWN)
|
|
continue;
|
|
|
|
// Set restriction to a valid value
|
|
m_pCHelper->SetValidRestriction(iRestrict);
|
|
|
|
pVariant = m_pCHelper->GetRestrictPtr(iRestrict);
|
|
|
|
TESTC(pVariant != NULL);
|
|
|
|
// We don't care about non-BSTR restrictions
|
|
if (V_VT(pVariant) != VT_BSTR)
|
|
continue;
|
|
|
|
// Now reset to an extremely large value. We assume that an extremely
|
|
// large value will be 1000 times that of the max value. Note this value likely does not
|
|
// match any rows, so there should be an empty rowset.
|
|
cchRestrictionMax *= 1000;
|
|
|
|
// Create a restriction value of the appropriate size. Use max size
|
|
// plus null terminator.
|
|
bstrMaxRestriction = SysAllocStringLen(NULL, cchRestrictionMax+1);
|
|
TESTC(bstrMaxRestriction != NULL);
|
|
|
|
memset(bstrMaxRestriction, 1, cchRestrictionMax*sizeof(WCHAR));
|
|
bstrMaxRestriction[cchRestrictionMax] = L'\0';
|
|
|
|
VariantClear(pVariant);
|
|
|
|
V_VT(pVariant) = VT_BSTR;
|
|
V_BSTR(pVariant) = bstrMaxRestriction;
|
|
bstrMaxRestriction = NULL; // Because the Variant now owns the BSTR.
|
|
|
|
// Over-ride the row count expected, we MUST get 0 rows
|
|
m_pCHelper->SetRowCount(EXACT_VALUE, 0);
|
|
|
|
// Get the rowset. Expect empty rowset (S_OK) or provider specific error (E_FAIL)
|
|
TEST2C_(m_pCHelper->GetRowsetHelper(), S_OK, E_FAIL);
|
|
|
|
// Clear the bogus restriction
|
|
m_pCHelper->ClearRestrictions();
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
// VariantClear(pVariant); Don't need to clear the variant as it's owned by the helper class
|
|
m_pCHelper->SetRowCount(MIN_VALUE, 1);
|
|
m_pCHelper->SetRestrictionArray(RT_SUPPORTED);
|
|
|
|
return fResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(44)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Security: Use %s in string restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_44()
|
|
{
|
|
BOOL fResult = FALSE;
|
|
ULONG iRestrict;
|
|
VARIANT * pVariant = NULL;
|
|
ULONG cchRestrictionMax = 0;
|
|
BSTR bstrMaxRestriction = NULL;
|
|
LPWSTR pwszMaxRestriction = NULL;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Use custom restrictions
|
|
m_pCHelper->SetRestrictionArray(RT_CUSTOM);
|
|
|
|
// Clear all
|
|
m_pCHelper->ClearRestrictions();
|
|
|
|
// for all possible restrictions
|
|
for (iRestrict = 1; iRestrict <= m_pCHelper->RestrictionCount(); iRestrict++)
|
|
{
|
|
// If this restriction isn't supported then don't test it
|
|
if (!m_pCHelper->IsSupportedRestriction(iRestrict))
|
|
continue;
|
|
|
|
// Get the max length for this restriction
|
|
cchRestrictionMax = m_pCHelper->GetRestrictionMaxLength(iRestrict);
|
|
|
|
// If the length is CCHMAXLENGTH_UNKNOWN, then the restriction does not have a max length OR
|
|
// the max length is unknown
|
|
if (cchRestrictionMax == CCHMAXLENGTH_UNKNOWN)
|
|
continue;
|
|
|
|
// Set restriction to a valid value
|
|
m_pCHelper->SetValidRestriction(iRestrict);
|
|
|
|
pVariant = m_pCHelper->GetRestrictPtr(iRestrict);
|
|
|
|
TESTC(pVariant != NULL);
|
|
|
|
// We don't care about non-BSTR restrictions
|
|
if (V_VT(pVariant) != VT_BSTR)
|
|
continue;
|
|
|
|
// Create a restriction value of the appropriate size
|
|
bstrMaxRestriction = SysAllocStringLen(NULL, cchRestrictionMax+1);
|
|
TESTC(bstrMaxRestriction != NULL);
|
|
|
|
memset(bstrMaxRestriction, 1, cchRestrictionMax*sizeof(WCHAR));
|
|
bstrMaxRestriction[cchRestrictionMax] = L'\0';
|
|
|
|
// Put a %s in the string restriction
|
|
wcsncpy(bstrMaxRestriction, L"%s", wcslen(L"%s"));
|
|
|
|
VariantClear(pVariant);
|
|
|
|
V_VT(pVariant) = VT_BSTR;
|
|
V_BSTR(pVariant) = bstrMaxRestriction;
|
|
bstrMaxRestriction = NULL; // Because the Variant now owns the BSTR.
|
|
|
|
// Over-ride the row count expected, we MUST get 0 rows
|
|
m_pCHelper->SetRowCount(EXACT_VALUE, 0);
|
|
|
|
// Get the rowset
|
|
TESTC_(m_pCHelper->GetRowsetHelper(), S_OK);
|
|
|
|
// Clear the bogus restriction
|
|
m_pCHelper->ClearRestrictions();
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
// VariantClear(pVariant); Don't need to clear the variant as it's owned by the helper class
|
|
m_pCHelper->SetRowCount(MIN_VALUE, 1);
|
|
m_pCHelper->SetRestrictionArray(RT_SUPPORTED);
|
|
|
|
return fResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(45)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Security: Use recursive variant in restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_45()
|
|
{
|
|
BOOL fResult = FALSE;
|
|
ULONG iRestrict;
|
|
VARIANT * pVariant = NULL;
|
|
ULONG cchRestrictionMax = 0;
|
|
BSTR bstrMaxRestriction = NULL;
|
|
LPWSTR pwszMaxRestriction = NULL;
|
|
VARIANT vVar;
|
|
VARIANT * pvVar = &vVar;
|
|
|
|
VariantInit(pvVar);
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Use custom restrictions
|
|
m_pCHelper->SetRestrictionArray(RT_CUSTOM);
|
|
|
|
// Clear all
|
|
m_pCHelper->ClearRestrictions();
|
|
|
|
// for all possible restrictions
|
|
for (iRestrict = 1; iRestrict <= m_pCHelper->RestrictionCount(); iRestrict++)
|
|
{
|
|
// If this restriction isn't supported then don't test it
|
|
if (!m_pCHelper->IsSupportedRestriction(iRestrict))
|
|
continue;
|
|
|
|
// Get the max length for this restriction
|
|
cchRestrictionMax = m_pCHelper->GetRestrictionMaxLength(iRestrict);
|
|
|
|
// If the length is CCHMAXLENGTH_UNKNOWN, then the restriction does not have a max length OR
|
|
// the max length is unknown
|
|
if (cchRestrictionMax == CCHMAXLENGTH_UNKNOWN)
|
|
continue;
|
|
|
|
// Set restriction to a valid value
|
|
m_pCHelper->SetValidRestriction(iRestrict);
|
|
|
|
pVariant = m_pCHelper->GetRestrictPtr(iRestrict);
|
|
|
|
TESTC(pVariant != NULL);
|
|
|
|
// Create a recursive variant
|
|
V_VT(pVariant) = VT_VARIANT;
|
|
V_VT(pvVar) = VT_VARIANT;
|
|
V_VARIANTREF(pVariant) = pvVar;
|
|
V_VARIANTREF(pvVar) = pVariant;
|
|
|
|
// Over-ride the row count expected, we MUST get 0 rows
|
|
m_pCHelper->SetRowCount(EXACT_VALUE, 0);
|
|
|
|
// Get the rowset
|
|
TESTC_(m_pCHelper->GetRowsetHelper(), E_INVALIDARG);
|
|
|
|
// Clear the bogus restriction
|
|
m_pCHelper->ClearRestrictions();
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
// VariantClear(pVariant); Don't need to clear the variant as it's owned by the helper class
|
|
m_pCHelper->SetRowCount(MIN_VALUE, 1);
|
|
m_pCHelper->SetRestrictionArray(RT_SUPPORTED);
|
|
|
|
return fResult;}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(46)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Security: Use unclosed quote in restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_46()
|
|
{
|
|
BOOL fResult = FALSE;
|
|
ULONG iRestrict;
|
|
VARIANT * pVariant = NULL;
|
|
ULONG cchRestrictionMax = 0;
|
|
BSTR bstrMaxRestriction = NULL;
|
|
LPWSTR pwszMaxRestriction = NULL;
|
|
HRESULT hr = E_NOINTERFACE;
|
|
|
|
if (!m_pCHelper->IsSupported())
|
|
{
|
|
odtLog << L"Schema not supported.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
|
|
// Use custom restrictions
|
|
m_pCHelper->SetRestrictionArray(RT_CUSTOM);
|
|
|
|
// Clear all
|
|
m_pCHelper->ClearRestrictions();
|
|
|
|
// for all possible restrictions
|
|
for (iRestrict = 1; iRestrict <= m_pCHelper->RestrictionCount(); iRestrict++)
|
|
{
|
|
// If this restriction isn't supported then don't test it
|
|
if (!m_pCHelper->IsSupportedRestriction(iRestrict))
|
|
continue;
|
|
|
|
// Get the max length for this restriction
|
|
cchRestrictionMax = m_pCHelper->GetRestrictionMaxLength(iRestrict);
|
|
|
|
// If the length is CCHMAXLENGTH_UNKNOWN, then the restriction does not have a max length OR
|
|
// the max length is unknown
|
|
if (cchRestrictionMax == CCHMAXLENGTH_UNKNOWN)
|
|
continue;
|
|
|
|
// Set restriction to a valid value
|
|
m_pCHelper->SetValidRestriction(iRestrict);
|
|
|
|
pVariant = m_pCHelper->GetRestrictPtr(iRestrict);
|
|
|
|
TESTC(pVariant != NULL);
|
|
|
|
// We don't care about non-BSTR restrictions
|
|
if (V_VT(pVariant) != VT_BSTR)
|
|
continue;
|
|
|
|
// Create a restriction value of the appropriate size
|
|
bstrMaxRestriction = SysAllocStringLen(NULL, cchRestrictionMax+1);
|
|
TESTC(bstrMaxRestriction != NULL);
|
|
|
|
memset(bstrMaxRestriction, 1, cchRestrictionMax*sizeof(WCHAR));
|
|
bstrMaxRestriction[cchRestrictionMax] = L'\0';
|
|
|
|
// Put an unclosed quote in the string restriction
|
|
wcsncpy(bstrMaxRestriction, L"'", wcslen(L"'"));
|
|
|
|
VariantClear(pVariant);
|
|
|
|
V_VT(pVariant) = VT_BSTR;
|
|
V_BSTR(pVariant) = bstrMaxRestriction;
|
|
bstrMaxRestriction = NULL; // Because the Variant now owns the BSTR.
|
|
|
|
// Over-ride the row count expected, we MUST get 0 rows
|
|
m_pCHelper->SetRowCount(EXACT_VALUE, 0);
|
|
|
|
// Get the rowset. May be empty rowset or a provider specific error
|
|
hr = m_pCHelper->GetRowsetHelper();
|
|
|
|
TEST2C_(hr, S_OK, E_FAIL);
|
|
|
|
// Clear the bogus restriction
|
|
m_pCHelper->ClearRestrictions();
|
|
}
|
|
|
|
fResult = TRUE;
|
|
|
|
CLEANUP:
|
|
|
|
// VariantClear(pVariant); Don't need to clear the variant as it's owned by the helper class
|
|
m_pCHelper->SetRowCount(MIN_VALUE, 1);
|
|
m_pCHelper->SetRestrictionArray(RT_SUPPORTED);
|
|
|
|
return fResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(47)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Synonyms: Use table synonym in table restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_47()
|
|
{
|
|
// No synonym support yet
|
|
return TEST_SKIPPED;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(48)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Synonyms: Use SYNONYM in table type restriction
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_48()
|
|
{
|
|
// No synonym support yet
|
|
return TEST_SKIPPED;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(49)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Synonyms: Use synonym for table name restriction and SYNONYM in table type restriction.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_49()
|
|
{
|
|
// No synonym support yet
|
|
return TEST_SKIPPED;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(50)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Security: SQLBU #363546: Use max size string restriction of closing square brackets
|
|
// This testing is needed because we internally escape the closing ] and if we don't properly
|
|
// keep track it will overflow buffers.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_50()
|
|
{
|
|
odtLog << L"This variation only supported against SQLNCLI.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(51)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Security: SQLBU #363546: Use extremely large string restriction of closing square brackets
|
|
// This testing is needed because we internally escape the closing ] and if we don't properly
|
|
// keep track it will overflow buffers.
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_51()
|
|
{
|
|
odtLog << L"This variation only supported against SQLNCLI.\n";
|
|
return TEST_SKIPPED;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(52)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc SQLBU #395368: Use a sortid that does not have a SQL collation
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CCommon::Variation_52()
|
|
{
|
|
return TEST_SKIPPED;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL CCommon::Terminate()
|
|
{
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
SAFE_DELETE(m_pCHelper);
|
|
return(CSchemaTest::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(CGetSchema)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: CGetSchema - test IDBSchemaRowset::GetSchemas
|
|
//| Created: 09/23/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL CGetSchema::Init()
|
|
{
|
|
// DON'T need restrictions in order to test schema
|
|
m_fDontCaptureRestrictions = TRUE;
|
|
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
if(CSchemaTest::Init())
|
|
// }}
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc E_INVALIDARG: pcSchemas = NULL
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CGetSchema::Variation_1()
|
|
{
|
|
INIT
|
|
|
|
GUID * rgSchemas=NULL;
|
|
ULONG cSchemas=0;
|
|
ULONG * rgRestrictionSupport=NULL;
|
|
|
|
// test method
|
|
if(CHECK(m_HR = m_pIDBSchemaRowset->GetSchemas(NULL,&rgSchemas,&rgRestrictionSupport),E_INVALIDARG))
|
|
m_fResult = TEST_PASS;
|
|
|
|
if((!COMPARE(rgRestrictionSupport,NULL)) ||
|
|
(!COMPARE(rgSchemas,NULL)))
|
|
m_fResult = TEST_FAIL;
|
|
|
|
FREE
|
|
|
|
return m_fResult;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: *prgSchemas = NULL, pcSchemas = 0
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CGetSchema::Variation_2()
|
|
{
|
|
INIT
|
|
|
|
GUID * rgSchemas=NULL;
|
|
ULONG cSchemas=0;
|
|
ULONG * rgRestrictionSupport=NULL;
|
|
|
|
// test method
|
|
if(CHECK(m_HR = m_pIDBSchemaRowset->GetSchemas(&cSchemas,&rgSchemas,&rgRestrictionSupport),S_OK))
|
|
m_fResult = TEST_PASS;
|
|
|
|
// Free the memory
|
|
PROVIDER_FREE(rgSchemas);
|
|
PROVIDER_FREE(rgRestrictionSupport);
|
|
|
|
// free the array
|
|
FREE
|
|
|
|
return m_fResult;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: prgRestrictionSupported = NULL
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CGetSchema::Variation_3()
|
|
{
|
|
INIT
|
|
|
|
GUID * rgSchemas=NULL;
|
|
ULONG cSchemas=0;
|
|
ULONG * rgRestrictionSupport=NULL;
|
|
|
|
m_fResult = TEST_FAIL;
|
|
|
|
// test method
|
|
if (m_ulOLEDBVer >= VER_25)
|
|
{
|
|
TESTC_(m_HR = m_pIDBSchemaRowset->GetSchemas(&cSchemas,&rgSchemas,NULL),S_OK);
|
|
|
|
// If we got S_OK then the following must be true
|
|
TESTC(cSchemas > 0);
|
|
TESTC(rgSchemas != NULL);
|
|
}
|
|
else
|
|
{
|
|
// Older providers return E_INVALIDARG
|
|
TESTC_(m_HR = m_pIDBSchemaRowset->GetSchemas(&cSchemas,&rgSchemas,NULL),E_INVALIDARG);
|
|
TESTC(cSchemas == 0);
|
|
TESTC(rgSchemas == NULL);
|
|
}
|
|
|
|
m_fResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
SAFE_FREE(rgSchemas);
|
|
|
|
// free the array
|
|
FREE
|
|
|
|
return m_fResult;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc E_INVALIDARG: prgSchemas = NULL
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CGetSchema::Variation_4()
|
|
{
|
|
INIT
|
|
|
|
GUID * rgSchemas=NULL;
|
|
ULONG cSchemas=0;
|
|
ULONG * rgRestrictionSupport=NULL;
|
|
|
|
// test method
|
|
if(CHECK(m_HR = m_pIDBSchemaRowset->GetSchemas(&cSchemas,NULL,&rgRestrictionSupport),E_INVALIDARG))
|
|
m_fResult = TEST_PASS;
|
|
|
|
if((!COMPARE(cSchemas,0)) ||
|
|
(!COMPARE(rgRestrictionSupport,NULL)))
|
|
m_fResult = TEST_FAIL;
|
|
|
|
FREE
|
|
|
|
return m_fResult;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: open schema rowset, try to open rowset from command object
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CGetSchema::Variation_5()
|
|
{
|
|
INIT
|
|
|
|
GUID * rgSchemas=NULL;
|
|
ULONG cSchemas=0;
|
|
ULONG * rgRestrictionSupport=NULL;
|
|
ULONG ulIndex=0;
|
|
IUnknown * pICommandRowset=NULL;
|
|
ICommandText * pICommandText=NULL;
|
|
WCHAR * pSQLText=NULL;
|
|
IDBCreateCommand * pIDBCreateCommand=NULL;
|
|
|
|
// test method
|
|
if(CHECK(m_HR = m_pIDBSchemaRowset->GetSchemas(&cSchemas,&rgSchemas,&rgRestrictionSupport),S_OK))
|
|
m_fResult = TEST_PASS;
|
|
|
|
if(m_pIDBCreateCommand)
|
|
{
|
|
if(!CHECK(m_pIDBCreateCommand->CreateCommand(NULL,IID_ICommandText,(IUnknown**)&pICommandText),S_OK))
|
|
return TEST_FAIL;
|
|
}
|
|
else
|
|
{
|
|
// Check to see if commands are supported
|
|
if(!VerifyInterface(m_pIOpenRowset, IID_IDBCreateCommand,
|
|
SESSION_INTERFACE, (IUnknown**)&pIDBCreateCommand))
|
|
goto CLEANUP;
|
|
|
|
if(!CHECK(pIDBCreateCommand->CreateCommand(NULL,IID_ICommandText,(IUnknown**)&pICommandText),S_OK))
|
|
{
|
|
m_cErrors++;
|
|
goto CLEANUP;
|
|
}
|
|
}
|
|
|
|
if(!CHECK(m_pTable->CreateSQLStmt(SELECT_ALLFROMTBL,m_pTable->GetTableName(),&pSQLText,NULL,NULL),S_OK))
|
|
{
|
|
m_cErrors++;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
if(!CHECK(pICommandText->SetCommandText(DBGUID_DBSQL,pSQLText),S_OK))
|
|
{
|
|
m_cErrors++;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
|
|
if(!CHECK(pICommandText->Execute(NULL,IID_IUnknown,NULL,NULL,&pICommandRowset),S_OK))
|
|
m_cErrors++;
|
|
|
|
if(pICommandRowset)
|
|
{
|
|
pICommandRowset->Release();
|
|
pICommandRowset=NULL;
|
|
}
|
|
|
|
|
|
CLEANUP:
|
|
|
|
// Free the memory
|
|
PROVIDER_FREE(rgSchemas);
|
|
PROVIDER_FREE(rgRestrictionSupport);
|
|
PROVIDER_FREE(pSQLText);
|
|
|
|
// free the array
|
|
FREE
|
|
|
|
if(pICommandText)
|
|
pICommandText->Release();
|
|
|
|
if(pIDBCreateCommand)
|
|
pIDBCreateCommand->Release();
|
|
|
|
if(m_cErrors)
|
|
return TEST_FAIL;
|
|
else
|
|
return TEST_PASS;
|
|
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(6)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc S_OK: don't initialize variables before sending
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CGetSchema::Variation_6()
|
|
{
|
|
INIT
|
|
|
|
GUID * rgSchemas;
|
|
ULONG cSchemas;
|
|
ULONG * rgRestrictionSupport;
|
|
|
|
// test method
|
|
if(CHECK(m_HR = m_pIDBSchemaRowset->GetSchemas(&cSchemas,&rgSchemas,&rgRestrictionSupport),S_OK))
|
|
m_fResult = TEST_PASS;
|
|
|
|
for(ULONG index=0;index<cSchemas;index++)
|
|
{
|
|
TraceSchemaName(rgSchemas[index],FALSE,TRUE);
|
|
TraceRestrictions(rgRestrictions,index,NULL,TRUE);
|
|
}
|
|
|
|
// Free the memory
|
|
PROVIDER_FREE(rgSchemas);
|
|
PROVIDER_FREE(rgRestrictionSupport);
|
|
|
|
// free the array
|
|
FREE
|
|
|
|
return m_fResult;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL CGetSchema::Terminate()
|
|
{
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(CSchemaTest::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(CZombie)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: CZombie - testing IDBSchemaRowset in zombie situation
|
|
//| Created: 09/24/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL CZombie::Init()
|
|
{
|
|
// Check to see if Transactions are usable
|
|
if(!IsUsableInterface(SESSION_INTERFACE, IID_ITransactionLocal))
|
|
return TEST_SKIPPED;
|
|
|
|
// Initialize to a invalid pointer
|
|
m_pITransactionLocal = INVALID(ITransactionLocal*);
|
|
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
if(CTransaction::Init())
|
|
// }}
|
|
{
|
|
// Register Interface with Zombie
|
|
if(RegisterInterface(SESSION_INTERFACE, IID_IDBSchemaRowset,0,NULL))
|
|
{
|
|
// This is a total hack for Sql Server. They cannot create an additional connection
|
|
// within a transaction, and the privlib transaction helper functions create a rowset,
|
|
// leave it active, and then when GetRowset is called to create an additional rowset
|
|
// we need to have one more available command object. When not using an ini file this
|
|
// is done automatically the create the CTable, but if using an ini file we need to
|
|
// create the second command here.
|
|
ICommand * pICmd = m_pCTable->get_ICommandPTR();
|
|
if (!m_pIDBCreateCommand || m_pCTable->get_ICommandPTR() ||
|
|
(m_pIDBCreateCommand &&
|
|
CHECK(m_pIDBCreateCommand->CreateCommand(NULL,IID_ICommand,
|
|
(IUnknown**)&pICmd),S_OK)))
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
// Check to see if ITransaction is supported
|
|
if(!m_pITransactionLocal)
|
|
return TEST_SKIPPED;
|
|
|
|
// Clear the bad pointer value
|
|
if(m_pITransactionLocal == INVALID(ITransactionLocal*))
|
|
m_pITransactionLocal = NULL;
|
|
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestTxn
|
|
// Tests commit/abort with respect to IAccessor on commands
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CZombie::TestTxnGetRowset
|
|
(
|
|
ETXN eTxn,
|
|
BOOL fRetaining,
|
|
GUID schema
|
|
)
|
|
{
|
|
|
|
BOOL fSuccess = FALSE;
|
|
ULONG index=0;
|
|
IDBSchemaRowset * pIDBSchemaRowset=NULL;
|
|
IRowset * pIRowset=NULL;
|
|
|
|
if (!StartTransaction(SELECT_ALLFROMTBL, (IUnknown **)&pIDBSchemaRowset,
|
|
0, NULL, NULL, ISOLATIONLEVEL_READUNCOMMITTED))
|
|
goto CLEANUP;
|
|
|
|
if (eTxn == ETXN_COMMIT)
|
|
{
|
|
//Commit the transaction, with retention as specified
|
|
if(!GetCommit(fRetaining))
|
|
goto CLEANUP;
|
|
}
|
|
else
|
|
{
|
|
//Abort the transaction, with retention as specified
|
|
if(!GetAbort(fRetaining))
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Make sure everything still works after commit or abort
|
|
fSuccess = CHECK(pIDBSchemaRowset->GetRowset(
|
|
NULL,
|
|
schema,
|
|
0,
|
|
NULL,
|
|
IID_IRowset,
|
|
0,
|
|
NULL,
|
|
PPI &pIRowset),S_OK);
|
|
|
|
|
|
CLEANUP:
|
|
|
|
if(pIDBSchemaRowset)
|
|
pIDBSchemaRowset->Release();
|
|
|
|
if(pIRowset)
|
|
pIRowset->Release();
|
|
|
|
//Return code of Commit/Abort will vary depending on whether
|
|
//or not we have an open txn, so adjust accordingly
|
|
if (fRetaining)
|
|
CleanUpTransaction(S_OK);
|
|
else
|
|
CleanUpTransaction(XACT_E_NOTRANSACTION);
|
|
|
|
if (fSuccess)
|
|
return TEST_PASS;
|
|
else
|
|
return TEST_FAIL;
|
|
|
|
}
|
|
|
|
int CZombie::TestTxnGetSchemas
|
|
(
|
|
ETXN eTxn,
|
|
BOOL fRetaining
|
|
)
|
|
{
|
|
|
|
BOOL fSuccess = FALSE;
|
|
ULONG index=0;
|
|
IDBSchemaRowset * pIDBSchemaRowset=NULL;
|
|
|
|
ULONG cTxnSchemas=0;
|
|
GUID * rgTxnSchemas=NULL;
|
|
ULONG * rgTxnRestrictions=NULL;
|
|
|
|
if (!StartTransaction(SELECT_ALLFROMTBL, (IUnknown **)&pIDBSchemaRowset,
|
|
0, NULL, NULL, ISOLATIONLEVEL_READUNCOMMITTED))
|
|
goto CLEANUP;
|
|
|
|
if (eTxn == ETXN_COMMIT)
|
|
{
|
|
//Commit the transaction, with retention as specified
|
|
if(!GetCommit(fRetaining))
|
|
goto CLEANUP;
|
|
}
|
|
else
|
|
{
|
|
//Abort the transaction, with retention as specified
|
|
if(!GetAbort(fRetaining))
|
|
goto CLEANUP;
|
|
}
|
|
|
|
//Make sure everything still works after commit or abort
|
|
fSuccess = CHECK(pIDBSchemaRowset->GetSchemas(
|
|
&cTxnSchemas,&rgTxnSchemas,&rgTxnRestrictions),S_OK);
|
|
|
|
|
|
CLEANUP:
|
|
|
|
// Free the memory
|
|
PROVIDER_FREE(rgTxnSchemas);
|
|
PROVIDER_FREE(rgTxnRestrictions);
|
|
|
|
if(pIDBSchemaRowset)
|
|
pIDBSchemaRowset->Release();
|
|
|
|
|
|
//Return code of Commit/Abort will vary depending on whether
|
|
//or not we have an open txn, so adjust accordingly
|
|
if (fRetaining)
|
|
CleanUpTransaction(S_OK);
|
|
else
|
|
CleanUpTransaction(XACT_E_NOTRANSACTION);
|
|
|
|
if (fSuccess)
|
|
return TEST_PASS;
|
|
else
|
|
return TEST_FAIL;
|
|
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc GetRowset: Commit with fRetaining set to TRUE
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CZombie::Variation_1()
|
|
{
|
|
for(ULONG index=0;index<cSchemas;index++)
|
|
TestTxnGetRowset(ETXN_ABORT, TRUE,rgSchemas[index]);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc GetRowset: Commit with fRetaining set to FALSE
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CZombie::Variation_2()
|
|
{
|
|
for(ULONG index=0;index<cSchemas;index++)
|
|
{
|
|
TestTxnGetRowset(ETXN_ABORT, FALSE,rgSchemas[index]);
|
|
}
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc GetRowset: Abort with fRetaining set to TRUE
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CZombie::Variation_3()
|
|
{
|
|
for(ULONG index=0;index<cSchemas;index++)
|
|
TestTxnGetRowset(ETXN_COMMIT, TRUE, rgSchemas[index]);
|
|
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc GetRowset: Abort with fRetaining set to FALSE
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CZombie::Variation_4()
|
|
{
|
|
for(ULONG index=0;index<cSchemas;index++)
|
|
{
|
|
TestTxnGetRowset(ETXN_COMMIT, FALSE, rgSchemas[index]);
|
|
}
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc GetSchemas: Commit with fRetaining set to TRUE
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CZombie::Variation_5()
|
|
{
|
|
return TestTxnGetSchemas (ETXN_COMMIT,TRUE);
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(6)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc GetSchemas: Commit with fRetaining set to FALSE
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CZombie::Variation_6()
|
|
{
|
|
return TestTxnGetSchemas (ETXN_COMMIT,FALSE);
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(7)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc GetSchemas: Abort with fRetaining set to TRUE
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CZombie::Variation_7()
|
|
{
|
|
return TestTxnGetSchemas (ETXN_ABORT,TRUE);
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(8)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc GetSchemas: Abort with fRetaining set to FALSE
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CZombie::Variation_8()
|
|
{
|
|
return TestTxnGetSchemas (ETXN_ABORT,TRUE);
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL CZombie::Terminate()
|
|
{
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(CTransaction::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(ExtendedErrors)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: ExtendedErrors - testing extended errors on IDBSchemaRowset
|
|
//| Created: 09/24/96
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL ExtendedErrors::Init()
|
|
{
|
|
//Create an object for checking extended errors, which will use
|
|
//m_pError to increment the error count as needed.
|
|
m_pExtError = new CExtError(m_pThisTestModule->m_ProviderClsid, m_pError);
|
|
|
|
if (!m_pExtError)
|
|
return FALSE;
|
|
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
if(CSchemaTest::Init())
|
|
// }}
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
CHelper * ExtendedErrors::GetSchemaHelper(GUID guidSchema)
|
|
{
|
|
if(IsEqualGUID(DBSCHEMA_ASSERTIONS,guidSchema))
|
|
return new CAssertionsHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_CATALOGS,guidSchema))
|
|
return new CCatalogsHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_CHARACTER_SETS,guidSchema))
|
|
return new CCharacterSetsHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_CHECK_CONSTRAINTS,guidSchema))
|
|
return new CCheckConstraintsHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_CHECK_CONSTRAINTS_BY_TABLE,guidSchema))
|
|
return new CCheckConstraintsByTableHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_COLLATIONS,guidSchema))
|
|
return new CCollationsHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_COLUMN_DOMAIN_USAGE,guidSchema))
|
|
return new CColumnDomainUsageHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_COLUMN_PRIVILEGES,guidSchema))
|
|
return new CColumnPrivilegesHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_COLUMNS,guidSchema))
|
|
return new CColumnsHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_CONSTRAINT_COLUMN_USAGE,guidSchema))
|
|
return new CConstraintColumnUsageHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_CONSTRAINT_TABLE_USAGE,guidSchema))
|
|
return new CConstraintTableUsageHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_FOREIGN_KEYS,guidSchema))
|
|
return new CForeignKeysHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_INDEXES,guidSchema))
|
|
return new CIndexesHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_KEY_COLUMN_USAGE,guidSchema))
|
|
return new CKeyColumnUsageHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_PRIMARY_KEYS,guidSchema))
|
|
return new CPrimaryKeysHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_PROCEDURE_COLUMNS,guidSchema))
|
|
return new CProcedureColumnsHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_PROCEDURE_PARAMETERS, guidSchema))
|
|
return new CProcedureParametersHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_PROCEDURES,guidSchema))
|
|
return new CProceduresHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_PROVIDER_TYPES,guidSchema))
|
|
return new CProviderTypesHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_REFERENTIAL_CONSTRAINTS,guidSchema))
|
|
return new CReferentialConstraintsHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_SCHEMATA,guidSchema))
|
|
return new CSchemataHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_SQL_LANGUAGES,guidSchema))
|
|
return NULL;
|
|
else if(IsEqualGUID(DBSCHEMA_STATISTICS,guidSchema))
|
|
return new CStatisticsHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_TABLES,guidSchema))
|
|
return new CTablesHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_TABLES_INFO,guidSchema))
|
|
return new CTablesInfoHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_TABLE_CONSTRAINTS,guidSchema))
|
|
return new CTableConstraintsHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_TABLE_PRIVILEGES,guidSchema))
|
|
return new CTablePrivilegesHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_TABLE_STATISTICS,guidSchema))
|
|
return new CTableStatisticsHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_TRANSLATIONS,guidSchema))
|
|
return NULL;
|
|
else if(IsEqualGUID(DBSCHEMA_TRUSTEE,guidSchema))
|
|
return new CTrusteeHelper();
|
|
else if(IsEqualGUID(DBSCHEMA_USAGE_PRIVILEGES,guidSchema))
|
|
return NULL;
|
|
else if(IsEqualGUID(DBSCHEMA_VIEW_COLUMN_USAGE,guidSchema))
|
|
return NULL;
|
|
else if(IsEqualGUID(DBSCHEMA_VIEW_TABLE_USAGE,guidSchema))
|
|
return NULL;
|
|
else if(IsEqualGUID(DBSCHEMA_VIEWS,guidSchema))
|
|
return new CViewsHelper();
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Valid GetSchemas Call with previous error object existing
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int ExtendedErrors::Variation_1()
|
|
{
|
|
INIT
|
|
|
|
GUID * rgSchemas=NULL;
|
|
ULONG cSchemas=0;
|
|
ULONG * rgRestrictionSupport=NULL;
|
|
|
|
//For each method of the interface, first create an error object on
|
|
//the current thread, try get a success from the IDBSchemaRowset method.
|
|
//We then check extended errors to verify the right extended error behavior.
|
|
|
|
m_fResult = FALSE;
|
|
|
|
//create an error object
|
|
m_pExtError->CauseError();
|
|
|
|
// test method
|
|
if(CHECK(m_HR = m_pIDBSchemaRowset->GetSchemas(&cSchemas,&rgSchemas,&rgRestrictionSupport),S_OK))
|
|
//Do extended check following GetSchemas
|
|
m_fResult = XCHECK(m_pIDBSchemaRowset, IID_IDBSchemaRowset, m_HR);
|
|
|
|
// Free the memory
|
|
PROVIDER_FREE(rgSchemas);
|
|
PROVIDER_FREE(rgRestrictionSupport);
|
|
|
|
FREE
|
|
|
|
if(m_fResult)
|
|
return TEST_PASS;
|
|
else
|
|
return TEST_FAIL;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(2)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Valid GetRowset call with previous error object existing
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int ExtendedErrors::Variation_2()
|
|
{
|
|
BOOL fResult= TRUE;
|
|
CHelper* pCHelper = NULL;
|
|
|
|
//For each method of the interface, first create an error object on
|
|
//the current thread, try get a success from the IDBSchemaRowset method.
|
|
//We then check extended errors to verify the right extended error behavior.
|
|
|
|
// for each valid schema, test method
|
|
for(ULONG ulIndex=0;ulIndex<m_cSchemasSupported;ulIndex++)
|
|
{
|
|
INIT
|
|
|
|
m_iid = IID_IRowset;
|
|
m_restrict = ZERO;
|
|
|
|
// don't need restrictions
|
|
m_fCountRestrictionsNULL = TRUE;
|
|
m_fRangeRestrictionsNULL = TRUE;
|
|
|
|
// don't need properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
// check to make sure it's a schema I want and
|
|
// get its info
|
|
if(GetSchemaInfo(SUPPORTED,ulIndex))
|
|
{
|
|
if(!m_fCaptureRestrictions)
|
|
TraceSchemaName(m_guid, FALSE,TRUE);
|
|
|
|
//create an error object
|
|
m_pExtError->CauseError();
|
|
|
|
|
|
if(fResult &= CHECK(m_HR=m_pIDBSchemaRowset->GetRowset(
|
|
m_punkOuter,
|
|
m_guid,
|
|
0,
|
|
NULL,
|
|
m_iid,
|
|
0,
|
|
0,
|
|
(IUnknown **) &m_pIRowset), S_OK))
|
|
{
|
|
//Do extended check following GetRowset
|
|
fResult &= XCHECK(m_pIDBSchemaRowset, IID_IDBSchemaRowset, m_HR);
|
|
|
|
// Get the helper object for this schema rowset
|
|
pCHelper = GetSchemaHelper(m_guid);
|
|
TESTC(pCHelper != NULL);
|
|
|
|
pCHelper->Init(this);
|
|
|
|
fResult &= pCHelper->CheckResults(m_HR, m_iid, m_pIRowset);
|
|
|
|
SAFE_DELETE(pCHelper);
|
|
}
|
|
|
|
}
|
|
FREE
|
|
}
|
|
|
|
CLEANUP:
|
|
SAFE_DELETE(pCHelper);
|
|
|
|
if(fResult)
|
|
return TEST_PASS;
|
|
else
|
|
return TEST_FAIL;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(3)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Valid GetSchemas call with previous error object existing
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int ExtendedErrors::Variation_3()
|
|
{
|
|
INIT
|
|
|
|
GUID * rgSchemas=NULL;
|
|
ULONG cSchemas=0;
|
|
ULONG * rgRestrictionSupport=NULL;
|
|
|
|
//For each method of the interface, first create an error object on
|
|
//the current thread, try get a failure from the IDBSchemaRowset method.
|
|
//We then check extended errors to verify the right extended error behavior.
|
|
|
|
m_fResult = FALSE;
|
|
|
|
//create an error object
|
|
m_pExtError->CauseError();
|
|
|
|
// test method
|
|
if(CHECK(m_HR = m_pIDBSchemaRowset->GetSchemas(NULL,&rgSchemas,&rgRestrictionSupport),E_INVALIDARG))
|
|
//Do extended check following GetSchemas
|
|
m_fResult = XCHECK(m_pIDBSchemaRowset, IID_IDBSchemaRowset, m_HR);
|
|
|
|
if((!COMPARE(rgRestrictionSupport,NULL)) ||
|
|
(!COMPARE(rgSchemas,NULL)))
|
|
m_fResult &= FALSE;
|
|
|
|
FREE
|
|
|
|
if(m_fResult)
|
|
return TEST_PASS;
|
|
else
|
|
return TEST_FAIL;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(4)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Invalid GetRowset call with previous error object existing
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int ExtendedErrors::Variation_4()
|
|
{
|
|
//first create an error object on the current thread, try get a failure from
|
|
//the IDBSchemaRowset method. We then check extended errors to verify the
|
|
//right extended error behavior.
|
|
|
|
INIT
|
|
|
|
m_fResult = FALSE;
|
|
|
|
m_iid = IID_IRowset;
|
|
m_guid = DBPROPSET_ROWSET;
|
|
|
|
// no restrictions
|
|
m_fCountRestrictionsNULL = TRUE;
|
|
m_fRangeRestrictionsNULL = TRUE;
|
|
|
|
// no properties
|
|
m_fCountPropSetNULL = TRUE;
|
|
m_fRangePropSetNULL = TRUE;
|
|
|
|
//create an error object
|
|
m_pExtError->CauseError();
|
|
|
|
//invalid m_guid
|
|
if(CHECK(m_HR=m_pIDBSchemaRowset->GetRowset(
|
|
m_punkOuter,
|
|
m_guid,
|
|
0,
|
|
NULL,
|
|
m_iid,
|
|
0,
|
|
0,
|
|
(IUnknown **) &m_pIRowset), E_INVALIDARG))
|
|
|
|
//Do extended check following GetRowset
|
|
m_fResult = XCHECK(m_pIDBSchemaRowset, IID_IDBSchemaRowset, m_HR);
|
|
|
|
FREE
|
|
if(m_fResult)
|
|
return TEST_PASS;
|
|
else
|
|
return TEST_FAIL;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(5)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Invalid GetSchemas call with previous error object existing
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int ExtendedErrors::Variation_5()
|
|
{
|
|
INIT
|
|
|
|
GUID * rgSchemas=NULL;
|
|
ULONG cSchemas=0;
|
|
ULONG * rgRestrictionSupport=NULL;
|
|
|
|
//For each method of the interface, with no error object on
|
|
//the current thread, try get a failure from the IDBSchemaRowset method.
|
|
//We then check extended errors to verify the right extended error behavior.
|
|
|
|
m_fResult = FALSE;
|
|
|
|
// test method
|
|
if(CHECK(m_HR = m_pIDBSchemaRowset->GetSchemas(&cSchemas,NULL,&rgRestrictionSupport),E_INVALIDARG))
|
|
//Do extended check following GetSchemas
|
|
m_fResult = XCHECK(m_pIDBSchemaRowset, IID_IDBSchemaRowset, m_HR);
|
|
|
|
if((!COMPARE(cSchemas,0)) ||
|
|
(!COMPARE(rgRestrictionSupport,NULL)))
|
|
m_fResult &= FALSE;
|
|
|
|
FREE
|
|
|
|
if(m_fResult)
|
|
return TEST_PASS;
|
|
else
|
|
return TEST_FAIL;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(6)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Invalid GetRowset call with previous error object existing
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int ExtendedErrors::Variation_6()
|
|
{
|
|
ULONG cErrors=0;
|
|
|
|
//For each method of the interface, with no error object on
|
|
//the current thread, try get a failure from the IDBSchemaRowset method.
|
|
//We then check extended errors to verify the right extended error behavior.
|
|
|
|
for(ULONG ulIndex = 0; ulIndex < m_cSchemasSupported; ulIndex++)
|
|
{
|
|
INIT
|
|
|
|
m_iid=IID_IDBProperties;
|
|
m_restrict = ZERO;
|
|
|
|
// don't pass restrictions
|
|
m_fCountRestrictionsNULL = TRUE;
|
|
m_fRangeRestrictionsNULL = TRUE;
|
|
|
|
// don't pass restrictions
|
|
m_fCountRestrictionsNULL = TRUE;
|
|
m_fRangeRestrictionsNULL = TRUE;
|
|
|
|
// if this is a schema I want then get information for schema
|
|
if(GetSchemaInfo(SUPPORTED,ulIndex))
|
|
{
|
|
PRVTRACE(L"Before call\n");
|
|
//invalid m_iid
|
|
CHECK(m_HR=m_pIDBSchemaRowset->GetRowset(
|
|
m_punkOuter,
|
|
m_guid,
|
|
0,
|
|
0,
|
|
m_iid,
|
|
0,
|
|
0,
|
|
(IUnknown **) &m_pIRowset), E_NOINTERFACE);
|
|
//Do extended check following GetRowset
|
|
PRVTRACE(L"After call\n");
|
|
m_fResult = XCHECK(m_pIDBSchemaRowset, IID_IDBSchemaRowset, m_HR);
|
|
if(!m_fResult)
|
|
cErrors++;
|
|
|
|
}
|
|
// free rowset
|
|
FREE
|
|
}
|
|
|
|
if(cErrors)
|
|
return TEST_FAIL;
|
|
else
|
|
return TEST_PASS;
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(7)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Open schema rowset DBSCHEMA_ASSERTIONS -- E_INVALIDARG
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int ExtendedErrors::Variation_7()
|
|
{
|
|
|
|
INIT
|
|
|
|
m_fResult = FALSE;
|
|
|
|
m_iid = IID_IRowset;
|
|
|
|
//create an error object
|
|
m_pExtError->CauseError();
|
|
|
|
//invalid m_guid
|
|
if(CHECK(m_HR=m_pIDBSchemaRowset->GetRowset(
|
|
NULL,
|
|
DBSCHEMA_ASSERTIONS,
|
|
0,
|
|
NULL,
|
|
m_iid,
|
|
0,
|
|
0,
|
|
(IUnknown **) &m_pIRowset), E_INVALIDARG))
|
|
|
|
//Do extended check following GetRowset
|
|
m_fResult = XCHECK(m_pIDBSchemaRowset, IID_IDBSchemaRowset, m_HR);
|
|
|
|
FREE
|
|
if(m_fResult)
|
|
return TEST_PASS;
|
|
else
|
|
return TEST_FAIL;
|
|
|
|
|
|
}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//--------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL ExtendedErrors::Terminate()
|
|
{
|
|
//free error object
|
|
if (m_pExtError)
|
|
delete m_pExtError;
|
|
m_pExtError = NULL;
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(CSchemaTest::Terminate());
|
|
} // }}
|
|
// }}
|
|
// }}
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(CBugRegressions)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: CBugRegressions - Test case for bug regressions
|
|
//| Created: 7/2/99
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL CBugRegressions::Init()
|
|
{
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
if(CSchemaTest::Init())
|
|
// }}
|
|
{
|
|
// TO DO: Add your own code here
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc GetRowset on schema TABLES after executing RETURN statement
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CBugRegressions::Variation_1()
|
|
{
|
|
// To repro this bug we must execute a statement that just contains "RETURN".
|
|
// We can just hard-code this since it's specific to this bug.
|
|
LPWSTR pwszReturn = L"RETURN";
|
|
IRowset * pIRowset = NULL;
|
|
BOOL fResult = TEST_FAIL;
|
|
|
|
// Must have commands
|
|
if(!(m_pTable->get_ICommandPTR()))
|
|
return TEST_SKIPPED;
|
|
|
|
// Execute the RETURN statement. This may not be supported, so don't check return
|
|
// code.
|
|
m_pTable->BuildCommand(pwszReturn, // SQL STMT
|
|
IID_IRowset, EXECUTE_ALWAYS, 0, NULL, NULL, NULL, (IUnknown **)&pIRowset);
|
|
|
|
// Shouldn't return a rowset
|
|
TESTC(pIRowset == NULL);
|
|
|
|
// Now execute a valid statement
|
|
TESTC_(m_pTable->ExecuteCommand(SELECT_VALIDATIONORDER, IID_IRowset, NULL,
|
|
NULL, NULL, NULL, EXECUTE_IFNOERROR, 0, NULL, NULL, (IUnknown**)&pIRowset), S_OK);
|
|
|
|
TESTC(pIRowset != NULL);
|
|
|
|
// Now get schema tables with table name restriction
|
|
TESTC(TestSchemaRestrictions(DBSCHEMA_TABLES, THIRD, EXACT_VALUE, 0));
|
|
|
|
fResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
SAFE_RELEASE(pIRowset);
|
|
|
|
return fResult;
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL CBugRegressions::Terminate()
|
|
{
|
|
// TO DO: Add your own code here
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(CSchemaTest::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|
|
|
|
// {{ TCW_TC_PROTOTYPE(CTableStatistics)
|
|
//*-----------------------------------------------------------------------
|
|
//| Test Case: CTableStatistics - Test DBSCHEMA_TABLE_STATISTICS
|
|
//| Created: 11/8/1999
|
|
//*-----------------------------------------------------------------------
|
|
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Initialization Routine
|
|
//
|
|
// @rdesc TRUE or FALSE
|
|
//
|
|
BOOL CTableStatistics::Init()
|
|
{
|
|
// {{ TCW_INIT_BASECLASS_CHECK
|
|
if(CSchemaTest::Init())
|
|
// }}
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// {{ TCW_VAR_PROTOTYPE(1)
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc Validate DBPROP_OPENROWSETSUPPORT, DBPROPVAL_ORS_HISTOGRAM
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
int CTableStatistics::Variation_1()
|
|
{
|
|
BOOL fTableStats = FALSE;
|
|
BOOL fOpenRowset = FALSE;
|
|
HRESULT hrExp = S_OK;
|
|
ULONG_PTR ulTableStatistics = 0;
|
|
ULONG_PTR ulOpenRowsetSupport = 0;
|
|
BOOL fResult = TEST_FAIL;
|
|
|
|
fTableStats = GetProperty(g_propTableStatistics, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &ulTableStatistics);
|
|
|
|
// If we support the schema we should be able to get DBPROP_TABLESTATISTICS
|
|
// otherwise we could get an error.
|
|
if (!IsSchemaSupported(DBSCHEMA_TABLE_STATISTICS))
|
|
{
|
|
// GetProperty may fail if prop isn't supported.
|
|
if(fTableStats)
|
|
{
|
|
// If the prop is supported it must return no
|
|
// histogram support
|
|
TESTC(ulTableStatistics == 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TESTC(fTableStats);
|
|
|
|
// Make sure no other bits are set
|
|
TESTC((ulTableStatistics & ~(DBPROPVAL_TS_CARDINALITY | DBPROPVAL_TS_HISTOGRAM)) == 0);
|
|
}
|
|
|
|
// We should be able to get DBPROP_OPENROWSETSUPPORT
|
|
fOpenRowset = GetProperty(DBPROP_OPENROWSETSUPPORT, DBPROPSET_DATASOURCEINFO, m_pIDBInitialize, &ulOpenRowsetSupport);
|
|
|
|
// If the provider supports TABLESTATISTICS prop and DBPROPVAL_TS_HISTOGRAM we will
|
|
// require the provider to support DBPROP_OPENROWSETSUPPORT and
|
|
// DBPROPVAL_ORS_HISTOGRAM per spec
|
|
if (fTableStats && (ulTableStatistics & DBPROPVAL_TS_HISTOGRAM))
|
|
TESTC(fOpenRowset && (ulOpenRowsetSupport & DBPROPVAL_ORS_HISTOGRAM));
|
|
|
|
// If the provider supports OPENROWSETSUPPORT prop and DBPROP_ORS_HISTOGRAM
|
|
// we will require DBPROP_TABLESTATISTICS and DBPROPVAL_TS_HISTOGRAM.
|
|
if (fOpenRowset && (ulOpenRowsetSupport & DBPROPVAL_ORS_HISTOGRAM))
|
|
TESTC(fTableStats && (ulTableStatistics & DBPROPVAL_TS_HISTOGRAM));
|
|
|
|
// And if the provider does support both props the histogram bit should agree.
|
|
if (fOpenRowset && fTableStats)
|
|
{
|
|
TESTC(!(ulTableStatistics & DBPROPVAL_TS_HISTOGRAM) ==
|
|
!(ulOpenRowsetSupport & DBPROPVAL_ORS_HISTOGRAM));
|
|
}
|
|
|
|
fResult = TEST_PASS;
|
|
|
|
CLEANUP:
|
|
|
|
return fResult;
|
|
|
|
}
|
|
// }} TCW_VAR_PROTOTYPE_END
|
|
|
|
// {{ TCW_TERMINATE_METHOD
|
|
//*-----------------------------------------------------------------------
|
|
// @mfunc TestCase Termination Routine
|
|
//
|
|
// @rdesc TEST_PASS or TEST_FAIL
|
|
//
|
|
BOOL CTableStatistics::Terminate()
|
|
{
|
|
|
|
// {{ TCW_TERM_BASECLASS_CHECK2
|
|
return(CSchemaTest::Terminate());
|
|
} // }}
|
|
// }} TCW_TERMINATE_METHOD_END
|
|
// }} TCW_TC_PROTOTYPE_END
|
|
|