diff --git a/src/backend/distributed/commands/statistics.c b/src/backend/distributed/commands/statistics.c index ed2525bdb..1265887ff 100644 --- a/src/backend/distributed/commands/statistics.c +++ b/src/backend/distributed/commands/statistics.c @@ -40,6 +40,7 @@ #include "miscadmin.h" #include "utils/builtins.h" #include "utils/fmgroids.h" +#include "utils/fmgrprotos.h" #include "utils/lsyscache.h" #include "utils/relcache.h" #include "utils/ruleutils.h" @@ -447,8 +448,20 @@ GetExplicitStatisticsCommandList(Oid relationId) foreach_oid(statisticsId, statisticsIdList) { /* we need create commands for already created stats before distribution */ - char *createStatisticsCommand = pg_get_statisticsobj_worker_compat(statisticsId, - false, false); + Datum commandText = DirectFunctionCall1(pg_get_statisticsobjdef, + ObjectIdGetDatum(statisticsId)); + + /* + * pg_get_statisticsobjdef doesn't throw an error if there is no such + * statistics object, be on the safe side. + */ + if (DatumGetPointer(commandText) == NULL) + { + ereport(ERROR, (errmsg("statistics with oid %u does not exist", + statisticsId))); + } + + char *createStatisticsCommand = TextDatumGetCString(commandText); explicitStatisticsCommandList = lappend(explicitStatisticsCommandList, diff --git a/src/backend/distributed/deparser/ruleutils_12.c b/src/backend/distributed/deparser/ruleutils_12.c index 43994120b..513678df1 100644 --- a/src/backend/distributed/deparser/ruleutils_12.c +++ b/src/backend/distributed/deparser/ruleutils_12.c @@ -427,7 +427,6 @@ static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, deparse_context *context); static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context); -char *pg_get_statisticsobj_worker(Oid statextid, bool missing_ok); static void get_opclass_name(Oid opclass, Oid actual_datatype, StringInfo buf); static Node *processIndirection(Node *node, deparse_context *context); @@ -7516,127 +7515,6 @@ get_tablesample_def(TableSampleClause *tablesample, deparse_context *context) } -char * -pg_get_statisticsobj_worker(Oid statextid, bool missing_ok) -{ - StringInfoData buf; - int colno; - bool isnull; - int i; - - HeapTuple statexttup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statextid)); - - if (!HeapTupleIsValid(statexttup)) - { - if (missing_ok) - { - return NULL; - } - elog(ERROR, "cache lookup failed for statistics object %u", statextid); - } - - Form_pg_statistic_ext statextrec = (Form_pg_statistic_ext) GETSTRUCT(statexttup); - - initStringInfo(&buf); - - char *nsp = get_namespace_name(statextrec->stxnamespace); - appendStringInfo(&buf, "CREATE STATISTICS %s", - quote_qualified_identifier(nsp, - NameStr(statextrec->stxname))); - - /* - * Decode the stxkind column so that we know which stats types to print. - */ - Datum datum = SysCacheGetAttr(STATEXTOID, statexttup, - Anum_pg_statistic_ext_stxkind, &isnull); - Assert(!isnull); - ArrayType *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"); - } - char *enabled = (char *) ARR_DATA_PTR(arr); - - bool ndistinct_enabled = false; - bool dependencies_enabled = false; - bool mcv_enabled = false; - - for (i = 0; i < ARR_DIMS(arr)[0]; i++) - { - if (enabled[i] == STATS_EXT_NDISTINCT) - { - ndistinct_enabled = true; - } - if (enabled[i] == STATS_EXT_DEPENDENCIES) - { - dependencies_enabled = true; - } - if (enabled[i] == STATS_EXT_MCV) - { - mcv_enabled = true; - } - } - - /* - * If any option is disabled, then we'll need to append the types clause - * to show which options are enabled. We omit the types clause on purpose - * when all options are enabled, so a pg_dump/pg_restore will create all - * statistics types on a newer postgres version, if the statistics had all - * options enabled on the original version. - */ - if (!ndistinct_enabled || !dependencies_enabled || !mcv_enabled) - { - bool gotone = false; - - appendStringInfoString(&buf, " ("); - - if (ndistinct_enabled) - { - appendStringInfoString(&buf, "ndistinct"); - gotone = true; - } - - if (dependencies_enabled) - { - appendStringInfo(&buf, "%sdependencies", gotone ? ", " : ""); - gotone = true; - } - - if (mcv_enabled) - { - appendStringInfo(&buf, "%smcv", gotone ? ", " : ""); - } - - appendStringInfoChar(&buf, ')'); - } - - appendStringInfoString(&buf, " ON "); - - for (colno = 0; colno < statextrec->stxkeys.dim1; colno++) - { - AttrNumber attnum = statextrec->stxkeys.values[colno]; - - if (colno > 0) - { - appendStringInfoString(&buf, ", "); - } - - char *attname = get_attname(statextrec->stxrelid, attnum, false); - - appendStringInfoString(&buf, quote_identifier(attname)); - } - - appendStringInfo(&buf, " FROM %s", - generate_relation_name(statextrec->stxrelid, NIL)); - - ReleaseSysCache(statexttup); - - return buf.data; -} - - /* * get_opclass_name - fetch name of an index operator class * diff --git a/src/backend/distributed/deparser/ruleutils_13.c b/src/backend/distributed/deparser/ruleutils_13.c index 885fdc70e..5c1749c5f 100644 --- a/src/backend/distributed/deparser/ruleutils_13.c +++ b/src/backend/distributed/deparser/ruleutils_13.c @@ -432,7 +432,6 @@ static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, deparse_context *context); static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context); -char *pg_get_statisticsobj_worker(Oid statextid, bool missing_ok); static void get_opclass_name(Oid opclass, Oid actual_datatype, StringInfo buf); static Node *processIndirection(Node *node, deparse_context *context); @@ -7574,127 +7573,6 @@ get_tablesample_def(TableSampleClause *tablesample, deparse_context *context) } -char * -pg_get_statisticsobj_worker(Oid statextid, bool missing_ok) -{ - StringInfoData buf; - int colno; - bool isnull; - int i; - - HeapTuple statexttup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statextid)); - - if (!HeapTupleIsValid(statexttup)) - { - if (missing_ok) - { - return NULL; - } - elog(ERROR, "cache lookup failed for statistics object %u", statextid); - } - - Form_pg_statistic_ext statextrec = (Form_pg_statistic_ext) GETSTRUCT(statexttup); - - initStringInfo(&buf); - - char *nsp = get_namespace_name(statextrec->stxnamespace); - appendStringInfo(&buf, "CREATE STATISTICS %s", - quote_qualified_identifier(nsp, - NameStr(statextrec->stxname))); - - /* - * Decode the stxkind column so that we know which stats types to print. - */ - Datum datum = SysCacheGetAttr(STATEXTOID, statexttup, - Anum_pg_statistic_ext_stxkind, &isnull); - Assert(!isnull); - ArrayType *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"); - } - char *enabled = (char *) ARR_DATA_PTR(arr); - - bool ndistinct_enabled = false; - bool dependencies_enabled = false; - bool mcv_enabled = false; - - for (i = 0; i < ARR_DIMS(arr)[0]; i++) - { - if (enabled[i] == STATS_EXT_NDISTINCT) - { - ndistinct_enabled = true; - } - if (enabled[i] == STATS_EXT_DEPENDENCIES) - { - dependencies_enabled = true; - } - if (enabled[i] == STATS_EXT_MCV) - { - mcv_enabled = true; - } - } - - /* - * If any option is disabled, then we'll need to append the types clause - * to show which options are enabled. We omit the types clause on purpose - * when all options are enabled, so a pg_dump/pg_restore will create all - * statistics types on a newer postgres version, if the statistics had all - * options enabled on the original version. - */ - if (!ndistinct_enabled || !dependencies_enabled || !mcv_enabled) - { - bool gotone = false; - - appendStringInfoString(&buf, " ("); - - if (ndistinct_enabled) - { - appendStringInfoString(&buf, "ndistinct"); - gotone = true; - } - - if (dependencies_enabled) - { - appendStringInfo(&buf, "%sdependencies", gotone ? ", " : ""); - gotone = true; - } - - if (mcv_enabled) - { - appendStringInfo(&buf, "%smcv", gotone ? ", " : ""); - } - - appendStringInfoChar(&buf, ')'); - } - - appendStringInfoString(&buf, " ON "); - - for (colno = 0; colno < statextrec->stxkeys.dim1; colno++) - { - AttrNumber attnum = statextrec->stxkeys.values[colno]; - - if (colno > 0) - { - appendStringInfoString(&buf, ", "); - } - - char *attname = get_attname(statextrec->stxrelid, attnum, false); - - appendStringInfoString(&buf, quote_identifier(attname)); - } - - appendStringInfo(&buf, " FROM %s", - generate_relation_name(statextrec->stxrelid, NIL)); - - ReleaseSysCache(statexttup); - - return buf.data; -} - - /* * get_opclass_name - fetch name of an index operator class * diff --git a/src/backend/distributed/deparser/ruleutils_14.c b/src/backend/distributed/deparser/ruleutils_14.c index 0fc731e5a..bde8e1b23 100644 --- a/src/backend/distributed/deparser/ruleutils_14.c +++ b/src/backend/distributed/deparser/ruleutils_14.c @@ -320,9 +320,6 @@ typedef struct * as a parameter, and append their text output to its contents. * ---------- */ -static char *deparse_expression_pretty(Node *expr, List *dpcontext, - bool forceprefix, bool showimplicit, - int prettyFlags, int startIndent); static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces, Bitmapset *rels_used); static void set_deparse_for_query(deparse_namespace *dpns, Query *query, @@ -440,8 +437,6 @@ static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, deparse_context *context); static void get_tablesample_def(TableSampleClause *tablesample, deparse_context *context); -char *pg_get_statisticsobj_worker(Oid statextid, bool columns_only, - bool missing_ok); static void get_opclass_name(Oid opclass, Oid actual_datatype, StringInfo buf); static Node *processIndirection(Node *node, deparse_context *context); @@ -648,51 +643,6 @@ pg_get_rule_expr(Node *expression) } -/* ---------- - * deparse_expression_pretty - General utility for deparsing expressions - * - * expr is the node tree to be deparsed. It must be a transformed expression - * tree (ie, not the raw output of gram.y). - * - * dpcontext is a list of deparse_namespace nodes representing the context - * for interpreting Vars in the node tree. It can be NIL if no Vars are - * expected. - * - * forceprefix is true to force all Vars to be prefixed with their table names. - * - * showimplicit is true to force all implicit casts to be shown explicitly. - * - * Tries to pretty up the output according to prettyFlags and startIndent. - * - * The result is a palloc'd string. - * ---------- - */ -static char * -deparse_expression_pretty(Node *expr, List *dpcontext, - bool forceprefix, bool showimplicit, - int prettyFlags, int startIndent) -{ - StringInfoData buf; - deparse_context context; - - initStringInfo(&buf); - context.buf = &buf; - context.namespaces = dpcontext; - context.windowClause = NIL; - context.windowTList = NIL; - context.varprefix = forceprefix; - context.prettyFlags = prettyFlags; - context.wrapColumn = WRAP_COLUMN_DEFAULT; - context.indentLevel = startIndent; - context.special_exprkind = EXPR_KIND_NONE; - context.appendparents = NULL; - - get_rule_expr(expr, &context, showimplicit); - - return buf.data; -} - - /* * set_rtable_names: select RTE aliases to be used in printing a query * @@ -8130,195 +8080,6 @@ get_tablesample_def(TableSampleClause *tablesample, deparse_context *context) } -char * -pg_get_statisticsobj_worker(Oid statextid, bool columns_only, bool missing_ok) -{ - StringInfoData buf; - int colno; - char *nsp; - ArrayType *arr; - char *enabled; - Datum datum; - bool isnull; - bool ndistinct_enabled; - bool dependencies_enabled; - bool mcv_enabled; - int i; - List *context; - ListCell *lc; - List *exprs = NIL; - bool has_exprs; - int ncolumns; - - HeapTuple statexttup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statextid)); - - if (!HeapTupleIsValid(statexttup)) - { - if (missing_ok) - { - return NULL; - } - elog(ERROR, "cache lookup failed for statistics object %u", statextid); - } - - /* has the statistics expressions? */ - has_exprs = !heap_attisnull(statexttup, Anum_pg_statistic_ext_stxexprs, NULL); - - Form_pg_statistic_ext statextrec = (Form_pg_statistic_ext) GETSTRUCT(statexttup); - - /* - * Get the statistics expressions, if any. (NOTE: we do not use the - * relcache versions of the expressions, because we want to display - * non-const-folded expressions.) - */ - if (has_exprs) - { - Datum exprsDatum; - bool isNull; - char *exprsString; - - exprsDatum = SysCacheGetAttr(STATEXTOID, statexttup, - Anum_pg_statistic_ext_stxexprs, &isNull); - Assert(!isNull); - exprsString = TextDatumGetCString(exprsDatum); - exprs = (List *) stringToNode(exprsString); - pfree(exprsString); - } - else - { - exprs = NIL; - } - - /* count the number of columns (attributes and expressions) */ - ncolumns = statextrec->stxkeys.dim1 + list_length(exprs); - - initStringInfo(&buf); - - if (!columns_only) - { - nsp = get_namespace_name(statextrec->stxnamespace); - appendStringInfo(&buf, "CREATE STATISTICS %s", - quote_qualified_identifier(nsp, - NameStr(statextrec->stxname))); - - /* - * Decode the stxkind column so that we know which stats types to - * print. - */ - datum = SysCacheGetAttr(STATEXTOID, statexttup, - Anum_pg_statistic_ext_stxkind, &isnull); - Assert(!isnull); - 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); - - ndistinct_enabled = false; - dependencies_enabled = false; - mcv_enabled = false; - - for (i = 0; i < ARR_DIMS(arr)[0]; i++) - { - if (enabled[i] == STATS_EXT_NDISTINCT) - ndistinct_enabled = true; - else if (enabled[i] == STATS_EXT_DEPENDENCIES) - dependencies_enabled = true; - else if (enabled[i] == STATS_EXT_MCV) - mcv_enabled = true; - - /* ignore STATS_EXT_EXPRESSIONS (it's built automatically) */ - } - - /* - * If any option is disabled, then we'll need to append the types - * clause to show which options are enabled. We omit the types clause - * on purpose when all options are enabled, so a pg_dump/pg_restore - * will create all statistics types on a newer postgres version, if - * the statistics had all options enabled on the original version. - * - * But if the statistics is defined on just a single column, it has to - * be an expression statistics. In that case we don't need to specify - * kinds. - */ - if ((!ndistinct_enabled || !dependencies_enabled || !mcv_enabled) && - (ncolumns > 1)) - { - bool gotone = false; - - appendStringInfoString(&buf, " ("); - - if (ndistinct_enabled) - { - appendStringInfoString(&buf, "ndistinct"); - gotone = true; - } - - if (dependencies_enabled) - { - appendStringInfo(&buf, "%sdependencies", gotone ? ", " : ""); - gotone = true; - } - - if (mcv_enabled) - appendStringInfo(&buf, "%smcv", gotone ? ", " : ""); - - appendStringInfoChar(&buf, ')'); - } - - appendStringInfoString(&buf, " ON "); - } - - /* decode simple column references */ - for (colno = 0; colno < statextrec->stxkeys.dim1; colno++) - { - AttrNumber attnum = statextrec->stxkeys.values[colno]; - - if (colno > 0) - { - appendStringInfoString(&buf, ", "); - } - - char *attname = get_attname(statextrec->stxrelid, attnum, false); - - appendStringInfoString(&buf, quote_identifier(attname)); - } - - context = deparse_context_for(get_relation_name(statextrec->stxrelid), - statextrec->stxrelid); - - foreach(lc, exprs) - { - Node *expr = (Node *) lfirst(lc); - char *str; - int prettyFlags = PRETTYFLAG_INDENT; - - str = deparse_expression_pretty(expr, context, false, false, - prettyFlags, 0); - - if (colno > 0) - appendStringInfoString(&buf, ", "); - - /* Need parens if it's not a bare function call */ - if (looks_like_function(expr)) - appendStringInfoString(&buf, str); - else - appendStringInfo(&buf, "(%s)", str); - - colno++; - } - - if (!columns_only) - appendStringInfo(&buf, " FROM %s", - generate_relation_name(statextrec->stxrelid, NIL)); - - ReleaseSysCache(statexttup); - - return buf.data; -} - - /* * get_opclass_name - fetch name of an index operator class * diff --git a/src/include/distributed/citus_ruleutils.h b/src/include/distributed/citus_ruleutils.h index ac8d942c2..239621415 100644 --- a/src/include/distributed/citus_ruleutils.h +++ b/src/include/distributed/citus_ruleutils.h @@ -54,12 +54,6 @@ bool get_merged_argument_list(CallStmt *stmt, List **mergedNamedArgList, char * pg_get_rule_expr(Node *expression); extern void deparse_shard_query(Query *query, Oid distrelid, int64 shardid, StringInfo buffer); -#if PG_VERSION_NUM >= PG_VERSION_14 -extern char * pg_get_statisticsobj_worker(Oid statextid, bool columns_only, - bool missing_ok); -#else -extern char * pg_get_statisticsobj_worker(Oid statextid, bool missing_ok); -#endif extern char * generate_relation_name(Oid relid, List *namespaces); extern char * generate_qualified_relation_name(Oid relid); extern char * generate_operator_name(Oid operid, Oid arg1, Oid arg2); diff --git a/src/include/pg_version_compat.h b/src/include/pg_version_compat.h index 39ba6ed53..ad7a8bbb0 100644 --- a/src/include/pg_version_compat.h +++ b/src/include/pg_version_compat.h @@ -35,7 +35,6 @@ #define RelationGetPartitionDesc_compat(a, b) RelationGetPartitionDesc(a, b) #define make_simple_restrictinfo_compat(a, b) make_simple_restrictinfo(a, b) #define pull_varnos_compat(a, b) pull_varnos(a, b) -#define pg_get_statisticsobj_worker_compat(a, b, c) pg_get_statisticsobj_worker(a, b, c) #else #define AlterTableStmtObjType_compat(a) ((a)->relkind) #define F_NEXTVAL F_NEXTVAL_OID @@ -68,7 +67,6 @@ #define PQ_LARGE_MESSAGE_LIMIT 0 #define make_simple_restrictinfo_compat(a, b) make_simple_restrictinfo(b) #define pull_varnos_compat(a, b) pull_varnos(b) -#define pg_get_statisticsobj_worker_compat(a, b, c) pg_get_statisticsobj_worker(a, c) #endif #if PG_VERSION_NUM >= PG_VERSION_13