|
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