Skip to content

Commit

Permalink
Refactor ON CONFLICT index inference parse tree representation.
Browse files Browse the repository at this point in the history
Defer lookup of opfamily and input type of a of a user specified opclass
until the optimizer selects among available unique indexes; and store
the opclass in the parse analyzed tree instead.  The primary reason for
doing this is that for rule deparsing it's easier to use the opclass
than the previous representation.

While at it also rename a variable in the inference code to better fit
it's purpose.

This is separate from the actual fixes for deparsing to make review
easier.
  • Loading branch information
anarazel committed May 19, 2015
1 parent b48437d commit 0740cbd
Show file tree
Hide file tree
Showing 8 changed files with 31 additions and 35 deletions.
3 changes: 1 addition & 2 deletions contrib/pg_stat_statements/pg_stat_statements.c
Expand Up @@ -2645,8 +2645,7 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
InferenceElem *ie = (InferenceElem *) node;

APP_JUMB(ie->infercollid);
APP_JUMB(ie->inferopfamily);
APP_JUMB(ie->inferopcinputtype);
APP_JUMB(ie->inferopclass);
JumbleExpr(jstate, ie->expr);
}
break;
Expand Down
3 changes: 1 addition & 2 deletions src/backend/nodes/copyfuncs.c
Expand Up @@ -1839,8 +1839,7 @@ _copyInferenceElem(const InferenceElem *from)

COPY_NODE_FIELD(expr);
COPY_SCALAR_FIELD(infercollid);
COPY_SCALAR_FIELD(inferopfamily);
COPY_SCALAR_FIELD(inferopcinputtype);
COPY_SCALAR_FIELD(inferopclass);

return newnode;
}
Expand Down
3 changes: 1 addition & 2 deletions src/backend/nodes/equalfuncs.c
Expand Up @@ -702,8 +702,7 @@ _equalInferenceElem(const InferenceElem *a, const InferenceElem *b)
{
COMPARE_NODE_FIELD(expr);
COMPARE_SCALAR_FIELD(infercollid);
COMPARE_SCALAR_FIELD(inferopfamily);
COMPARE_SCALAR_FIELD(inferopcinputtype);
COMPARE_SCALAR_FIELD(inferopclass);

return true;
}
Expand Down
3 changes: 1 addition & 2 deletions src/backend/nodes/outfuncs.c
Expand Up @@ -1474,8 +1474,7 @@ _outInferenceElem(StringInfo str, const InferenceElem *node)

WRITE_NODE_FIELD(expr);
WRITE_OID_FIELD(infercollid);
WRITE_OID_FIELD(inferopfamily);
WRITE_OID_FIELD(inferopcinputtype);
WRITE_OID_FIELD(inferopclass);
}

static void
Expand Down
3 changes: 1 addition & 2 deletions src/backend/nodes/readfuncs.c
Expand Up @@ -1214,8 +1214,7 @@ _readInferenceElem(void)

READ_NODE_FIELD(expr);
READ_OID_FIELD(infercollid);
READ_OID_FIELD(inferopfamily);
READ_OID_FIELD(inferopcinputtype);
READ_OID_FIELD(inferopclass);

READ_DONE();
}
Expand Down
34 changes: 22 additions & 12 deletions src/backend/optimizer/util/plancat.c
Expand Up @@ -438,8 +438,8 @@ infer_arbiter_indexes(PlannerInfo *root)
Bitmapset *inferAttrs = NULL;
List *inferElems = NIL;

/* Result */
List *candidates = NIL;
/* Results */
List *results = NIL;

/*
* Quickly return NIL for ON CONFLICT DO NOTHING without an inference
Expand Down Expand Up @@ -565,11 +565,11 @@ infer_arbiter_indexes(PlannerInfo *root)
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("ON CONFLICT DO UPDATE not supported with exclusion constraints")));

candidates = lappend_oid(candidates, idxForm->indexrelid);
results = lappend_oid(results, idxForm->indexrelid);
list_free(indexList);
index_close(idxRel, NoLock);
heap_close(relation, NoLock);
return candidates;
return results;
}
else if (indexOidFromConstraint != InvalidOid)
{
Expand Down Expand Up @@ -633,7 +633,7 @@ infer_arbiter_indexes(PlannerInfo *root)
* index definition.
*/
if (elem->infercollid != InvalidOid ||
elem->inferopfamily != InvalidOid ||
elem->inferopclass != InvalidOid ||
list_member(idxExprs, elem->expr))
continue;

