tqual.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:17k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * tqual.c
  4.  *   POSTGRES "time" qualification code.
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.29.2.1 1999/08/02 05:25:19 scrappy Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. /* #define TQUALDEBUG 1 */
  15. #include "postgres.h"
  16. #include "utils/tqual.h"
  17. extern bool PostgresIsInitialized;
  18. SnapshotData SnapshotDirtyData;
  19. Snapshot SnapshotDirty = &SnapshotDirtyData;
  20. Snapshot QuerySnapshot = NULL;
  21. Snapshot SerializableSnapshot = NULL;
  22. /*
  23.  * XXX Transaction system override hacks start here
  24.  */
  25. #ifndef GOODAMI
  26. TransactionId HeapSpecialTransactionId = InvalidTransactionId;
  27. CommandId HeapSpecialCommandId = FirstCommandId;
  28. void
  29. setheapoverride(bool on)
  30. {
  31. if (on)
  32. {
  33. TransactionIdStore(GetCurrentTransactionId(),
  34.    &HeapSpecialTransactionId);
  35. HeapSpecialCommandId = GetCurrentCommandId();
  36. }
  37. else
  38. HeapSpecialTransactionId = InvalidTransactionId;
  39. }
  40. #endif  /* !defined(GOODAMI) */
  41. /*
  42.  * XXX Transaction system override hacks end here
  43.  */
  44. /*
  45.  * HeapTupleSatisfiesItself
  46.  * True iff heap tuple is valid for "itself."
  47.  * "{it}self" means valid as of everything that's happened
  48.  * in the current transaction, _including_ the current command.
  49.  *
  50.  * Note:
  51.  * Assumes heap tuple is valid.
  52.  */
  53. /*
  54.  * The satisfaction of "itself" requires the following:
  55.  *
  56.  * ((Xmin == my-transaction && the row was updated by the current transaction, and
  57.  * (Xmax is null it was not deleted
  58.  *  [|| Xmax != my-transaction)]) [or it was deleted by another transaction]
  59.  * ||
  60.  *
  61.  * (Xmin is committed && the row was modified by a committed transaction, and
  62.  * (Xmax is null || the row has not been deleted, or
  63.  * (Xmax != my-transaction && the row was deleted by another transaction
  64.  *  Xmax is not committed))) that has not been committed
  65.  */
  66. bool
  67. HeapTupleSatisfiesItself(HeapTupleHeader tuple)
  68. {
  69. if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
  70. {
  71. if (tuple->t_infomask & HEAP_XMIN_INVALID)
  72. return false;
  73. if (tuple->t_infomask & HEAP_MOVED_OFF)
  74. {
  75. if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
  76. {
  77. tuple->t_infomask |= HEAP_XMIN_INVALID;
  78. return false;
  79. }
  80. }
  81. else if (tuple->t_infomask & HEAP_MOVED_IN)
  82. {
  83. if (!TransactionIdDidCommit((TransactionId) tuple->t_cmin))
  84. {
  85. tuple->t_infomask |= HEAP_XMIN_INVALID;
  86. return false;
  87. }
  88. }
  89. else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
  90. {
  91. if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
  92. return true;
  93. if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  94. return true;
  95. return false;
  96. }
  97. else if (!TransactionIdDidCommit(tuple->t_xmin))
  98. {
  99. if (TransactionIdDidAbort(tuple->t_xmin))
  100. tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
  101. return false;
  102. }
  103. tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  104. }
  105. /* the tuple was inserted validly */
  106. if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
  107. return true;
  108. if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
  109. {
  110. if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  111. return true;
  112. return false; /* updated by other */
  113. }
  114. if (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
  115. {
  116. if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  117. return true;
  118. return false;
  119. }
  120. if (!TransactionIdDidCommit(tuple->t_xmax))
  121. {
  122. if (TransactionIdDidAbort(tuple->t_xmax))
  123. tuple->t_infomask |= HEAP_XMAX_INVALID; /* aborted */
  124. return true;
  125. }
  126. /* by here, deleting transaction has committed */
  127. tuple->t_infomask |= HEAP_XMAX_COMMITTED;
  128. if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  129. return true;
  130. return false;
  131. }
  132. /*
  133.  * HeapTupleSatisfiesNow
  134.  * True iff heap tuple is valid "now."
  135.  * "now" means valid including everything that's happened
  136.  *  in the current transaction _up to, but not including,_
  137.  *  the current command.
  138.  *
  139.  * Note:
  140.  * Assumes heap tuple is valid.
  141.  */
  142. /*
  143.  * The satisfaction of "now" requires the following:
  144.  *
  145.  * ((Xmin == my-transaction && changed by the current transaction
  146.  *  Cmin != my-command && but not by this command, and
  147.  * (Xmax is null || the row has not been deleted, or
  148.  * (Xmax == my-transaction && it was deleted by the current transaction
  149.  *  Cmax != my-command))) but not by this command,
  150.  * || or
  151.  *
  152.  * (Xmin is committed && the row was modified by a committed transaction, and
  153.  * (Xmax is null || the row has not been deleted, or
  154.  * (Xmax == my-transaction && the row is being deleted by this command, or
  155.  *  Cmax == my-command) ||
  156.  * (Xmax is not committed && the row was deleted by another transaction
  157.  *  Xmax != my-transaction)))) that has not been committed
  158.  *
  159.  * mao says 17 march 1993:  the tests in this routine are correct;
  160.  * if you think they're not, you're wrong, and you should think
  161.  * about it again.  i know, it happened to me.  we don't need to
  162.  * check commit time against the start time of this transaction
  163.  * because 2ph locking protects us from doing the wrong thing.
  164.  * if you mess around here, you'll break serializability.  the only
  165.  * problem with this code is that it does the wrong thing for system
  166.  * catalog updates, because the catalogs aren't subject to 2ph, so
  167.  * the serializability guarantees we provide don't extend to xacts
  168.  * that do catalog accesses.  this is unfortunate, but not critical.
  169.  */
  170. bool
  171. HeapTupleSatisfiesNow(HeapTupleHeader tuple)
  172. {
  173. if (AMI_OVERRIDE)
  174. return true;
  175. /*
  176.  * If the transaction system isn't yet initialized, then we assume
  177.  * that transactions committed.  We only look at system catalogs
  178.  * during startup, so this is less awful than it seems, but it's still
  179.  * pretty awful.
  180.  */
  181. if (!PostgresIsInitialized)
  182. return ((bool) (TransactionIdIsValid(tuple->t_xmin) &&
  183. !TransactionIdIsValid(tuple->t_xmax)));
  184. if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
  185. {
  186. if (tuple->t_infomask & HEAP_XMIN_INVALID)
  187. return false;
  188. if (tuple->t_infomask & HEAP_MOVED_OFF)
  189. {
  190. if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
  191. {
  192. tuple->t_infomask |= HEAP_XMIN_INVALID;
  193. return false;
  194. }
  195. }
  196. else if (tuple->t_infomask & HEAP_MOVED_IN)
  197. {
  198. if (!TransactionIdDidCommit((TransactionId) tuple->t_cmin))
  199. {
  200. tuple->t_infomask |= HEAP_XMIN_INVALID;
  201. return false;
  202. }
  203. }
  204. else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
  205. {
  206. if (CommandIdGEScanCommandId(tuple->t_cmin))
  207. return false; /* inserted after scan started */
  208. if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
  209. return true;
  210. Assert(TransactionIdIsCurrentTransactionId(tuple->t_xmax));
  211. if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  212. return true;
  213. if (CommandIdGEScanCommandId(tuple->t_cmax))
  214. return true; /* deleted after scan started */
  215. else
  216. return false; /* deleted before scan started */
  217. }
  218. else if (!TransactionIdDidCommit(tuple->t_xmin))
  219. {
  220. if (TransactionIdDidAbort(tuple->t_xmin))
  221. tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
  222. return false;
  223. }
  224. tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  225. }
  226. /* by here, the inserting transaction has committed */
  227. if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
  228. return true;
  229. if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
  230. {
  231. if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  232. return true;
  233. return false;
  234. }
  235. if (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
  236. {
  237. if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  238. return true;
  239. if (CommandIdGEScanCommandId(tuple->t_cmax))
  240. return true; /* deleted after scan started */
  241. else
  242. return false; /* deleted before scan started */
  243. }
  244. if (!TransactionIdDidCommit(tuple->t_xmax))
  245. {
  246. if (TransactionIdDidAbort(tuple->t_xmax))
  247. tuple->t_infomask |= HEAP_XMAX_INVALID; /* aborted */
  248. return true;
  249. }
  250. /* xmax transaction committed */
  251. tuple->t_infomask |= HEAP_XMAX_COMMITTED;
  252. if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  253. return true;
  254. return false;
  255. }
  256. int
  257. HeapTupleSatisfiesUpdate(HeapTuple tuple)
  258. {
  259. HeapTupleHeader th = tuple->t_data;
  260. if (AMI_OVERRIDE)
  261. return HeapTupleMayBeUpdated;
  262. if (!(th->t_infomask & HEAP_XMIN_COMMITTED))
  263. {
  264. if (th->t_infomask & HEAP_XMIN_INVALID) /* xid invalid or aborted */
  265. return HeapTupleInvisible;
  266. if (th->t_infomask & HEAP_MOVED_OFF)
  267. {
  268. if (TransactionIdDidCommit((TransactionId) th->t_cmin))
  269. {
  270. th->t_infomask |= HEAP_XMIN_INVALID;
  271. return HeapTupleInvisible;
  272. }
  273. }
  274. else if (th->t_infomask & HEAP_MOVED_IN)
  275. {
  276. if (!TransactionIdDidCommit((TransactionId) th->t_cmin))
  277. {
  278. th->t_infomask |= HEAP_XMIN_INVALID;
  279. return HeapTupleInvisible;
  280. }
  281. }
  282. else if (TransactionIdIsCurrentTransactionId(th->t_xmin))
  283. {
  284. if (CommandIdGEScanCommandId(th->t_cmin) && !heapisoverride())
  285. return HeapTupleInvisible; /* inserted after scan
  286.  * started */
  287. if (th->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
  288. return HeapTupleMayBeUpdated;
  289. Assert(TransactionIdIsCurrentTransactionId(th->t_xmax));
  290. if (th->t_infomask & HEAP_MARKED_FOR_UPDATE)
  291. return HeapTupleMayBeUpdated;
  292. if (CommandIdGEScanCommandId(th->t_cmax))
  293. return HeapTupleSelfUpdated; /* updated after scan
  294.  * started */
  295. else
  296. return HeapTupleInvisible; /* updated before scan
  297.  * started */
  298. }
  299. else if (!TransactionIdDidCommit(th->t_xmin))
  300. {
  301. if (TransactionIdDidAbort(th->t_xmin))
  302. th->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
  303. return HeapTupleInvisible;
  304. }
  305. th->t_infomask |= HEAP_XMIN_COMMITTED;
  306. }
  307. /* by here, the inserting transaction has committed */
  308. if (th->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
  309. return HeapTupleMayBeUpdated;
  310. if (th->t_infomask & HEAP_XMAX_COMMITTED)
  311. {
  312. if (th->t_infomask & HEAP_MARKED_FOR_UPDATE)
  313. return HeapTupleMayBeUpdated;
  314. return HeapTupleUpdated;/* updated by other */
  315. }
  316. if (TransactionIdIsCurrentTransactionId(th->t_xmax))
  317. {
  318. if (th->t_infomask & HEAP_MARKED_FOR_UPDATE)
  319. return HeapTupleMayBeUpdated;
  320. if (CommandIdGEScanCommandId(th->t_cmax))
  321. return HeapTupleSelfUpdated; /* updated after scan
  322.  * started */
  323. else
  324. return HeapTupleInvisible; /* updated before scan started */
  325. }
  326. if (!TransactionIdDidCommit(th->t_xmax))
  327. {
  328. if (TransactionIdDidAbort(th->t_xmax))
  329. {
  330. th->t_infomask |= HEAP_XMAX_INVALID; /* aborted */
  331. return HeapTupleMayBeUpdated;
  332. }
  333. /* running xact */
  334. return HeapTupleBeingUpdated; /* in updation by other */
  335. }
  336. /* xmax transaction committed */
  337. th->t_infomask |= HEAP_XMAX_COMMITTED;
  338. if (th->t_infomask & HEAP_MARKED_FOR_UPDATE)
  339. return HeapTupleMayBeUpdated;
  340. return HeapTupleUpdated; /* updated by other */
  341. }
  342. bool
  343. HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
  344. {
  345. SnapshotDirty->xmin = SnapshotDirty->xmax = InvalidTransactionId;
  346. ItemPointerSetInvalid(&(SnapshotDirty->tid));
  347. if (AMI_OVERRIDE)
  348. return true;
  349. if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
  350. {
  351. if (tuple->t_infomask & HEAP_XMIN_INVALID)
  352. return false;
  353. if (tuple->t_infomask & HEAP_MOVED_OFF)
  354. {
  355. /*
  356.  * HeapTupleSatisfiesDirty is used by unique btree-s and so
  357.  * may be used while vacuuming.
  358.  */
  359. if (TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
  360. return false;
  361. if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
  362. {
  363. tuple->t_infomask |= HEAP_XMIN_INVALID;
  364. return false;
  365. }
  366. tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  367. }
  368. else if (tuple->t_infomask & HEAP_MOVED_IN)
  369. {
  370. if (!TransactionIdIsCurrentTransactionId((TransactionId) tuple->t_cmin))
  371. {
  372. if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
  373. tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  374. else
  375. {
  376. tuple->t_infomask |= HEAP_XMIN_INVALID;
  377. return false;
  378. }
  379. }
  380. }
  381. else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
  382. {
  383. if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
  384. return true;
  385. Assert(TransactionIdIsCurrentTransactionId(tuple->t_xmax));
  386. if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  387. return true;
  388. return false;
  389. }
  390. else if (!TransactionIdDidCommit(tuple->t_xmin))
  391. {
  392. if (TransactionIdDidAbort(tuple->t_xmin))
  393. {
  394. tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
  395. return false;
  396. }
  397. SnapshotDirty->xmin = tuple->t_xmin;
  398. return true; /* in insertion by other */
  399. }
  400. else
  401. tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  402. }
  403. /* by here, the inserting transaction has committed */
  404. if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
  405. return true;
  406. if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
  407. {
  408. if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  409. return true;
  410. SnapshotDirty->tid = tuple->t_ctid;
  411. return false; /* updated by other */
  412. }
  413. if (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
  414. return false;
  415. if (!TransactionIdDidCommit(tuple->t_xmax))
  416. {
  417. if (TransactionIdDidAbort(tuple->t_xmax))
  418. {
  419. tuple->t_infomask |= HEAP_XMAX_INVALID; /* aborted */
  420. return true;
  421. }
  422. /* running xact */
  423. SnapshotDirty->xmax = tuple->t_xmax;
  424. return true; /* in updation by other */
  425. }
  426. /* xmax transaction committed */
  427. tuple->t_infomask |= HEAP_XMAX_COMMITTED;
  428. if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  429. return true;
  430. SnapshotDirty->tid = tuple->t_ctid;
  431. return false; /* updated by other */
  432. }
  433. bool
  434. HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
  435. {
  436. if (AMI_OVERRIDE)
  437. return true;
  438. if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
  439. {
  440. if (tuple->t_infomask & HEAP_XMIN_INVALID)
  441. return false;
  442. if (tuple->t_infomask & HEAP_MOVED_OFF)
  443. {
  444. if (TransactionIdDidCommit((TransactionId) tuple->t_cmin))
  445. {
  446. tuple->t_infomask |= HEAP_XMIN_INVALID;
  447. return false;
  448. }
  449. }
  450. else if (tuple->t_infomask & HEAP_MOVED_IN)
  451. {
  452. if (!TransactionIdDidCommit((TransactionId) tuple->t_cmin))
  453. {
  454. tuple->t_infomask |= HEAP_XMIN_INVALID;
  455. return false;
  456. }
  457. }
  458. else if (TransactionIdIsCurrentTransactionId(tuple->t_xmin))
  459. {
  460. if (CommandIdGEScanCommandId(tuple->t_cmin))
  461. return false; /* inserted after scan started */
  462. if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid */
  463. return true;
  464. Assert(TransactionIdIsCurrentTransactionId(tuple->t_xmax));
  465. if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  466. return true;
  467. if (CommandIdGEScanCommandId(tuple->t_cmax))
  468. return true; /* deleted after scan started */
  469. else
  470. return false; /* deleted before scan started */
  471. }
  472. else if (!TransactionIdDidCommit(tuple->t_xmin))
  473. {
  474. if (TransactionIdDidAbort(tuple->t_xmin))
  475. tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
  476. return false;
  477. }
  478. tuple->t_infomask |= HEAP_XMIN_COMMITTED;
  479. }
  480. /*
  481.  * By here, the inserting transaction has committed - have to check
  482.  * when...
  483.  */
  484. if (tuple->t_xmin >= snapshot->xmax)
  485. return false;
  486. if (tuple->t_xmin >= snapshot->xmin)
  487. {
  488. uint32 i;
  489. for (i = 0; i < snapshot->xcnt; i++)
  490. {
  491. if (tuple->t_xmin == snapshot->xip[i])
  492. return false;
  493. }
  494. }
  495. if (tuple->t_infomask & HEAP_XMAX_INVALID) /* xid invalid or aborted */
  496. return true;
  497. if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
  498. return true;
  499. if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
  500. {
  501. if (TransactionIdIsCurrentTransactionId(tuple->t_xmax))
  502. {
  503. if (CommandIdGEScanCommandId(tuple->t_cmax))
  504. return true; /* deleted after scan started */
  505. else
  506. return false; /* deleted before scan started */
  507. }
  508. if (!TransactionIdDidCommit(tuple->t_xmax))
  509. {
  510. if (TransactionIdDidAbort(tuple->t_xmax))
  511. tuple->t_infomask |= HEAP_XMAX_INVALID; /* aborted */
  512. return true;
  513. }
  514. /* xmax transaction committed */
  515. tuple->t_infomask |= HEAP_XMAX_COMMITTED;
  516. }
  517. if (tuple->t_xmax >= snapshot->xmax)
  518. return true;
  519. if (tuple->t_xmax >= snapshot->xmin)
  520. {
  521. uint32 i;
  522. for (i = 0; i < snapshot->xcnt; i++)
  523. {
  524. if (tuple->t_xmax == snapshot->xip[i])
  525. return true;
  526. }
  527. }
  528. return false;
  529. }
  530. void
  531. SetQuerySnapshot(void)
  532. {
  533. /* 1st call in xaction */
  534. if (SerializableSnapshot == NULL)
  535. {
  536. SerializableSnapshot = GetSnapshotData(true);
  537. QuerySnapshot = SerializableSnapshot;
  538. Assert(QuerySnapshot != NULL);
  539. return;
  540. }
  541. if (QuerySnapshot != SerializableSnapshot)
  542. {
  543. free(QuerySnapshot->xip);
  544. free(QuerySnapshot);
  545. }
  546. if (XactIsoLevel == XACT_SERIALIZABLE)
  547. QuerySnapshot = SerializableSnapshot;
  548. else
  549. QuerySnapshot = GetSnapshotData(false);
  550. Assert(QuerySnapshot != NULL);
  551. }
  552. void
  553. FreeXactSnapshot(void)
  554. {
  555. if (QuerySnapshot != NULL && QuerySnapshot != SerializableSnapshot)
  556. {
  557. free(QuerySnapshot->xip);
  558. free(QuerySnapshot);
  559. }
  560. QuerySnapshot = NULL;
  561. if (SerializableSnapshot != NULL)
  562. {
  563. free(SerializableSnapshot->xip);
  564. free(SerializableSnapshot);
  565. }
  566. SerializableSnapshot = NULL;
  567. }