aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2016-05-11 17:06:53 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2016-05-11 17:06:53 -0400
commit8a13d5e6d1bb9ff9460c72992657077e57e30c32 (patch)
tree308abc7b6a332002846001a25736c0468fe31cb8 /src
parent26e66184d6136643d16f6fb167db517fb18b8f89 (diff)
downloadpostgresql-8a13d5e6d1bb9ff9460c72992657077e57e30c32.tar.gz
postgresql-8a13d5e6d1bb9ff9460c72992657077e57e30c32.zip
Fix infer_arbiter_indexes() to not barf on system columns.
While it could be argued that rejecting system column mentions in the ON CONFLICT list is an unsupported feature, falling over altogether just because the table has a unique index on OID is indubitably a bug. As far as I can tell, fixing infer_arbiter_indexes() is sufficient to make ON CONFLICT (oid) actually work, though making a regression test for that case is problematic because of the impossibility of setting the OID counter to a known value. Minor cosmetic cleanups along with the bug fix.
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/util/plancat.c43
1 files changed, 16 insertions, 27 deletions
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 4f399a5b854..b0b606ebc82 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -558,26 +558,18 @@ infer_arbiter_indexes(PlannerInfo *root)
/*
* Build normalized/BMS representation of plain indexed attributes, as
- * well as direct list of inference elements. This is required for
- * matching the cataloged definition of indexes.
+ * well as a separate list of expression items. This simplifies matching
+ * the cataloged definition of indexes.
*/
foreach(l, onconflict->arbiterElems)
{
- InferenceElem *elem;
+ InferenceElem *elem = (InferenceElem *) lfirst(l);
Var *var;
int attno;
- elem = (InferenceElem *) lfirst(l);
-
- /*
- * Parse analysis of inference elements performs full parse analysis
- * of Vars, even for non-expression indexes (in contrast with utility
- * command related use of IndexElem). However, indexes are cataloged
- * with simple attribute numbers for non-expression indexes. Those
- * are handled later.
- */
if (!IsA(elem->expr, Var))
{
+ /* If not a plain Var, just shove it in inferElems for now */
inferElems = lappend(inferElems, elem->expr);
continue;
}
@@ -585,14 +577,13 @@ infer_arbiter_indexes(PlannerInfo *root)
var = (Var *) elem->expr;
attno = var->varattno;
- if (attno < 0)
+ if (attno == 0)
ereport(ERROR,
- (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
- errmsg("system columns cannot be used in an ON CONFLICT clause")));
- else if (attno == 0)
- elog(ERROR, "whole row unique index inference specifications are not valid");
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("whole row unique index inference specifications are not supported")));
- inferAttrs = bms_add_member(inferAttrs, attno);
+ inferAttrs = bms_add_member(inferAttrs,
+ attno - FirstLowInvalidHeapAttributeNumber);
}
/*
@@ -609,18 +600,18 @@ infer_arbiter_indexes(PlannerInfo *root)
errmsg("constraint in ON CONFLICT clause has no associated index")));
}
- indexList = RelationGetIndexList(relation);
-
/*
* Using that representation, iterate through the list of indexes on the
* target relation to try and find a match
*/
+ indexList = RelationGetIndexList(relation);
+
foreach(l, indexList)
{
Oid indexoid = lfirst_oid(l);
Relation idxRel;
Form_pg_index idxForm;
- Bitmapset *indexedAttrs = NULL;
+ Bitmapset *indexedAttrs;
List *idxExprs;
List *predExprs;
AttrNumber natt;
@@ -679,17 +670,15 @@ infer_arbiter_indexes(PlannerInfo *root)
if (!idxForm->indisunique)
goto next;
- /* Build BMS representation of cataloged index attributes */
+ /* Build BMS representation of plain (non expression) index attrs */
+ indexedAttrs = NULL;
for (natt = 0; natt < idxForm->indnatts; natt++)
{
int attno = idxRel->rd_index->indkey.values[natt];
- /* XXX broken */
- if (attno < 0)
- elog(ERROR, "system column in index");
-
if (attno != 0)
- indexedAttrs = bms_add_member(indexedAttrs, attno);
+ indexedAttrs = bms_add_member(indexedAttrs,
+ attno - FirstLowInvalidHeapAttributeNumber);
}
/* Non-expression attributes (if any) must match */