753 lines
20 KiB
C++
753 lines
20 KiB
C++
//-----------------------------------------------------------------------------
|
|
// Microsoft OLE DB TABLECOPY Sample
|
|
// Copyright (C) 1991-2000 Microsoft Corporation
|
|
//
|
|
// @doc
|
|
//
|
|
// @module STEP2.CPP
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Includes
|
|
//
|
|
/////////////////////////////////////////////////////////////////////
|
|
#include "wizard.h"
|
|
#include "common.h"
|
|
#include "tablecopy.h"
|
|
#include "table.h"
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// Defines
|
|
//
|
|
/////////////////////////////////////////////////////////////////////
|
|
//Enum Index Header for the ListView controls
|
|
enum COL_HEADERS
|
|
{
|
|
//IDL_INDEXES
|
|
COL_INDEXNAME = 0, //IndexInfo.wszIndexName
|
|
COL_INDEXCOLNAME = 1, //IndexInfo.wszColName
|
|
COL_UNIQUE = 2, //IndexInfo.fUnique
|
|
COL_PRIMARYKEY = 3, //IndexInfo.fIsPrimaryKey
|
|
COL_COLLATION = 4, //IndexInfo.dwCollation
|
|
COL_AUTOUPDATE = 5, //IndexInfo.fAutoUpdate
|
|
COL_NULLS = 6, //IndexInfo.dwNulls
|
|
};
|
|
|
|
enum INDEX_TYPE
|
|
{
|
|
INDEXTYPE_INDEX = 0,
|
|
INDEXTYPE_PRIMARYKEY = 1,
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// CS2Dialog::CS2Dialog
|
|
//
|
|
/////////////////////////////////////////////////////////////////////
|
|
CS2Dialog::CS2Dialog(HWND hWnd, HINSTANCE hInst, CTableCopy* pCTableCopy)
|
|
: CDialogBase(hWnd, hInst)
|
|
{
|
|
ASSERT(pCTableCopy);
|
|
m_pCTableCopy = pCTableCopy;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// CS2Dialog::~CS2Dialog
|
|
//
|
|
/////////////////////////////////////////////////////////////////////
|
|
CS2Dialog::~CS2Dialog()
|
|
{
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// ULONG CS2Dialog::Display
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
INT_PTR CS2Dialog::Display()
|
|
{
|
|
//Create a modal dialog box
|
|
return DialogBoxParam(m_hInst, MAKEINTRESOURCE(IDD_INDEX_INFO), NULL, (DLGPROC)DlgProc, (LPARAM)this);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////
|
|
// CS2Dialog::DlgProc
|
|
//
|
|
/////////////////////////////////////////////////////////////////////
|
|
BOOL WINAPI CS2Dialog::DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch(msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
Busy();
|
|
//Store the "this" pointer, since this is a static method
|
|
CS2Dialog* pThis = (CS2Dialog*)lParam;
|
|
SetWindowLongPtrA(hWnd, GWLP_USERDATA, (LONG_PTR)pThis);
|
|
CTableCopy* pCTableCopy = pThis->m_pCTableCopy;
|
|
CWizard* pCWizard = pCTableCopy->m_pCWizard;
|
|
|
|
LONG iPrevStep = pCWizard->m_iPrevStep;
|
|
|
|
//On INIT we know we have a valid hWnd to store
|
|
CenterDialog(hWnd);
|
|
pThis->m_hWnd = hWnd;
|
|
|
|
pThis->InitControls();
|
|
pThis->RefreshControls();
|
|
|
|
pThis->ResetIndexList(GetDlgItem(hWnd, IDL_INDEXES));
|
|
pCWizard->DestroyPrevStep(WIZ_STEP2);
|
|
|
|
//No since in even displaying this Dialog if there
|
|
//are no indexes...
|
|
if(pCTableCopy->m_pCFromTable->m_cIndexes == 0)
|
|
pCWizard->DisplayStep(iPrevStep==WIZ_STEP1 ? WIZ_STEP3 : WIZ_STEP1);
|
|
|
|
return HANDLED_MSG;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
//Obtain the "this" pointer
|
|
CS2Dialog* pThis = (CS2Dialog*)GetWindowLongPtrA(hWnd, GWLP_USERDATA);
|
|
|
|
// All buttons are handled the same way
|
|
switch(GET_WM_COMMAND_ID(wParam, lParam))
|
|
{
|
|
case IDOK:
|
|
case IDB_PREV:
|
|
//Record all selected indexes
|
|
Busy();
|
|
pThis->RecordSelectedIndexes(GetDlgItem(hWnd, IDL_INDEXES));
|
|
pThis->m_pCTableCopy->m_pCWizard->DisplayStep((GET_WM_COMMAND_ID(wParam, lParam) == IDOK) ? WIZ_STEP3 : WIZ_STEP1);
|
|
return HANDLED_MSG;
|
|
|
|
case IDCANCEL:
|
|
//Record all selected indexes
|
|
Busy();
|
|
EndDialog(hWnd, GET_WM_COMMAND_ID(wParam, lParam));
|
|
return HANDLED_MSG;
|
|
}
|
|
}
|
|
}
|
|
|
|
return UNHANDLED_MSG;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// BOOL CS2Dialog::InitControls
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CS2Dialog::InitControls()
|
|
{
|
|
HWND hWndIndexes = GetDlgItem(m_hWnd, IDL_INDEXES);
|
|
|
|
//Create the Index ImageList
|
|
HIMAGELIST hIndexImageList = ImageList_Create(16, 16, ILC_MASK, 1, 0 );
|
|
|
|
//IDI_INDEX - normal index icon
|
|
HICON hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_INDEX));
|
|
ImageList_AddIcon(hIndexImageList, hIcon);
|
|
//IDI_PRIMARYKEY - primary key index icon
|
|
hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_PRIMARYKEY));
|
|
ImageList_AddIcon(hIndexImageList, hIcon);
|
|
|
|
//Set image list to the Table Window
|
|
ListView_SetImageList(hWndIndexes, hIndexImageList, LVSIL_SMALL);
|
|
|
|
//ListView COLUMNS
|
|
LV_InsertColumn(hWndIndexes, COL_INDEXNAME, "Index");
|
|
LV_InsertColumn(hWndIndexes, COL_INDEXCOLNAME, "ColName");
|
|
LV_InsertColumn(hWndIndexes, COL_UNIQUE, "Unique");
|
|
LV_InsertColumn(hWndIndexes, COL_PRIMARYKEY, "PrimaryKey");
|
|
LV_InsertColumn(hWndIndexes, COL_COLLATION, "Collation");
|
|
LV_InsertColumn(hWndIndexes, COL_AUTOUPDATE, "AutoUpdate");
|
|
LV_InsertColumn(hWndIndexes, COL_NULLS, "Nulls");
|
|
|
|
//AutoSize all columns
|
|
for(ULONG i=0; i<=COL_NULLS; i++)
|
|
SendMessage(hWndIndexes, LVM_SETCOLUMNWIDTH, (WPARAM)i, (LPARAM)LVSCW_AUTOSIZE_USEHEADER);
|
|
|
|
//Use Extended ListView Styles!
|
|
SendMessage(hWndIndexes, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_SUBITEMIMAGES, LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TWOCLICKACTIVATE | LVS_EX_SUBITEMIMAGES);
|
|
return TRUE;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// BOOL CS2Dialog::RefreshControls
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CS2Dialog::RefreshControls()
|
|
{
|
|
BOOL fSchemas = m_pCTableCopy->m_pCFromTable->m_pCDataSource->m_pIDBSchemaRowset != NULL;
|
|
|
|
//Display IndexWindow if there are on Schemas
|
|
EnableWindow(GetDlgItem(m_hWnd, IDT_INDEXMSG), fSchemas);
|
|
EnableWindow(GetDlgItem(m_hWnd, IDL_INDEXES), fSchemas);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// BOOL CS2Dialog::ResetIndexList
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CS2Dialog::ResetIndexList(HWND hWnd)
|
|
{
|
|
HRESULT hr;
|
|
CHAR szBuffer[MAX_NAME_LEN*2];
|
|
|
|
HROW* rghRows = NULL;
|
|
ULONG i;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
IRowset* pIRowset = NULL;
|
|
|
|
IAccessor* pIAccessor = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
|
|
//Use the passed in Session interface
|
|
CTable* pCFromTable = m_pCTableCopy->m_pCFromTable;
|
|
IOpenRowset* pIOpenRowset = pCFromTable->m_pCDataSource->m_pIOpenRowset;
|
|
IDBSchemaRowset* pIDBSchemaRowset = pCFromTable->m_pCDataSource->m_pIDBSchemaRowset;
|
|
|
|
//Provider doesn't have to support IDBSchemaRowset
|
|
if(pIDBSchemaRowset == NULL)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
//Save the currently selected indexes
|
|
ULONG cSelIndexes = pCFromTable->m_cIndexes;
|
|
INDEXINFO* rgSelIndexInfo = pCFromTable->m_rgIndexInfo;
|
|
|
|
//Reset the current IndexInfo
|
|
pCFromTable->m_cIndexes = 0;
|
|
pCFromTable->m_rgIndexInfo = NULL;
|
|
|
|
// Now make the call
|
|
SendMessage(hWnd, LVM_DELETEALLITEMS, (WPARAM)0, (LPARAM)0);
|
|
|
|
// Bind the user and table name for the list
|
|
const static ULONG cBindings = 13;
|
|
const static DBBINDING rgBindings[cBindings] =
|
|
{
|
|
//INDEX_NAME
|
|
6,
|
|
offsetof(INDEXINFO, wszIndexName),
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DBPART_VALUE,
|
|
DBMEMOWNER_CLIENTOWNED,
|
|
DBPARAMIO_NOTPARAM,
|
|
MAX_NAME_LEN,
|
|
0,
|
|
DBTYPE_WSTR,
|
|
0,
|
|
0,
|
|
|
|
//UNIQUE
|
|
8,
|
|
offsetof(INDEXINFO, fUnique),
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DBPART_VALUE,
|
|
DBMEMOWNER_CLIENTOWNED,
|
|
DBPARAMIO_NOTPARAM,
|
|
sizeof(VARIANT_BOOL),
|
|
0,
|
|
DBTYPE_BOOL,
|
|
0,
|
|
0,
|
|
|
|
//CLUSTERED
|
|
9,
|
|
offsetof(INDEXINFO, fClustered),
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DBPART_VALUE,
|
|
DBMEMOWNER_CLIENTOWNED,
|
|
DBPARAMIO_NOTPARAM,
|
|
sizeof(VARIANT_BOOL),
|
|
0,
|
|
DBTYPE_BOOL,
|
|
0,
|
|
0,
|
|
|
|
//TYPE
|
|
10,
|
|
offsetof(INDEXINFO, wType),
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DBPART_VALUE,
|
|
DBMEMOWNER_CLIENTOWNED,
|
|
DBPARAMIO_NOTPARAM,
|
|
sizeof(DBTYPE),
|
|
0,
|
|
DBTYPE_UI2,
|
|
0,
|
|
0,
|
|
|
|
//FILL_FACTOR
|
|
11,
|
|
offsetof(INDEXINFO, dwFillFactor),
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DBPART_VALUE,
|
|
DBMEMOWNER_CLIENTOWNED,
|
|
DBPARAMIO_NOTPARAM,
|
|
sizeof(LONG),
|
|
0,
|
|
DBTYPE_I4,
|
|
0,
|
|
0,
|
|
|
|
//INITIAL_SIZE
|
|
12,
|
|
offsetof(INDEXINFO, dwInitialSize),
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DBPART_VALUE,
|
|
DBMEMOWNER_CLIENTOWNED,
|
|
DBPARAMIO_NOTPARAM,
|
|
sizeof(LONG),
|
|
0,
|
|
DBTYPE_I4,
|
|
0,
|
|
0,
|
|
|
|
//NULLS
|
|
13,
|
|
offsetof(INDEXINFO, dwNulls),
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DBPART_VALUE,
|
|
DBMEMOWNER_CLIENTOWNED,
|
|
DBPARAMIO_NOTPARAM,
|
|
sizeof(LONG),
|
|
0,
|
|
DBTYPE_I4,
|
|
0,
|
|
0,
|
|
|
|
//SORT_BOOKMARKS
|
|
14,
|
|
offsetof(INDEXINFO, fSortBookmarks),
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DBPART_VALUE,
|
|
DBMEMOWNER_CLIENTOWNED,
|
|
DBPARAMIO_NOTPARAM,
|
|
sizeof(VARIANT_BOOL),
|
|
0,
|
|
DBTYPE_BOOL,
|
|
0,
|
|
0,
|
|
|
|
//AUTO_UPDATE
|
|
15,
|
|
offsetof(INDEXINFO, fAutoUpdate),
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DBPART_VALUE,
|
|
DBMEMOWNER_CLIENTOWNED,
|
|
DBPARAMIO_NOTPARAM,
|
|
sizeof(VARIANT_BOOL),
|
|
0,
|
|
DBTYPE_BOOL,
|
|
0,
|
|
0,
|
|
|
|
//NULL_COLLATION
|
|
16,
|
|
offsetof(INDEXINFO, dwNullCollation),
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DBPART_VALUE,
|
|
DBMEMOWNER_CLIENTOWNED,
|
|
DBPARAMIO_NOTPARAM,
|
|
sizeof(LONG),
|
|
0,
|
|
DBTYPE_I4,
|
|
0,
|
|
0,
|
|
|
|
//ORDINAL_POSITION
|
|
17,
|
|
offsetof(INDEXINFO, iOrdinal),
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DBPART_VALUE,
|
|
DBMEMOWNER_CLIENTOWNED,
|
|
DBPARAMIO_NOTPARAM,
|
|
sizeof(ULONG),
|
|
0,
|
|
DBTYPE_UI4,
|
|
0,
|
|
0,
|
|
|
|
//COLUMN_NAME
|
|
18,
|
|
offsetof(INDEXINFO, wszColName),
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DBPART_VALUE,
|
|
DBMEMOWNER_CLIENTOWNED,
|
|
DBPARAMIO_NOTPARAM,
|
|
MAX_NAME_LEN,
|
|
0,
|
|
DBTYPE_WSTR,
|
|
0,
|
|
0,
|
|
|
|
//COLLATION
|
|
21,
|
|
offsetof(INDEXINFO, dwCollation),
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DBPART_VALUE,
|
|
DBMEMOWNER_CLIENTOWNED,
|
|
DBPARAMIO_NOTPARAM,
|
|
sizeof(DWORD),
|
|
0,
|
|
DBTYPE_I4,
|
|
0,
|
|
0,
|
|
};
|
|
|
|
//set up the restrictions
|
|
const ULONG cRestrictions = 5;
|
|
VARIANT rgRestrictions[cRestrictions];
|
|
|
|
//set up the restrictions
|
|
InitVariants(cRestrictions, rgRestrictions);
|
|
SetRestriction(&rgRestrictions[0], pCFromTable->m_pCDataSource->m_pwszCatalog);
|
|
SetRestriction(&rgRestrictions[1], pCFromTable->m_TableInfo.wszSchemaName);
|
|
SetRestriction(&rgRestrictions[4], pCFromTable->m_TableInfo.wszTableName);
|
|
|
|
//GetRowset
|
|
//DBSCHEMA_INDEXES may not be supported by the driver.
|
|
//If an error occurs, just don't display IndexInfo
|
|
QTESTC(hr = pIDBSchemaRowset->GetRowset(NULL, DBSCHEMA_INDEXES, cRestrictions, rgRestrictions,
|
|
IID_IRowset, 0, NULL, (IUnknown **)&pIRowset));
|
|
|
|
XTESTC(hr = pIRowset->QueryInterface(IID_IAccessor, (void **)&pIAccessor));
|
|
|
|
//Create Accessor for IndexInfo
|
|
XTESTC(hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, cBindings, rgBindings, 0, &hAccessor, NULL));
|
|
|
|
while(TRUE)
|
|
{
|
|
XTESTC(hr = pIRowset->GetNextRows(NULL, 0, MAX_BLOCK_SIZE, &cRowsObtained, &rghRows));
|
|
|
|
//ENDOFROWSET
|
|
if(cRowsObtained==0)
|
|
break;
|
|
|
|
//Realloc Table struct for Indexes
|
|
SAFE_REALLOC(pCFromTable->m_rgIndexInfo, INDEXINFO, pCFromTable->m_cIndexes + cRowsObtained);
|
|
memset(&pCFromTable->m_rgIndexInfo[pCFromTable->m_cIndexes], 0, cRowsObtained*sizeof(INDEXINFO));
|
|
|
|
//Loop over rows obtained
|
|
for(ULONG i=0; i<cRowsObtained; i++)
|
|
{
|
|
INDEXINFO* pIndexInfo = &pCFromTable->m_rgIndexInfo[pCFromTable->m_cIndexes];
|
|
|
|
//Get the Data
|
|
XTESTC(hr = pIRowset->GetData(rghRows[i], hAccessor, (void*)pIndexInfo));
|
|
|
|
//If this is an index the ordinal will be 1 based
|
|
if(pIndexInfo->iOrdinal==0)
|
|
continue;
|
|
|
|
//Only list the index if the column was selected to be copied
|
|
for(ULONG iCol=0; iCol<pCFromTable->m_cColumns; iCol++)
|
|
{
|
|
if(wcscmp(pCFromTable->m_rgColDesc[iCol].wszColName, pIndexInfo->wszColName)==0)
|
|
{
|
|
//Now that we have an actual index...
|
|
pCFromTable->m_cIndexes++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//Release all the rows
|
|
XTESTC(hr = pIRowset->ReleaseRows(cRowsObtained, rghRows, NULL, NULL, NULL));
|
|
SAFE_FREE(rghRows);
|
|
}
|
|
|
|
//GetPrimaryKey info
|
|
//Since DBSCHEMA_INDEXES doesn't have to return PrimaryKey info correctly (NULL)
|
|
//we will call DBSCHEMA_PRIMARYKEYS before displaying IndexInfo to make sure
|
|
//which columns are really PrimaryKeys.
|
|
GetPrimaryKeys();
|
|
|
|
//Now list all indexes to the Index ListView window
|
|
for(i=0; i<pCFromTable->m_cIndexes; i++)
|
|
{
|
|
INDEXINFO* pIndexInfo = &pCFromTable->m_rgIndexInfo[i];
|
|
|
|
//INDEXNAME (item)
|
|
ConvertToMBCS(pIndexInfo->wszIndexName, szBuffer, MAX_NAME_LEN);
|
|
LV_InsertItem(hWnd, i, COL_INDEXNAME, szBuffer, 0, pIndexInfo->fIsPrimaryKey ? INDEXTYPE_PRIMARYKEY : INDEXTYPE_INDEX);
|
|
|
|
//INDEXCOLNAME (subitem)
|
|
ConvertToMBCS(pIndexInfo->wszColName, szBuffer, MAX_NAME_LEN);
|
|
LV_InsertItem(hWnd, i, COL_INDEXCOLNAME, szBuffer);
|
|
|
|
//FLAGS (subitem)
|
|
LV_InsertItem(hWnd, i, COL_UNIQUE, pIndexInfo->fUnique ? "TRUE" : "FALSE");
|
|
LV_InsertItem(hWnd, i, COL_PRIMARYKEY, pIndexInfo->fIsPrimaryKey ? "TRUE" : "FALSE");
|
|
LV_InsertItem(hWnd, i, COL_AUTOUPDATE, pIndexInfo->fAutoUpdate ? "TRUE" : "FALSE");
|
|
LV_InsertItem(hWnd, i, COL_COLLATION, (pIndexInfo->dwCollation == DB_COLLATION_ASC) ? "ASC" : (pIndexInfo->dwCollation == DB_COLLATION_DESC) ? "DESC" : "NULL");
|
|
LV_InsertItem(hWnd, i, COL_NULLS, (pIndexInfo->dwNulls == DBPROPVAL_IN_DISALLOWNULL) ? "DISALLOWNULL" : (pIndexInfo->dwNulls == DBPROPVAL_IN_IGNORENULL) ? "IGNORENULL" : "IGNOREANYNULL");
|
|
}
|
|
|
|
|
|
// If there was a previous selection, select it again on Back
|
|
if(rgSelIndexInfo)
|
|
{
|
|
LONG lFoundIndex = -1;
|
|
for(i=0; i<cSelIndexes; i++)
|
|
{
|
|
//Find the "index" of the existing index
|
|
ConvertToMBCS(rgSelIndexInfo[i].wszIndexName, szBuffer, MAX_NAME_LEN);
|
|
lFoundIndex = LV_FindItem(hWnd, szBuffer, lFoundIndex);
|
|
|
|
//If there was a selection, select it now
|
|
if(lFoundIndex != LVM_ERR)
|
|
{
|
|
LV_SetItemState(hWnd, lFoundIndex, COL_INDEXNAME, LVIS_SELECTED, LVIS_SELECTED);
|
|
|
|
//Ensure that the first item is visible
|
|
if(i==0)
|
|
SendMessage(hWnd, LVM_ENSUREVISIBLE, (WPARAM)lFoundIndex, (LPARAM)FALSE);
|
|
}
|
|
}
|
|
|
|
}
|
|
//Otherwise select all as default
|
|
else
|
|
{
|
|
for(i=0; i<pCFromTable->m_cIndexes; i++)
|
|
LV_SetItemState(hWnd, i, COL_INDEXNAME, LVIS_SELECTED, LVIS_SELECTED);
|
|
}
|
|
|
|
//Only enable the ListBox/Title if there are indexes
|
|
EnableWindow(GetDlgItem(m_hWnd, IDT_INDEXMSG), pCFromTable->m_cIndexes);
|
|
EnableWindow(hWnd, pCFromTable->m_cIndexes);
|
|
|
|
//AutoSize Index/ColName
|
|
if(pCFromTable->m_cIndexes)
|
|
{
|
|
SendMessage(hWnd, LVM_SETCOLUMNWIDTH, (WPARAM)COL_INDEXNAME, (LPARAM)LVSCW_AUTOSIZE);
|
|
SendMessage(hWnd, LVM_SETCOLUMNWIDTH, (WPARAM)COL_INDEXCOLNAME, (LPARAM)LVSCW_AUTOSIZE);
|
|
}
|
|
|
|
CLEANUP:
|
|
//Free Resriticions
|
|
FreeVariants(cRestrictions, rgRestrictions);
|
|
|
|
if(hAccessor && pIAccessor)
|
|
XTEST(pIAccessor->ReleaseAccessor(hAccessor,NULL));
|
|
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIAccessor);
|
|
SAFE_FREE(rghRows);
|
|
SAFE_FREE(rgSelIndexInfo);
|
|
return hr==S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// BOOL CS2Dialog::GetPrimaryKeys
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CS2Dialog::GetPrimaryKeys()
|
|
{
|
|
HRESULT hr;
|
|
|
|
HROW* rghRows = NULL;
|
|
DBCOUNTITEM cRowsObtained = 0;
|
|
IRowset* pIRowset = NULL;
|
|
|
|
IAccessor* pIAccessor = NULL;
|
|
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
|
|
|
|
PRIMARYKEY PrimaryKey;
|
|
|
|
//Use the passed in Session interface
|
|
CTable* pCFromTable = m_pCTableCopy->m_pCFromTable;
|
|
IOpenRowset* pIOpenRowset = pCFromTable->m_pCDataSource->m_pIOpenRowset;
|
|
IDBSchemaRowset* pIDBSchemaRowset = pCFromTable->m_pCDataSource->m_pIDBSchemaRowset;
|
|
|
|
//Provider doesn't have to support IDBSchemaRowset
|
|
if(pIDBSchemaRowset == NULL)
|
|
return TRUE;
|
|
|
|
// Bind the user and table name for the list
|
|
const static ULONG cBindings = 1;
|
|
const static DBBINDING rgBindings[cBindings] =
|
|
{
|
|
4,
|
|
offsetof(PRIMARYKEY, wszColName),
|
|
0,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
DBPART_VALUE,
|
|
DBMEMOWNER_CLIENTOWNED,
|
|
DBPARAMIO_NOTPARAM,
|
|
MAX_NAME_LEN,
|
|
0,
|
|
DBTYPE_WSTR,
|
|
0,
|
|
0,
|
|
};
|
|
|
|
//set up the restrictions
|
|
const ULONG cRestrictions = 3;
|
|
VARIANT rgRestrictions[cRestrictions];
|
|
|
|
//set up the restrictions
|
|
InitVariants(cRestrictions, rgRestrictions);
|
|
SetRestriction(&rgRestrictions[0], pCFromTable->m_pCDataSource->m_pwszCatalog);
|
|
SetRestriction(&rgRestrictions[1], pCFromTable->m_TableInfo.wszSchemaName);
|
|
SetRestriction(&rgRestrictions[2], pCFromTable->m_TableInfo.wszTableName);
|
|
|
|
//GetRowset
|
|
//DBSCHEMA_PRIMARY_KEYS may not be supported by the driver.
|
|
//If an error occurs, just don't display PrimaryKey info
|
|
QTESTC(hr = pIDBSchemaRowset->GetRowset(NULL, DBSCHEMA_PRIMARY_KEYS, cRestrictions, rgRestrictions,
|
|
IID_IRowset, 0, NULL, (IUnknown **)&pIRowset));
|
|
|
|
XTESTC(hr = pIRowset->QueryInterface(IID_IAccessor, (void **)&pIAccessor));
|
|
|
|
//Create Accessor for IndexInfo
|
|
XTESTC(hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, cBindings, rgBindings, 0, &hAccessor, NULL));
|
|
|
|
while(TRUE)
|
|
{
|
|
XTESTC(hr = pIRowset->GetNextRows(NULL, 0, MAX_BLOCK_SIZE, &cRowsObtained, &rghRows));
|
|
|
|
//ENDOFROWSET
|
|
if(cRowsObtained==0)
|
|
break;
|
|
|
|
for(ULONG i=0; i<cRowsObtained; i++)
|
|
{
|
|
//Reset the PrimaryKey
|
|
memset(&PrimaryKey, 0, sizeof(PRIMARYKEY));
|
|
|
|
//Get the Data
|
|
XTESTC(hr = pIRowset->GetData(rghRows[i], hAccessor, (void*)&PrimaryKey));
|
|
|
|
//Need to find the corresponding column in IndexInfo and
|
|
//mark it as a primary key column
|
|
for(ULONG iIndex=0; iIndex<pCFromTable->m_cIndexes; iIndex++)
|
|
if(wcscmp(PrimaryKey.wszColName, pCFromTable->m_rgIndexInfo[iIndex].wszColName)==0)
|
|
pCFromTable->m_rgIndexInfo[iIndex].fIsPrimaryKey = TRUE;
|
|
|
|
//Need to find the corresponding column in m_rgColDesc and mark it as a primary key column
|
|
for(i=0; i<pCFromTable->m_cColumns; i++)
|
|
if(wcscmp(PrimaryKey.wszColName, pCFromTable->m_rgColDesc[i].wszColName)==0)
|
|
pCFromTable->m_rgColDesc[i].fIsPrimaryKey = TRUE;
|
|
}
|
|
|
|
//Release all the rows
|
|
XTESTC(hr = pIRowset->ReleaseRows(cRowsObtained, rghRows, NULL, NULL, NULL));
|
|
SAFE_FREE(rghRows);
|
|
}
|
|
|
|
CLEANUP:
|
|
//Free Resriticions
|
|
FreeVariants(cRestrictions, rgRestrictions);
|
|
|
|
if(hAccessor && pIAccessor)
|
|
XTEST(pIAccessor->ReleaseAccessor(hAccessor,NULL));
|
|
|
|
SAFE_RELEASE(pIRowset);
|
|
SAFE_RELEASE(pIAccessor);
|
|
SAFE_FREE(rghRows);
|
|
return hr==S_OK;
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// BOOL CS2Dialog::RecordSelectedIndexes
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CS2Dialog::RecordSelectedIndexes(HWND hWnd)
|
|
{
|
|
CTable* pCTable = m_pCTableCopy->m_pCFromTable;
|
|
LONG i;
|
|
|
|
// Get the count of selected items
|
|
LONG cSelIndexes = (LONG)SendMessage(hWnd, LVM_GETSELECTEDCOUNT, (WPARAM)0, (LPARAM)0);
|
|
LONG iIndex = -1;
|
|
|
|
//Loop over all the indexes
|
|
pCTable->m_cIndexes = cSelIndexes;
|
|
for(i=0; i<cSelIndexes; i++)
|
|
{
|
|
iIndex = (LONG)SendMessage(hWnd, LVM_GETNEXTITEM, (WPARAM)iIndex, (LPARAM)LVNI_SELECTED);
|
|
|
|
//"compact" the m_rgColDesc array to only the selected items
|
|
if(iIndex != LVM_ERR)
|
|
memmove(&pCTable->m_rgIndexInfo[i], &pCTable->m_rgIndexInfo[iIndex], sizeof(INDEXINFO));
|
|
}
|
|
|
|
return TRUE;
|
|
}
|