aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2017-09-21 18:13:11 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2017-09-21 18:13:11 -0400
commitb572b435ca67a2c032187d376baa271f9049b7cf (patch)
tree2ca521ed45fa68cf5801ba8696d1f92ee97d5bfc
parente5b8b771e7a98e3620679cd9873ad2507ab87fb5 (diff)
downloadpostgresql-b572b435ca67a2c032187d376baa271f9049b7cf.tar.gz
postgresql-b572b435ca67a2c032187d376baa271f9049b7cf.zip
Give a better error for duplicate entries in VACUUM/ANALYZE column list.
Previously, the code didn't think about this case and would just try to analyze such a column twice. That would fail at the point of inserting the second version of the pg_statistic row, with obscure error messsages like "duplicate key value violates unique constraint" or "tuple already updated by self", depending on context and PG version. We could allow the case by ignoring duplicate column specifications, but it seems better to reject it explicitly. The bogus error messages seem like arguably a bug, so back-patch to all supported versions. Nathan Bossart, per a report from Michael Paquier, and whacked around a bit by me. Discussion: https://postgr.es/m/E061A8E3-5E3D-494D-94F0-E8A9B312BBFC@amazon.com
-rw-r--r--src/backend/commands/analyze.c13
-rw-r--r--src/test/regress/expected/vacuum.out5
-rw-r--r--src/test/regress/sql/vacuum.sql4
3 files changed, 21 insertions, 1 deletions
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 5161bac5457..4dad36820d0 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -370,10 +370,14 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
/*
* 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 (vacstmt->va_cols != NIL)
{
+ Bitmapset *unique_cols = NULL;
ListCell *le;
vacattrstats = (VacAttrStats **) palloc(list_length(vacstmt->va_cols) *
@@ -389,6 +393,13 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
(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++;
diff --git a/src/test/regress/expected/vacuum.out b/src/test/regress/expected/vacuum.out
index d2d75038286..bf5034ad685 100644
--- a/src/test/regress/expected/vacuum.out
+++ b/src/test/regress/expected/vacuum.out
@@ -79,5 +79,10 @@ ERROR: ANALYZE cannot be executed from VACUUM or ANALYZE
CONTEXT: SQL function "do_analyze" statement 1
SQL function "wrap_do_analyze" statement 1
VACUUM FULL vactst;
+-- check behavior with duplicate column mentions
+VACUUM ANALYZE vaccluster(i,i);
+ERROR: column "i" of relation "vaccluster" is specified twice
+ANALYZE vaccluster(i,i);
+ERROR: column "i" of relation "vaccluster" is specified twice
DROP TABLE vaccluster;
DROP TABLE vactst;
diff --git a/src/test/regress/sql/vacuum.sql b/src/test/regress/sql/vacuum.sql
index f8412016cf3..0d58376b943 100644
--- a/src/test/regress/sql/vacuum.sql
+++ b/src/test/regress/sql/vacuum.sql
@@ -60,5 +60,9 @@ VACUUM FULL pg_database;
VACUUM FULL vaccluster;
VACUUM FULL vactst;
+-- check behavior with duplicate column mentions
+VACUUM ANALYZE vaccluster(i,i);
+ANALYZE vaccluster(i,i);
+
DROP TABLE vaccluster;
DROP TABLE vactst;