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.

287 lines
8.4 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 "ssib.h"
  8. #include "page.h"
  9. #include "fucb.h"
  10. #include "fcb.h"
  11. #include "stapi.h"
  12. #include "fdb.h"
  13. #include "idb.h"
  14. #include "nver.h"
  15. #include "dirapi.h"
  16. #include "logapi.h"
  17. #include "recapi.h"
  18. #include "spaceapi.h"
  19. #include "recint.h"
  20. DeclAssertFile; /* Declare file name for assert macros */
  21. /**************************** INTERNAL STUFF ***************************/
  22. typedef struct DFIPB { /*** DeleteFromIndexParameterBlock ***/
  23. FUCB *pfucb;
  24. FUCB *pfucbIdx; // index's FUCB (can be pfucbNil)
  25. LINE lineRecord; // deleted data record
  26. SRID sridRecord; // SRID of deleted record
  27. BOOL fFreeFUCB; // free index FUCB?
  28. } DFIPB;
  29. ERR ErrRECIDeleteFromIndex( FCB *pfcbIdx, DFIPB *pdfipb );
  30. //+API
  31. // ErrIsamDelete
  32. // ========================================================================
  33. // ErrIsamDelete(ppib, pfucb)
  34. // PIB *ppib; // IN PIB of this user
  35. // FUCB *pfucb; // INOUT FUCB for file to delete from
  36. // Deletes the current record from data file. All indexes on the data
  37. // file are updated to reflect the deletion.
  38. //
  39. // PARAMETERS
  40. // ppib PIB of this user
  41. // pfucb FUCB for file to delete from
  42. // RETURNS
  43. // Error code, one of the following:
  44. // JET_errSuccess Everything went OK.
  45. // -NoCurrentRecord There is no current record
  46. // to delete.
  47. // SIDE EFFECTS
  48. // After the deletion, file currency is left just before
  49. // the next record. Index currency (if any) is left just
  50. // before the next index entry. If the deleted record was
  51. // the last in the file, the currencies are left after the
  52. // new last record. If the deleted record was the only record
  53. // in the entire file, the currencies are left in the
  54. // "beginning of file" state. On failure, the currencies are
  55. // returned to their initial states.
  56. // If there is a working buffer for SetField commands,
  57. // it is discarded.
  58. // COMMENTS
  59. // If the currencies are not ON a record, the delete will fail.
  60. // A transaction is wrapped around this function. Thus, any
  61. // work done will be undone if a failure occurs.
  62. // Index entries are not made for entirely-null keys.
  63. // For temporary files, transaction logging is deactivated
  64. // for the duration of the routine.
  65. //-
  66. ERR VTAPI ErrIsamDelete( PIB *ppib, FUCB *pfucb )
  67. {
  68. ERR err;
  69. FCB *pfcbFile; // file's FCB
  70. FCB *pfcbIdx; // loop variable for each index on file
  71. DFIPB dfipb; // parameter to ErrRECIDeleteFromIndex
  72. CheckPIB( ppib );
  73. CheckTable( ppib, pfucb );
  74. CheckNonClustered( pfucb );
  75. /* ensure that table is updatable
  76. /**/
  77. CallR( FUCBCheckUpdatable( pfucb ) );
  78. /* reset copy buffer status on record delete
  79. /**/
  80. if ( FFUCBUpdatePrepared( pfucb ) )
  81. {
  82. CallR( ErrIsamPrepareUpdate( ppib, pfucb, JET_prepCancel ) );
  83. }
  84. /* efficiency variables
  85. /**/
  86. pfcbFile = pfucb->u.pfcb;
  87. Assert( pfcbFile != pfcbNil );
  88. CallR( ErrDIRBeginTransaction( ppib ) );
  89. /* abort if index is being built on file
  90. /**/
  91. if ( FFCBDenyDDL( pfcbFile, ppib ) )
  92. {
  93. err = JET_errWriteConflict;
  94. goto HandleError;
  95. }
  96. /* refresh currency since pfucb->lineData may be invalid
  97. /**/
  98. Call( ErrDIRGet( pfucb ) );
  99. /* allocate working buffer if needed
  100. /**/
  101. if ( pfucb->pbfWorkBuf == NULL )
  102. {
  103. Call( ErrBFAllocTempBuffer( &pfucb->pbfWorkBuf ) );
  104. }
  105. pfucb->lineWorkBuf.pb = (BYTE *)pfucb->pbfWorkBuf->ppage;
  106. Assert( pfucb->pbfWorkBuf != pbfNil );
  107. /* copy record to be deleted into copy buffer
  108. /**/
  109. LineCopy( &pfucb->lineWorkBuf, &pfucb->lineData );
  110. /* cache record pointer for delete index and
  111. /* delete long value operations.
  112. /**/
  113. dfipb.lineRecord = pfucb->lineWorkBuf;
  114. /* get SRID of record being deleted for updating indexes
  115. /**/
  116. Assert( ppib->level < levelMax );
  117. Assert( PcsrCurrent( pfucb ) != pcsrNil );
  118. DIRGetBookmark( pfucb, &dfipb.sridRecord );
  119. /* delete record
  120. /**/
  121. Call( ErrDIRDelete( pfucb, fDIRVersion ) );
  122. /* delete from non-clustered indexes
  123. /**/
  124. dfipb.pfucb = pfucb;
  125. dfipb.fFreeFUCB = fFalse;
  126. for( pfcbIdx = pfcbFile->pfcbNextIndex;
  127. pfcbIdx != pfcbNil;
  128. pfcbIdx = pfcbIdx->pfcbNextIndex )
  129. {
  130. dfipb.fFreeFUCB = pfcbIdx->pfcbNextIndex == pfcbNil;
  131. Call( ErrRECIDeleteFromIndex( pfcbIdx, &dfipb ) );
  132. }
  133. // UNDONE: optimize record deletion by detecting presence of long values
  134. // on table basis.
  135. /* delete record long values
  136. /**/
  137. Call( ErrRECAffectLongFields( pfucb, &dfipb.lineRecord, fDereference ) );
  138. /* commit transaction if we started it and everything went OK
  139. /**/
  140. Call( ErrDIRCommitTransaction( ppib ) );
  141. return err;
  142. HandleError:
  143. /* if operation failed then rollback changes.
  144. /**/
  145. Assert( err < 0 );
  146. CallS( ErrDIRRollback( ppib ) );
  147. return err;
  148. }
  149. //+INTERNAL
  150. // ErrRECIDeleteFromIndex
  151. // ========================================================================
  152. // ErrRECIDeleteFromIndex( FCB *pfcbIdx, DFIPB *pdfipb )
  153. //
  154. // Extracts key from data record, opens the index, deletes the key with
  155. // the given SRID, and closes the index.
  156. //
  157. // PARAMETERS
  158. // pfcbIdx FCB of index to delete from
  159. // pdfipb->ppib who is calling this routine
  160. // pdfipb->pfucbIdx pointer to index's FUCB.
  161. // pdfipb->lineRecord.cb length of deleted record
  162. // pdfipb->lineRecord.pb deleted record to extract key from
  163. // pdfipb->sridRecord SRID of deleted record
  164. // pdfipb->fFreeFUCB free index FUCB?
  165. // RETURNS
  166. // JET_errSuccess, or error code from failing routine
  167. // SIDE EFFECTS
  168. // If fFreeFUCB is fFalse, patipb->pfucbIdx should
  169. // be used in a subsequent ErrDIROpen.
  170. // SEE ALSO ErrRECDelete
  171. //-
  172. ERR ErrRECIDeleteFromIndex( FCB *pfcbIdx, DFIPB *pdfipb )
  173. {
  174. ERR err; // error code of various utility
  175. KEY keyDead; // key extracted from old data record
  176. BYTE rgbDeadKeyBuf[ JET_cbKeyMost ]; // buffer for keyDead
  177. ULONG itagSequence; // used to extract keys
  178. BOOL fHasMultivalue; // index key has a tagged field?
  179. Assert( pfcbIdx != pfcbNil );
  180. Assert( pfcbIdx->pfdb != pfdbNil );
  181. Assert( pfcbIdx->pidb != pidbNil );
  182. Assert( pdfipb != NULL );
  183. Assert( !FLineNull( &pdfipb->lineRecord ) );
  184. Assert( pdfipb->pfucb != pfucbNil );
  185. /* open FUCB on this index
  186. /**/
  187. CallR( ErrDIROpen( pdfipb->pfucb->ppib, pfcbIdx, 0, &pdfipb->pfucbIdx ) );
  188. Assert( pdfipb->pfucbIdx != pfucbNil );
  189. FUCBSetIndex( pdfipb->pfucbIdx );
  190. FUCBSetNonClustered( pdfipb->pfucbIdx );
  191. /* delete all keys from this index for dying data record
  192. /**/
  193. fHasMultivalue = pfcbIdx->pidb->fidb & fidbHasMultivalue;
  194. keyDead.pb = rgbDeadKeyBuf;
  195. for ( itagSequence = 1; ; itagSequence++ )
  196. {
  197. // Call( ErrDIRGet( pdfipb->pfucb ) );
  198. // pdfipb->lineRecord = pdfipb->pfucb->lineData;
  199. Call( ErrRECExtractKey( pdfipb->pfucb, (FDB *)pfcbIdx->pfdb, pfcbIdx->pidb,
  200. &pdfipb->lineRecord, &keyDead, itagSequence ) );
  201. Assert( err == wrnFLDNullKey ||
  202. err == wrnFLDOutOfKeys ||
  203. err == wrnFLDNullSeg ||
  204. err == JET_errSuccess );
  205. if ( err == wrnFLDOutOfKeys )
  206. {
  207. Assert( itagSequence > 1 );
  208. break;
  209. }
  210. /* record must honor index no NULL segment requirements
  211. /**/
  212. Assert( !( pfcbIdx->pidb->fidb & fidbNoNullSeg ) ||
  213. ( err != wrnFLDNullSeg && err != wrnFLDNullKey ) );
  214. if ( err == wrnFLDNullKey )
  215. {
  216. if ( pfcbIdx->pidb->fidb & fidbAllowAllNulls )
  217. {
  218. /* move to DATA root and seek to index entry and delete it
  219. /**/
  220. DIRGotoDataRoot( pdfipb->pfucbIdx );
  221. Call( ErrDIRDownKeyBookmark( pdfipb->pfucbIdx, &keyDead, pdfipb->sridRecord ) );
  222. Call( ErrDIRDelete( pdfipb->pfucbIdx, fDIRVersion ) );
  223. }
  224. break;
  225. }
  226. else
  227. {
  228. if ( err == wrnFLDNullSeg && !( pfcbIdx->pidb->fidb & fidbAllowSomeNulls ) )
  229. break;
  230. }
  231. DIRGotoDataRoot( pdfipb->pfucbIdx );
  232. Call( ErrDIRDownKeyBookmark( pdfipb->pfucbIdx, &keyDead, pdfipb->sridRecord ) );
  233. Call( ErrDIRDelete( pdfipb->pfucbIdx, fDIRVersion ) );
  234. /* dont keep extracting for keys with no tagged segments
  235. /**/
  236. if ( !fHasMultivalue )
  237. break;
  238. }
  239. /* supress warnings
  240. /**/
  241. Assert( err == wrnFLDNullKey ||
  242. err == wrnFLDOutOfKeys ||
  243. err == wrnFLDNullSeg ||
  244. err == JET_errSuccess );
  245. err = JET_errSuccess;
  246. HandleError:
  247. /* close the FUCB
  248. /**/
  249. DIRClose( pdfipb->pfucbIdx );
  250. Assert( err < 0 || err == JET_errSuccess );
  251. return err;
  252. }
  253.