~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to src/backend/executor/tstoreReceiver.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * tstoreReceiver.c
 
4
 *        An implementation of DestReceiver that stores the result tuples in
 
5
 *        a Tuplestore.
 
6
 *
 
7
 * Optionally, we can force detoasting (but not decompression) of out-of-line
 
8
 * toasted values.      This is to support cursors WITH HOLD, which must retain
 
9
 * data even if the underlying table is dropped.
 
10
 *
 
11
 *
 
12
 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
 
13
 * Portions Copyright (c) 1994, Regents of the University of California
 
14
 *
 
15
 * IDENTIFICATION
 
16
 *        src/backend/executor/tstoreReceiver.c
 
17
 *
 
18
 *-------------------------------------------------------------------------
 
19
 */
 
20
 
 
21
#include "postgres.h"
 
22
 
 
23
#include "access/tuptoaster.h"
 
24
#include "executor/tstoreReceiver.h"
 
25
 
 
26
 
 
27
typedef struct
 
28
{
 
29
        DestReceiver pub;
 
30
        /* parameters: */
 
31
        Tuplestorestate *tstore;        /* where to put the data */
 
32
        MemoryContext cxt;                      /* context containing tstore */
 
33
        bool            detoast;                /* were we told to detoast? */
 
34
        /* workspace: */
 
35
        Datum      *outvalues;          /* values array for result tuple */
 
36
        Datum      *tofree;                     /* temp values to be pfree'd */
 
37
} TStoreState;
 
38
 
 
39
 
 
40
static void tstoreReceiveSlot_notoast(TupleTableSlot *slot, DestReceiver *self);
 
41
static void tstoreReceiveSlot_detoast(TupleTableSlot *slot, DestReceiver *self);
 
42
 
 
43
 
 
44
/*
 
45
 * Prepare to receive tuples from executor.
 
46
 */
 
47
static void
 
48
tstoreStartupReceiver(DestReceiver *self, int operation, TupleDesc typeinfo)
 
49
{
 
50
        TStoreState *myState = (TStoreState *) self;
 
51
        bool            needtoast = false;
 
52
        Form_pg_attribute *attrs = typeinfo->attrs;
 
53
        int                     natts = typeinfo->natts;
 
54
        int                     i;
 
55
 
 
56
        /* Check if any columns require detoast work */
 
57
        if (myState->detoast)
 
58
        {
 
59
                for (i = 0; i < natts; i++)
 
60
                {
 
61
                        if (attrs[i]->attisdropped)
 
62
                                continue;
 
63
                        if (attrs[i]->attlen == -1)
 
64
                        {
 
65
                                needtoast = true;
 
66
                                break;
 
67
                        }
 
68
                }
 
69
        }
 
70
 
 
71
        /* Set up appropriate callback */
 
72
        if (needtoast)
 
73
        {
 
74
                myState->pub.receiveSlot = tstoreReceiveSlot_detoast;
 
75
                /* Create workspace */
 
76
                myState->outvalues = (Datum *)
 
77
                        MemoryContextAlloc(myState->cxt, natts * sizeof(Datum));
 
78
                myState->tofree = (Datum *)
 
79
                        MemoryContextAlloc(myState->cxt, natts * sizeof(Datum));
 
80
        }
 
81
        else
 
82
        {
 
83
                myState->pub.receiveSlot = tstoreReceiveSlot_notoast;
 
84
                myState->outvalues = NULL;
 
85
                myState->tofree = NULL;
 
86
        }
 
87
}
 
88
 
 
89
/*
 
90
 * Receive a tuple from the executor and store it in the tuplestore.
 
91
 * This is for the easy case where we don't have to detoast.
 
92
 */
 
93
static void
 
94
tstoreReceiveSlot_notoast(TupleTableSlot *slot, DestReceiver *self)
 
95
{
 
96
        TStoreState *myState = (TStoreState *) self;
 
97
 
 
98
        tuplestore_puttupleslot(myState->tstore, slot);
 
99
}
 
100
 
 
101
/*
 
102
 * Receive a tuple from the executor and store it in the tuplestore.
 
103
 * This is for the case where we have to detoast any toasted values.
 
104
 */
 
105
static void
 
106
tstoreReceiveSlot_detoast(TupleTableSlot *slot, DestReceiver *self)
 
