26
26
*
27
27
*
28
28
* IDENTIFICATION
29
- * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.310 2008/07/18 18:23:46 tgl Exp $
29
+ * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.311 2008/07/26 19:15:35 tgl Exp $
30
30
*
31
31
*-------------------------------------------------------------------------
32
32
*/
@@ -694,9 +694,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
694
694
695
695
/*
696
696
* Initialize the junk filter if needed. SELECT and INSERT queries need a
697
- * filter if there are any junk attrs in the tlist. INSERT and SELECT
698
- * INTO also need a filter if the plan may return raw disk tuples (else
699
- * heap_insert will be scribbling on the source relation!). UPDATE and
697
+ * filter if there are any junk attrs in the tlist. UPDATE and
700
698
* DELETE always need a filter, since there's always a junk 'ctid'
701
699
* attribute present --- no need to look first.
702
700
*/
@@ -718,10 +716,6 @@ InitPlan(QueryDesc *queryDesc, int eflags)
718
716
break ;
719
717
}
720
718
}
721
- if (!junk_filter_needed &&
722
- (operation == CMD_INSERT || estate -> es_select_into ) &&
723
- ExecMayReturnRawTuples (planstate ))
724
- junk_filter_needed = true;
725
719
break ;
726
720
case CMD_UPDATE :
727
721
case CMD_DELETE :
@@ -2424,8 +2418,6 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq)
2424
2418
epqstate -> es_result_relation_info = estate -> es_result_relation_info ;
2425
2419
epqstate -> es_junkFilter = estate -> es_junkFilter ;
2426
2420
/* es_trig_target_relations must NOT be copied */
2427
- epqstate -> es_into_relation_descriptor = estate -> es_into_relation_descriptor ;
2428
- epqstate -> es_into_relation_use_wal = estate -> es_into_relation_use_wal ;
2429
2421
epqstate -> es_param_list_info = estate -> es_param_list_info ;
2430
2422
if (estate -> es_plannedstmt -> nParamExec > 0 )
2431
2423
epqstate -> es_param_exec_vals = (ParamExecData * )
@@ -2559,15 +2551,14 @@ ExecGetActivePlanTree(QueryDesc *queryDesc)
2559
2551
*
2560
2552
* We implement SELECT INTO by diverting SELECT's normal output with
2561
2553
* a specialized DestReceiver type.
2562
- *
2563
- * TODO: remove some of the INTO-specific cruft from EState, and keep
2564
- * it in the DestReceiver instead.
2565
2554
*/
2566
2555
2567
2556
typedef struct
2568
2557
{
2569
2558
DestReceiver pub ; /* publicly-known function pointers */
2570
2559
EState * estate ; /* EState we are working with */
2560
+ Relation rel ; /* Relation to write to */
2561
+ bool use_wal ; /* do we need to WAL-log our writes? */
2571
2562
} DR_intorel ;
2572
2563
2573
2564
/*
@@ -2692,22 +2683,22 @@ OpenIntoRel(QueryDesc *queryDesc)
2692
2683
*/
2693
2684
intoRelationDesc = heap_open (intoRelationId , AccessExclusiveLock );
2694
2685
2695
- /* use_wal off requires rd_targblock be initially invalid */
2696
- Assert (intoRelationDesc -> rd_targblock == InvalidBlockNumber );
2697
-
2698
- /*
2699
- * We can skip WAL-logging the insertions, unless PITR is in use.
2700
- */
2701
- estate -> es_into_relation_use_wal = XLogArchivingActive ();
2702
- estate -> es_into_relation_descriptor = intoRelationDesc ;
2703
-
2704
2686
/*
2705
2687
* Now replace the query's DestReceiver with one for SELECT INTO
2706
2688
*/
2707
2689
queryDesc -> dest = CreateDestReceiver (DestIntoRel , NULL );
2708
2690
myState = (DR_intorel * ) queryDesc -> dest ;
2709
2691
Assert (myState -> pub .mydest == DestIntoRel );
2710
2692
myState -> estate = estate ;
2693
+
2694
+ /*
2695
+ * We can skip WAL-logging the insertions, unless PITR is in use.
2696
+ */
2697
+ myState -> use_wal = XLogArchivingActive ();
2698
+ myState -> rel = intoRelationDesc ;
2699
+
2700
+ /* use_wal off requires rd_targblock be initially invalid */
2701
+ Assert (intoRelationDesc -> rd_targblock == InvalidBlockNumber );
2711
2702
}
2712
2703
2713
2704
/*
@@ -2716,42 +2707,40 @@ OpenIntoRel(QueryDesc *queryDesc)
2716
2707
static void
2717
2708
CloseIntoRel (QueryDesc * queryDesc )
2718
2709
{
2719
- EState * estate = queryDesc -> estate ;
2710
+ DR_intorel * myState = ( DR_intorel * ) queryDesc -> dest ;
2720
2711
2721
2712
/* OpenIntoRel might never have gotten called */
2722
- if (estate -> es_into_relation_descriptor )
2713
+ if (myState && myState -> pub . mydest == DestIntoRel && myState -> rel )
2723
2714
{
2724
2715
/* If we skipped using WAL, must heap_sync before commit */
2725
- if (!estate -> es_into_relation_use_wal )
2726
- heap_sync (estate -> es_into_relation_descriptor );
2716
+ if (!myState -> use_wal )
2717
+ heap_sync (myState -> rel );
2727
2718
2728
2719
/* close rel, but keep lock until commit */
2729
- heap_close (estate -> es_into_relation_descriptor , NoLock );
2720
+ heap_close (myState -> rel , NoLock );
2730
2721
2731
- estate -> es_into_relation_descriptor = NULL ;
2722
+ myState -> rel = NULL ;
2732
2723
}
2733
2724
}
2734
2725
2735
2726
/*
2736
2727
* CreateIntoRelDestReceiver -- create a suitable DestReceiver object
2737
2728
*
2738
2729
* Since CreateDestReceiver doesn't accept the parameters we'd need,
2739
- * we just leave the private fields empty here. OpenIntoRel will
2730
+ * we just leave the private fields zeroed here. OpenIntoRel will
2740
2731
* fill them in.
2741
2732
*/
2742
2733
DestReceiver *
2743
2734
CreateIntoRelDestReceiver (void )
2744
2735
{
2745
- DR_intorel * self = (DR_intorel * ) palloc (sizeof (DR_intorel ));
2736
+ DR_intorel * self = (DR_intorel * ) palloc0 (sizeof (DR_intorel ));
2746
2737
2747
2738
self -> pub .receiveSlot = intorel_receive ;
2748
2739
self -> pub .rStartup = intorel_startup ;
2749
2740
self -> pub .rShutdown = intorel_shutdown ;
2750
2741
self -> pub .rDestroy = intorel_destroy ;
2751
2742
self -> pub .mydest = DestIntoRel ;
2752
2743
2753
- self -> estate = NULL ;
2754
-
2755
2744
return (DestReceiver * ) self ;
2756
2745
}
2757
2746
@@ -2771,21 +2760,22 @@ static void
2771
2760
intorel_receive (TupleTableSlot * slot , DestReceiver * self )
2772
2761
{
2773
2762
DR_intorel * myState = (DR_intorel * ) self ;
2774
- EState * estate = myState -> estate ;
2775
2763
HeapTuple tuple ;
2776
2764
2777
- tuple = ExecCopySlotTuple (slot );
2765
+ /*
2766
+ * get the heap tuple out of the tuple table slot, making sure we have a
2767
+ * writable copy
2768
+ */
2769
+ tuple = ExecMaterializeSlot (slot );
2778
2770
2779
- heap_insert (estate -> es_into_relation_descriptor ,
2771
+ heap_insert (myState -> rel ,
2780
2772
tuple ,
2781
- estate -> es_output_cid ,
2782
- estate -> es_into_relation_use_wal ,
2773
+ myState -> estate -> es_output_cid ,
2774
+ myState -> use_wal ,
2783
2775
false); /* never any point in using FSM */
2784
2776
2785
2777
/* We know this is a newly created relation, so there are no indexes */
2786
2778
2787
- heap_freetuple (tuple );
2788
-
2789
2779
IncrAppended ();
2790
2780
}
2791
2781
0 commit comments