diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 08fc18e96b..1248b2ee5c 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -370,10 +370,14 @@ do_analyze_rel(Relation onerel, int options, VacuumParams *params, /* * Determine which columns to analyze * - * Note that system attributes are never analyzed. + * Note that system attributes are never analyzed, so we just reject them + * at the lookup stage. We also reject duplicate column mentions. (We + * could alternatively ignore duplicates, but analyzing a column twice + * won't work; we'd end up making a conflicting update in pg_statistic.) */ if (va_cols != NIL) { + Bitmapset *unique_cols = NULL; ListCell *le; vacattrstats = (VacAttrStats **) palloc(list_length(va_cols) * @@ -389,6 +393,13 @@ do_analyze_rel(Relation onerel, int options, VacuumParams *params, (errcode(ERRCODE_UNDEFINED_COLUMN), errmsg("column \"%s\" of relation \"%s\" does not exist", col, RelationGetRelationName(onerel)))); + if (bms_is_member(i, unique_cols)) + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_COLUMN), + errmsg("column \"%s\" of relation \"%s\" is specified twice", + col, RelationGetRelationName(onerel)))); + unique_cols = bms_add_member(unique_cols, i); + vacattrstats[tcnt] = examine_attribute(onerel, i, NULL); if (vacattrstats[tcnt] != NULL) tcnt++; @@ -527,9 +538,9 @@ do_analyze_rel(Relation onerel, int options, VacuumParams *params, stats->rows = rows; stats->tupDesc = onerel->rd_att; stats->compute_stats(stats, - std_fetch_func, - numrows, - totalrows); + std_fetch_func, + numrows, + totalrows); /* * If the appropriate flavor of the n_distinct option is @@ -831,9 +842,9 @@ compute_index_stats(Relation onerel, double totalrows, stats->exprnulls = exprnulls + i; stats->rowstride = attr_cnt; stats->compute_stats(stats, - ind_fetch_func, - numindexrows, - totalindexrows); + ind_fetch_func, + numindexrows, + totalindexrows); /* * If the n_distinct option is specified, it overrides the diff --git a/src/test/regress/expected/vacuum.out b/src/test/regress/expected/vacuum.out index 6f68663087..a16f26da7e 100644 --- a/src/test/regress/expected/vacuum.out +++ b/src/test/regress/expected/vacuum.out @@ -90,4 +90,9 @@ UPDATE vacparted SET b = 'b'; VACUUM (ANALYZE) vacparted; VACUUM (FULL) vacparted; VACUUM (FREEZE) vacparted; +-- check behavior with duplicate column mentions +VACUUM ANALYZE vacparted(a,b,a); +ERROR: column "a" of relation "vacparted" is specified twice +ANALYZE vacparted(a,b,b); +ERROR: column "b" of relation "vacparted" is specified twice DROP TABLE vacparted; diff --git a/src/test/regress/sql/vacuum.sql b/src/test/regress/sql/vacuum.sql index 7c5fb04917..96a848ca95 100644 --- a/src/test/regress/sql/vacuum.sql +++ b/src/test/regress/sql/vacuum.sql @@ -73,4 +73,9 @@ UPDATE vacparted SET b = 'b'; VACUUM (ANALYZE) vacparted; VACUUM (FULL) vacparted; VACUUM (FREEZE) vacparted; + +-- check behavior with duplicate column mentions +VACUUM ANALYZE vacparted(a,b,a); +ANALYZE vacparted(a,b,b); + DROP TABLE vacparted;