LCOV - differential code coverage report
Current view: top level - src/backend/statistics - relation_stats.c (source / functions) Coverage Total Hit UBC CBC
Current: 77aeca80249c9e640c811e80633a2e334a9320de vs 38afc3dcb25c45b744d4025029ce0a6c90b7059f Lines: 95.6 % 113 108 5 108
Current Date: 2026-07-25 19:08:27 +0900 Functions: 100.0 % 5 5 5
Baseline: lcov-20260725-baseline Branches: 72.0 % 50 36 14 36
Baseline Date: 2026-07-25 19:09:19 +0900 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 100.0 % 33 33 33
(30,360] days: 100.0 % 2 2 2
(360..) days: 93.6 % 78 73 5 73
Function coverage date bins:
(7,30] days: 100.0 % 2 2 2
(360..) days: 100.0 % 3 3 3
Branch coverage date bins:
(7,30] days: 50.0 % 8 4 4 4
(360..) days: 76.2 % 42 32 10 32

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

Generated by: LCOV version 2.0-1