LCOV - differential code coverage report
Current view: top level - src/backend/executor - tstoreReceiver.c (source / functions) Coverage Total Hit UBC GIC GNC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 99.0 % 100 99 1 1 98
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 8 8 1 7
Baseline: 16@8cea358b128 Branches: 88.1 % 42 37 5 37
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 99.0 % 100 99 1 1 98
Function coverage date bins:
(240..) days: 100.0 % 8 8 1 7
Branch coverage date bins:
(240..) days: 88.1 % 42 37 5 37

 Age         Owner                    Branch data    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-2024, 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
 7647 tgl@sss.pgh.pa.us          56                 :CBC       22403 : tstoreStartupReceiver(DestReceiver *self, int operation, TupleDesc typeinfo)
                                 57                 :                : {
 5613                            58                 :          22403 :     TStoreState *myState = (TStoreState *) self;
                                 59                 :          22403 :     bool        needtoast = false;
                                 60                 :          22403 :     int         natts = typeinfo->natts;
                                 61                 :                :     int         i;
                                 62                 :                : 
                                 63                 :                :     /* Check if any columns require detoast work */
                                 64         [ +  + ]:          22403 :     if (myState->detoast)
                                 65                 :                :     {
                                 66         [ +  + ]:            171 :         for (i = 0; i < natts; i++)
                                 67                 :                :         {
 2429 andres@anarazel.de         68                 :            140 :             Form_pg_attribute attr = TupleDescAttr(typeinfo, i);
                                 69                 :                : 
                                 70         [ -  + ]:            140 :             if (attr->attisdropped)
 5613 tgl@sss.pgh.pa.us          71                 :UBC           0 :                 continue;
 2429 andres@anarazel.de         72         [ +  + ]:CBC         140 :             if (attr->attlen == -1)
                                 73                 :                :             {
 5613 tgl@sss.pgh.pa.us          74                 :             10 :                 needtoast = true;
                                 75                 :             10 :                 break;
                                 76                 :                :             }
                                 77                 :                :         }
                                 78                 :                :     }
                                 79                 :                : 
                                 80                 :                :     /* Check if tuple conversion is needed */
 1402                            81         [ +  + ]:          22403 :     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                 :          21076 :         myState->tupmap = NULL;
                                 87                 :                : 
                                 88                 :                :     /* Set up appropriate callback */
 5613                            89         [ +  + ]:          22403 :     if (needtoast)
                                 90                 :                :     {
 1402                            91         [ -  + ]:             10 :         Assert(!myState->tupmap);
 5613                            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));
 1402                            98                 :             10 :         myState->mapslot = NULL;
                                 99                 :                :     }
                                100         [ +  + ]:          22393 :     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                 :                :     {
 5613                           110                 :          22375 :         myState->pub.receiveSlot = tstoreReceiveSlot_notoast;
                                111                 :          22375 :         myState->outvalues = NULL;
                                112                 :          22375 :         myState->tofree = NULL;
 1402                           113                 :          22375 :         myState->mapslot = NULL;
                                114                 :                :     }
 7689 bruce@momjian.us          115                 :          22403 : }
                                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
 5613 tgl@sss.pgh.pa.us         122                 :         235539 : tstoreReceiveSlot_notoast(TupleTableSlot *slot, DestReceiver *self)
                                123                 :                : {
 7689 bruce@momjian.us          124                 :         235539 :     TStoreState *myState = (TStoreState *) self;
                                125                 :                : 
 6501 tgl@sss.pgh.pa.us         126                 :         235539 :     tuplestore_puttupleslot(myState->tstore, slot);
                                127                 :                : 
 2869 rhaas@postgresql.org      128                 :         235539 :     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
 5613 tgl@sss.pgh.pa.us         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];
 2429 andres@anarazel.de        157                 :             41 :         Form_pg_attribute attr = TupleDescAttr(typeinfo, i);
                                158                 :                : 
                                159   [ +  -  +  +  :             41 :         if (!attr->attisdropped && attr->attlen == -1 && !slot->tts_isnull[i])
                                              +  + ]
                                160                 :                :         {
 5613 tgl@sss.pgh.pa.us         161         [ +  + ]:             20 :             if (VARATT_IS_EXTERNAL(DatumGetPointer(val)))
                                162                 :                :             {
 1654 rhaas@postgresql.org      163                 :              5 :                 val = PointerGetDatum(detoast_external_attr((struct varlena *)
 2489 tgl@sss.pgh.pa.us         164                 :              5 :                                                             DatumGetPointer(val)));
 5613                           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,
 5613 tgl@sss.pgh.pa.us         177                 :GIC          23 :                          myState->outvalues, slot->tts_isnull);
 5613 tgl@sss.pgh.pa.us         178                 :CBC          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                 :                : 
 2869 rhaas@postgresql.org      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
 1402 tgl@sss.pgh.pa.us         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
 7649                           206                 :          22335 : tstoreShutdownReceiver(DestReceiver *self)
                                207                 :                : {
 5613                           208                 :          22335 :     TStoreState *myState = (TStoreState *) self;
                                209                 :                : 
                                210                 :                :     /* Release workspace if any */
                                211         [ +  + ]:          22335 :     if (myState->outvalues)
                                212                 :             10 :         pfree(myState->outvalues);
                                213                 :          22335 :     myState->outvalues = NULL;
                                214         [ +  + ]:          22335 :     if (myState->tofree)
                                215                 :             10 :         pfree(myState->tofree);
                                216                 :          22335 :     myState->tofree = NULL;
 1402                           217         [ +  + ]:          22335 :     if (myState->tupmap)
                                218                 :             18 :         free_conversion_map(myState->tupmap);
                                219                 :          22335 :     myState->tupmap = NULL;
                                220         [ +  + ]:          22335 :     if (myState->mapslot)
                                221                 :             18 :         ExecDropSingleTupleTableSlot(myState->mapslot);
                                222                 :          22335 :     myState->mapslot = NULL;
 7689 bruce@momjian.us          223                 :          22335 : }
                                224                 :                : 
                                225                 :                : /*
                                226                 :                :  * Destroy receiver when done with it
                                227                 :                :  */
                                228                 :                : static void
 7649 tgl@sss.pgh.pa.us         229                 :          22335 : tstoreDestroyReceiver(DestReceiver *self)
                                230                 :                : {
                                231                 :          22335 :     pfree(self);
                                232                 :          22335 : }
                                233                 :                : 
                                234                 :                : /*
                                235                 :                :  * Initially create a DestReceiver object.
                                236                 :                :  */
                                237                 :                : DestReceiver *
 5614                           238                 :          22522 : CreateTuplestoreDestReceiver(void)
                                239                 :                : {
                                240                 :          22522 :     TStoreState *self = (TStoreState *) palloc0(sizeof(TStoreState));
                                241                 :                : 
 5613                           242                 :          22522 :     self->pub.receiveSlot = tstoreReceiveSlot_notoast;   /* might change */
 7557                           243                 :          22522 :     self->pub.rStartup = tstoreStartupReceiver;
                                244                 :          22522 :     self->pub.rShutdown = tstoreShutdownReceiver;
                                245                 :          22522 :     self->pub.rDestroy = tstoreDestroyReceiver;
 6737 alvherre@alvh.no-ip.      246                 :          22522 :     self->pub.mydest = DestTuplestore;
                                247                 :                : 
                                248                 :                :     /* private fields will be set by SetTuplestoreDestReceiverParams */
                                249                 :                : 
 7689 bruce@momjian.us          250                 :          22522 :     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
 5614 tgl@sss.pgh.pa.us         266                 :          22522 : SetTuplestoreDestReceiverParams(DestReceiver *self,
                                267                 :                :                                 Tuplestorestate *tStore,
                                268                 :                :                                 MemoryContext tContext,
                                269                 :                :                                 bool detoast,
                                270                 :                :                                 TupleDesc target_tupdesc,
                                271                 :                :                                 const char *map_failure_msg)
                                272                 :                : {
                                273                 :          22522 :     TStoreState *myState = (TStoreState *) self;
                                274                 :                : 
 1402                           275   [ +  +  -  + ]:          22522 :     Assert(!(detoast && target_tupdesc));
                                276                 :                : 
 5614                           277         [ -  + ]:          22522 :     Assert(myState->pub.mydest == DestTuplestore);
                                278                 :          22522 :     myState->tstore = tStore;
                                279                 :          22522 :     myState->cxt = tContext;
 5613                           280                 :          22522 :     myState->detoast = detoast;
 1402                           281                 :          22522 :     myState->target_tupdesc = target_tupdesc;
                                282                 :          22522 :     myState->map_failure_msg = map_failure_msg;
 5614                           283                 :          22522 : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622