|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.129 2005/11/23 20:27:57 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.130 2005/12/02 20:03:40 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
|
24 | 24 | * ExecAssignResultType
|
25 | 25 | * etc
|
26 | 26 | *
|
| 27 | + * ExecOpenScanRelation Common code for scan node init routines. |
| 28 | + * ExecCloseScanRelation |
| 29 | + * |
27 | 30 | * ExecOpenIndices \
|
28 | 31 | * ExecCloseIndices | referenced by InitPlan, EndPlan,
|
29 | 32 | * ExecInsertIndexTuples / ExecInsert, ExecUpdate
|
|
45 | 48 | #include "catalog/pg_index.h"
|
46 | 49 | #include "executor/execdebug.h"
|
47 | 50 | #include "miscadmin.h"
|
| 51 | +#include "parser/parsetree.h" |
48 | 52 | #include "utils/builtins.h"
|
49 | 53 | #include "utils/fmgroids.h"
|
50 | 54 | #include "utils/memutils.h"
|
@@ -684,6 +688,90 @@ ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
|
684 | 688 | }
|
685 | 689 |
|
686 | 690 |
|
| 691 | +/* ---------------------------------------------------------------- |
| 692 | + * Scan node support |
| 693 | + * ---------------------------------------------------------------- |
| 694 | + */ |
| 695 | + |
| 696 | +/* ---------------------------------------------------------------- |
| 697 | + * ExecOpenScanRelation |
| 698 | + * |
| 699 | + * Open the heap relation to be scanned by a base-level scan plan node. |
| 700 | + * This should be called during the node's ExecInit routine. |
| 701 | + * |
| 702 | + * By default, this acquires AccessShareLock on the relation. However, |
| 703 | + * if the relation was already locked by InitPlan, we don't need to acquire |
| 704 | + * any additional lock. This saves trips to the shared lock manager. |
| 705 | + * ---------------------------------------------------------------- |
| 706 | + */ |
| 707 | +Relation |
| 708 | +ExecOpenScanRelation(EState *estate, Index scanrelid) |
| 709 | +{ |
| 710 | + RangeTblEntry *rtentry; |
| 711 | + Oid reloid; |
| 712 | + LOCKMODE lockmode; |
| 713 | + ResultRelInfo *resultRelInfos; |
| 714 | + int i; |
| 715 | + |
| 716 | + /* |
| 717 | + * First determine the lock type we need. Scan to see if target relation |
| 718 | + * is either a result relation or a FOR UPDATE/FOR SHARE relation. |
| 719 | + */ |
| 720 | + lockmode = AccessShareLock; |
| 721 | + resultRelInfos = estate->es_result_relations; |
| 722 | + for (i = 0; i < estate->es_num_result_relations; i++) |
| 723 | + { |
| 724 | + if (resultRelInfos[i].ri_RangeTableIndex == scanrelid) |
| 725 | + { |
| 726 | + lockmode = NoLock; |
| 727 | + break; |
| 728 | + } |
| 729 | + } |
| 730 | + |
| 731 | + if (lockmode == AccessShareLock) |
| 732 | + { |
| 733 | + ListCell *l; |
| 734 | + |
| 735 | + foreach(l, estate->es_rowMarks) |
| 736 | + { |
| 737 | + ExecRowMark *erm = lfirst(l); |
| 738 | + |
| 739 | + if (erm->rti == scanrelid) |
| 740 | + { |
| 741 | + lockmode = NoLock; |
| 742 | + break; |
| 743 | + } |
| 744 | + } |
| 745 | + } |
| 746 | + |
| 747 | + /* OK, open the relation and acquire lock as needed */ |
| 748 | + rtentry = rt_fetch(scanrelid, estate->es_range_table); |
| 749 | + reloid = rtentry->relid; |
| 750 | + |
| 751 | + return heap_open(reloid, lockmode); |
| 752 | +} |
| 753 | + |
| 754 | +/* ---------------------------------------------------------------- |
| 755 | + * ExecCloseScanRelation |
| 756 | + * |
| 757 | + * Close the heap relation scanned by a base-level scan plan node. |
| 758 | + * This should be called during the node's ExecEnd routine. |
| 759 | + * |
| 760 | + * Currently, we do not release the lock acquired by ExecOpenScanRelation. |
| 761 | + * This lock should be held till end of transaction. (There is a faction |
| 762 | + * that considers this too much locking, however.) |
| 763 | + * |
| 764 | + * If we did want to release the lock, we'd have to repeat the logic in |
| 765 | + * ExecOpenScanRelation in order to figure out what to release. |
| 766 | + * ---------------------------------------------------------------- |
| 767 | + */ |
| 768 | +void |
| 769 | +ExecCloseScanRelation(Relation scanrel) |
| 770 | +{ |
| 771 | + heap_close(scanrel, NoLock); |
| 772 | +} |
| 773 | + |
| 774 | + |
687 | 775 | /* ----------------------------------------------------------------
|
688 | 776 | * ExecInsertIndexTuples support
|
689 | 777 | * ----------------------------------------------------------------
|
@@ -760,7 +848,7 @@ ExecOpenIndices(ResultRelInfo *resultRelInfo)
|
760 | 848 | *
|
761 | 849 | * If the index AM is not safe for concurrent updates, obtain an
|
762 | 850 | * exclusive lock on the index to lock out other updaters as well as
|
763 |
| - * readers (index_beginscan places AccessShareLock). |
| 851 | + * readers (index_beginscan places AccessShareLock on the index). |
764 | 852 | *
|
765 | 853 | * If there are multiple not-concurrent-safe indexes, all backends
|
766 | 854 | * must lock the indexes in the same order or we will get deadlocks
|
|
0 commit comments