mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-03-07 19:47:50 +08:00
Refactor ON CONFLICT index inference parse tree representation.
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.
This commit is contained in:
parent
b48437d11b
commit
0740cbd759
@ -2645,8 +2645,7 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
|
|||||||
InferenceElem *ie = (InferenceElem *) node;
|
InferenceElem *ie = (InferenceElem *) node;
|
||||||
|
|
||||||
APP_JUMB(ie->infercollid);
|
APP_JUMB(ie->infercollid);
|
||||||
APP_JUMB(ie->inferopfamily);
|
APP_JUMB(ie->inferopclass);
|
||||||
APP_JUMB(ie->inferopcinputtype);
|
|
||||||
JumbleExpr(jstate, ie->expr);
|
JumbleExpr(jstate, ie->expr);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1839,8 +1839,7 @@ _copyInferenceElem(const InferenceElem *from)
|
|||||||
|
|
||||||
COPY_NODE_FIELD(expr);
|
COPY_NODE_FIELD(expr);
|
||||||
COPY_SCALAR_FIELD(infercollid);
|
COPY_SCALAR_FIELD(infercollid);
|
||||||
COPY_SCALAR_FIELD(inferopfamily);
|
COPY_SCALAR_FIELD(inferopclass);
|
||||||
COPY_SCALAR_FIELD(inferopcinputtype);
|
|
||||||
|
|
||||||
return newnode;
|
return newnode;
|
||||||
}
|
}
|
||||||
|
@ -702,8 +702,7 @@ _equalInferenceElem(const InferenceElem *a, const InferenceElem *b)
|
|||||||
{
|
{
|
||||||
COMPARE_NODE_FIELD(expr);
|
COMPARE_NODE_FIELD(expr);
|
||||||
COMPARE_SCALAR_FIELD(infercollid);
|
COMPARE_SCALAR_FIELD(infercollid);
|
||||||
COMPARE_SCALAR_FIELD(inferopfamily);
|
COMPARE_SCALAR_FIELD(inferopclass);
|
||||||
COMPARE_SCALAR_FIELD(inferopcinputtype);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1474,8 +1474,7 @@ _outInferenceElem(StringInfo str, const InferenceElem *node)
|
|||||||
|
|
||||||
WRITE_NODE_FIELD(expr);
|
WRITE_NODE_FIELD(expr);
|
||||||
WRITE_OID_FIELD(infercollid);
|
WRITE_OID_FIELD(infercollid);
|
||||||
WRITE_OID_FIELD(inferopfamily);
|
WRITE_OID_FIELD(inferopclass);
|
||||||
WRITE_OID_FIELD(inferopcinputtype);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1214,8 +1214,7 @@ _readInferenceElem(void)
|
|||||||
|
|
||||||
READ_NODE_FIELD(expr);
|
READ_NODE_FIELD(expr);
|
||||||
READ_OID_FIELD(infercollid);
|
READ_OID_FIELD(infercollid);
|
||||||
READ_OID_FIELD(inferopfamily);
|
READ_OID_FIELD(inferopclass);
|
||||||
READ_OID_FIELD(inferopcinputtype);
|
|
||||||
|
|
||||||
READ_DONE();
|
READ_DONE();
|
||||||
}
|
}
|
||||||
|
@ -438,8 +438,8 @@ infer_arbiter_indexes(PlannerInfo *root)
|
|||||||
Bitmapset *inferAttrs = NULL;
|
Bitmapset *inferAttrs = NULL;
|
||||||
List *inferElems = NIL;
|
List *inferElems = NIL;
|
||||||
|
|
||||||
/* Result */
|
/* Results */
|
||||||
List *candidates = NIL;
|
List *results = NIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Quickly return NIL for ON CONFLICT DO NOTHING without an inference
|
* Quickly return NIL for ON CONFLICT DO NOTHING without an inference
|
||||||
@ -565,11 +565,11 @@ infer_arbiter_indexes(PlannerInfo *root)
|
|||||||
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
|
||||||
errmsg("ON CONFLICT DO UPDATE not supported with exclusion constraints")));
|
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);
|
list_free(indexList);
|
||||||
index_close(idxRel, NoLock);
|
index_close(idxRel, NoLock);
|
||||||
heap_close(relation, NoLock);
|
heap_close(relation, NoLock);
|
||||||
return candidates;
|
return results;
|
||||||
}
|
}
|
||||||
else if (indexOidFromConstraint != InvalidOid)
|
else if (indexOidFromConstraint != InvalidOid)
|
||||||
{
|
{
|
||||||
@ -633,7 +633,7 @@ infer_arbiter_indexes(PlannerInfo *root)
|
|||||||
* index definition.
|
* index definition.
|
||||||
*/
|
*/
|
||||||
if (elem->infercollid != InvalidOid ||
|
if (elem->infercollid != InvalidOid ||
|
||||||
elem->inferopfamily != InvalidOid ||
|
elem->inferopclass != InvalidOid ||
|
||||||
list_member(idxExprs, elem->expr))
|
list_member(idxExprs, elem->expr))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -660,7 +660,7 @@ infer_arbiter_indexes(PlannerInfo *root)
|
|||||||
if (!predicate_implied_by(predExprs, whereExplicit))
|
if (!predicate_implied_by(predExprs, whereExplicit))
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
candidates = lappend_oid(candidates, idxForm->indexrelid);
|
results = lappend_oid(results, idxForm->indexrelid);
|
||||||
next:
|
next:
|
||||||
index_close(idxRel, NoLock);
|
index_close(idxRel, NoLock);
|
||||||
}
|
}
|
||||||
@ -668,12 +668,12 @@ next:
|
|||||||
list_free(indexList);
|
list_free(indexList);
|
||||||
heap_close(relation, NoLock);
|
heap_close(relation, NoLock);
|
||||||
|
|
||||||
if (candidates == NIL)
|
if (results == NIL)
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
||||||
errmsg("there is no unique or exclusion constraint matching the ON CONFLICT specification")));
|
errmsg("there is no unique or exclusion constraint matching the ON CONFLICT specification")));
|
||||||
|
|
||||||
return candidates;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -709,23 +709,33 @@ infer_collation_opclass_match(InferenceElem *elem, Relation idxRel,
|
|||||||
Bitmapset *inferAttrs, List *idxExprs)
|
Bitmapset *inferAttrs, List *idxExprs)
|
||||||
{
|
{
|
||||||
AttrNumber natt;
|
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
|
* If inference specification element lacks collation/opclass, then no
|
||||||
* need to check for exact match.
|
* need to check for exact match.
|
||||||
*/
|
*/
|
||||||
if (elem->infercollid == InvalidOid && elem->inferopfamily == InvalidOid)
|
if (elem->infercollid == InvalidOid && elem->inferopclass == InvalidOid)
|
||||||
return true;
|
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++)
|
for (natt = 1; natt <= idxRel->rd_att->natts; natt++)
|
||||||
{
|
{
|
||||||
Oid opfamily = idxRel->rd_opfamily[natt - 1];
|
Oid opfamily = idxRel->rd_opfamily[natt - 1];
|
||||||
Oid opcinputtype = idxRel->rd_opcintype[natt - 1];
|
Oid opcinputtype = idxRel->rd_opcintype[natt - 1];
|
||||||
Oid collation = idxRel->rd_indcollation[natt - 1];
|
Oid collation = idxRel->rd_indcollation[natt - 1];
|
||||||
|
|
||||||
if (elem->inferopfamily != InvalidOid &&
|
if (elem->inferopclass != InvalidOid &&
|
||||||
(elem->inferopfamily != opfamily ||
|
(inferopfamily != opfamily || inferopcinputtype != opcinputtype))
|
||||||
elem->inferopcinputtype != opcinputtype))
|
|
||||||
{
|
{
|
||||||
/* Attribute needed to match opclass, but didn't */
|
/* Attribute needed to match opclass, but didn't */
|
||||||
continue;
|
continue;
|
||||||
|
@ -2730,18 +2730,10 @@ resolve_unique_index_expr(ParseState *pstate, InferClause *infer,
|
|||||||
exprLocation(pInfer->expr));
|
exprLocation(pInfer->expr));
|
||||||
|
|
||||||
if (!ielem->opclass)
|
if (!ielem->opclass)
|
||||||
{
|
pInfer->inferopclass = InvalidOid;
|
||||||
pInfer->inferopfamily = InvalidOid;
|
|
||||||
pInfer->inferopcinputtype = InvalidOid;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
pInfer->inferopclass = get_opclass_oid(BTREE_AM_OID,
|
||||||
Oid opclass = get_opclass_oid(BTREE_AM_OID, ielem->opclass,
|
ielem->opclass, false);
|
||||||
false);
|
|
||||||
|
|
||||||
pInfer->inferopfamily = get_opclass_family(opclass);
|
|
||||||
pInfer->inferopcinputtype = get_opclass_input_type(opclass);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = lappend(result, pInfer);
|
result = lappend(result, pInfer);
|
||||||
}
|
}
|
||||||
|
@ -1198,8 +1198,7 @@ typedef struct InferenceElem
|
|||||||
Expr xpr;
|
Expr xpr;
|
||||||
Node *expr; /* expression to infer from, or NULL */
|
Node *expr; /* expression to infer from, or NULL */
|
||||||
Oid infercollid; /* OID of collation, or InvalidOid */
|
Oid infercollid; /* OID of collation, or InvalidOid */
|
||||||
Oid inferopfamily; /* OID of att opfamily, or InvalidOid */
|
Oid inferopclass; /* OID of att opclass, or InvalidOid */
|
||||||
Oid inferopcinputtype; /* OID of att input type, or InvalidOid */
|
|
||||||
} InferenceElem;
|
} InferenceElem;
|
||||||
|
|
||||||
/*--------------------
|
/*--------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user