1
0
mirror of https://github.com/postgres/postgres.git synced 2026-01-26 09:41:40 +03:00

Introduce routines to validate and free MVNDistinct and MVDependencies

These routines are useful to perform some basic validation checks on
each object structure, working currently on attribute numbers for
non-expression and expression attnums.  These checks could be extended
in the future.

Note that this code is not used yet in the tree, and that these
functions will become handy for an upcoming patch for the import of
extended statistics data.  However, they are worth their own independent
change as they are actually useful by themselves, with at least the
extension code argument in mind (or perhaps I am just feeling more
pedantic today).

Extracted from a larger patch by the same author, with many adjustments
and fixes by me.

Author: Corey Huinker <corey.huinker@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Discussion: https://postgr.es/m/CADkLM=dpz3KFnqP-dgJ-zvRvtjsa8UZv8wDAQdqho=qN3kX0Zg@mail.gmail.com
This commit is contained in:
Michael Paquier
2026-01-15 09:36:05 +09:00
parent ed425b5a20
commit 32e27bd320
3 changed files with 160 additions and 0 deletions

View File

@@ -579,6 +579,82 @@ statext_dependencies_deserialize(bytea *data)
return dependencies;
}
/*
* Free allocations of a MVDependencies.
*/
void
statext_dependencies_free(MVDependencies *dependencies)
{
for (int i = 0; i < dependencies->ndeps; i++)
pfree(dependencies->deps[i]);
pfree(dependencies);
}
/*
* Validate a set of MVDependencies against the extended statistics object
* definition.
*
* Every MVDependencies must be checked to ensure that the attnums in the
* attributes list correspond to attnums/expressions defined by the
* extended statistics object.
*
* Positive attnums are attributes which must be found in the stxkeys, while
* negative attnums correspond to an expression number, no attribute number
* can be below (0 - numexprs).
*/
bool
statext_dependencies_validate(const MVDependencies *dependencies,
const int2vector *stxkeys,
int numexprs, int elevel)
{
int attnum_expr_lowbound = 0 - numexprs;
/* Scan through each dependency entry */
for (int i = 0; i < dependencies->ndeps; i++)
{
const MVDependency *dep = dependencies->deps[i];
/*
* Cross-check each attribute in a dependency entry with the extended
* stats object definition.
*/
for (int j = 0; j < dep->nattributes; j++)
{
AttrNumber attnum = dep->attributes[j];
bool ok = false;
if (attnum > 0)
{
/* attribute number in stxkeys */
for (int k = 0; k < stxkeys->dim1; k++)
{
if (attnum == stxkeys->values[k])
{
ok = true;
break;
}
}
}
else if ((attnum < 0) && (attnum >= attnum_expr_lowbound))
{
/* attribute number for an expression */
ok = true;
}
if (!ok)
{
ereport(elevel,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("could not validate \"%s\" object: invalid attribute number %d found",
"pg_dependencies", attnum)));
return false;
}
}
}
return true;
}
/*
* dependency_is_fully_matched
* checks that a functional dependency is fully matched given clauses on

View File

@@ -325,6 +325,82 @@ statext_ndistinct_deserialize(bytea *data)
return ndistinct;
}
/*
* Free allocations of a MVNDistinct.
*/
void
statext_ndistinct_free(MVNDistinct *ndistinct)
{
for (int i = 0; i < ndistinct->nitems; i++)
pfree(ndistinct->items[i].attributes);
pfree(ndistinct);
}
/*
* Validate a set of MVNDistincts against the extended statistics object
* definition.
*
* Every MVNDistinctItem must be checked to ensure that the attnums in the
* attributes list correspond to attnums/expressions defined by the extended
* statistics object.
*
* Positive attnums are attributes which must be found in the stxkeys,
* while negative attnums correspond to an expression number, no attribute
* number can be below (0 - numexprs).
*/
bool
statext_ndistinct_validate(const MVNDistinct *ndistinct,
const int2vector *stxkeys,
int numexprs, int elevel)
{
int attnum_expr_lowbound = 0 - numexprs;
/* Scan through each MVNDistinct entry */
for (int i = 0; i < ndistinct->nitems; i++)
{
MVNDistinctItem item = ndistinct->items[i];
/*
* Cross-check each attribute in a MVNDistinct entry with the extended
* stats object definition.
*/
for (int j = 0; j < item.nattributes; j++)
{
AttrNumber attnum = item.attributes[j];
bool ok = false;
if (attnum > 0)
{
/* attribute number in stxkeys */
for (int k = 0; k < stxkeys->dim1; k++)
{
if (attnum == stxkeys->values[k])
{
ok = true;
break;
}
}
}
else if ((attnum < 0) && (attnum >= attnum_expr_lowbound))
{
/* attribute number for an expression */
ok = true;
}
if (!ok)
{
ereport(elevel,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("could not validate \"%s\" object: invalid attribute number %d found",
"pg_ndistinct", attnum)));
return false;
}
}
}
return true;
}
/*
* ndistinct_for_combination
* Estimates number of distinct values in a combination of columns.

View File

@@ -72,10 +72,18 @@ typedef struct StatsBuildData
extern MVNDistinct *statext_ndistinct_build(double totalrows, StatsBuildData *data);
extern bytea *statext_ndistinct_serialize(MVNDistinct *ndistinct);
extern MVNDistinct *statext_ndistinct_deserialize(bytea *data);
extern bool statext_ndistinct_validate(const MVNDistinct *ndistinct,
const int2vector *stxkeys,
int numexprs, int elevel);
extern void statext_ndistinct_free(MVNDistinct *ndistinct);
extern MVDependencies *statext_dependencies_build(StatsBuildData *data);
extern bytea *statext_dependencies_serialize(MVDependencies *dependencies);
extern MVDependencies *statext_dependencies_deserialize(bytea *data);
extern bool statext_dependencies_validate(const MVDependencies *dependencies,
const int2vector *stxkeys,
int numexprs, int elevel);
extern void statext_dependencies_free(MVDependencies *dependencies);
extern MCVList *statext_mcv_build(StatsBuildData *data,
double totalrows, int stattarget);