LCOV - differential code coverage report
Current view: top level - src/backend/statistics - relation_stats.c (source / functions) Coverage Total Hit UBC GNC CBC DCB
Current: ba12a202ce1b5581dc0ed149cf3f637d7897ad5d vs 2866d8c7dbfc9d882a7d80fef93fbbe763709932 Lines: 98.3 % 116 114 2 13 101 13
Current Date: 2026-08-27 14:31:44 +0300 Functions: 100.0 % 5 5 2 3
Baseline: lcov-20260827-baseline Branches: 78.6 % 56 44 12 44
Baseline Date: 2026-08-27 14:31:58 +0300 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(1,7] days: 100.0 % 13 13 13
(7,30] days: 100.0 % 4 4 4
(30,360] days: 100.0 % 31 31 31
(360..) days: 97.1 % 68 66 2 66
Function coverage date bins:
(30,360] days: 100.0 % 2 2 1 1
(360..) days: 100.0 % 3 3 1 2
Branch coverage date bins:
(7,30] days: 87.5 % 8 7 1 7
(30,360] days: 50.0 % 8 4 4 4
(360..) days: 82.5 % 40 33 7 33

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  * relation_stats.c
                                  3                 :                :  *
                                  4                 :                :  *    PostgreSQL relation statistics manipulation
                                  5                 :                :  *
                                  6                 :                :  * Code supporting the direct import of relation statistics, similar to
                                  7                 :                :  * what is done by the ANALYZE command.
                                  8                 :                :  *
                                  9                 :                :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
                                 10                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                 11                 :                :  *
                                 12                 :                :  * IDENTIFICATION
                                 13                 :                :  *       src/backend/statistics/relation_stats.c
                                 14                 :                :  *
                                 15                 :                :  *-------------------------------------------------------------------------
                                 16                 :                :  */
                                 17                 :                : 
                                 18                 :                : #include "postgres.h"
                                 19                 :                : 
                                 20                 :                : #include <math.h>
                                 21                 :                : 
                                 22                 :                : #include "access/heapam.h"
                                 23                 :                : #include "catalog/indexing.h"
                                 24                 :                : #include "catalog/namespace.h"
                                 25                 :                : #include "nodes/makefuncs.h"
                                 26                 :                : #include "statistics/statistics.h"
                                 27                 :                : #include "statistics/stat_utils.h"
                                 28                 :                : #include "utils/builtins.h"
                                 29                 :                : #include "utils/fmgroids.h"
                                 30                 :                : #include "utils/fmgrprotos.h"
                                 31                 :                : #include "utils/lsyscache.h"
                                 32                 :                : #include "utils/syscache.h"
                                 33                 :                : 
                                 34                 :                : 
                                 35                 :                : /*
                                 36                 :                :  * Positional argument numbers, names, and types for
                                 37                 :                :  * relation_statistics_update().
                                 38                 :                :  */
                                 39                 :                : 
                                 40                 :                : enum relation_stats_argnum
                                 41                 :                : {
                                 42                 :                :     RELSCHEMA_ARG = 0,
                                 43                 :                :     RELNAME_ARG,
                                 44                 :                :     RELPAGES_ARG,
                                 45                 :                :     RELTUPLES_ARG,
                                 46                 :                :     RELALLVISIBLE_ARG,
                                 47                 :                :     RELALLFROZEN_ARG,
                                 48                 :                :     NUM_RELATION_STATS_ARGS
                                 49                 :                : };
                                 50                 :                : 
                                 51                 :                : static struct StatsArgInfo relarginfo[] =
                                 52                 :                : {
                                 53                 :                :     [RELSCHEMA_ARG] = {"schemaname", TEXTOID},
                                 54                 :                :     [RELNAME_ARG] = {"relname", TEXTOID},
                                 55                 :                :     [RELPAGES_ARG] = {"relpages", INT4OID},
                                 56                 :                :     [RELTUPLES_ARG] = {"reltuples", FLOAT4OID},
                                 57                 :                :     [RELALLVISIBLE_ARG] = {"relallvisible", INT4OID},
                                 58                 :                :     [RELALLFROZEN_ARG] = {"relallfrozen", INT4OID},
                                 59                 :                :     [NUM_RELATION_STATS_ARGS] = {0}
                                 60                 :                : };
                                 61                 :                : 
                                 62                 :                : static bool relation_statistics_update(FunctionCallInfo fcinfo);
                                 63                 :                : static bool relation_statistics_update_internal(Oid reloid,
                                 64                 :                :                                                 FunctionCallInfo fcinfo);
                                 65                 :                : 
                                 66                 :                : /*
                                 67                 :                :  * Internal function for modifying statistics for a relation.
                                 68                 :                :  */
                                 69                 :                : static bool
  548 jdavis@postgresql.or       70                 :CBC        1249 : relation_statistics_update(FunctionCallInfo fcinfo)
                                 71                 :                : {
                                 72                 :                :     char       *nspname;
                                 73                 :                :     char       *relname;
                                 74                 :                :     Oid         reloid;
  316 nathan@postgresql.or       75                 :           1249 :     Oid         locked_table = InvalidOid;
                                 76                 :                : 
  520 jdavis@postgresql.or       77                 :           1249 :     stats_check_required_arg(fcinfo, relarginfo, RELSCHEMA_ARG);
                                 78                 :           1241 :     stats_check_required_arg(fcinfo, relarginfo, RELNAME_ARG);
                                 79                 :                : 
                                 80                 :           1233 :     nspname = TextDatumGetCString(PG_GETARG_DATUM(RELSCHEMA_ARG));
                                 81                 :           1233 :     relname = TextDatumGetCString(PG_GETARG_DATUM(RELNAME_ARG));
                                 82                 :                : 
                                 83         [ -  + ]:           1233 :     if (RecoveryInProgress())
  520 jdavis@postgresql.or       84         [ #  # ]:UBC           0 :         ereport(ERROR,
                                 85                 :                :                 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                                 86                 :                :                  errmsg("recovery is in progress"),
                                 87                 :                :                  errhint("Statistics cannot be modified during recovery.")));
                                 88                 :                : 
  316 nathan@postgresql.or       89                 :CBC        1233 :     reloid = RangeVarGetRelidExtended(makeRangeVar(nspname, relname, -1),
                                 90                 :                :                                       ShareUpdateExclusiveLock, 0,
                                 91                 :                :                                       RangeVarCallbackForStats, &locked_table);
                                 92                 :                : 
   48 efujita@postgresql.o       93                 :           1217 :     return relation_statistics_update_internal(reloid, fcinfo);
                                 94                 :                : }
                                 95                 :                : 
                                 96                 :                : /*
                                 97                 :                :  * Workhorse function for relation_statistics_update.
                                 98                 :                :  */
                                 99                 :                : static bool
                                100                 :           1224 : relation_statistics_update_internal(Oid reloid, FunctionCallInfo fcinfo)
                                101                 :                : {
    2 peter@eisentraut.org      102                 :GNC        1224 :     int32       relpages = 0;
   48 efujita@postgresql.o      103                 :CBC        1224 :     bool        update_relpages = false;
    2 peter@eisentraut.org      104                 :GNC        1224 :     float4      reltuples = 0;
   48 efujita@postgresql.o      105                 :CBC        1224 :     bool        update_reltuples = false;
    2 peter@eisentraut.org      106                 :GNC        1224 :     int32       relallvisible = 0;
   48 efujita@postgresql.o      107                 :CBC        1224 :     bool        update_relallvisible = false;
    2 peter@eisentraut.org      108                 :GNC        1224 :     int32       relallfrozen = 0;
   48 efujita@postgresql.o      109                 :CBC        1224 :     bool        update_relallfrozen = false;
                                110                 :                :     Relation    crel;
                                111                 :                :     HeapTuple   ctup;
                                112                 :                :     Form_pg_class pgcform;
                                113                 :           1224 :     int         replaces[4] = {0};
                                114                 :           1224 :     Datum       values[4] = {0};
                                115                 :           1224 :     bool        nulls[4] = {0};
                                116                 :           1224 :     int         nreplaces = 0;
                                117                 :           1224 :     bool        result = true;
                                118                 :                : 
  685 jdavis@postgresql.or      119         [ +  + ]:           1224 :     if (!PG_ARGISNULL(RELPAGES_ARG))
                                120                 :                :     {
    2 peter@eisentraut.org      121                 :GNC        1184 :         relpages = PG_GETARG_INT32(RELPAGES_ARG);
  549 tgl@sss.pgh.pa.us         122                 :CBC        1184 :         update_relpages = true;
                                123                 :                :     }
                                124                 :                : 
  685 jdavis@postgresql.or      125         [ +  + ]:           1224 :     if (!PG_ARGISNULL(RELTUPLES_ARG))
                                126                 :                :     {
  625                           127                 :           1200 :         reltuples = PG_GETARG_FLOAT4(RELTUPLES_ARG);
   28 tomas.vondra@postgre      128   [ +  +  +  + ]:           1200 :         if (isnan(reltuples) || isinf(reltuples))
                                129                 :                :         {
                                130         [ +  - ]:             12 :             ereport(WARNING,
                                131                 :                :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                132                 :                :                      errmsg("argument \"%s\" must be a finite value", "reltuples")));
                                133                 :             12 :             result = false;
                                134                 :                :         }
                                135         [ +  + ]:           1188 :         else if (reltuples < -1.0)
                                136                 :                :         {
  548 jdavis@postgresql.or      137         [ +  - ]:              4 :             ereport(WARNING,
                                138                 :                :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                139                 :                :                      errmsg("argument \"%s\" must not be less than -1.0", "reltuples")));
  672                           140                 :              4 :             result = false;
                                141                 :                :         }
                                142                 :                :         else
  625                           143                 :           1184 :             update_reltuples = true;
                                144                 :                :     }
                                145                 :                : 
  685                           146         [ +  + ]:           1224 :     if (!PG_ARGISNULL(RELALLVISIBLE_ARG))
                                147                 :                :     {
    2 peter@eisentraut.org      148                 :GNC        1169 :         relallvisible = PG_GETARG_INT32(RELALLVISIBLE_ARG);
  549 tgl@sss.pgh.pa.us         149                 :CBC        1169 :         update_relallvisible = true;
                                150                 :                :     }
                                151                 :                : 
  542 melanieplageman@gmai      152         [ +  + ]:           1224 :     if (!PG_ARGISNULL(RELALLFROZEN_ARG))
                                153                 :                :     {
    2 peter@eisentraut.org      154                 :GNC        1169 :         relallfrozen = PG_GETARG_INT32(RELALLFROZEN_ARG);
  542 melanieplageman@gmai      155                 :CBC        1169 :         update_relallfrozen = true;
                                156                 :                :     }
                                157                 :                : 
                                158                 :                :     /*
                                159                 :                :      * Take RowExclusiveLock on pg_class, consistent with
                                160                 :                :      * vac_update_relstats().
                                161                 :                :      */
  625 jdavis@postgresql.or      162                 :           1224 :     crel = table_open(RelationRelationId, RowExclusiveLock);
                                163                 :                : 
  549                           164                 :           1224 :     ctup = SearchSysCache1(RELOID, ObjectIdGetDatum(reloid));
                                165         [ -  + ]:           1224 :     if (!HeapTupleIsValid(ctup))
  540 jdavis@postgresql.or      166         [ #  # ]:UBC           0 :         elog(ERROR, "pg_class entry for relid %u not found", reloid);
                                167                 :                : 
  549 jdavis@postgresql.or      168                 :CBC        1224 :     pgcform = (Form_pg_class) GETSTRUCT(ctup);
                                169                 :                : 
                                170   [ +  +  +  + ]:           1224 :     if (update_relpages && relpages != pgcform->relpages)
                                171                 :                :     {
                                172                 :            597 :         replaces[nreplaces] = Anum_pg_class_relpages;
    2 peter@eisentraut.org      173                 :GNC         597 :         values[nreplaces] = Int32GetDatum(relpages);
  549 jdavis@postgresql.or      174                 :CBC         597 :         nreplaces++;
                                175                 :                :     }
                                176                 :                : 
                                177   [ +  +  +  + ]:           1224 :     if (update_reltuples && reltuples != pgcform->reltuples)
                                178                 :                :     {
                                179                 :            541 :         replaces[nreplaces] = Anum_pg_class_reltuples;
                                180                 :            541 :         values[nreplaces] = Float4GetDatum(reltuples);
                                181                 :            541 :         nreplaces++;
                                182                 :                :     }
                                183                 :                : 
                                184   [ +  +  +  + ]:           1224 :     if (update_relallvisible && relallvisible != pgcform->relallvisible)
                                185                 :                :     {
                                186                 :            167 :         replaces[nreplaces] = Anum_pg_class_relallvisible;
    2 peter@eisentraut.org      187                 :GNC         167 :         values[nreplaces] = Int32GetDatum(relallvisible);
  549 jdavis@postgresql.or      188                 :CBC         167 :         nreplaces++;
                                189                 :                :     }
                                190                 :                : 
  542 melanieplageman@gmai      191   [ +  +  +  + ]:           1224 :     if (update_relallfrozen && relallfrozen != pgcform->relallfrozen)
                                192                 :                :     {
                                193                 :            114 :         replaces[nreplaces] = Anum_pg_class_relallfrozen;
    2 peter@eisentraut.org      194                 :GNC         114 :         values[nreplaces] = Int32GetDatum(relallfrozen);
  542 melanieplageman@gmai      195                 :CBC         114 :         nreplaces++;
                                196                 :                :     }
                                197                 :                : 
  549 jdavis@postgresql.or      198         [ +  + ]:           1224 :     if (nreplaces > 0)
                                199                 :                :     {
                                200                 :            713 :         TupleDesc   tupdesc = RelationGetDescr(crel);
                                201                 :                :         HeapTuple   newtup;
                                202                 :                : 
                                203                 :            713 :         newtup = heap_modify_tuple_by_cols(ctup, tupdesc, nreplaces,
                                204                 :                :                                            replaces, values, nulls);
                                205                 :            713 :         CatalogTupleUpdate(crel, &newtup->t_self, newtup);
                                206                 :            713 :         heap_freetuple(newtup);
                                207                 :                :     }
                                208                 :                : 
                                209                 :           1224 :     ReleaseSysCache(ctup);
                                210                 :                : 
                                211                 :                :     /* release the lock, consistent with vac_update_relstats() */
  685                           212                 :           1224 :     table_close(crel, RowExclusiveLock);
                                213                 :                : 
  667                           214                 :           1224 :     CommandCounterIncrement();
                                215                 :                : 
  672                           216                 :           1224 :     return result;
                                217                 :                : }
                                218                 :                : 
                                219                 :                : /*
                                220                 :                :  * Clear statistics for a given pg_class entry; that is, set back to initial
                                221                 :                :  * stats for a newly-created table.
                                222                 :                :  */
                                223                 :                : Datum
  685                           224                 :             16 : pg_clear_relation_stats(PG_FUNCTION_ARGS)
                                225                 :                : {
  520                           226                 :             16 :     LOCAL_FCINFO(newfcinfo, 6);
                                227                 :                : 
                                228                 :             16 :     InitFunctionCallInfoData(*newfcinfo, NULL, 6, InvalidOid, NULL, NULL);
                                229                 :                : 
                                230                 :             16 :     newfcinfo->args[0].value = PG_GETARG_DATUM(0);
  685                           231                 :             16 :     newfcinfo->args[0].isnull = PG_ARGISNULL(0);
  520                           232                 :             16 :     newfcinfo->args[1].value = PG_GETARG_DATUM(1);
                                233                 :             16 :     newfcinfo->args[1].isnull = PG_ARGISNULL(1);
    2 peter@eisentraut.org      234                 :GNC          16 :     newfcinfo->args[2].value = Int32GetDatum(0);
  685 jdavis@postgresql.or      235                 :CBC          16 :     newfcinfo->args[2].isnull = false;
  520                           236                 :             16 :     newfcinfo->args[3].value = Float4GetDatum(-1.0);
  685                           237                 :             16 :     newfcinfo->args[3].isnull = false;
    2 peter@eisentraut.org      238                 :GNC          16 :     newfcinfo->args[4].value = Int32GetDatum(0);
  542 melanieplageman@gmai      239                 :CBC          16 :     newfcinfo->args[4].isnull = false;
    2 peter@eisentraut.org      240                 :GNC          16 :     newfcinfo->args[5].value = Int32GetDatum(0);
  520 jdavis@postgresql.or      241                 :CBC          16 :     newfcinfo->args[5].isnull = false;
                                242                 :                : 
  548                           243                 :             16 :     relation_statistics_update(newfcinfo);
  674                           244                 :              8 :     PG_RETURN_VOID();
                                245                 :                : }
                                246                 :                : 
                                247                 :                : Datum
  672                           248                 :           1241 : pg_restore_relation_stats(PG_FUNCTION_ARGS)
                                249                 :                : {
                                250                 :           1241 :     LOCAL_FCINFO(positional_fcinfo, NUM_RELATION_STATS_ARGS);
                                251                 :           1241 :     bool        result = true;
                                252                 :                : 
                                253                 :           1241 :     InitFunctionCallInfoData(*positional_fcinfo, NULL,
                                254                 :                :                              NUM_RELATION_STATS_ARGS,
                                255                 :                :                              InvalidOid, NULL, NULL);
                                256                 :                : 
                                257         [ +  + ]:           1241 :     if (!stats_fill_fcinfo_from_arg_pairs(fcinfo, positional_fcinfo,
                                258                 :                :                                           relarginfo))
                                259                 :             16 :         result = false;
                                260                 :                : 
  548                           261         [ +  + ]:           1233 :     if (!relation_statistics_update(positional_fcinfo))
  672                           262                 :             16 :         result = false;
                                263                 :                : 
                                264                 :           1209 :     PG_RETURN_BOOL(result);
                                265                 :                : }
                                266                 :                : 
                                267                 :                : /*
                                268                 :                :  * Import relation statistics from NullableDatum inputs for all statistical
                                269                 :                :  * values.
                                270                 :                :  *
                                271                 :                :  * For now, the 'version' argument is ignored. In the future it can be used
                                272                 :                :  * to interpret older statistics properly.
                                273                 :                :  */
                                274                 :                : bool
   48 efujita@postgresql.o      275                 :              7 : import_relation_statistics(Relation rel,
                                276                 :                :                            const NullableDatum *version,
                                277                 :                :                            const NullableDatum *relpages,
                                278                 :                :                            const NullableDatum *reltuples,
                                279                 :                :                            const NullableDatum *relallvisible,
                                280                 :                :                            const NullableDatum *relallfrozen)
                                281                 :                : {
                                282                 :              7 :     LOCAL_FCINFO(newfcinfo, NUM_RELATION_STATS_ARGS);
                                283                 :                : 
                                284         [ -  + ]:              7 :     Assert(relpages);
                                285         [ -  + ]:              7 :     Assert(reltuples);
                                286         [ -  + ]:              7 :     Assert(relallvisible);
                                287         [ -  + ]:              7 :     Assert(relallfrozen);
                                288                 :                : 
                                289                 :              7 :     InitFunctionCallInfoData(*newfcinfo, NULL, NUM_RELATION_STATS_ARGS,
                                290                 :                :                              InvalidOid, NULL, NULL);
                                291                 :                : 
                                292                 :              7 :     newfcinfo->args[RELSCHEMA_ARG].value =
                                293                 :              7 :         CStringGetTextDatum(get_namespace_name(RelationGetNamespace(rel)));
                                294                 :              7 :     newfcinfo->args[RELSCHEMA_ARG].isnull = false;
                                295                 :              7 :     newfcinfo->args[RELNAME_ARG].value =
                                296                 :              7 :         CStringGetTextDatum(RelationGetRelationName(rel));
                                297                 :              7 :     newfcinfo->args[RELNAME_ARG].isnull = false;
                                298                 :                : 
                                299                 :              7 :     newfcinfo->args[RELPAGES_ARG] = *relpages;
                                300                 :              7 :     newfcinfo->args[RELTUPLES_ARG] = *reltuples;
                                301                 :              7 :     newfcinfo->args[RELALLVISIBLE_ARG] = *relallvisible;
                                302                 :              7 :     newfcinfo->args[RELALLFROZEN_ARG] = *relallfrozen;
                                303                 :                : 
                                304                 :              7 :     return relation_statistics_update_internal(RelationGetRelid(rel),
                                305                 :                :                                                newfcinfo);
                                306                 :                : }
        

Generated by: LCOV version 2.0-1