Expand All @@ -660,20 +660,20 @@ infer_arbiter_indexes(PlannerInfo *root)
if (!predicate_implied_by(predExprs, whereExplicit))
goto next;

candidates = lappend_oid(candidates, idxForm->indexrelid);
results = lappend_oid(results, idxForm->indexrelid);
next:
index_close(idxRel, NoLock);
}

list_free(indexList);
heap_close(relation, NoLock);

if (candidates == NIL)
if (results == NIL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("there is no unique or exclusion constraint matching the ON CONFLICT specification")));

return candidates;
return results;
}

/*
Expand Down Expand Up @@ -709,23 +709,33 @@ infer_collation_opclass_match(InferenceElem *elem, Relation idxRel,
Bitmapset *inferAttrs, List *idxExprs)
{
AttrNumber natt;
Oid inferopfamily = InvalidOid; /* OID of att opfamily */
Oid inferopcinputtype = InvalidOid; /* OID of att opfamily */

/*
* If inference specification element lacks collation/opclass, then no
* need to check for exact match.
*/
if (elem->infercollid == InvalidOid && elem->inferopfamily == InvalidOid)
if (elem->infercollid == InvalidOid && elem->inferopclass == InvalidOid)
return true;

/*
* Lookup opfamily and input type, for matching indexes
*/
if (elem->inferopclass)
{
inferopfamily = get_opclass_family(elem->inferopclass);
inferopcinputtype = get_opclass_input_type(elem->inferopclass);
}

for (natt = 1; natt <= idxRel->rd_att->natts; natt++)
{
Oid opfamily = idxRel->rd_opfamily[natt - 1];
Oid opcinputtype = idxRel->rd_opcintype[natt - 1];
Oid collation = idxRel->rd_indcollation[natt - 1];

if (elem->inferopfamily != InvalidOid &&
(elem->inferopfamily != opfamily ||
elem->inferopcinputtype != opcinputtype))
if (elem->inferopclass != InvalidOid &&
(inferopfamily != opfamily || inferopcinputtype != opcinputtype))
{
/* Attribute needed to match opclass, but didn't */
continue;
Expand Down
14 changes: 3 additions & 11 deletions src/backend/parser/parse_clause.c
Expand Up @@ -2730,18 +2730,10 @@ resolve_unique_index_expr(ParseState *pstate, InferClause *infer,
exprLocation(pInfer->expr));

if (!ielem->opclass)
{
pInfer->inferopfamily = InvalidOid;
pInfer->inferopcinputtype = InvalidOid;
}
pInfer->inferopclass = InvalidOid;
else
{
Oid opclass = get_opclass_oid(BTREE_AM_OID, ielem->opclass,
false);

pInfer->inferopfamily = get_opclass_family(opclass);
pInfer->inferopcinputtype = get_opclass_input_type(opclass);
}
pInfer->inferopclass = get_opclass_oid(BTREE_AM_OID,
ielem->opclass, false);

result = lappend(result, pInfer);
}
Expand Down
3 changes: 1 addition & 2 deletions src/include/nodes/primnodes.h
Expand Up @@ -1198,8 +1198,7 @@ typedef struct InferenceElem
Expr xpr;
Node *expr; /* expression to infer from, or NULL */
Oid infercollid; /* OID of collation, or InvalidOid */
Oid inferopfamily; /* OID of att opfamily, or InvalidOid */
Oid inferopcinputtype; /* OID of att input type, or InvalidOid */
Oid inferopclass; /* OID of att opclass, or InvalidOid */
} InferenceElem;

/*--------------------
Expand Down

0 comments on commit 0740cbd

Please sign in to comment.