LCOV - differential code coverage report
Current view: top level - src/backend/executor - tstoreReceiver.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 99.0 % 99 98 1 98
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 8 8 8
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (240..) days: 99.0 % 99 98 1 98
Legend: Lines: hit not hit Function coverage date bins:
(240..) days: 100.0 % 8 8 8

 Age         Owner                  TLA  Line data    Source code
                                  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                 :  * Also optionally, we can apply a tuple conversion map before storing.
                                 12                 :  *
                                 13                 :  *
                                 14                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                 15                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                 16                 :  *
                                 17                 :  * IDENTIFICATION
                                 18                 :  *    src/backend/executor/tstoreReceiver.c
                                 19                 :  *
                                 20                 :  *-------------------------------------------------------------------------
                                 21                 :  */
                                 22                 : 
                                 23                 : #include "postgres.h"
                                 24                 : 
                                 25                 : #include "access/detoast.h"
                                 26                 : #include "access/tupconvert.h"
                                 27                 : #include "executor/tstoreReceiver.h"
                                 28                 : 
                                 29                 : 
                                 30                 : typedef struct
                                 31                 : {
                                 32                 :     DestReceiver pub;
                                 33                 :     /* parameters: */
                                 34                 :     Tuplestorestate *tstore;    /* where to put the data */
                                 35                 :     MemoryContext cxt;          /* context containing tstore */
                                 36                 :     bool        detoast;        /* were we told to detoast? */
                                 37                 :     TupleDesc   target_tupdesc; /* target tupdesc, or NULL if none */
                                 38                 :     const char *map_failure_msg;    /* tupdesc mapping failure message */
                                 39                 :     /* workspace: */
                                 40                 :     Datum      *outvalues;      /* values array for result tuple */
                                 41                 :     Datum      *tofree;         /* temp values to be pfree'd */
                                 42                 :     TupleConversionMap *tupmap; /* conversion map, if needed */
                                 43                 :     TupleTableSlot *mapslot;    /* slot for mapped tuples */
                                 44                 : } TStoreState;
                                 45                 : 
                                 46                 : 
                                 47                 : static bool tstoreReceiveSlot_notoast(TupleTableSlot *slot, DestReceiver *self);
                                 48                 : static bool tstoreReceiveSlot_detoast(TupleTableSlot *slot, DestReceiver *self);
                                 49                 : static bool tstoreReceiveSlot_tupmap(TupleTableSlot *slot, DestReceiver *self);
                                 50                 : 
                                 51                 : 
                                 52                 : /*
                                 53                 :  * Prepare to receive tuples from executor.
                                 54                 :  */
                                 55                 : static void
 7276 tgl                        56 CBC       20166 : tstoreStartupReceiver(DestReceiver *self, int operation, TupleDesc typeinfo)
                                 57                 : {
 5242                            58           20166 :     TStoreState *myState = (TStoreState *) self;
                                 59           20166 :     bool        needtoast = false;
                                 60           20166 :     int         natts = typeinfo->natts;
                                 61                 :     int         i;
                                 62                 : 
                                 63                 :     /* Check if any columns require detoast work */
                                 64           20166 :     if (myState->detoast)
                                 65                 :     {
                                 66             171 :         for (i = 0; i < natts; i++)
                                 67                 :         {
 2058 andres                     68             140 :             Form_pg_attribute attr = TupleDescAttr(typeinfo, i);
                                 69                 : 
                                 70             140 :             if (attr->attisdropped)
 5242 tgl                        71 UBC           0 :                 continue;
 2058 andres                     72 CBC         140 :             if (attr->attlen == -1)
                                 73                 :             {
 5242 tgl                        74              10 :                 needtoast = true;
                                 75              10 :                 break;
                                 76                 :             }
                                 77                 :         }
                                 78                 :     }
                                 79                 : 
                                 80                 :     /* Check if tuple conversion is needed */
 1031                            81           20166 :     if (myState->target_tupdesc)
                                 82            1327 :         myState->tupmap = convert_tuples_by_position(typeinfo,
                                 83                 :                                                      myState->target_tupdesc,
                                 84                 :                                                      myState->map_failure_msg);
                                 85                 :     else
                                 86           18839 :         myState->tupmap = NULL;
                                 87                 : 
                                 88                 :     /* Set up appropriate callback */
 5242                            89           20166 :     if (needtoast)
                                 90                 :     {
 1031                            91              10 :         Assert(!myState->tupmap);
 5242                            92              10 :         myState->pub.receiveSlot = tstoreReceiveSlot_detoast;
                                 93                 :         /* Create workspace */
                                 94              10 :         myState->outvalues = (Datum *)
                                 95              10 :             MemoryContextAlloc(myState->cxt, natts * sizeof(Datum));
                                 96              10 :         myState->tofree = (Datum *)
                                 97              10 :             MemoryContextAlloc(myState->cxt, natts * sizeof(Datum));
 1031                            98              10 :         myState->mapslot = NULL;
                                 99                 :     }
                                100           20156 :     else if (myState->tupmap)
                                101                 :     {
                                102              18 :         myState->pub.receiveSlot = tstoreReceiveSlot_tupmap;
                                103              18 :         myState->outvalues = NULL;
                                104              18 :         myState->tofree = NULL;
                                105              18 :         myState->mapslot = MakeSingleTupleTableSlot(myState->target_tupdesc,
                                106                 :                                                     &TTSOpsVirtual);
                                107                 :     }
                                108                 :     else
                                109                 :     {
 5242                           110           20138 :         myState->pub.receiveSlot = tstoreReceiveSlot_notoast;
                                111           20138 :         myState->outvalues = NULL;
                                112           20138 :         myState->tofree = NULL;
 1031                           113           20138 :         myState->mapslot = NULL;
                                114                 :     }
 7318 bruce                     115           20166 : }
                                116                 : 
                                117                 : /*
                                118                 :  * Receive a tuple from the executor and store it in the tuplestore.
                                119                 :  * This is for the easy case where we don't have to detoast nor map anything.
                                120                 :  */
                                121                 : static bool
 5242 tgl                       122          228037 : tstoreReceiveSlot_notoast(TupleTableSlot *slot, DestReceiver *self)
                                123                 : {
 7318 bruce                     124          228037 :     TStoreState *myState = (TStoreState *) self;
                                125                 : 
 6130 tgl                       126          228037 :     tuplestore_puttupleslot(myState->tstore, slot);
                                127                 : 
 2498 rhaas                     128          228037 :     return true;
                                129                 : }
                                130                 : 
                                131                 : /*
                                132                 :  * Receive a tuple from the executor and store it in the tuplestore.
                                133                 :  * This is for the case where we have to detoast any toasted values.
                                134                 :  */
                                135                 : static bool
 5242 tgl                       136              23 : tstoreReceiveSlot_detoast(TupleTableSlot *slot, DestReceiver *self)
                                137                 : {
                                138              23 :     TStoreState *myState = (TStoreState *) self;
                                139              23 :     TupleDesc   typeinfo = slot->tts_tupleDescriptor;
                                140              23 :     int         natts = typeinfo->natts;
                                141                 :     int         nfree;
                                142                 :     int         i;
                                143                 :     MemoryContext oldcxt;
                                144                 : 
                                145                 :     /* Make sure the tuple is fully deconstructed */
                                146              23 :     slot_getallattrs(slot);
                                147                 : 
                                148                 :     /*
                                149                 :      * Fetch back any out-of-line datums.  We build the new datums array in
                                150                 :      * myState->outvalues[] (but we can re-use the slot's isnull array). Also,
                                151                 :      * remember the fetched values to free afterwards.
                                152                 :      */
                                153              23 :     nfree = 0;
                                154              64 :     for (i = 0; i < natts; i++)
                                155                 :     {
                                156              41 :         Datum       val = slot->tts_values[i];
 2058 andres                    157              41 :         Form_pg_attribute attr = TupleDescAttr(typeinfo, i);
                                158                 : 
                                159              41 :         if (!attr->attisdropped && attr->attlen == -1 && !slot->tts_isnull[i])
                                160                 :         {
 5242 tgl                       161              20 :             if (VARATT_IS_EXTERNAL(DatumGetPointer(val)))
                                162                 :             {
 1283 rhaas                     163               5 :                 val = PointerGetDatum(detoast_external_attr((struct varlena *)
 2118 tgl                       164               5 :                                                             DatumGetPointer(val)));
 5242                           165               5 :                 myState->tofree[nfree++] = val;
                                166                 :             }
                                167                 :         }
                                168                 : 
                                169              41 :         myState->outvalues[i] = val;
                                170                 :     }
                                171                 : 
                                172                 :     /*
                                173                 :      * Push the modified tuple into the tuplestore.
                                174                 :      */
                                175              23 :     oldcxt = MemoryContextSwitchTo(myState->cxt);
                                176              23 :     tuplestore_putvalues(myState->tstore, typeinfo,
                                177                 :                          myState->outvalues, slot->tts_isnull);
                                178              23 :     MemoryContextSwitchTo(oldcxt);
                                179                 : 
                                180                 :     /* And release any temporary detoasted values */
                                181              28 :     for (i = 0; i < nfree; i++)
                                182               5 :         pfree(DatumGetPointer(myState->tofree[i]));
                                183                 : 
 2498 rhaas                     184              23 :     return true;
                                185                 : }
                                186                 : 
                                187                 : /*
                                188                 :  * Receive a tuple from the executor and store it in the tuplestore.
                                189                 :  * This is for the case where we must apply a tuple conversion map.
                                190                 :  */
                                191                 : static bool
 1031 tgl                       192              36 : tstoreReceiveSlot_tupmap(TupleTableSlot *slot, DestReceiver *self)
                                193                 : {
                                194              36 :     TStoreState *myState = (TStoreState *) self;
                                195                 : 
                                196              36 :     execute_attr_map_slot(myState->tupmap->attrMap, slot, myState->mapslot);
                                197              36 :     tuplestore_puttupleslot(myState->tstore, myState->mapslot);
                                198                 : 
                                199              36 :     return true;
                                200                 : }
                                201                 : 
                                202                 : /*
                                203                 :  * Clean up at end of an executor run
                                204                 :  */
                                205                 : static void
 7278                           206           20098 : tstoreShutdownReceiver(DestReceiver *self)
                                207                 : {
 5242                           208           20098 :     TStoreState *myState = (TStoreState *) self;
                                209                 : 
                                210                 :     /* Release workspace if any */
                                211           20098 :     if (myState->outvalues)
                                212              10 :         pfree(myState->outvalues);
                                213           20098 :     myState->outvalues = NULL;
                                214           20098 :     if (myState->tofree)
                                215              10 :         pfree(myState->tofree);
                                216           20098 :     myState->tofree = NULL;
 1031                           217           20098 :     if (myState->tupmap)
                                218              18 :         free_conversion_map(myState->tupmap);
                                219           20098 :     myState->tupmap = NULL;
                                220           20098 :     if (myState->mapslot)
                                221              18 :         ExecDropSingleTupleTableSlot(myState->mapslot);
                                222           20098 :     myState->mapslot = NULL;
 7318 bruce                     223           20098 : }
                                224                 : 
                                225                 : /*
                                226                 :  * Destroy receiver when done with it
                                227                 :  */
                                228                 : static void
 7278 tgl                       229           20098 : tstoreDestroyReceiver(DestReceiver *self)
                                230                 : {
                                231           20098 :     pfree(self);
                                232           20098 : }
                                233                 : 
                                234                 : /*
                                235                 :  * Initially create a DestReceiver object.
                                236                 :  */
                                237                 : DestReceiver *
 5243                           238           20283 : CreateTuplestoreDestReceiver(void)
                                239                 : {
                                240           20283 :     TStoreState *self = (TStoreState *) palloc0(sizeof(TStoreState));
                                241                 : 
 5242                           242           20283 :     self->pub.receiveSlot = tstoreReceiveSlot_notoast;   /* might change */
 7186                           243           20283 :     self->pub.rStartup = tstoreStartupReceiver;
                                244           20283 :     self->pub.rShutdown = tstoreShutdownReceiver;
                                245           20283 :     self->pub.rDestroy = tstoreDestroyReceiver;
 6366 alvherre                  246           20283 :     self->pub.mydest = DestTuplestore;
                                247                 : 
                                248                 :     /* private fields will be set by SetTuplestoreDestReceiverParams */
                                249                 : 
 7318 bruce                     250           20283 :     return (DestReceiver *) self;
                                251                 : }
                                252                 : 
                                253                 : /*
                                254                 :  * Set parameters for a TuplestoreDestReceiver
                                255                 :  *
                                256                 :  * tStore: where to store the tuples
                                257                 :  * tContext: memory context containing tStore
                                258                 :  * detoast: forcibly detoast contained data?
                                259                 :  * target_tupdesc: if not NULL, forcibly convert tuples to this rowtype
                                260                 :  * map_failure_msg: error message to use if mapping to target_tupdesc fails
                                261                 :  *
                                262                 :  * We don't currently support both detoast and target_tupdesc at the same
                                263                 :  * time, just because no existing caller needs that combination.
                                264                 :  */
                                265                 : void
 5243 tgl                       266           20283 : SetTuplestoreDestReceiverParams(DestReceiver *self,
                                267                 :                                 Tuplestorestate *tStore,
                                268                 :                                 MemoryContext tContext,
                                269                 :                                 bool detoast,
                                270                 :                                 TupleDesc target_tupdesc,
                                271                 :                                 const char *map_failure_msg)
                                272                 : {
                                273           20283 :     TStoreState *myState = (TStoreState *) self;
                                274                 : 
 1031                           275           20283 :     Assert(!(detoast && target_tupdesc));
                                276                 : 
 5243                           277           20283 :     Assert(myState->pub.mydest == DestTuplestore);
                                278           20283 :     myState->tstore = tStore;
                                279           20283 :     myState->cxt = tContext;
 5242                           280           20283 :     myState->detoast = detoast;
 1031                           281           20283 :     myState->target_tupdesc = target_tupdesc;
                                282           20283 :     myState->map_failure_msg = map_failure_msg;
 5243                           283           20283 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a