|
26 | 26 | *
|
27 | 27 | *
|
28 | 28 | * IDENTIFICATION
|
29 |
| - * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.328 2009/09/26 22:42:01 tgl Exp $ |
| 29 | + * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.329 2009/09/27 20:09:57 tgl Exp $ |
30 | 30 | *
|
31 | 31 | *-------------------------------------------------------------------------
|
32 | 32 | */
|
@@ -755,40 +755,12 @@ InitPlan(QueryDesc *queryDesc, int eflags)
|
755 | 755 | }
|
756 | 756 |
|
757 | 757 | /*
|
758 |
| - * Initialize the executor "tuple" table. We need slots for all the plan |
759 |
| - * nodes, plus possibly output slots for the junkfilter(s). At this point |
760 |
| - * we aren't sure if we need junkfilters, so just add slots for them |
761 |
| - * unconditionally. Also, if it's not a SELECT, set up a slot for use for |
762 |
| - * trigger output tuples. Also, one for RETURNING-list evaluation. |
| 758 | + * Initialize the executor's tuple table. Also, if it's not a SELECT, |
| 759 | + * set up a tuple table slot for use for trigger output tuples. |
763 | 760 | */
|
764 |
| - { |
765 |
| - int nSlots; |
766 |
| - |
767 |
| - /* Slots for the main plan tree */ |
768 |
| - nSlots = ExecCountSlotsNode(plan); |
769 |
| - /* Add slots for subplans and initplans */ |
770 |
| - foreach(l, plannedstmt->subplans) |
771 |
| - { |
772 |
| - Plan *subplan = (Plan *) lfirst(l); |
773 |
| - |
774 |
| - nSlots += ExecCountSlotsNode(subplan); |
775 |
| - } |
776 |
| - /* Add slots for junkfilter(s) */ |
777 |
| - if (plannedstmt->resultRelations != NIL) |
778 |
| - nSlots += list_length(plannedstmt->resultRelations); |
779 |
| - else |
780 |
| - nSlots += 1; |
781 |
| - if (operation != CMD_SELECT) |
782 |
| - nSlots++; /* for es_trig_tuple_slot */ |
783 |
| - if (plannedstmt->returningLists) |
784 |
| - nSlots++; /* for RETURNING projection */ |
785 |
| - |
786 |
| - estate->es_tupleTable = ExecCreateTupleTable(nSlots); |
787 |
| - |
788 |
| - if (operation != CMD_SELECT) |
789 |
| - estate->es_trig_tuple_slot = |
790 |
| - ExecAllocTableSlot(estate->es_tupleTable); |
791 |
| - } |
| 761 | + estate->es_tupleTable = NIL; |
| 762 | + if (operation != CMD_SELECT) |
| 763 | + estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate); |
792 | 764 |
|
793 | 765 | /* mark EvalPlanQual not active */
|
794 | 766 | estate->es_plannedstmt = plannedstmt;
|
@@ -909,7 +881,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
|
909 | 881 |
|
910 | 882 | j = ExecInitJunkFilter(subplan->plan->targetlist,
|
911 | 883 | resultRelInfo->ri_RelationDesc->rd_att->tdhasoid,
|
912 |
| - ExecAllocTableSlot(estate->es_tupleTable)); |
| 884 | + ExecInitExtraTupleSlot(estate)); |
913 | 885 |
|
914 | 886 | /*
|
915 | 887 | * Since it must be UPDATE/DELETE, there had better be a
|
@@ -953,7 +925,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
|
953 | 925 |
|
954 | 926 | j = ExecInitJunkFilter(planstate->plan->targetlist,
|
955 | 927 | tupType->tdhasoid,
|
956 |
| - ExecAllocTableSlot(estate->es_tupleTable)); |
| 928 | + ExecInitExtraTupleSlot(estate)); |
957 | 929 | estate->es_junkFilter = j;
|
958 | 930 | if (estate->es_result_relation_info)
|
959 | 931 | estate->es_result_relation_info->ri_junkFilter = j;
|
@@ -1026,7 +998,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
|
1026 | 998 | false);
|
1027 | 999 |
|
1028 | 1000 | /* Set up a slot for the output of the RETURNING projection(s) */
|
1029 |
| - slot = ExecAllocTableSlot(estate->es_tupleTable); |
| 1001 | + slot = ExecInitExtraTupleSlot(estate); |
1030 | 1002 | ExecSetSlotDescriptor(slot, tupType);
|
1031 | 1003 | /* Need an econtext too */
|
1032 | 1004 | econtext = CreateExprContext(estate);
|
@@ -1387,10 +1359,12 @@ ExecEndPlan(PlanState *planstate, EState *estate)
|
1387 | 1359 | }
|
1388 | 1360 |
|
1389 | 1361 | /*
|
1390 |
| - * destroy the executor "tuple" table. |
| 1362 | + * destroy the executor's tuple table. Actually we only care about |
| 1363 | + * releasing buffer pins and tupdesc refcounts; there's no need to |
| 1364 | + * pfree the TupleTableSlots, since the containing memory context |
| 1365 | + * is about to go away anyway. |
1391 | 1366 | */
|
1392 |
| - ExecDropTupleTable(estate->es_tupleTable, true); |
1393 |
| - estate->es_tupleTable = NULL; |
| 1367 | + ExecResetTupleTable(estate->es_tupleTable, false); |
1394 | 1368 |
|
1395 | 1369 | /*
|
1396 | 1370 | * close the result relation(s) if any, but hold locks until xact commit.
|
@@ -2712,10 +2686,9 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq)
|
2712 | 2686 | epqstate->es_evTuple = priorepq->estate->es_evTuple;
|
2713 | 2687 |
|
2714 | 2688 | /*
|
2715 |
| - * Create sub-tuple-table; we needn't redo the CountSlots work though. |
| 2689 | + * Each epqstate also has its own tuple table. |
2716 | 2690 | */
|
2717 |
| - epqstate->es_tupleTable = |
2718 |
| - ExecCreateTupleTable(estate->es_tupleTable->size); |
| 2691 | + epqstate->es_tupleTable = NIL; |
2719 | 2692 |
|
2720 | 2693 | /*
|
2721 | 2694 | * Initialize private state information for each SubPlan. We must do this
|
@@ -2770,8 +2743,9 @@ EvalPlanQualStop(evalPlanQual *epq)
|
2770 | 2743 | ExecEndNode(subplanstate);
|
2771 | 2744 | }
|
2772 | 2745 |
|
2773 |
| - ExecDropTupleTable(epqstate->es_tupleTable, true); |
2774 |
| - epqstate->es_tupleTable = NULL; |
| 2746 | + /* throw away the per-epqstate tuple table completely */ |
| 2747 | + ExecResetTupleTable(epqstate->es_tupleTable, true); |
| 2748 | + epqstate->es_tupleTable = NIL; |
2775 | 2749 |
|
2776 | 2750 | if (epqstate->es_evTuple[epq->rti - 1] != NULL)
|
2777 | 2751 | {
|
|
0 commit comments