LCOV - code coverage report
Current view: top level - src/backend/statistics - extended_stats_funcs.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 222 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 7 0
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 0.0 % 97 0

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * extended_stats_funcs.c
       4                 :             :  *        Functions for manipulating extended statistics.
       5                 :             :  *
       6                 :             :  * This file includes the set of facilities required to support the direct
       7                 :             :  * manipulations of extended statistics objects.
       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/extended_stats_funcs.c
      14                 :             :  *
      15                 :             :  *-------------------------------------------------------------------------
      16                 :             :  */
      17                 :             : #include "postgres.h"
      18                 :             : 
      19                 :             : #include "access/heapam.h"
      20                 :             : #include "catalog/indexing.h"
      21                 :             : #include "catalog/namespace.h"
      22                 :             : #include "catalog/pg_database.h"
      23                 :             : #include "catalog/pg_statistic_ext.h"
      24                 :             : #include "catalog/pg_statistic_ext_data.h"
      25                 :             : #include "miscadmin.h"
      26                 :             : #include "nodes/makefuncs.h"
      27                 :             : #include "statistics/extended_stats_internal.h"
      28                 :             : #include "statistics/stat_utils.h"
      29                 :             : #include "utils/acl.h"
      30                 :             : #include "utils/array.h"
      31                 :             : #include "utils/builtins.h"
      32                 :             : #include "utils/fmgroids.h"
      33                 :             : #include "utils/lsyscache.h"
      34                 :             : #include "utils/syscache.h"
      35                 :             : 
      36                 :             : 
      37                 :             : /*
      38                 :             :  * Index of the arguments for the SQL functions.
      39                 :             :  */
      40                 :             : enum extended_stats_argnum
      41                 :             : {
      42                 :             :         RELSCHEMA_ARG = 0,
      43                 :             :         RELNAME_ARG,
      44                 :             :         STATSCHEMA_ARG,
      45                 :             :         STATNAME_ARG,
      46                 :             :         INHERITED_ARG,
      47                 :             :         NDISTINCT_ARG,
      48                 :             :         NUM_EXTENDED_STATS_ARGS,
      49                 :             : };
      50                 :             : 
      51                 :             : /*
      52                 :             :  * The argument names and type OIDs of the arguments for the SQL
      53                 :             :  * functions.
      54                 :             :  */
      55                 :             : static struct StatsArgInfo extarginfo[] =
      56                 :             : {
      57                 :             :         [RELSCHEMA_ARG] = {"schemaname", TEXTOID},
      58                 :             :         [RELNAME_ARG] = {"relname", TEXTOID},
      59                 :             :         [STATSCHEMA_ARG] = {"statistics_schemaname", TEXTOID},
      60                 :             :         [STATNAME_ARG] = {"statistics_name", TEXTOID},
      61                 :             :         [INHERITED_ARG] = {"inherited", BOOLOID},
      62                 :             :         [NDISTINCT_ARG] = {"n_distinct", PG_NDISTINCTOID},
      63                 :             :         [NUM_EXTENDED_STATS_ARGS] = {0},
      64                 :             : };
      65                 :             : 
      66                 :             : static bool extended_statistics_update(FunctionCallInfo fcinfo);
      67                 :             : 
      68                 :             : static HeapTuple get_pg_statistic_ext(Relation pg_stext, Oid nspoid,
      69                 :             :                                                                           const char *stxname);
      70                 :             : static bool delete_pg_statistic_ext_data(Oid stxoid, bool inherited);
      71                 :             : 
      72                 :             : /*
      73                 :             :  * Track the extended statistics kinds expected for a pg_statistic_ext
      74                 :             :  * tuple.
      75                 :             :  */
      76                 :             : typedef struct
      77                 :             : {
      78                 :             :         bool            ndistinct;
      79                 :             :         bool            dependencies;
      80                 :             :         bool            mcv;
      81                 :             :         bool            expressions;
      82                 :             : } StakindFlags;
      83                 :             : 
      84                 :             : static void expand_stxkind(HeapTuple tup, StakindFlags *enabled);
      85                 :             : static void upsert_pg_statistic_ext_data(const Datum *values,
      86                 :             :                                                                                  const bool *nulls,
      87                 :             :                                                                                  const bool *replaces);
      88                 :             : 
      89                 :             : /*
      90                 :             :  * Fetch a pg_statistic_ext row by name and namespace OID.
      91                 :             :  */
      92                 :             : static HeapTuple
      93                 :           0 : get_pg_statistic_ext(Relation pg_stext, Oid nspoid, const char *stxname)
      94                 :             : {
      95                 :           0 :         ScanKeyData key[2];
      96                 :           0 :         SysScanDesc scan;
      97                 :           0 :         HeapTuple       tup;
      98                 :           0 :         Oid                     stxoid = InvalidOid;
      99                 :             : 
     100                 :           0 :         ScanKeyInit(&key[0],
     101                 :             :                                 Anum_pg_statistic_ext_stxname,
     102                 :             :                                 BTEqualStrategyNumber,
     103                 :             :                                 F_NAMEEQ,
     104                 :           0 :                                 CStringGetDatum(stxname));
     105                 :           0 :         ScanKeyInit(&key[1],
     106                 :             :                                 Anum_pg_statistic_ext_stxnamespace,
     107                 :             :                                 BTEqualStrategyNumber,
     108                 :             :                                 F_OIDEQ,
     109                 :           0 :                                 ObjectIdGetDatum(nspoid));
     110                 :             : 
     111                 :             :         /*
     112                 :             :          * Try to find matching pg_statistic_ext row.
     113                 :             :          */
     114                 :           0 :         scan = systable_beginscan(pg_stext,
     115                 :             :                                                           StatisticExtNameIndexId,
     116                 :             :                                                           true,
     117                 :             :                                                           NULL,
     118                 :             :                                                           2,
     119                 :           0 :                                                           key);
     120                 :             : 
     121                 :             :         /* Lookup is based on a unique index, so we get either 0 or 1 tuple. */
     122                 :           0 :         tup = systable_getnext(scan);
     123                 :             : 
     124         [ #  # ]:           0 :         if (HeapTupleIsValid(tup))
     125                 :           0 :                 stxoid = ((Form_pg_statistic_ext) GETSTRUCT(tup))->oid;
     126                 :             : 
     127                 :           0 :         systable_endscan(scan);
     128                 :             : 
     129         [ #  # ]:           0 :         if (!OidIsValid(stxoid))
     130                 :           0 :                 return NULL;
     131                 :             : 
     132                 :           0 :         return SearchSysCacheCopy1(STATEXTOID, ObjectIdGetDatum(stxoid));
     133                 :           0 : }
     134                 :             : 
     135                 :             : /*
     136                 :             :  * Decode the stxkind column so that we know which stats types to expect,
     137                 :             :  * returning a StakindFlags set depending on the stats kinds expected by
     138                 :             :  * a pg_statistic_ext tuple.
     139                 :             :  */
     140                 :             : static void
     141                 :           0 : expand_stxkind(HeapTuple tup, StakindFlags *enabled)
     142                 :             : {
     143                 :           0 :         Datum           datum;
     144                 :           0 :         ArrayType  *arr;
     145                 :           0 :         char       *kinds;
     146                 :             : 
     147                 :           0 :         datum = SysCacheGetAttrNotNull(STATEXTOID,
     148                 :           0 :                                                                    tup,
     149                 :             :                                                                    Anum_pg_statistic_ext_stxkind);
     150                 :           0 :         arr = DatumGetArrayTypeP(datum);
     151         [ #  # ]:           0 :         if (ARR_NDIM(arr) != 1 || ARR_HASNULL(arr) || ARR_ELEMTYPE(arr) != CHAROID)
     152   [ #  #  #  # ]:           0 :                 elog(ERROR, "stxkind is not a one-dimension char array");
     153                 :             : 
     154         [ #  # ]:           0 :         kinds = (char *) ARR_DATA_PTR(arr);
     155                 :             : 
     156         [ #  # ]:           0 :         for (int i = 0; i < ARR_DIMS(arr)[0]; i++)
     157                 :             :         {
     158   [ #  #  #  #  :           0 :                 switch (kinds[i])
                      # ]
     159                 :             :                 {
     160                 :             :                         case STATS_EXT_NDISTINCT:
     161                 :           0 :                                 enabled->ndistinct = true;
     162                 :           0 :                                 break;
     163                 :             :                         case STATS_EXT_DEPENDENCIES:
     164                 :           0 :                                 enabled->dependencies = true;
     165                 :           0 :                                 break;
     166                 :             :                         case STATS_EXT_MCV:
     167                 :           0 :                                 enabled->mcv = true;
     168                 :           0 :                                 break;
     169                 :             :                         case STATS_EXT_EXPRESSIONS:
     170                 :           0 :                                 enabled->expressions = true;
     171                 :           0 :                                 break;
     172                 :             :                         default:
     173   [ #  #  #  # ]:           0 :                                 elog(ERROR, "incorrect stxkind %c found", kinds[i]);
     174                 :           0 :                                 break;
     175                 :             :                 }
     176                 :           0 :         }
     177                 :           0 : }
     178                 :             : 
     179                 :             : /*
     180                 :             :  * Perform the actual storage of a pg_statistic_ext_data tuple.
     181                 :             :  */
     182                 :             : static void
     183                 :           0 : upsert_pg_statistic_ext_data(const Datum *values, const bool *nulls,
     184                 :             :                                                          const bool *replaces)
     185                 :             : {
     186                 :           0 :         Relation        pg_stextdata;
     187                 :           0 :         HeapTuple       stxdtup;
     188                 :           0 :         HeapTuple       newtup;
     189                 :             : 
     190                 :           0 :         pg_stextdata = table_open(StatisticExtDataRelationId, RowExclusiveLock);
     191                 :             : 
     192                 :           0 :         stxdtup = SearchSysCache2(STATEXTDATASTXOID,
     193                 :           0 :                                                           values[Anum_pg_statistic_ext_data_stxoid - 1],
     194                 :           0 :                                                           values[Anum_pg_statistic_ext_data_stxdinherit - 1]);
     195                 :             : 
     196         [ #  # ]:           0 :         if (HeapTupleIsValid(stxdtup))
     197                 :             :         {
     198                 :           0 :                 newtup = heap_modify_tuple(stxdtup,
     199                 :           0 :                                                                    RelationGetDescr(pg_stextdata),
     200                 :           0 :                                                                    values,
     201                 :           0 :                                                                    nulls,
     202                 :           0 :                                                                    replaces);
     203                 :           0 :                 CatalogTupleUpdate(pg_stextdata, &newtup->t_self, newtup);
     204                 :           0 :                 ReleaseSysCache(stxdtup);
     205                 :           0 :         }
     206                 :             :         else
     207                 :             :         {
     208                 :           0 :                 newtup = heap_form_tuple(RelationGetDescr(pg_stextdata), values, nulls);
     209                 :           0 :                 CatalogTupleInsert(pg_stextdata, newtup);
     210                 :             :         }
     211                 :             : 
     212                 :           0 :         heap_freetuple(newtup);
     213                 :             : 
     214                 :           0 :         CommandCounterIncrement();
     215                 :             : 
     216                 :           0 :         table_close(pg_stextdata, RowExclusiveLock);
     217                 :           0 : }
     218                 :             : 
     219                 :             : /*
     220                 :             :  * Insert or update an extended statistics object.
     221                 :             :  *
     222                 :             :  * Major errors, such as the table not existing or permission errors, are
     223                 :             :  * reported as ERRORs.  There are a couple of paths that generate a WARNING,
     224                 :             :  * like when the statistics object or its schema do not exist, a conversion
     225                 :             :  * failure on one statistic kind, or when other statistic kinds may still
     226                 :             :  * be updated.
     227                 :             :  */
     228                 :             : static bool
     229                 :           0 : extended_statistics_update(FunctionCallInfo fcinfo)
     230                 :             : {
     231                 :           0 :         char       *relnspname;
     232                 :           0 :         char       *relname;
     233                 :           0 :         Oid                     nspoid;
     234                 :           0 :         char       *nspname;
     235                 :           0 :         char       *stxname;
     236                 :           0 :         bool            inherited;
     237                 :           0 :         Relation        pg_stext = NULL;
     238                 :           0 :         HeapTuple       tup = NULL;
     239                 :             : 
     240                 :           0 :         StakindFlags enabled = {false, false, false, false};
     241                 :           0 :         StakindFlags has = {false, false, false, false};
     242                 :             : 
     243                 :           0 :         Form_pg_statistic_ext stxform;
     244                 :             : 
     245                 :           0 :         Datum           values[Natts_pg_statistic_ext_data] = {0};
     246                 :           0 :         bool            nulls[Natts_pg_statistic_ext_data] = {0};
     247                 :           0 :         bool            replaces[Natts_pg_statistic_ext_data] = {0};
     248                 :           0 :         bool            success = true;
     249                 :           0 :         int                     numexprs = 0;
     250                 :             : 
     251                 :             :         /* arrays of type info, if we need them */
     252                 :           0 :         Oid                     relid;
     253                 :           0 :         Oid                     locked_table = InvalidOid;
     254                 :             : 
     255                 :             :         /*
     256                 :             :          * Fill out the StakindFlags "has" structure based on which parameters
     257                 :             :          * were provided to the function.
     258                 :             :          */
     259                 :           0 :         has.ndistinct = !PG_ARGISNULL(NDISTINCT_ARG);
     260                 :             : 
     261         [ #  # ]:           0 :         if (RecoveryInProgress())
     262                 :             :         {
     263   [ #  #  #  # ]:           0 :                 ereport(WARNING,
     264                 :             :                                 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
     265                 :             :                                 errmsg("recovery is in progress"),
     266                 :             :                                 errhint("Statistics cannot be modified during recovery."));
     267                 :           0 :                 return false;
     268                 :             :         }
     269                 :             : 
     270                 :             :         /* relation arguments */
     271                 :           0 :         stats_check_required_arg(fcinfo, extarginfo, RELSCHEMA_ARG);
     272                 :           0 :         relnspname = TextDatumGetCString(PG_GETARG_DATUM(RELSCHEMA_ARG));
     273                 :           0 :         stats_check_required_arg(fcinfo, extarginfo, RELNAME_ARG);
     274                 :           0 :         relname = TextDatumGetCString(PG_GETARG_DATUM(RELNAME_ARG));
     275                 :             : 
     276                 :             :         /* extended statistics arguments */
     277                 :           0 :         stats_check_required_arg(fcinfo, extarginfo, STATSCHEMA_ARG);
     278                 :           0 :         nspname = TextDatumGetCString(PG_GETARG_DATUM(STATSCHEMA_ARG));
     279                 :           0 :         stats_check_required_arg(fcinfo, extarginfo, STATNAME_ARG);
     280                 :           0 :         stxname = TextDatumGetCString(PG_GETARG_DATUM(STATNAME_ARG));
     281                 :           0 :         stats_check_required_arg(fcinfo, extarginfo, INHERITED_ARG);
     282                 :           0 :         inherited = PG_GETARG_BOOL(INHERITED_ARG);
     283                 :             : 
     284                 :             :         /*
     285                 :             :          * First open the relation where we expect to find the statistics.  This
     286                 :             :          * is similar to relation and attribute statistics, so as ACL checks are
     287                 :             :          * done before any locks are taken, even before any attempts related to
     288                 :             :          * the extended stats object.
     289                 :             :          */
     290                 :           0 :         relid = RangeVarGetRelidExtended(makeRangeVar(relnspname, relname, -1),
     291                 :             :                                                                          ShareUpdateExclusiveLock, 0,
     292                 :             :                                                                          RangeVarCallbackForStats, &locked_table);
     293                 :             : 
     294                 :           0 :         nspoid = get_namespace_oid(nspname, true);
     295         [ #  # ]:           0 :         if (nspoid == InvalidOid)
     296                 :             :         {
     297   [ #  #  #  # ]:           0 :                 ereport(WARNING,
     298                 :             :                                 errcode(ERRCODE_UNDEFINED_OBJECT),
     299                 :             :                                 errmsg("could not find schema \"%s\"", nspname));
     300                 :           0 :                 success = false;
     301                 :           0 :                 goto cleanup;
     302                 :             :         }
     303                 :             : 
     304                 :           0 :         pg_stext = table_open(StatisticExtRelationId, RowExclusiveLock);
     305                 :           0 :         tup = get_pg_statistic_ext(pg_stext, nspoid, stxname);
     306                 :             : 
     307         [ #  # ]:           0 :         if (!HeapTupleIsValid(tup))
     308                 :             :         {
     309   [ #  #  #  # ]:           0 :                 ereport(WARNING,
     310                 :             :                                 errcode(ERRCODE_UNDEFINED_OBJECT),
     311                 :             :                                 errmsg("could not find extended statistics object \"%s\".\"%s\"",
     312                 :             :                                            quote_identifier(nspname),
     313                 :             :                                            quote_identifier(stxname)));
     314                 :           0 :                 success = false;
     315                 :           0 :                 goto cleanup;
     316                 :             :         }
     317                 :             : 
     318                 :           0 :         stxform = (Form_pg_statistic_ext) GETSTRUCT(tup);
     319                 :             : 
     320                 :             :         /*
     321                 :             :          * The relation tracked by the stats object has to match with the relation
     322                 :             :          * we have already locked.
     323                 :             :          */
     324         [ #  # ]:           0 :         if (stxform->stxrelid != relid)
     325                 :             :         {
     326   [ #  #  #  # ]:           0 :                 ereport(WARNING,
     327                 :             :                                 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     328                 :             :                                 errmsg("could not restore extended statistics object \"%s\".\"%s\": incorrect relation \"%s\".\"%s\" specified",
     329                 :             :                                            quote_identifier(nspname),
     330                 :             :                                            quote_identifier(stxname),
     331                 :             :                                            quote_identifier(relnspname),
     332                 :             :                                            quote_identifier(relname)));
     333                 :             : 
     334                 :           0 :                 success = false;
     335                 :           0 :                 goto cleanup;
     336                 :             :         }
     337                 :             : 
     338                 :             :         /* Find out what extended statistics kinds we should expect. */
     339                 :           0 :         expand_stxkind(tup, &enabled);
     340                 :             : 
     341                 :             :         /*
     342                 :             :          * If the object cannot support ndistinct, we should not have data for it.
     343                 :             :          */
     344   [ #  #  #  # ]:           0 :         if (has.ndistinct && !enabled.ndistinct)
     345                 :             :         {
     346   [ #  #  #  # ]:           0 :                 ereport(WARNING,
     347                 :             :                                 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     348                 :             :                                 errmsg("cannot not specify parameter \"%s\"",
     349                 :             :                                            extarginfo[NDISTINCT_ARG].argname),
     350                 :             :                                 errhint("Extended statistics object \"%s\".\"%s\" does not support statistics of this type.",
     351                 :             :                                                 quote_identifier(nspname),
     352                 :             :                                                 quote_identifier(stxname)));
     353                 :             : 
     354                 :           0 :                 has.ndistinct = false;
     355                 :           0 :                 success = false;
     356                 :           0 :         }
     357                 :             : 
     358                 :             :         /*
     359                 :             :          * Populate the pg_statistic_ext_data result tuple.
     360                 :             :          */
     361                 :             : 
     362                 :             :         /* Primary Key: cannot be NULL or replaced. */
     363                 :           0 :         values[Anum_pg_statistic_ext_data_stxoid - 1] = ObjectIdGetDatum(stxform->oid);
     364                 :           0 :         nulls[Anum_pg_statistic_ext_data_stxoid - 1] = false;
     365                 :           0 :         values[Anum_pg_statistic_ext_data_stxdinherit - 1] = BoolGetDatum(inherited);
     366                 :           0 :         nulls[Anum_pg_statistic_ext_data_stxdinherit - 1] = false;
     367                 :             : 
     368                 :             :         /* All unspecified parameters will be left unmodified */
     369                 :           0 :         nulls[Anum_pg_statistic_ext_data_stxdndistinct - 1] = true;
     370                 :           0 :         nulls[Anum_pg_statistic_ext_data_stxddependencies - 1] = true;
     371                 :           0 :         nulls[Anum_pg_statistic_ext_data_stxdmcv - 1] = true;
     372                 :           0 :         nulls[Anum_pg_statistic_ext_data_stxdexpr - 1] = true;
     373                 :             : 
     374                 :             :         /*
     375                 :             :          * For each stats kind, deserialize the data at hand and perform a round
     376                 :             :          * of validation.  The resulting tuple is filled with a set of updated
     377                 :             :          * values.
     378                 :             :          */
     379                 :             : 
     380         [ #  # ]:           0 :         if (has.ndistinct)
     381                 :             :         {
     382                 :           0 :                 Datum           ndistinct_datum = PG_GETARG_DATUM(NDISTINCT_ARG);
     383                 :           0 :                 bytea      *data = DatumGetByteaPP(ndistinct_datum);
     384                 :           0 :                 MVNDistinct *ndistinct = statext_ndistinct_deserialize(data);
     385                 :             : 
     386   [ #  #  #  # ]:           0 :                 if (statext_ndistinct_validate(ndistinct, &stxform->stxkeys,
     387                 :           0 :                                                                            numexprs, WARNING))
     388                 :             :                 {
     389                 :           0 :                         values[Anum_pg_statistic_ext_data_stxdndistinct - 1] = ndistinct_datum;
     390                 :           0 :                         nulls[Anum_pg_statistic_ext_data_stxdndistinct - 1] = false;
     391                 :           0 :                         replaces[Anum_pg_statistic_ext_data_stxdndistinct - 1] = true;
     392                 :           0 :                 }
     393                 :             :                 else
     394                 :           0 :                         success = false;
     395                 :             : 
     396                 :           0 :                 statext_ndistinct_free(ndistinct);
     397                 :           0 :         }
     398                 :             : 
     399                 :           0 :         upsert_pg_statistic_ext_data(values, nulls, replaces);
     400                 :             : 
     401                 :             : cleanup:
     402         [ #  # ]:           0 :         if (HeapTupleIsValid(tup))
     403                 :           0 :                 heap_freetuple(tup);
     404         [ #  # ]:           0 :         if (pg_stext != NULL)
     405                 :           0 :                 table_close(pg_stext, RowExclusiveLock);
     406                 :           0 :         return success;
     407                 :           0 : }
     408                 :             : 
     409                 :             : /*
     410                 :             :  * Remove an existing pg_statistic_ext_data row for a given pg_statistic_ext
     411                 :             :  * row and "inherited" pair.
     412                 :             :  */
     413                 :             : static bool
     414                 :           0 : delete_pg_statistic_ext_data(Oid stxoid, bool inherited)
     415                 :             : {
     416                 :           0 :         Relation        sed = table_open(StatisticExtDataRelationId, RowExclusiveLock);
     417                 :           0 :         HeapTuple       oldtup;
     418                 :           0 :         bool            result = false;
     419                 :             : 
     420                 :             :         /* Is there already a pg_statistic tuple for this attribute? */
     421                 :           0 :         oldtup = SearchSysCache2(STATEXTDATASTXOID,
     422                 :           0 :                                                          ObjectIdGetDatum(stxoid),
     423                 :           0 :                                                          BoolGetDatum(inherited));
     424                 :             : 
     425         [ #  # ]:           0 :         if (HeapTupleIsValid(oldtup))
     426                 :             :         {
     427                 :           0 :                 CatalogTupleDelete(sed, &oldtup->t_self);
     428                 :           0 :                 ReleaseSysCache(oldtup);
     429                 :           0 :                 result = true;
     430                 :           0 :         }
     431                 :             : 
     432                 :           0 :         table_close(sed, RowExclusiveLock);
     433                 :             : 
     434                 :           0 :         CommandCounterIncrement();
     435                 :             : 
     436                 :           0 :         return result;
     437                 :           0 : }
     438                 :             : 
     439                 :             : /*
     440                 :             :  * Restore (insert or replace) statistics for the given statistics object.
     441                 :             :  *
     442                 :             :  * This function accepts variadic arguments in key-value pairs, which are
     443                 :             :  * given to stats_fill_fcinfo_from_arg_pairs to be mapped into positional
     444                 :             :  * arguments.
     445                 :             :  */
     446                 :             : Datum
     447                 :           0 : pg_restore_extended_stats(PG_FUNCTION_ARGS)
     448                 :             : {
     449                 :           0 :         LOCAL_FCINFO(positional_fcinfo, NUM_EXTENDED_STATS_ARGS);
     450                 :           0 :         bool            result = true;
     451                 :             : 
     452                 :           0 :         InitFunctionCallInfoData(*positional_fcinfo, NULL, NUM_EXTENDED_STATS_ARGS,
     453                 :             :                                                          InvalidOid, NULL, NULL);
     454                 :             : 
     455         [ #  # ]:           0 :         if (!stats_fill_fcinfo_from_arg_pairs(fcinfo, positional_fcinfo, extarginfo))
     456                 :           0 :                 result = false;
     457                 :             : 
     458         [ #  # ]:           0 :         if (!extended_statistics_update(positional_fcinfo))
     459                 :           0 :                 result = false;
     460                 :             : 
     461                 :           0 :         PG_RETURN_BOOL(result);
     462                 :           0 : }
     463                 :             : 
     464                 :             : /*
     465                 :             :  * Delete statistics for the given statistics object.
     466                 :             :  */
     467                 :             : Datum
     468                 :           0 : pg_clear_extended_stats(PG_FUNCTION_ARGS)
     469                 :             : {
     470                 :           0 :         char       *relnspname;
     471                 :           0 :         char       *relname;
     472                 :           0 :         char       *nspname;
     473                 :           0 :         Oid                     nspoid;
     474                 :           0 :         Oid                     relid;
     475                 :           0 :         char       *stxname;
     476                 :           0 :         bool            inherited;
     477                 :           0 :         Relation        pg_stext;
     478                 :           0 :         HeapTuple       tup;
     479                 :           0 :         Form_pg_statistic_ext stxform;
     480                 :           0 :         Oid                     locked_table = InvalidOid;
     481                 :             : 
     482                 :             :         /* relation arguments */
     483                 :           0 :         stats_check_required_arg(fcinfo, extarginfo, RELSCHEMA_ARG);
     484                 :           0 :         relnspname = TextDatumGetCString(PG_GETARG_DATUM(RELSCHEMA_ARG));
     485                 :           0 :         stats_check_required_arg(fcinfo, extarginfo, RELNAME_ARG);
     486                 :           0 :         relname = TextDatumGetCString(PG_GETARG_DATUM(RELNAME_ARG));
     487                 :             : 
     488                 :             :         /* extended statistics arguments */
     489                 :           0 :         stats_check_required_arg(fcinfo, extarginfo, STATSCHEMA_ARG);
     490                 :           0 :         nspname = TextDatumGetCString(PG_GETARG_DATUM(STATSCHEMA_ARG));
     491                 :           0 :         stats_check_required_arg(fcinfo, extarginfo, STATNAME_ARG);
     492                 :           0 :         stxname = TextDatumGetCString(PG_GETARG_DATUM(STATNAME_ARG));
     493                 :           0 :         stats_check_required_arg(fcinfo, extarginfo, INHERITED_ARG);
     494                 :           0 :         inherited = PG_GETARG_BOOL(INHERITED_ARG);
     495                 :             : 
     496         [ #  # ]:           0 :         if (RecoveryInProgress())
     497                 :             :         {
     498   [ #  #  #  # ]:           0 :                 ereport(WARNING,
     499                 :             :                                 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
     500                 :             :                                 errmsg("recovery is in progress"),
     501                 :             :                                 errhint("Statistics cannot be modified during recovery."));
     502                 :           0 :                 PG_RETURN_VOID();
     503                 :             :         }
     504                 :             : 
     505                 :             :         /*
     506                 :             :          * First open the relation where we expect to find the statistics.  This
     507                 :             :          * is similar to relation and attribute statistics, so as ACL checks are
     508                 :             :          * done before any locks are taken, even before any attempts related to
     509                 :             :          * the extended stats object.
     510                 :             :          */
     511                 :           0 :         relid = RangeVarGetRelidExtended(makeRangeVar(relnspname, relname, -1),
     512                 :             :                                                                          ShareUpdateExclusiveLock, 0,
     513                 :             :                                                                          RangeVarCallbackForStats, &locked_table);
     514                 :             : 
     515                 :             :         /* Now check if the namespace of the stats object exists. */
     516                 :           0 :         nspoid = get_namespace_oid(nspname, true);
     517         [ #  # ]:           0 :         if (nspoid == InvalidOid)
     518                 :             :         {
     519   [ #  #  #  # ]:           0 :                 ereport(WARNING,
     520                 :             :                                 errcode(ERRCODE_UNDEFINED_OBJECT),
     521                 :             :                                 errmsg("could not find schema \"%s\"", nspname));
     522                 :           0 :                 PG_RETURN_VOID();
     523                 :             :         }
     524                 :             : 
     525                 :           0 :         pg_stext = table_open(StatisticExtRelationId, RowExclusiveLock);
     526                 :           0 :         tup = get_pg_statistic_ext(pg_stext, nspoid, stxname);
     527                 :             : 
     528         [ #  # ]:           0 :         if (!HeapTupleIsValid(tup))
     529                 :             :         {
     530                 :           0 :                 table_close(pg_stext, RowExclusiveLock);
     531   [ #  #  #  # ]:           0 :                 ereport(WARNING,
     532                 :             :                                 errcode(ERRCODE_UNDEFINED_OBJECT),
     533                 :             :                                 errmsg("could not find extended statistics object \"%s\".\"%s\"",
     534                 :             :                                            nspname, stxname));
     535                 :           0 :                 PG_RETURN_VOID();
     536                 :             :         }
     537                 :             : 
     538                 :           0 :         stxform = (Form_pg_statistic_ext) GETSTRUCT(tup);
     539                 :             : 
     540                 :             :         /*
     541                 :             :          * This should be consistent, based on the lock taken on the table when we
     542                 :             :          * started.
     543                 :             :          */
     544         [ #  # ]:           0 :         if (stxform->stxrelid != relid)
     545                 :             :         {
     546                 :           0 :                 table_close(pg_stext, RowExclusiveLock);
     547   [ #  #  #  # ]:           0 :                 ereport(WARNING,
     548                 :             :                                 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     549                 :             :                                 errmsg("could not clear extended statistics object \"%s\".\"%s\": incorrect relation \"%s\".\"%s\" specified",
     550                 :             :                                            get_namespace_name(nspoid), stxname,
     551                 :             :                                            relnspname, relname));
     552                 :           0 :                 PG_RETURN_VOID();
     553                 :             :         }
     554                 :             : 
     555                 :           0 :         delete_pg_statistic_ext_data(stxform->oid, inherited);
     556                 :           0 :         heap_freetuple(tup);
     557                 :             : 
     558                 :           0 :         table_close(pg_stext, RowExclusiveLock);
     559                 :             : 
     560                 :           0 :         PG_RETURN_VOID();
     561                 :           0 : }
        

Generated by: LCOV version 2.3.2-1