diff options
Diffstat (limited to 'src/backend/parser/parse_utilcmd.c')
-rw-r--r-- | src/backend/parser/parse_utilcmd.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 6029eb13d7f..8c7bd686397 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -39,6 +39,7 @@ #include "catalog/pg_constraint_fn.h" #include "catalog/pg_opclass.h" #include "catalog/pg_operator.h" +#include "catalog/pg_statistic_ext.h" #include "catalog/pg_type.h" #include "commands/comment.h" #include "commands/defrem.h" @@ -85,6 +86,7 @@ typedef struct List *fkconstraints; /* FOREIGN KEY constraints */ List *ixconstraints; /* index-creating constraints */ List *inh_indexes; /* cloned indexes from INCLUDING INDEXES */ + List *extstats; /* cloned extended statistics */ List *blist; /* "before list" of things to do before * creating the table */ List *alist; /* "after list" of things to do after creating @@ -118,11 +120,14 @@ static void transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_clause); static void transformOfType(CreateStmtContext *cxt, TypeName *ofTypename); +static CreateStatsStmt *generateClonedExtStatsStmt(RangeVar *heapRel, + Oid heapRelid, Oid source_statsid); static List *get_collation(Oid collation, Oid actual_datatype); static List *get_opclass(Oid opclass, Oid actual_datatype); static void transformIndexConstraints(CreateStmtContext *cxt); static IndexStmt *transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt); +static void transformExtendedStatistics(CreateStmtContext *cxt); static void transformFKConstraints(CreateStmtContext *cxt, bool skipValidation, bool isAddConstraint); @@ -234,6 +239,7 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) cxt.fkconstraints = NIL; cxt.ixconstraints = NIL; cxt.inh_indexes = NIL; + cxt.extstats = NIL; cxt.blist = NIL; cxt.alist = NIL; cxt.pkey = NULL; @@ -335,6 +341,11 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) transformCheckConstraints(&cxt, !is_foreign_table ? true : false); /* + * Postprocess extended statistics. + */ + transformExtendedStatistics(&cxt); + + /* * Output results. */ stmt->tableElts = cxt.columns; @@ -1190,6 +1201,43 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla } /* + * Likewise, copy extended statistics if requested + */ + if (table_like_clause->options & CREATE_TABLE_LIKE_STATISTICS) + { + List *parent_extstats; + ListCell *l; + + parent_extstats = RelationGetStatExtList(relation); + + foreach(l, parent_extstats) + { + Oid parent_stat_oid = lfirst_oid(l); + CreateStatsStmt *stats_stmt; + + stats_stmt = generateClonedExtStatsStmt(cxt->relation, + RelationGetRelid(relation), + parent_stat_oid); + + /* Copy comment on statistics object, if requested */ + if (table_like_clause->options & CREATE_TABLE_LIKE_COMMENTS) + { + comment = GetComment(parent_stat_oid, StatisticExtRelationId, 0); + + /* + * We make use of CreateStatsStmt's stxcomment option, so as + * not to need to know now what name the statistics will have. + */ + stats_stmt->stxcomment = comment; + } + + cxt->extstats = lappend(cxt->extstats, stats_stmt); + } + + list_free(parent_extstats); + } + + /* * Close the parent rel, but keep our AccessShareLock on it until xact * commit. That will prevent someone else from deleting or ALTERing the * parent before the child is committed. @@ -1567,6 +1615,85 @@ generateClonedIndexStmt(RangeVar *heapRel, Oid heapRelid, Relation source_idx, } /* + * Generate a CreateStatsStmt node using information from an already existing + * extended statistic "source_statsid", for the rel identified by heapRel and + * heapRelid. + */ +static CreateStatsStmt * +generateClonedExtStatsStmt(RangeVar *heapRel, Oid heapRelid, + Oid source_statsid) +{ + HeapTuple ht_stats; + Form_pg_statistic_ext statsrec; + CreateStatsStmt *stats; + List *stat_types = NIL; + List *def_names = NIL; + bool isnull; + Datum datum; + ArrayType *arr; + char *enabled; + int i; + + Assert(OidIsValid(heapRelid)); + Assert(heapRel != NULL); + + /* + * Fetch pg_statistic_ext tuple of source statistics object. + */ + ht_stats = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(source_statsid)); + if (!HeapTupleIsValid(ht_stats)) + elog(ERROR, "cache lookup failed for statistics object %u", source_statsid); + statsrec = (Form_pg_statistic_ext) GETSTRUCT(ht_stats); + + /* Determine which statistics types exist */ + datum = SysCacheGetAttr(STATEXTOID, ht_stats, + 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); + for (i = 0; i < ARR_DIMS(arr)[0]; i++) + { + if (enabled[i] == STATS_EXT_NDISTINCT) + stat_types = lappend(stat_types, makeString("ndistinct")); + else if (enabled[i] == STATS_EXT_DEPENDENCIES) + stat_types = lappend(stat_types, makeString("dependencies")); + else + elog(ERROR, "unrecognized statistics kind %c", enabled[i]); + } + + /* Determine which columns the statistics are on */ + for (i = 0; i < statsrec->stxkeys.dim1; i++) + { + ColumnRef *cref = makeNode(ColumnRef); + AttrNumber attnum = statsrec->stxkeys.values[i]; + + cref->fields = list_make1(makeString(get_attname(heapRelid, + attnum, false))); + cref->location = -1; + + def_names = lappend(def_names, cref); + } + + /* finally, build the output node */ + stats = makeNode(CreateStatsStmt); + stats->defnames = NULL; + stats->stat_types = stat_types; + stats->exprs = def_names; + stats->relations = list_make1(heapRel); + stats->stxcomment = NULL; + stats->if_not_exists = false; + + /* Clean up */ + ReleaseSysCache(ht_stats); + + return stats; +} + +/* * get_collation - fetch qualified name of a collation * * If collation is InvalidOid or is the default for the given actual_datatype, @@ -2120,6 +2247,18 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt) } /* + * transformExtendedStatistics + * Handle extended statistic objects + * + * Right now, there's nothing to do here, so we just copy the list. + */ +static void +transformExtendedStatistics(CreateStmtContext *cxt) +{ + cxt->alist = list_concat(cxt->alist, cxt->extstats); +} + +/* * transformCheckConstraints * handle CHECK constraints * @@ -2695,6 +2834,7 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, cxt.fkconstraints = NIL; cxt.ixconstraints = NIL; cxt.inh_indexes = NIL; + cxt.extstats = NIL; cxt.blist = NIL; cxt.alist = NIL; cxt.pkey = NULL; @@ -2957,6 +3097,9 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt, newcmds = lappend(newcmds, newcmd); } + /* Append extended statistic objects */ + transformExtendedStatistics(&cxt); + /* Close rel */ relation_close(rel, NoLock); |