Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "postgres.h"
00022
00023 #include "access/tuptoaster.h"
00024 #include "executor/tstoreReceiver.h"
00025
00026
00027 typedef struct
00028 {
00029 DestReceiver pub;
00030
00031 Tuplestorestate *tstore;
00032 MemoryContext cxt;
00033 bool detoast;
00034
00035 Datum *outvalues;
00036 Datum *tofree;
00037 } TStoreState;
00038
00039
00040 static void tstoreReceiveSlot_notoast(TupleTableSlot *slot, DestReceiver *self);
00041 static void tstoreReceiveSlot_detoast(TupleTableSlot *slot, DestReceiver *self);
00042
00043
00044
00045
00046
00047 static void
00048 tstoreStartupReceiver(DestReceiver *self, int operation, TupleDesc typeinfo)
00049 {
00050 TStoreState *myState = (TStoreState *) self;
00051 bool needtoast = false;
00052 Form_pg_attribute *attrs = typeinfo->attrs;
00053 int natts = typeinfo->natts;
00054 int i;
00055
00056
00057 if (myState->detoast)
00058 {
00059 for (i = 0; i < natts; i++)
00060 {
00061 if (attrs[i]->attisdropped)
00062 continue;
00063 if (attrs[i]->attlen == -1)
00064 {
00065 needtoast = true;
00066 break;
00067 }
00068 }
00069 }
00070
00071
00072 if (needtoast)
00073 {
00074 myState->pub.receiveSlot = tstoreReceiveSlot_detoast;
00075
00076 myState->outvalues = (Datum *)
00077 MemoryContextAlloc(myState->cxt, natts * sizeof(Datum));
00078 myState->tofree = (Datum *)
00079 MemoryContextAlloc(myState->cxt, natts * sizeof(Datum));
00080 }
00081 else
00082 {
00083 myState->pub.receiveSlot = tstoreReceiveSlot_notoast;
00084 myState->outvalues = NULL;
00085 myState->tofree = NULL;
00086 }
00087 }
00088
00089
00090
00091
00092
00093 static void
00094 tstoreReceiveSlot_notoast(TupleTableSlot *slot, DestReceiver *self)
00095 {
00096 TStoreState *myState = (TStoreState *) self;
00097
00098 tuplestore_puttupleslot(myState->tstore, slot);
00099 }
00100
00101
00102
00103
00104
00105 static void
00106 tstoreReceiveSlot_detoast(TupleTableSlot *slot, DestReceiver *self)
00107 {
00108 TStoreState *myState = (TStoreState *) self;
00109 TupleDesc typeinfo = slot->tts_tupleDescriptor;
00110 Form_pg_attribute *attrs = typeinfo->attrs;
00111 int natts = typeinfo->natts;
00112 int nfree;
00113 int i;
00114 MemoryContext oldcxt;
00115
00116
00117 slot_getallattrs(slot);
00118
00119
00120
00121
00122
00123
00124 nfree = 0;
00125 for (i = 0; i < natts; i++)
00126 {
00127 Datum val = slot->tts_values[i];
00128
00129 if (!attrs[i]->attisdropped &&
00130 attrs[i]->attlen == -1 &&
00131 !slot->tts_isnull[i])
00132 {
00133 if (VARATT_IS_EXTERNAL(DatumGetPointer(val)))
00134 {
00135 val = PointerGetDatum(heap_tuple_fetch_attr((struct varlena *)
00136 DatumGetPointer(val)));
00137 myState->tofree[nfree++] = val;
00138 }
00139 }
00140
00141 myState->outvalues[i] = val;
00142 }
00143
00144
00145
00146
00147 oldcxt = MemoryContextSwitchTo(myState->cxt);
00148 tuplestore_putvalues(myState->tstore, typeinfo,
00149 myState->outvalues, slot->tts_isnull);
00150 MemoryContextSwitchTo(oldcxt);
00151
00152
00153 for (i = 0; i < nfree; i++)
00154 pfree(DatumGetPointer(myState->tofree[i]));
00155 }
00156
00157
00158
00159
00160 static void
00161 tstoreShutdownReceiver(DestReceiver *self)
00162 {
00163 TStoreState *myState = (TStoreState *) self;
00164
00165
00166 if (myState->outvalues)
00167 pfree(myState->outvalues);
00168 myState->outvalues = NULL;
00169 if (myState->tofree)
00170 pfree(myState->tofree);
00171 myState->tofree = NULL;
00172 }
00173
00174
00175
00176
00177 static void
00178 tstoreDestroyReceiver(DestReceiver *self)
00179 {
00180 pfree(self);
00181 }
00182
00183
00184
00185
00186 DestReceiver *
00187 CreateTuplestoreDestReceiver(void)
00188 {
00189 TStoreState *self = (TStoreState *) palloc0(sizeof(TStoreState));
00190
00191 self->pub.receiveSlot = tstoreReceiveSlot_notoast;
00192 self->pub.rStartup = tstoreStartupReceiver;
00193 self->pub.rShutdown = tstoreShutdownReceiver;
00194 self->pub.rDestroy = tstoreDestroyReceiver;
00195 self->pub.mydest = DestTuplestore;
00196
00197
00198
00199 return (DestReceiver *) self;
00200 }
00201
00202
00203
00204
00205 void
00206 SetTuplestoreDestReceiverParams(DestReceiver *self,
00207 Tuplestorestate *tStore,
00208 MemoryContext tContext,
00209 bool detoast)
00210 {
00211 TStoreState *myState = (TStoreState *) self;
00212
00213 Assert(myState->pub.mydest == DestTuplestore);
00214 myState->tstore = tStore;
00215 myState->cxt = tContext;
00216 myState->detoast = detoast;
00217 }