Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

560 lines
14 KiB

  1. #include "config.h"
  2. #include <string.h>
  3. #include "daedef.h"
  4. #include "pib.h"
  5. #include "util.h"
  6. #include "fmp.h"
  7. #include "page.h"
  8. #include "ssib.h"
  9. #include "fucb.h"
  10. #include "fcb.h"
  11. #include "stapi.h"
  12. #include "fdb.h"
  13. #include "idb.h"
  14. #include "fileint.h"
  15. #include "recint.h"
  16. #include "logapi.h"
  17. #include "nver.h"
  18. #include "dirapi.h"
  19. #include "recapi.h"
  20. #include "fileapi.h"
  21. #include "dbapi.h"
  22. #include "systab.h"
  23. #include "bm.h"
  24. DeclAssertFile; /* Declare file name for assert macros */
  25. #ifdef DEBUG
  26. //#define TRACE
  27. #endif
  28. //+API
  29. // ErrIsamDeleteTable
  30. // ========================================================================
  31. // ERR ErrIsamDeleteTable( PIB *ppib, ULONG_PTR vdbid, CHAR *szName )
  32. //
  33. // Calls ErrFILEIDeleteTable to
  34. // delete a file and all indexes associated with it.
  35. //
  36. // RETURNS JET_errSuccess or err from called routine.
  37. //
  38. // SEE ALSO ErrIsamCreateTable
  39. //-
  40. ERR VTAPI ErrIsamDeleteTable( PIB *ppib, ULONG_PTR vdbid, CHAR *szName )
  41. {
  42. ERR err;
  43. DBID dbid = DbidOfVDbid (vdbid);
  44. CHAR szTable[(JET_cbNameMost + 1)];
  45. OBJID objid;
  46. JET_OBJTYP objtyp;
  47. /* ensure that database is updatable
  48. /**/
  49. CallR( VDbidCheckUpdatable( vdbid ) );
  50. CheckPIB( ppib );
  51. CheckDBID( ppib, dbid );
  52. CallR( ErrCheckName( szTable, szName, (JET_cbNameMost + 1) ) );
  53. #ifdef SYSTABLES
  54. if ( FSysTabDatabase( dbid ) )
  55. {
  56. err = ErrFindObjidFromIdName( ppib, dbid, objidTblContainer, szTable, &objid, &objtyp );
  57. if ( err < 0 )
  58. {
  59. return err;
  60. }
  61. else
  62. {
  63. if ( objtyp == JET_objtypQuery || objtyp == JET_objtypLink || objtyp == JET_objtypSQLLink )
  64. {
  65. err = ErrIsamDeleteObject( (JET_SESID)ppib, vdbid, objid );
  66. return err;
  67. }
  68. }
  69. }
  70. #endif /* SYSTABLES */
  71. err = ErrFILEDeleteTable( ppib, dbid, szName );
  72. return err;
  73. }
  74. // ErrFILEDeleteTable
  75. // ========================================================================
  76. // ERR ErrFILEDeleteTable( PIB *ppib, DBID dbid, CHAR *szName )
  77. //
  78. // Deletes a file and all indexes associated with it.
  79. //
  80. // RETURNS JET_errSuccess or err from called routine.
  81. //
  82. // COMMENTS
  83. // Acquires an exclusive lock on the file [FCBSetDelete].
  84. // A transaction is wrapped around this function. Thus,
  85. // any work done will be undone if a failure occurs.
  86. // Transaction logging is turned off for temporary files.
  87. //
  88. // SEE ALSO ErrIsamCreateTable
  89. //-
  90. ERR ErrFILEDeleteTable( PIB *ppib, DBID dbid, CHAR *szTable )
  91. {
  92. ERR err;
  93. FUCB *pfucb = pfucbNil;
  94. PGNO pgnoFDP;
  95. BOOL fSetDomainOperation = fFalse;
  96. FCB *pfcb;
  97. FCB *pfcbT;
  98. CheckPIB( ppib );
  99. CheckDBID( ppib, dbid );
  100. CallR( ErrDIRBeginTransaction( ppib ) );
  101. /* open cursor on database
  102. /**/
  103. Call( ErrDIROpen( ppib, pfcbNil, dbid, &pfucb ) );
  104. /* seek to table without locking
  105. /**/
  106. Call( ErrFILESeek( pfucb, szTable ) );
  107. Assert( ppib != ppibNil );
  108. Assert( ppib->level < levelMax );
  109. Assert( PcsrCurrent( pfucb ) != pcsrNil );
  110. Assert( PcsrCurrent( pfucb )->csrstat == csrstatOnFDPNode );
  111. pgnoFDP = PcsrCurrent( pfucb )->pgno;
  112. /* abort if index is being built on file
  113. /**/
  114. if ( FFCBDenyDDL( pfucb->u.pfcb, ppib ) )
  115. {
  116. err = JET_errWriteConflict;
  117. goto HandleError;
  118. }
  119. /* get table FCB or sentinel FCB
  120. /**/
  121. pfcb = PfcbFCBGet( dbid, pgnoFDP );
  122. /* wait for other domain operation
  123. /**/
  124. while ( pfcb != pfcbNil && FFCBDomainOperation( pfcb ) )
  125. {
  126. BFSleep( cmsecWaitGeneric );
  127. pfcb = PfcbFCBGet( dbid, pgnoFDP );
  128. }
  129. if ( pfcb != pfcbNil )
  130. {
  131. FCBSetDomainOperation( pfcb );
  132. fSetDomainOperation = fTrue;
  133. }
  134. /* handle error for above call
  135. /**/
  136. Call( ErrFCBSetDeleteTable( ppib, dbid, pgnoFDP ) );
  137. if ( pfcb == pfcbNil )
  138. {
  139. pfcb = PfcbFCBGet( dbid, pgnoFDP );
  140. Assert( pfcb != pfcbNil );
  141. }
  142. FCBSetDenyDDL( pfucb->u.pfcb, ppib );
  143. err = ErrVERFlag( pfucb, operDeleteTable, &pgnoFDP, sizeof(pgnoFDP) );
  144. if ( err < 0 )
  145. {
  146. FCBResetDenyDDL( pfucb->u.pfcb );
  147. FCBResetDeleteTable( dbid, pgnoFDP );
  148. goto HandleError;
  149. }
  150. /* delete table FDP pointer node. This will recursively delete
  151. /* table and free table space. Note that table space is defer
  152. /* freed until commit to transaction level 0. This is done to
  153. /* facillitate rollback.
  154. /**/
  155. Call( ErrDIRDelete( pfucb, fDIRVersion ) );
  156. /* remove MPL entries for this table and all indexes
  157. /**/
  158. Assert( pfcb->pgnoFDP == pgnoFDP );
  159. for ( pfcbT = pfcb; pfcbT != pfcbNil; pfcbT = pfcbT->pfcbNextIndex )
  160. {
  161. Assert( dbid == pfcbT->dbid );
  162. MPLPurgeFDP( dbid, pfcbT->pgnoFDP );
  163. FCBSetDeletePending( pfcbT );
  164. }
  165. DIRClose( pfucb );
  166. pfucb = pfucbNil;
  167. #ifdef SYSTABLES
  168. /* remove table record from MSysObjects before committing.
  169. /* Also remove associated columns and indexes in MSC/MSI.
  170. /* Pass 0 for tblid; MSO case in STD figures it out.
  171. /**/
  172. if ( dbid != dbidTemp )
  173. {
  174. Call( ErrSysTabDelete( ppib, dbid, itableSo, szTable, 0 ) );
  175. }
  176. #endif /* SYSTABLES */
  177. #ifdef TRACE
  178. FPrintF2( "delete table at %d.%lu\n", pfcb->dbid, pfcb->pgnoFDP );
  179. #endif
  180. if ( fSetDomainOperation )
  181. FCBResetDomainOperation( pfcb );
  182. Call( ErrDIRCommitTransaction( ppib ) );
  183. return err;
  184. HandleError:
  185. if ( fSetDomainOperation )
  186. FCBResetDomainOperation( pfcb );
  187. if ( pfucb != pfucbNil )
  188. DIRClose( pfucb );
  189. CallS( ErrDIRRollback( ppib ) );
  190. return err;
  191. }
  192. //+API
  193. // DeleteIndex
  194. // ========================================================================
  195. // ERR DeleteIndex( PIB *ppib, FUCB *pfucb, CHAR *szIndex )
  196. //
  197. // Deletes an index definition and all index entries it contains.
  198. //
  199. // PARAMETERS ppib PIB of user
  200. // pfucb Exclusively opened FUCB on file
  201. // szName name of index to delete
  202. // RETURNS Error code from DIRMAN or
  203. // JET_errSuccess Everything worked OK.
  204. // -TableInvalid There is no file corresponding
  205. // to the file name given.
  206. // -TableNoSuchIndex There is no index corresponding
  207. // to the index name given.
  208. // -IndexMustStay The clustered index of a file may
  209. // not be deleted.
  210. // COMMENTS
  211. // There must not be anyone currently using the file.
  212. // A transaction is wrapped around this function. Thus,
  213. // any work done will be undone if a failure occurs.
  214. // Transaction logging is turned off for temporary files.
  215. // SEE ALSO DeleteTable, CreateTable, CreateIndex
  216. //-
  217. ERR VTAPI ErrIsamDeleteIndex( PIB *ppib, FUCB *pfucb, CHAR *szName )
  218. {
  219. ERR err;
  220. CHAR szIndex[ (JET_cbNameMost + 1) ];
  221. BYTE rgbIndexNorm[ JET_cbKeyMost ];
  222. DIB dib;
  223. KEY key;
  224. FCB *pfcb;
  225. FCB *pfcbIdx;
  226. CheckPIB( ppib );
  227. CheckTable( ppib, pfucb );
  228. CallR( ErrCheckName( szIndex, szName, ( JET_cbNameMost + 1 ) ) );
  229. /* ensure that table is updatable
  230. /**/
  231. CallR( FUCBCheckUpdatable( pfucb ) );
  232. Assert( ppib != ppibNil );
  233. Assert( pfucb != pfucbNil );
  234. Assert( pfucb->u.pfcb != pfcbNil );
  235. pfcb = pfucb->u.pfcb;
  236. /* wait for other domain operation
  237. /**/
  238. while ( FFCBDomainOperation( pfcb ) )
  239. {
  240. BFSleep( cmsecWaitGeneric );
  241. }
  242. FCBSetDomainOperation( pfcb );
  243. /* normalize index and set key to normalized index
  244. /**/
  245. SysNormText( szIndex, strlen( szIndex ), rgbIndexNorm, sizeof( rgbIndexNorm ), &key.cb );
  246. key.pb = rgbIndexNorm;
  247. err = ErrDIRBeginTransaction( ppib );
  248. if ( err < 0 )
  249. {
  250. FCBResetDomainOperation( pfcb );
  251. return err;
  252. }
  253. /* move to FDP root
  254. /**/
  255. DIRGotoFDPRoot( pfucb );
  256. /* down to indexes, check against clustered index name
  257. /**/
  258. dib.pos = posDown;
  259. dib.pkey = (KEY *)pkeyIndexes;
  260. dib.fFlags = fDIRNull;
  261. Call( ErrDIRDown( pfucb, &dib ) );
  262. if ( pfucb->lineData.cb != 0 &&
  263. pfucb->lineData.cb == key.cb &&
  264. memcmp( pfucb->lineData.pb, rgbIndexNorm, pfucb->lineData.cb ) == 0 )
  265. {
  266. err = JET_errIndexMustStay;
  267. goto HandleError;
  268. }
  269. /* down to index node
  270. /**/
  271. Assert( dib.pos == posDown );
  272. dib.pkey = &key;
  273. Assert( dib.fFlags == fDIRNull );
  274. Call( ErrDIRDown( pfucb, &dib ) );
  275. if ( err == wrnNDFoundLess || err == wrnNDFoundGreater )
  276. {
  277. err = JET_errIndexNotFound;
  278. goto HandleError;
  279. }
  280. /* abort if DDL is being done on file
  281. /**/
  282. if ( FFCBDenyDDL( pfcb, ppib ) )
  283. {
  284. err = JET_errWriteConflict;
  285. goto HandleError;
  286. }
  287. FCBSetDenyDDL( pfcb, ppib );
  288. /* flag delete index
  289. /**/
  290. pfcbIdx = PfcbFCBFromIndexName( pfcb, szIndex );
  291. if ( pfcbIdx == NULL )
  292. {
  293. // NOTE: This case goes away when the data structures
  294. // are versioned also.
  295. // This case means basically, that another session
  296. // has changed this index BUT has not committed to level 0
  297. // BUT has changed the RAM data structures.
  298. FCBResetDenyDDL( pfcb );
  299. err = JET_errWriteConflict;
  300. goto HandleError;
  301. }
  302. err = ErrFCBSetDeleteIndex( ppib, pfcb, szIndex );
  303. if ( err < 0 )
  304. {
  305. FCBResetDenyDDL( pfcb );
  306. goto HandleError;
  307. }
  308. err = ErrVERFlag( pfucb, operDeleteIndex, &pfcbIdx, sizeof(pfcbIdx) );
  309. if ( err < 0 )
  310. {
  311. FCBResetDeleteIndex( pfcbIdx );
  312. FCBResetDenyDDL( pfcb );
  313. goto HandleError;
  314. }
  315. /* purge MPL entries -- must be done after FCBSetDeletePending
  316. /**/
  317. MPLPurgeFDP( pfucb->dbid, pfcbIdx->pgnoFDP );
  318. /* assert not deleting current non-clustered index
  319. /**/
  320. Assert( pfucb->pfucbCurIndex == pfucbNil ||
  321. SysCmpText( szIndex, pfucb->pfucbCurIndex->u.pfcb->pidb->szName ) != 0 );
  322. /* delete index node
  323. /**/
  324. Call( ErrDIRDelete( pfucb, fDIRVersion ) );
  325. /* back up to file node
  326. /**/
  327. DIRUp( pfucb, 2 );
  328. /* update index count and DDL time stamp
  329. /**/
  330. Call( ErrFILEIUpdateFDPData( pfucb, fDropIndexCount | fDDLStamp ) );
  331. #ifdef SYSTABLES
  332. /* remove index record from MSysIndexes before committing...
  333. /**/
  334. if ( FSysTabDatabase( pfucb->dbid ) )
  335. {
  336. Call( ErrSysTabDelete( ppib, pfucb->dbid, itableSi, szIndex, pfucb->u.pfcb->pgnoFDP ) );
  337. }
  338. #endif /* SYSTABLES */
  339. Call( ErrDIRCommitTransaction( ppib ) );
  340. /* set currency to before first
  341. /**/
  342. DIRBeforeFirst( pfucb );
  343. #ifdef TRACE
  344. FPrintF2( "delete index at %d.%lu\n", pfcbIdx->dbid, pfcbIdx->pgnoFDP );
  345. #endif
  346. FCBResetDomainOperation( pfcb );
  347. return JET_errSuccess;
  348. HandleError:
  349. CallS( ErrDIRRollback( ppib ) );
  350. FCBResetDomainOperation( pfcb );
  351. return err;
  352. }
  353. ERR VTAPI ErrIsamDeleteColumn( PIB *ppib, FUCB *pfucb, CHAR *szName )
  354. {
  355. ERR err;
  356. DIB dib;
  357. INT iidxseg;
  358. KEY key;
  359. CHAR szColumn[ (JET_cbNameMost + 1) ];
  360. BYTE rgbColumnNorm[ JET_cbKeyMost ];
  361. FCB *pfcb;
  362. LINE lineField;
  363. FIELDDEFDATA fdd;
  364. FCB *pfcbIndex;
  365. CheckPIB( ppib );
  366. CheckTable( ppib, pfucb );
  367. CallR( ErrCheckName( szColumn, szName, (JET_cbNameMost + 1) ) );
  368. /* ensure that table is updatable
  369. /**/
  370. CallR( FUCBCheckUpdatable( pfucb ) );
  371. Assert( ppib != ppibNil );
  372. Assert( pfucb != pfucbNil );
  373. Assert( pfucb->u.pfcb != pfcbNil );
  374. pfcb = pfucb->u.pfcb;
  375. // if ( !( FFCBDenyReadByUs( pfcb, ppib ) ) )
  376. // return JET_errTableNotLocked;
  377. /* normalize column name and set key
  378. /**/
  379. SysNormText( szColumn, strlen( szColumn ), rgbColumnNorm, sizeof( rgbColumnNorm ), &key.cb );
  380. key.pb = rgbColumnNorm;
  381. CallR( ErrDIRBeginTransaction( ppib ) );
  382. /* abort if DDL is being done on file
  383. /**/
  384. if ( FFCBDenyDDL( pfcb, ppib ) )
  385. {
  386. err = JET_errWriteConflict;
  387. goto HandleError;
  388. }
  389. FCBSetDenyDDL( pfcb, ppib );
  390. err = ErrVERFlag( pfucb, operDeleteColumn, (VOID *)&pfcb->pfdb, sizeof(pfcb->pfdb) );
  391. if ( err < 0 )
  392. {
  393. FCBResetDenyDDL( pfcb );
  394. }
  395. /* move to FDP root and update FDP timestamp
  396. /**/
  397. DIRGotoFDPRoot( pfucb );
  398. Call( ErrFILEIUpdateFDPData( pfucb, fDDLStamp ) );
  399. /* down to fields\rgbColumnNorm to find field id (and verify existance)
  400. /**/
  401. dib.pos = posDown;
  402. dib.pkey = (KEY *)pkeyFields;
  403. dib.fFlags = fDIRNull;
  404. Call( ErrDIRDown( pfucb, &dib ) );
  405. dib.pkey = &key;
  406. err = ErrDIRDown( pfucb, &dib );
  407. if ( err != JET_errSuccess )
  408. {
  409. err = JET_errColumnNotFound;
  410. goto HandleError;
  411. }
  412. fdd = *(FIELDDEFDATA *)pfucb->lineData.pb;
  413. /* search for column in use in indexes
  414. /**/
  415. for ( pfcbIndex = pfucb->u.pfcb;
  416. pfcbIndex != pfcbNil;
  417. pfcbIndex = pfcbIndex->pfcbNextIndex )
  418. {
  419. if ( pfcbIndex->pidb != NULL )
  420. {
  421. for ( iidxseg = 0;
  422. iidxseg < pfcbIndex->pidb->iidxsegMac;
  423. iidxseg++ )
  424. {
  425. if ( pfcbIndex->pidb->rgidxseg[iidxseg] < 0 )
  426. {
  427. if ( (FID)( -pfcbIndex->pidb->rgidxseg[iidxseg] ) == fdd.fid )
  428. Call( JET_errColumnInUse );
  429. }
  430. else
  431. {
  432. if ( (FID)pfcbIndex->pidb->rgidxseg[iidxseg] == fdd.fid )
  433. Call( JET_errColumnInUse );
  434. }
  435. }
  436. }
  437. }
  438. Call( ErrDIRDelete( pfucb, fDIRVersion ) );
  439. /* if fixed field, insert a placeholder for computing offsets
  440. /**/
  441. if ( fdd.fid <= fidFixedMost )
  442. {
  443. BYTE bSav = *rgbColumnNorm;
  444. fdd.bFlags = ffieldDeleted; // flag deleted fixed field
  445. fdd.cbDefault = 0; // get rid of the default value
  446. *rgbColumnNorm = ' '; // clobber the key
  447. key.cb = 1; // (any value will work)
  448. lineField.pb = (BYTE *)&fdd; // point to the field definition
  449. lineField.cb = sizeof(fdd);
  450. /* up to the FIELDS node
  451. /**/
  452. DIRUp( pfucb, 1 );
  453. Call( ErrDIRInsert(pfucb, &lineField, &key, fDIRVersion | fDIRDuplicate ) );
  454. *rgbColumnNorm = bSav;
  455. }
  456. /* up to "FIELDS" node
  457. /**/
  458. DIRUp( pfucb, 1 );
  459. /* rebuild FDB and default record value
  460. /**/
  461. Call( ErrDIRGet( pfucb ) );
  462. Call( ErrFDBConstruct(pfucb, pfcb, fTrue /*fBuildDefault*/ ) );
  463. /* set currencies at BeforeFirst and remove unused CSR
  464. /**/
  465. DIRUp( pfucb, 1 );
  466. Assert( PcsrCurrent( pfucb ) != pcsrNil );
  467. PcsrCurrent( pfucb )->csrstat = csrstatBeforeFirst;
  468. if ( pfucb->pfucbCurIndex != pfucbNil )
  469. {
  470. Assert( PcsrCurrent( pfucb->pfucbCurIndex ) != pcsrNil );
  471. PcsrCurrent( pfucb->pfucbCurIndex )->csrstat = csrstatBeforeFirst;
  472. }
  473. #ifdef SYSTABLES
  474. /* remove column record from MSysColumns before committing...
  475. /**/
  476. if ( FSysTabDatabase( pfucb->dbid ) )
  477. {
  478. Call( ErrSysTabDelete( ppib, pfucb->dbid, itableSc, szColumn, pfucb->u.pfcb->pgnoFDP ) );
  479. }
  480. #endif /* SYSTABLES */
  481. Call( ErrDIRCommitTransaction( ppib ) );
  482. return JET_errSuccess;
  483. HandleError:
  484. CallS( ErrDIRRollback( ppib ) );
  485. return err;
  486. }
  487.