From 0797a698495c21baaef3b633e78425bcd7b16821 Mon Sep 17 00:00:00 2001 From: Corey Huinker Date: Mon, 11 Dec 2023 03:23:28 -0500 Subject: [PATCH v3 6/9] Create create_stat_ext_entry() from fetch_statentries_for_relation(). Refactor fetch_statentries_for_relation() to use create_stat_ext_entry() in its inner loop. Later commits will make use of create_stat_ext_entry(). This was made its own commit for code clarity. --- src/backend/statistics/extended_stats.c | 146 +++++++++++++----------- 1 file changed, 78 insertions(+), 68 deletions(-) diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c index 7f014a0cbb..718826ecf1 100644 --- a/src/backend/statistics/extended_stats.c +++ b/src/backend/statistics/extended_stats.c @@ -418,6 +418,83 @@ statext_is_kind_built(HeapTuple htup, char type) return !heap_attisnull(htup, attnum, NULL); } +/* + * Create a single StatExtEntry from a fetched heap tuple + */ +static StatExtEntry * +create_stat_ext_entry(HeapTuple htup) +{ + StatExtEntry *entry; + Datum datum; + bool isnull; + int i; + ArrayType *arr; + char *enabled; + Form_pg_statistic_ext staForm; + List *exprs = NIL; + + entry = palloc0(sizeof(StatExtEntry)); + staForm = (Form_pg_statistic_ext) GETSTRUCT(htup); + entry->statOid = staForm->oid; + entry->schema = get_namespace_name(staForm->stxnamespace); + entry->name = pstrdup(NameStr(staForm->stxname)); + entry->stattarget = staForm->stxstattarget; + for (i = 0; i < staForm->stxkeys.dim1; i++) + { + entry->columns = bms_add_member(entry->columns, + staForm->stxkeys.values[i]); + } + + /* decode the stxkind char array into a list of chars */ + datum = SysCacheGetAttrNotNull(STATEXTOID, htup, + Anum_pg_statistic_ext_stxkind); + arr = DatumGetArrayTypeP(datum); + if (ARR_NDIM(arr) != 1 || + ARR_HASNULL(arr) || + ARR_ELEMTYPE(arr) != CHAROID) + elog(ERROR, "stxkind is not a 1-D char array"); + enabled = (char *) ARR_DATA_PTR(arr); + for (i = 0; i < ARR_DIMS(arr)[0]; i++) + { + Assert((enabled[i] == STATS_EXT_NDISTINCT) || + (enabled[i] == STATS_EXT_DEPENDENCIES) || + (enabled[i] == STATS_EXT_MCV) || + (enabled[i] == STATS_EXT_EXPRESSIONS)); + entry->types = lappend_int(entry->types, (int) enabled[i]); + } + + /* decode expression (if any) */ + datum = SysCacheGetAttr(STATEXTOID, htup, + Anum_pg_statistic_ext_stxexprs, &isnull); + + if (!isnull) + { + char *exprsString; + + exprsString = TextDatumGetCString(datum); + exprs = (List *) stringToNode(exprsString); + + pfree(exprsString); + + /* + * Run the expressions through eval_const_expressions. This is not + * just an optimization, but is necessary, because the planner + * will be comparing them to similarly-processed qual clauses, and + * may fail to detect valid matches without this. We must not use + * canonicalize_qual, however, since these aren't qual + * expressions. + */ + exprs = (List *) eval_const_expressions(NULL, (Node *) exprs); + + /* May as well fix opfuncids too */ + fix_opfuncids((Node *) exprs); + } + + entry->exprs = exprs; + + return entry; +} + /* * Return a list (of StatExtEntry) of statistics objects for the given relation. */ @@ -443,74 +520,7 @@ fetch_statentries_for_relation(Relation pg_statext, Oid relid) while (HeapTupleIsValid(htup = systable_getnext(scan))) { - StatExtEntry *entry; - Datum datum; - bool isnull; - int i; - ArrayType *arr; - char *enabled; - Form_pg_statistic_ext staForm; - List *exprs = NIL; - - entry = palloc0(sizeof(StatExtEntry)); - staForm = (Form_pg_statistic_ext) GETSTRUCT(htup); - entry->statOid = staForm->oid; - entry->schema = get_namespace_name(staForm->stxnamespace); - entry->name = pstrdup(NameStr(staForm->stxname)); - entry->stattarget = staForm->stxstattarget; - for (i = 0; i < staForm->stxkeys.dim1; i++) - { - entry->columns = bms_add_member(entry->columns, - staForm->stxkeys.values[i]); - } - - /* decode the stxkind char array into a list of chars */ - datum = SysCacheGetAttrNotNull(STATEXTOID, htup, - Anum_pg_statistic_ext_stxkind); - arr = DatumGetArrayTypeP(datum); - if (ARR_NDIM(arr) != 1 || - ARR_HASNULL(arr) || - ARR_ELEMTYPE(arr) != CHAROID) - elog(ERROR, "stxkind is not a 1-D char array"); - enabled = (char *) ARR_DATA_PTR(arr); - for (i = 0; i < ARR_DIMS(arr)[0]; i++) - { - Assert((enabled[i] == STATS_EXT_NDISTINCT) || - (enabled[i] == STATS_EXT_DEPENDENCIES) || - (enabled[i] == STATS_EXT_MCV) || - (enabled[i] == STATS_EXT_EXPRESSIONS)); - entry->types = lappend_int(entry->types, (int) enabled[i]); - } - - /* decode expression (if any) */ - datum = SysCacheGetAttr(STATEXTOID, htup, - Anum_pg_statistic_ext_stxexprs, &isnull); - - if (!isnull) - { - char *exprsString; - - exprsString = TextDatumGetCString(datum); - exprs = (List *) stringToNode(exprsString); - - pfree(exprsString); - - /* - * Run the expressions through eval_const_expressions. This is not - * just an optimization, but is necessary, because the planner - * will be comparing them to similarly-processed qual clauses, and - * may fail to detect valid matches without this. We must not use - * canonicalize_qual, however, since these aren't qual - * expressions. - */ - exprs = (List *) eval_const_expressions(NULL, (Node *) exprs); - - /* May as well fix opfuncids too */ - fix_opfuncids((Node *) exprs); - } - - entry->exprs = exprs; - + StatExtEntry *entry = create_stat_ext_entry(htup); result = lappend(result, entry); } -- 2.43.0