107
{
 
108
        TStoreState *myState = (TStoreState *) self;
 
109
        TupleDesc       typeinfo = slot->tts_tupleDescriptor;
 
110
        Form_pg_attribute *attrs = typeinfo->attrs;
 
111
        int                     natts = typeinfo->natts;
 
112
        int                     nfree;
 
113
        int                     i;
 
114
        MemoryContext oldcxt;
 
115
 
 
116
        /* Make sure the tuple is fully deconstructed */
 
117
        slot_getallattrs(slot);
 
118
 
 
119
        /*
 
120
         * Fetch back any out-of-line datums.  We build the new datums array in
 
121
         * myState->outvalues[] (but we can re-use the slot's isnull array). Also,
 
122
         * remember the fetched values to free afterwards.
 
123
         */
 
124
        nfree = 0;
 
125
        for (i = 0; i < natts; i++)
 
126
        {
 
127
                Datum           val = slot->tts_values[i];
 
128
 
 
129
                if (!attrs[i]->attisdropped &&
 
130
                        attrs[i]->attlen == -1 &&
 
131
                        !slot->tts_isnull[i])
 
132
                {
 
133
                        if (VARATT_IS_EXTERNAL(DatumGetPointer(val)))
 
134
                        {
 
135
                                val = PointerGetDatum(heap_tuple_fetch_attr((struct varlena *)
 
136
                                                                                                          DatumGetPointer(val)));
 
137
                                myState->tofree[nfree++] = val;
 
138
                        }
 
139
                }
 
140
 
 
141
                myState->outvalues[i] = val;
 
142
        }
 
143
 
 
144
        /*
 
145
         * Push the modified tuple into the tuplestore.
 
146
         */
 
147
        oldcxt = MemoryContextSwitchTo(myState->cxt);
 
148
        tuplestore_putvalues(myState->tstore, typeinfo,
 
149
                                                 myState->outvalues, slot->tts_isnull);
 
150
        MemoryContextSwitchTo(oldcxt);
 
151
 
 
152
        /* And release any temporary detoasted values */
 
153
        for (i = 0; i < nfree; i++)
 
154
                pfree(DatumGetPointer(myState->tofree[i]));
 
155
}
 
156
 
 
157
/*
 
158
 * Clean up at end of an executor run
 
159
 */
 
160
static void
 
161
tstoreShutdownReceiver(DestReceiver *self)
 
162
{
 
163
        TStoreState *myState = (TStoreState *) self;
 
164
 
 
165
        /* Release workspace if any */
 
166
        if (myState->outvalues)
 
167
                pfree(myState->outvalues);
 
168
        myState->outvalues = NULL;
 
169
        if (myState->tofree)
 
170
                pfree(myState->tofree);
 
171
        myState->tofree = NULL;
 
172
}
 
173
 
 
174
/*
 
175
 * Destroy receiver when done with it
 
176
 */
 
177
static void
 
178
tstoreDestroyReceiver(DestReceiver *self)
 
179
{
 
180
        pfree(self);
 
181
}
 
182
 
 
183
/*
 
184
 * Initially create a DestReceiver object.
 
185
 */
 
186
DestReceiver *
 
187
CreateTuplestoreDestReceiver(void)
 
188
{
 
189
        TStoreState *self = (TStoreState *) palloc0(sizeof(TStoreState));
 
190
 
 
191
        self->pub.receiveSlot = tstoreReceiveSlot_notoast;      /* might change */
 
192
        self->pub.rStartup = tstoreStartupReceiver;
 
193
        self->pub.rShutdown = tstoreShutdownReceiver;
 
194
        self->pub.rDestroy = tstoreDestroyReceiver;
 
195
        self->pub.mydest = DestTuplestore;
 
196
 
 
197
        /* private fields will be set by SetTuplestoreDestReceiverParams */
 
198
 
 
199
        return (DestReceiver *) self;
 
200
}
 
201
 
 
202
/*
 
203
 * Set parameters for a TuplestoreDestReceiver
 
204
 */
 
205
void
 
206
SetTuplestoreDestReceiverParams(DestReceiver *self,
 
207
                                                                Tuplestorestate *tStore,
 
208
                                                                MemoryContext tContext,
 
209
                                                                bool detoast)
 
210
{
 
211
        TStoreState *myState = (TStoreState *) self;
 
212
 
 
213
        Assert(myState->pub.mydest == DestTuplestore);
 
214
        myState->tstore = tStore;
 
215
        myState->cxt = tContext;
 
216
        myState->detoast = detoast;
 
217
}