LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - partitionfuncs.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 98.7 % 76 75 1 75
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 4 4 4
Baseline: 16@8cea358b128 Branches: 85.4 % 48 41 7 41
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: 98.7 % 76 75 1 75
Function coverage date bins:
(240..) days: 100.0 % 4 4 4
Branch coverage date bins:
(240..) days: 85.4 % 48 41 7 41

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * partitionfuncs.c
                                  4                 :                :  *    Functions for accessing partition-related metadata
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
                                  7                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :                :  *
                                  9                 :                :  *
                                 10                 :                :  * IDENTIFICATION
                                 11                 :                :  *    src/backend/utils/adt/partitionfuncs.c
                                 12                 :                :  *
                                 13                 :                :  *-------------------------------------------------------------------------
                                 14                 :                :  */
                                 15                 :                : 
                                 16                 :                : #include "postgres.h"
                                 17                 :                : 
                                 18                 :                : #include "access/htup_details.h"
                                 19                 :                : #include "catalog/partition.h"
                                 20                 :                : #include "catalog/pg_class.h"
                                 21                 :                : #include "catalog/pg_inherits.h"
                                 22                 :                : #include "funcapi.h"
                                 23                 :                : #include "utils/fmgrprotos.h"
                                 24                 :                : #include "utils/lsyscache.h"
                                 25                 :                : #include "utils/syscache.h"
                                 26                 :                : 
                                 27                 :                : /*
                                 28                 :                :  * Checks if a given relation can be part of a partition tree.  Returns
                                 29                 :                :  * false if the relation cannot be processed, in which case it is up to
                                 30                 :                :  * the caller to decide what to do, by either raising an error or doing
                                 31                 :                :  * something else.
                                 32                 :                :  */
                                 33                 :                : static bool
 1892 michael@paquier.xyz        34                 :CBC        1196 : check_rel_can_be_partition(Oid relid)
                                 35                 :                : {
                                 36                 :                :     char        relkind;
                                 37                 :                :     bool        relispartition;
                                 38                 :                : 
                                 39                 :                :     /* Check if relation exists */
                                 40         [ +  + ]:           1196 :     if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relid)))
                                 41                 :              9 :         return false;
                                 42                 :                : 
                                 43                 :           1187 :     relkind = get_rel_relkind(relid);
 1870                            44                 :           1187 :     relispartition = get_rel_relispartition(relid);
                                 45                 :                : 
                                 46                 :                :     /* Only allow relation types that can appear in partition trees. */
  863 peter@eisentraut.org       47   [ +  +  +  +  :           1187 :     if (!relispartition && !RELKIND_HAS_PARTITIONS(relkind))
                                              +  + ]
 1892 michael@paquier.xyz        48                 :            237 :         return false;
                                 49                 :                : 
                                 50                 :            950 :     return true;
                                 51                 :                : }
                                 52                 :                : 
                                 53                 :                : /*
                                 54                 :                :  * pg_partition_tree
                                 55                 :                :  *
                                 56                 :                :  * Produce a view with one row per member of a partition tree, beginning
                                 57                 :                :  * from the top-most parent given by the caller.  This gives information
                                 58                 :                :  * about each partition, its immediate partitioned parent, if it is
                                 59                 :                :  * a leaf partition and its level in the hierarchy.
                                 60                 :                :  */
                                 61                 :                : Datum
 1993                            62                 :            473 : pg_partition_tree(PG_FUNCTION_ARGS)
                                 63                 :                : {
                                 64                 :                : #define PG_PARTITION_TREE_COLS  4
                                 65                 :            473 :     Oid         rootrelid = PG_GETARG_OID(0);
                                 66                 :                :     FuncCallContext *funcctx;
                                 67                 :                :     List       *partitions;
                                 68                 :                : 
                                 69                 :                :     /* stuff done only on the first call of the function */
                                 70         [ +  + ]:            473 :     if (SRF_IS_FIRSTCALL())
                                 71                 :                :     {
                                 72                 :                :         MemoryContext oldcxt;
                                 73                 :                :         TupleDesc   tupdesc;
                                 74                 :                : 
                                 75                 :                :         /* create a function context for cross-call persistence */
                                 76                 :            101 :         funcctx = SRF_FIRSTCALL_INIT();
                                 77                 :                : 
 1871                            78         [ +  + ]:            101 :         if (!check_rel_can_be_partition(rootrelid))
                                 79                 :             18 :             SRF_RETURN_DONE(funcctx);
                                 80                 :                : 
                                 81                 :                :         /* switch to memory context appropriate for multiple function calls */
 1993                            82                 :             83 :         oldcxt = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
                                 83                 :                : 
                                 84                 :                :         /*
                                 85                 :                :          * Find all members of inheritance set.  We only need AccessShareLock
                                 86                 :                :          * on the children for the partition information lookup.
                                 87                 :                :          */
                                 88                 :             83 :         partitions = find_all_inheritors(rootrelid, AccessShareLock, NULL);
                                 89                 :                : 
  480                            90         [ -  + ]:             83 :         if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
  480 michael@paquier.xyz        91         [ #  # ]:UBC           0 :             elog(ERROR, "return type must be a row type");
  480 michael@paquier.xyz        92                 :CBC          83 :         funcctx->tuple_desc = tupdesc;
                                 93                 :                : 
                                 94                 :                :         /* The only state we need is the partition list */
 1735 tgl@sss.pgh.pa.us          95                 :             83 :         funcctx->user_fctx = (void *) partitions;
                                 96                 :                : 
 1993 michael@paquier.xyz        97                 :             83 :         MemoryContextSwitchTo(oldcxt);
                                 98                 :                :     }
                                 99                 :                : 
                                100                 :                :     /* stuff done on every call of the function */
                                101                 :            455 :     funcctx = SRF_PERCALL_SETUP();
 1735 tgl@sss.pgh.pa.us         102                 :            455 :     partitions = (List *) funcctx->user_fctx;
                                103                 :                : 
                                104         [ +  + ]:            455 :     if (funcctx->call_cntr < list_length(partitions))
                                105                 :                :     {
                                106                 :                :         Datum       result;
  638 peter@eisentraut.org      107                 :            372 :         Datum       values[PG_PARTITION_TREE_COLS] = {0};
                                108                 :            372 :         bool        nulls[PG_PARTITION_TREE_COLS] = {0};
                                109                 :                :         HeapTuple   tuple;
 1993 michael@paquier.xyz       110                 :            372 :         Oid         parentid = InvalidOid;
 1735 tgl@sss.pgh.pa.us         111                 :            372 :         Oid         relid = list_nth_oid(partitions, funcctx->call_cntr);
 1993 michael@paquier.xyz       112                 :            372 :         char        relkind = get_rel_relkind(relid);
                                113                 :            372 :         int         level = 0;
 1735 tgl@sss.pgh.pa.us         114                 :            372 :         List       *ancestors = get_partition_ancestors(relid);
                                115                 :                :         ListCell   *lc;
                                116                 :                : 
                                117                 :                :         /*
                                118                 :                :          * Form tuple with appropriate data.
                                119                 :                :          */
                                120                 :                : 
                                121                 :                :         /* relid */
 1993 michael@paquier.xyz       122                 :            372 :         values[0] = ObjectIdGetDatum(relid);
                                123                 :                : 
                                124                 :                :         /* parentid */
                                125         [ +  + ]:            372 :         if (ancestors != NIL)
                                126                 :            307 :             parentid = linitial_oid(ancestors);
                                127         [ +  + ]:            372 :         if (OidIsValid(parentid))
                                128                 :            307 :             values[1] = ObjectIdGetDatum(parentid);
                                129                 :                :         else
                                130                 :             65 :             nulls[1] = true;
                                131                 :                : 
                                132                 :                :         /* isleaf */
  863 peter@eisentraut.org      133   [ +  +  +  + ]:            372 :         values[2] = BoolGetDatum(!RELKIND_HAS_PARTITIONS(relkind));
                                134                 :                : 
                                135                 :                :         /* level */
 1993 michael@paquier.xyz       136         [ +  + ]:            372 :         if (relid != rootrelid)
                                137                 :                :         {
                                138   [ +  -  +  -  :            412 :             foreach(lc, ancestors)
                                              +  - ]
                                139                 :                :             {
                                140                 :            412 :                 level++;
                                141         [ +  + ]:            412 :                 if (lfirst_oid(lc) == rootrelid)
                                142                 :            289 :                     break;
                                143                 :                :             }
                                144                 :                :         }
                                145                 :            372 :         values[3] = Int32GetDatum(level);
                                146                 :                : 
                                147                 :            372 :         tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
                                148                 :            372 :         result = HeapTupleGetDatum(tuple);
                                149                 :            372 :         SRF_RETURN_NEXT(funcctx, result);
                                150                 :                :     }
                                151                 :                : 
                                152                 :                :     /* done when there are no more elements left */
                                153                 :             83 :     SRF_RETURN_DONE(funcctx);
                                154                 :                : }
                                155                 :                : 
                                156                 :                : /*
                                157                 :                :  * pg_partition_root
                                158                 :                :  *
                                159                 :                :  * Returns the top-most parent of the partition tree to which a given
                                160                 :                :  * relation belongs, or NULL if it's not (or cannot be) part of any
                                161                 :                :  * partition tree.
                                162                 :                :  */
                                163                 :                : Datum
 1892                           164                 :             48 : pg_partition_root(PG_FUNCTION_ARGS)
                                165                 :                : {
                                166                 :             48 :     Oid         relid = PG_GETARG_OID(0);
                                167                 :                :     Oid         rootrelid;
                                168                 :                :     List       *ancestors;
                                169                 :                : 
                                170         [ +  + ]:             48 :     if (!check_rel_can_be_partition(relid))
                                171                 :             18 :         PG_RETURN_NULL();
                                172                 :                : 
                                173                 :                :     /* fetch the list of ancestors */
                                174                 :             30 :     ancestors = get_partition_ancestors(relid);
                                175                 :                : 
                                176                 :                :     /*
                                177                 :                :      * If the input relation is already the top-most parent, just return
                                178                 :                :      * itself.
                                179                 :                :      */
 1850                           180         [ +  + ]:             30 :     if (ancestors == NIL)
                                181                 :              6 :         PG_RETURN_OID(relid);
                                182                 :                : 
 1892                           183                 :             24 :     rootrelid = llast_oid(ancestors);
                                184                 :             24 :     list_free(ancestors);
                                185                 :                : 
                                186                 :                :     /*
                                187                 :                :      * "rootrelid" must contain a valid OID, given that the input relation is
                                188                 :                :      * a valid partition tree member as checked above.
                                189                 :                :      */
                                190         [ -  + ]:             24 :     Assert(OidIsValid(rootrelid));
                                191                 :             24 :     PG_RETURN_OID(rootrelid);
                                192                 :                : }
                                193                 :                : 
                                194                 :                : /*
                                195                 :                :  * pg_partition_ancestors
                                196                 :                :  *
                                197                 :                :  * Produces a view with one row per ancestor of the given partition,
                                198                 :                :  * including the input relation itself.
                                199                 :                :  */
                                200                 :                : Datum
 1868 alvherre@alvh.no-ip.      201                 :           2500 : pg_partition_ancestors(PG_FUNCTION_ARGS)
                                202                 :                : {
                                203                 :           2500 :     Oid         relid = PG_GETARG_OID(0);
                                204                 :                :     FuncCallContext *funcctx;
                                205                 :                :     List       *ancestors;
                                206                 :                : 
                                207         [ +  + ]:           2500 :     if (SRF_IS_FIRSTCALL())
                                208                 :                :     {
                                209                 :                :         MemoryContext oldcxt;
                                210                 :                : 
                                211                 :           1047 :         funcctx = SRF_FIRSTCALL_INIT();
                                212                 :                : 
                                213         [ +  + ]:           1047 :         if (!check_rel_can_be_partition(relid))
                                214                 :            210 :             SRF_RETURN_DONE(funcctx);
                                215                 :                : 
                                216                 :            837 :         oldcxt = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
                                217                 :                : 
                                218                 :            837 :         ancestors = get_partition_ancestors(relid);
                                219                 :            837 :         ancestors = lcons_oid(relid, ancestors);
                                220                 :                : 
                                221                 :                :         /* The only state we need is the ancestors list */
 1735 tgl@sss.pgh.pa.us         222                 :            837 :         funcctx->user_fctx = (void *) ancestors;
                                223                 :                : 
 1868 alvherre@alvh.no-ip.      224                 :            837 :         MemoryContextSwitchTo(oldcxt);
                                225                 :                :     }
                                226                 :                : 
                                227                 :           2290 :     funcctx = SRF_PERCALL_SETUP();
 1735 tgl@sss.pgh.pa.us         228                 :           2290 :     ancestors = (List *) funcctx->user_fctx;
                                229                 :                : 
                                230         [ +  + ]:           2290 :     if (funcctx->call_cntr < list_length(ancestors))
                                231                 :                :     {
  557 drowley@postgresql.o      232                 :           1453 :         Oid         resultrel = list_nth_oid(ancestors, funcctx->call_cntr);
                                233                 :                : 
                                234                 :           1453 :         SRF_RETURN_NEXT(funcctx, ObjectIdGetDatum(resultrel));
                                235                 :                :     }
                                236                 :                : 
 1868 alvherre@alvh.no-ip.      237                 :            837 :     SRF_RETURN_DONE(funcctx);
                                238                 :                : }
        

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