STEP2.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:20k
源码类别:

Windows编程

开发平台:

Visual C++

  1. //-----------------------------------------------------------------------------
  2. // Microsoft OLE DB TABLECOPY Sample
  3. // Copyright (C) 1995-1998 Microsoft Corporation
  4. //
  5. // @doc
  6. //
  7. // @module STEP2.CPP
  8. //
  9. //-----------------------------------------------------------------------------
  10. /////////////////////////////////////////////////////////////////////
  11. // Includes
  12. //
  13. /////////////////////////////////////////////////////////////////////
  14. #include "wizard.h"
  15. #include "common.h"
  16. #include "tablecopy.h"
  17. #include "table.h"
  18. /////////////////////////////////////////////////////////////////////
  19. // Defines
  20. //
  21. /////////////////////////////////////////////////////////////////////
  22. //Enum Index Header for the ListView controls
  23. enum COL_HEADERS
  24. {
  25. //IDL_INDEXES
  26. COL_INDEXNAME = 0, //IndexInfo.wszIndexName
  27. COL_INDEXCOLNAME = 1, //IndexInfo.wszColName
  28. COL_UNIQUE = 2, //IndexInfo.fUnique
  29. COL_PRIMARYKEY = 3, //IndexInfo.fIsPrimaryKey
  30. COL_COLLATION = 4, //IndexInfo.dwCollation
  31. COL_AUTOUPDATE = 5, //IndexInfo.fAutoUpdate
  32. COL_NULLS = 6, //IndexInfo.dwNulls
  33. };
  34. enum INDEX_TYPE
  35. {
  36. INDEXTYPE_INDEX = 0,
  37. INDEXTYPE_PRIMARYKEY = 1,
  38. };
  39. /////////////////////////////////////////////////////////////////////
  40. // CS2Dialog::CS2Dialog
  41. //
  42. /////////////////////////////////////////////////////////////////////
  43. CS2Dialog::CS2Dialog(HWND hWnd, HINSTANCE hInst, CTableCopy* pCTableCopy)
  44. : CDialogBase(hWnd, hInst)
  45. {
  46. ASSERT(pCTableCopy);
  47. m_pCTableCopy = pCTableCopy;
  48. }
  49. /////////////////////////////////////////////////////////////////////
  50. // CS2Dialog::~CS2Dialog
  51. //
  52. /////////////////////////////////////////////////////////////////////
  53. CS2Dialog::~CS2Dialog()
  54. {
  55. }
  56. /////////////////////////////////////////////////////////////////////////////
  57. // ULONG CS2Dialog::Display
  58. //
  59. /////////////////////////////////////////////////////////////////////////////
  60. ULONG CS2Dialog::Display()
  61. {
  62. //Create a modal dialog box
  63. return DialogBoxParam(m_hInst, MAKEINTRESOURCE(IDD_INDEX_INFO), NULL, DlgProc, (LPARAM)this);
  64. }
  65. /////////////////////////////////////////////////////////////////////
  66. // CS2Dialog::DlgProc
  67. //
  68. /////////////////////////////////////////////////////////////////////
  69. BOOL WINAPI CS2Dialog::DlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  70. {
  71. switch(msg) 
  72. {
  73. case WM_INITDIALOG:
  74. {
  75. Busy();
  76. //Store the "this" pointer, since this is a static method
  77. CS2Dialog* pThis = (CS2Dialog*)lParam;
  78. SetWindowLong(hWnd, GWL_USERDATA, (LONG)pThis);
  79. CTableCopy* pCTableCopy = pThis->m_pCTableCopy;
  80. CWizard* pCWizard = pCTableCopy->m_pCWizard;
  81. LONG iPrevStep = pCWizard->m_iPrevStep;
  82. //On INIT we know we have a valid hWnd to store
  83. CenterDialog(hWnd);
  84. pThis->m_hWnd = hWnd;
  85. pThis->InitControls();
  86. pThis->RefreshControls();
  87. pThis->ResetIndexList(GetDlgItem(hWnd, IDL_INDEXES));
  88. pCWizard->DestroyPrevStep(WIZ_STEP2);
  89. //No since in even displaying this Dialog if there
  90. //are no indexes...
  91. if(pCTableCopy->m_pCFromTable->m_cIndexes == 0)
  92. pCWizard->DisplayStep(iPrevStep==WIZ_STEP1 ? WIZ_STEP3 : WIZ_STEP1);
  93. return HANDLED_MSG;
  94. }
  95. case WM_COMMAND:
  96. {
  97. //Obtain the "this" pointer
  98. CS2Dialog* pThis = (CS2Dialog*)GetWindowLong(hWnd, GWL_USERDATA);
  99. // All buttons are handled the same way
  100. switch(GET_WM_COMMAND_ID(wParam, lParam)) 
  101. {
  102. case IDOK:
  103.                 case IDB_PREV:
  104. //Record all selected indexes
  105. Busy();
  106. pThis->RecordSelectedIndexes(GetDlgItem(hWnd, IDL_INDEXES));
  107. pThis->m_pCTableCopy->m_pCWizard->DisplayStep((GET_WM_COMMAND_ID(wParam, lParam) == IDOK) ? WIZ_STEP3 : WIZ_STEP1);
  108.                  return HANDLED_MSG;
  109. case IDCANCEL:
  110. //Record all selected indexes
  111. Busy();
  112. EndDialog(hWnd, GET_WM_COMMAND_ID(wParam, lParam));
  113.                  return HANDLED_MSG;
  114. }
  115. }
  116. }
  117. return UNHANDLED_MSG;
  118. }
  119. /////////////////////////////////////////////////////////////////////////////
  120. // BOOL CS2Dialog::InitControls
  121. //
  122. /////////////////////////////////////////////////////////////////////////////
  123. BOOL CS2Dialog::InitControls()
  124. {
  125. HWND hWndIndexes = GetDlgItem(m_hWnd, IDL_INDEXES);
  126. //Create the Index ImageList
  127. HIMAGELIST hIndexImageList = ImageList_Create(16, 16, ILC_MASK, 1, 0 );
  128. //IDI_INDEX - normal index icon
  129. HICON hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_INDEX));
  130. ImageList_AddIcon(hIndexImageList, hIcon);
  131. //IDI_PRIMARYKEY - primary key index icon
  132. hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_PRIMARYKEY));
  133. ImageList_AddIcon(hIndexImageList, hIcon);
  134. //Set image list to the Table Window 
  135. ListView_SetImageList(hWndIndexes, hIndexImageList, LVSIL_SMALL);
  136. //ListView COLUMNS
  137. LV_InsertColumn(hWndIndexes, COL_INDEXNAME, "Index");
  138. LV_InsertColumn(hWndIndexes, COL_INDEXCOLNAME, "ColName");
  139. LV_InsertColumn(hWndIndexes, COL_UNIQUE, "Unique");
  140. LV_InsertColumn(hWndIndexes, COL_PRIMARYKEY, "PrimaryKey");
  141. LV_InsertColumn(hWndIndexes, COL_COLLATION, "Collation");
  142. LV_InsertColumn(hWndIndexes, COL_AUTOUPDATE, "AutoUpdate");
  143. LV_InsertColumn(hWndIndexes, COL_NULLS, "Nulls");
  144. //AutoSize all columns
  145. for(ULONG i=0; i<=COL_NULLS; i++)
  146. SendMessage(hWndIndexes, LVM_SETCOLUMNWIDTH, (WPARAM)i, (LPARAM)LVSCW_AUTOSIZE_USEHEADER);
  147. //Use Extended ListView Styles!
  148. 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);
  149. return TRUE;
  150. }
  151. /////////////////////////////////////////////////////////////////////////////
  152. // BOOL CS2Dialog::RefreshControls
  153. //
  154. /////////////////////////////////////////////////////////////////////////////
  155. BOOL CS2Dialog::RefreshControls()
  156. {
  157. BOOL fSchemas = m_pCTableCopy->m_pCFromTable->m_pCDataSource->m_pIDBSchemaRowset != NULL;
  158. //Display IndexWindow if there are on Schemas
  159. EnableWindow(GetDlgItem(m_hWnd, IDT_INDEXMSG), fSchemas);
  160. EnableWindow(GetDlgItem(m_hWnd, IDL_INDEXES), fSchemas);
  161. return TRUE;
  162. }
  163. /////////////////////////////////////////////////////////////////////////////
  164. // BOOL CS2Dialog::ResetIndexList
  165. //
  166. /////////////////////////////////////////////////////////////////////////////
  167. BOOL CS2Dialog::ResetIndexList(HWND hWnd)
  168. {
  169. HRESULT hr;
  170. CHAR szBuffer[MAX_NAME_LEN*2];
  171. HROW* rghRows = NULL;
  172. ULONG i,cRowsObtained = 0;
  173. IRowset* pIRowset = NULL;
  174. IAccessor* pIAccessor = NULL;
  175. HACCESSOR hAccessor = DB_NULL_HACCESSOR;
  176. //Use the passed in Session interface
  177. CTable* pCFromTable = m_pCTableCopy->m_pCFromTable;
  178. IOpenRowset* pIOpenRowset = pCFromTable->m_pCDataSource->m_pIOpenRowset;
  179. IDBSchemaRowset* pIDBSchemaRowset = pCFromTable->m_pCDataSource->m_pIDBSchemaRowset;
  180. //Provider doesn't have to support IDBSchemaRowset
  181. if(pIDBSchemaRowset == NULL)
  182. {
  183. return TRUE;
  184. }
  185. //Save the currently selected indexes
  186. ULONG cSelIndexes = pCFromTable->m_cIndexes;
  187. INDEXINFO* rgSelIndexInfo = pCFromTable->m_rgIndexInfo;
  188. //Reset the current IndexInfo
  189. pCFromTable->m_cIndexes = 0;
  190. pCFromTable->m_rgIndexInfo = NULL;
  191. // Now make the call
  192. SendMessage(hWnd, LVM_DELETEALLITEMS, (WPARAM)0, (LPARAM)0);
  193. // Bind the user and table name for the list
  194. const static ULONG cBindings = 13;
  195. const static DBBINDING rgBindings[cBindings] = 
  196. {
  197. //INDEX_NAME
  198. 6,  
  199. offsetof(INDEXINFO, wszIndexName),
  200. 0,
  201. 0,
  202. NULL,
  203. NULL, 
  204. NULL,
  205. DBPART_VALUE,
  206. DBMEMOWNER_CLIENTOWNED,
  207. DBPARAMIO_NOTPARAM, 
  208. MAX_NAME_LEN, 
  209. 0, 
  210. DBTYPE_WSTR, 
  211. 0,
  212. 0, 
  213. //UNIQUE
  214. 8,  
  215. offsetof(INDEXINFO, fUnique),
  216. 0,
  217. 0,
  218. NULL,
  219. NULL, 
  220. NULL,
  221. DBPART_VALUE,
  222. DBMEMOWNER_CLIENTOWNED,
  223. DBPARAMIO_NOTPARAM, 
  224. sizeof(VARIANT_BOOL), 
  225. 0, 
  226. DBTYPE_BOOL, 
  227. 0,
  228. 0, 
  229. //CLUSTERED
  230. 9,  
  231. offsetof(INDEXINFO, fClustered),
  232. 0,
  233. 0,
  234. NULL,
  235. NULL, 
  236. NULL,
  237. DBPART_VALUE,
  238. DBMEMOWNER_CLIENTOWNED,
  239. DBPARAMIO_NOTPARAM, 
  240. sizeof(VARIANT_BOOL), 
  241. 0, 
  242. DBTYPE_BOOL, 
  243. 0,
  244. 0, 
  245. //TYPE
  246. 10,  
  247. offsetof(INDEXINFO, wType),
  248. 0,
  249. 0,
  250. NULL,
  251. NULL, 
  252. NULL,
  253. DBPART_VALUE,
  254. DBMEMOWNER_CLIENTOWNED,
  255. DBPARAMIO_NOTPARAM, 
  256. sizeof(DBTYPE), 
  257. 0, 
  258. DBTYPE_UI2, 
  259. 0,
  260. 0, 
  261. //FILL_FACTOR
  262. 11,  
  263. offsetof(INDEXINFO, dwFillFactor),
  264. 0,
  265. 0,
  266. NULL,
  267. NULL, 
  268. NULL,
  269. DBPART_VALUE,
  270. DBMEMOWNER_CLIENTOWNED,
  271. DBPARAMIO_NOTPARAM, 
  272. sizeof(LONG), 
  273. 0, 
  274. DBTYPE_I4, 
  275. 0,
  276. 0, 
  277. //INITIAL_SIZE
  278. 12,  
  279. offsetof(INDEXINFO, dwInitialSize),
  280. 0,
  281. 0,
  282. NULL,
  283. NULL, 
  284. NULL,
  285. DBPART_VALUE,
  286. DBMEMOWNER_CLIENTOWNED,
  287. DBPARAMIO_NOTPARAM, 
  288. sizeof(LONG), 
  289. 0, 
  290. DBTYPE_I4, 
  291. 0,
  292. 0, 
  293. //NULLS
  294. 13,  
  295. offsetof(INDEXINFO, dwNulls),
  296. 0,
  297. 0,
  298. NULL,
  299. NULL, 
  300. NULL,
  301. DBPART_VALUE,
  302. DBMEMOWNER_CLIENTOWNED,
  303. DBPARAMIO_NOTPARAM, 
  304. sizeof(LONG), 
  305. 0, 
  306. DBTYPE_I4, 
  307. 0,
  308. 0, 
  309. //SORT_BOOKMARKS
  310. 14,  
  311. offsetof(INDEXINFO, fSortBookmarks),
  312. 0,
  313. 0,
  314. NULL,
  315. NULL, 
  316. NULL,
  317. DBPART_VALUE,
  318. DBMEMOWNER_CLIENTOWNED,
  319. DBPARAMIO_NOTPARAM, 
  320. sizeof(VARIANT_BOOL), 
  321. 0, 
  322. DBTYPE_BOOL, 
  323. 0,
  324. 0, 
  325. //AUTO_UPDATE
  326. 15,  
  327. offsetof(INDEXINFO, fAutoUpdate),
  328. 0,
  329. 0,
  330. NULL,
  331. NULL, 
  332. NULL,
  333. DBPART_VALUE,
  334. DBMEMOWNER_CLIENTOWNED,
  335. DBPARAMIO_NOTPARAM, 
  336. sizeof(VARIANT_BOOL), 
  337. 0, 
  338. DBTYPE_BOOL, 
  339. 0,
  340. 0, 
  341. //NULL_COLLATION
  342. 16,  
  343. offsetof(INDEXINFO, dwNullCollation),
  344. 0,
  345. 0,
  346. NULL,
  347. NULL, 
  348. NULL,
  349. DBPART_VALUE,
  350. DBMEMOWNER_CLIENTOWNED,
  351. DBPARAMIO_NOTPARAM, 
  352. sizeof(LONG), 
  353. 0, 
  354. DBTYPE_I4, 
  355. 0,
  356. 0, 
  357. //ORDINAL_POSITION
  358. 17,  
  359. offsetof(INDEXINFO, iOrdinal),
  360. 0,
  361. 0,
  362. NULL,
  363. NULL, 
  364. NULL,
  365. DBPART_VALUE,
  366. DBMEMOWNER_CLIENTOWNED,
  367. DBPARAMIO_NOTPARAM, 
  368. sizeof(ULONG), 
  369. 0, 
  370. DBTYPE_UI4, 
  371. 0,
  372. 0, 
  373. //COLUMN_NAME
  374. 18,  
  375. offsetof(INDEXINFO, wszColName),
  376. 0,
  377. 0,
  378. NULL,
  379. NULL, 
  380. NULL,
  381. DBPART_VALUE,
  382. DBMEMOWNER_CLIENTOWNED,
  383. DBPARAMIO_NOTPARAM, 
  384. MAX_NAME_LEN, 
  385. 0, 
  386. DBTYPE_WSTR, 
  387. 0,
  388. 0, 
  389. //COLLATION
  390. 21,  
  391. offsetof(INDEXINFO, dwCollation),
  392. 0,
  393. 0,
  394. NULL,
  395. NULL, 
  396. NULL,
  397. DBPART_VALUE, 
  398. DBMEMOWNER_CLIENTOWNED,
  399. DBPARAMIO_NOTPARAM, 
  400. sizeof(DWORD), 
  401. 0, 
  402. DBTYPE_I4, 
  403. 0,
  404. 0, 
  405. };
  406. //set up the restrictions
  407. const ULONG cRestrictions = 5;
  408. VARIANT  rgRestrictions[cRestrictions];
  409. //set up the restrictions
  410. InitVariants(cRestrictions, rgRestrictions);
  411. SetRestriction(&rgRestrictions[0], pCFromTable->m_pCDataSource->m_pwszCatalog);
  412. SetRestriction(&rgRestrictions[1], pCFromTable->m_TableInfo.wszSchemaName);
  413. SetRestriction(&rgRestrictions[4], pCFromTable->m_TableInfo.wszTableName);
  414. //GetRowset
  415. //DBSCHEMA_INDEXES may not be supported by the driver. 
  416. //If an error occurs, just don't display IndexInfo
  417. QTESTC(hr = pIDBSchemaRowset->GetRowset(NULL, DBSCHEMA_INDEXES, cRestrictions, rgRestrictions, 
  418. IID_IRowset, 0, NULL, (IUnknown **)&pIRowset));
  419. XTESTC(hr = pIRowset->QueryInterface(IID_IAccessor, (void **)&pIAccessor));
  420. //Create Accessor for IndexInfo
  421. XTESTC(hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, cBindings, rgBindings, 0, &hAccessor, NULL));
  422. while(TRUE)
  423. {
  424. XTESTC(hr = pIRowset->GetNextRows(NULL, 0, MAX_BLOCK_SIZE, &cRowsObtained, &rghRows));
  425. //ENDOFROWSET
  426. if(cRowsObtained==0) 
  427. break;
  428. //Realloc Table struct for Indexes
  429. SAFE_REALLOC(pCFromTable->m_rgIndexInfo, INDEXINFO, pCFromTable->m_cIndexes + cRowsObtained);
  430. memset(&pCFromTable->m_rgIndexInfo[pCFromTable->m_cIndexes], 0, cRowsObtained*sizeof(INDEXINFO));
  431. //Loop over rows obtained
  432. for(ULONG i=0; i<cRowsObtained; i++) 
  433. {
  434. INDEXINFO* pIndexInfo = &pCFromTable->m_rgIndexInfo[pCFromTable->m_cIndexes];
  435. //Get the Data
  436. XTESTC(hr = pIRowset->GetData(rghRows[i], hAccessor, (void*)pIndexInfo));
  437. //If this is an index the ordinal will be 1 based
  438. if(pIndexInfo->iOrdinal==0)
  439. continue;
  440. //Only list the index if the column was selected to be copied
  441. for(ULONG iCol=0; iCol<pCFromTable->m_cColumns; iCol++)
  442. {
  443. if(wcscmp(pCFromTable->m_rgColDesc[iCol].wszColName, pIndexInfo->wszColName)==0)
  444. {
  445. //Now that we have an actual index...
  446. pCFromTable->m_cIndexes++;
  447. break;
  448. }
  449. }
  450. }
  451. //Release all the rows
  452. XTESTC(hr = pIRowset->ReleaseRows(cRowsObtained, rghRows, NULL, NULL, NULL));
  453. SAFE_FREE(rghRows);
  454. }
  455. //GetPrimaryKey info
  456. //Since DBSCHEMA_INDEXES doesn't have to return PrimaryKey info correctly (NULL)
  457. //we will call DBSCHEMA_PRIMARYKEYS before displaying IndexInfo to make sure
  458. //which columns are really PrimaryKeys.
  459. GetPrimaryKeys();
  460. //Now list all indexes to the Index ListView window
  461. for(i=0; i<pCFromTable->m_cIndexes; i++)
  462. {
  463. INDEXINFO* pIndexInfo = &pCFromTable->m_rgIndexInfo[i];
  464. //INDEXNAME (item)
  465. ConvertToMBCS(pIndexInfo->wszIndexName, szBuffer, MAX_NAME_LEN);
  466. LV_InsertItem(hWnd, i, COL_INDEXNAME, szBuffer, 0, pIndexInfo->fIsPrimaryKey ? INDEXTYPE_PRIMARYKEY : INDEXTYPE_INDEX);
  467. //INDEXCOLNAME (subitem)
  468. ConvertToMBCS(pIndexInfo->wszColName, szBuffer, MAX_NAME_LEN);
  469. LV_InsertItem(hWnd, i, COL_INDEXCOLNAME, szBuffer);
  470. //FLAGS (subitem)
  471. LV_InsertItem(hWnd, i, COL_UNIQUE, pIndexInfo->fUnique ? "TRUE" : "FALSE");
  472. LV_InsertItem(hWnd, i, COL_PRIMARYKEY, pIndexInfo->fIsPrimaryKey ? "TRUE" : "FALSE");
  473. LV_InsertItem(hWnd, i, COL_AUTOUPDATE, pIndexInfo->fAutoUpdate ? "TRUE" : "FALSE");
  474. LV_InsertItem(hWnd, i, COL_COLLATION, (pIndexInfo->dwCollation == DB_COLLATION_ASC) ? "ASC" : (pIndexInfo->dwCollation == DB_COLLATION_DESC) ? "DESC" : "NULL");
  475. LV_InsertItem(hWnd, i, COL_NULLS, (pIndexInfo->dwNulls == DBPROPVAL_IN_DISALLOWNULL) ? "DISALLOWNULL" : (pIndexInfo->dwNulls == DBPROPVAL_IN_IGNORENULL) ? "IGNORENULL" : "IGNOREANYNULL");
  476. }
  477. // If there was a previous selection, select it again on Back
  478. if(rgSelIndexInfo)
  479. {
  480. LONG lFoundIndex = -1;
  481. for(i=0; i<cSelIndexes; i++)
  482. {
  483. //Find the "index" of the existing index
  484. ConvertToMBCS(rgSelIndexInfo[i].wszIndexName, szBuffer, MAX_NAME_LEN);
  485. lFoundIndex = LV_FindItem(hWnd, szBuffer, lFoundIndex);
  486.      //If there was a selection, select it now
  487.      if(lFoundIndex != LVM_ERR)
  488. {
  489. LV_SetItemState(hWnd, lFoundIndex, COL_INDEXNAME, LVIS_SELECTED, LVIS_SELECTED);
  490. //Ensure that the first item is visible
  491. if(i==0)
  492. SendMessage(hWnd, LVM_ENSUREVISIBLE, (WPARAM)lFoundIndex, (LPARAM)FALSE);
  493. }
  494. }
  495. }    
  496. //Otherwise select all as default
  497. else 
  498. {
  499. for(i=0; i<pCFromTable->m_cIndexes; i++)
  500. LV_SetItemState(hWnd, i, COL_INDEXNAME, LVIS_SELECTED, LVIS_SELECTED);
  501. }
  502. //Only enable the ListBox/Title if there are indexes
  503. EnableWindow(GetDlgItem(m_hWnd, IDT_INDEXMSG), pCFromTable->m_cIndexes);
  504. EnableWindow(hWnd, pCFromTable->m_cIndexes);
  505.     //AutoSize Index/ColName
  506. if(pCFromTable->m_cIndexes)
  507. {
  508. SendMessage(hWnd, LVM_SETCOLUMNWIDTH, (WPARAM)COL_INDEXNAME, (LPARAM)LVSCW_AUTOSIZE);
  509. SendMessage(hWnd, LVM_SETCOLUMNWIDTH, (WPARAM)COL_INDEXCOLNAME, (LPARAM)LVSCW_AUTOSIZE);
  510. }
  511. CLEANUP:
  512. //Free Resriticions
  513. FreeVariants(cRestrictions, rgRestrictions);
  514. if(hAccessor && pIAccessor)
  515. XTEST(pIAccessor->ReleaseAccessor(hAccessor,NULL));
  516. SAFE_RELEASE(pIRowset);
  517. SAFE_RELEASE(pIAccessor);
  518. SAFE_FREE(rghRows);
  519. SAFE_FREE(rgSelIndexInfo);
  520. return hr==S_OK;
  521. }
  522. /////////////////////////////////////////////////////////////////////////////
  523. // BOOL CS2Dialog::GetPrimaryKeys
  524. //
  525. /////////////////////////////////////////////////////////////////////////////
  526. BOOL CS2Dialog::GetPrimaryKeys()
  527. {
  528. HRESULT hr;
  529. HROW* rghRows = NULL;
  530. ULONG cRowsObtained = 0;
  531. IRowset* pIRowset = NULL;
  532. IAccessor* pIAccessor = NULL;
  533. HACCESSOR hAccessor = DB_NULL_HACCESSOR;
  534. PRIMARYKEY PrimaryKey;
  535. //Use the passed in Session interface
  536. CTable* pCFromTable = m_pCTableCopy->m_pCFromTable;
  537. IOpenRowset* pIOpenRowset = pCFromTable->m_pCDataSource->m_pIOpenRowset;
  538. IDBSchemaRowset* pIDBSchemaRowset = pCFromTable->m_pCDataSource->m_pIDBSchemaRowset;
  539. //Provider doesn't have to support IDBSchemaRowset
  540. if(pIDBSchemaRowset == NULL)
  541. return TRUE;
  542. // Bind the user and table name for the list
  543. const static ULONG cBindings = 1;
  544. const static DBBINDING rgBindings[cBindings] = 
  545. {
  546. 4,  
  547. offsetof(PRIMARYKEY, wszColName),
  548. 0,
  549. 0,
  550. NULL,
  551. NULL, 
  552. NULL,
  553. DBPART_VALUE,
  554. DBMEMOWNER_CLIENTOWNED,
  555. DBPARAMIO_NOTPARAM, 
  556. MAX_NAME_LEN, 
  557. 0, 
  558. DBTYPE_WSTR, 
  559. 0,
  560. 0, 
  561. };
  562. //set up the restrictions
  563. const ULONG cRestrictions = 3;
  564. VARIANT  rgRestrictions[cRestrictions];
  565. //set up the restrictions
  566. InitVariants(cRestrictions, rgRestrictions);
  567. SetRestriction(&rgRestrictions[0], pCFromTable->m_pCDataSource->m_pwszCatalog);
  568. SetRestriction(&rgRestrictions[1], pCFromTable->m_TableInfo.wszSchemaName);
  569. SetRestriction(&rgRestrictions[2], pCFromTable->m_TableInfo.wszTableName);
  570. //GetRowset
  571. //DBSCHEMA_PRIMARY_KEYS may not be supported by the driver. 
  572. //If an error occurs, just don't display PrimaryKey info
  573. QTESTC(hr = pIDBSchemaRowset->GetRowset(NULL, DBSCHEMA_PRIMARY_KEYS, cRestrictions, rgRestrictions, 
  574. IID_IRowset, 0, NULL, (IUnknown **)&pIRowset));
  575. XTESTC(hr = pIRowset->QueryInterface(IID_IAccessor, (void **)&pIAccessor));
  576. //Create Accessor for IndexInfo
  577. XTESTC(hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, cBindings, rgBindings, 0, &hAccessor, NULL));
  578. while(TRUE)
  579. {
  580. XTESTC(hr = pIRowset->GetNextRows(NULL, 0, MAX_BLOCK_SIZE, &cRowsObtained, &rghRows));
  581. //ENDOFROWSET
  582. if(cRowsObtained==0)
  583. break;
  584. for(ULONG i=0; i<cRowsObtained; i++) 
  585. {
  586. //Reset the PrimaryKey
  587. memset(&PrimaryKey, 0, sizeof(PRIMARYKEY));
  588. //Get the Data
  589. XTESTC(hr = pIRowset->GetData(rghRows[i], hAccessor, (void*)&PrimaryKey));
  590. //Need to find the corresponding column in IndexInfo and 
  591. //mark it as a primary key column
  592. for(ULONG iIndex=0; iIndex<pCFromTable->m_cIndexes; iIndex++)
  593. if(wcscmp(PrimaryKey.wszColName, pCFromTable->m_rgIndexInfo[iIndex].wszColName)==0)
  594. pCFromTable->m_rgIndexInfo[iIndex].fIsPrimaryKey = TRUE;
  595. //Need to find the corresponding column in m_rgColDesc and mark it as a primary key column
  596. for(i=0; i<pCFromTable->m_cColumns; i++)
  597. if(wcscmp(PrimaryKey.wszColName, pCFromTable->m_rgColDesc[i].wszColName)==0)
  598. pCFromTable->m_rgColDesc[i].fIsPrimaryKey = TRUE;
  599. }
  600. //Release all the rows
  601. XTESTC(hr = pIRowset->ReleaseRows(cRowsObtained, rghRows, NULL, NULL, NULL));
  602. SAFE_FREE(rghRows);
  603. }
  604. CLEANUP:
  605. //Free Resriticions
  606. FreeVariants(cRestrictions, rgRestrictions);
  607. if(hAccessor && pIAccessor)
  608. XTEST(pIAccessor->ReleaseAccessor(hAccessor,NULL));
  609. SAFE_RELEASE(pIRowset);
  610. SAFE_RELEASE(pIAccessor);
  611. SAFE_FREE(rghRows);
  612. return hr==S_OK;
  613. }
  614. /////////////////////////////////////////////////////////////////////////////
  615. // BOOL CS2Dialog::RecordSelectedIndexes
  616. //
  617. /////////////////////////////////////////////////////////////////////////////
  618. BOOL CS2Dialog::RecordSelectedIndexes(HWND hWnd)
  619. {
  620. CTable* pCTable = m_pCTableCopy->m_pCFromTable;
  621. LONG i;
  622. // Get the count of selected items
  623. LONG cSelIndexes = SendMessage(hWnd, LVM_GETSELECTEDCOUNT, (WPARAM)0, (LPARAM)0);
  624. LONG iIndex = -1;
  625. //Loop over all the indexes
  626. pCTable->m_cIndexes = cSelIndexes;
  627. for(i=0; i<cSelIndexes; i++) 
  628. {
  629. iIndex = SendMessage(hWnd, LVM_GETNEXTITEM, (WPARAM)iIndex, (LPARAM)LVNI_SELECTED);
  630. //"compact" the m_rgColDesc array to only the selected items
  631. if(iIndex != LVM_ERR)
  632. memmove(&pCTable->m_rgIndexInfo[i], &pCTable->m_rgIndexInfo[iIndex], sizeof(INDEXINFO));
  633. }
  634. return TRUE;
  635. }