diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/dependency.c | 9 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 17 | ||||
-rw-r--r-- | src/backend/optimizer/plan/subselect.c | 1 | ||||
-rw-r--r-- | src/backend/optimizer/prep/prepjointree.c | 26 | ||||
-rw-r--r-- | src/backend/optimizer/util/plancat.c | 9 | ||||
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 7 |
6 files changed, 57 insertions, 12 deletions
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index a6180a64f21..04d78402903 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -1789,6 +1789,15 @@ find_expr_references_walker(Node *node, add_object_address(OCLASS_TYPE, cd->resulttype, 0, context->addrs); } + else if (IsA(node, OnConflictExpr)) + { + OnConflictExpr *onconflict = (OnConflictExpr *) node; + + if (OidIsValid(onconflict->constraint)) + add_object_address(OCLASS_CONSTRAINT, onconflict->constraint, 0, + context->addrs); + /* fall through to examine arguments */ + } else if (IsA(node, SortGroupClause)) { SortGroupClause *sgc = (SortGroupClause *) node; diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 6770836dc89..75d93c08db2 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -77,6 +77,7 @@ create_upper_paths_hook_type create_upper_paths_hook = NULL; #define EXPRKIND_APPINFO 7 #define EXPRKIND_PHV 8 #define EXPRKIND_TABLESAMPLE 9 +#define EXPRKIND_ARBITER_ELEM 10 /* Passthrough data for standard_qp_callback */ typedef struct @@ -620,13 +621,23 @@ subquery_planner(PlannerGlobal *glob, Query *parse, if (parse->onConflict) { + parse->onConflict->arbiterElems = (List *) + preprocess_expression(root, + (Node *) parse->onConflict->arbiterElems, + EXPRKIND_ARBITER_ELEM); + parse->onConflict->arbiterWhere = + preprocess_expression(root, + parse->onConflict->arbiterWhere, + EXPRKIND_QUAL); parse->onConflict->onConflictSet = (List *) - preprocess_expression(root, (Node *) parse->onConflict->onConflictSet, + preprocess_expression(root, + (Node *) parse->onConflict->onConflictSet, EXPRKIND_TARGET); - parse->onConflict->onConflictWhere = - preprocess_expression(root, (Node *) parse->onConflict->onConflictWhere, + preprocess_expression(root, + parse->onConflict->onConflictWhere, EXPRKIND_QUAL); + /* exclRelTlist contains only Vars, so no preprocessing needed */ } root->append_rel_list = (List *) diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 1ff430229dd..0849b1d5634 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -2507,6 +2507,7 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params, &context); finalize_primnode((Node *) mtplan->onConflictWhere, &context); + /* exclRelTlist contains only Vars, doesn't need examination */ foreach(l, mtplan->plans) { context.paramids = diff --git a/src/backend/optimizer/prep/prepjointree.c b/src/backend/optimizer/prep/prepjointree.c index 75577bce2ca..a334f15773a 100644 --- a/src/backend/optimizer/prep/prepjointree.c +++ b/src/backend/optimizer/prep/prepjointree.c @@ -1039,8 +1039,19 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte, parse->returningList = (List *) pullup_replace_vars((Node *) parse->returningList, &rvcontext); if (parse->onConflict) + { parse->onConflict->onConflictSet = (List *) - pullup_replace_vars((Node *) parse->onConflict->onConflictSet, &rvcontext); + pullup_replace_vars((Node *) parse->onConflict->onConflictSet, + &rvcontext); + parse->onConflict->onConflictWhere = + pullup_replace_vars(parse->onConflict->onConflictWhere, + &rvcontext); + + /* + * We assume ON CONFLICT's arbiterElems, arbiterWhere, exclRelTlist + * can't contain any references to a subquery + */ + } replace_vars_in_jointree((Node *) parse->jointree, &rvcontext, lowest_nulling_outer_join); Assert(parse->setOperations == NULL); @@ -1633,8 +1644,19 @@ pull_up_simple_values(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte) parse->returningList = (List *) pullup_replace_vars((Node *) parse->returningList, &rvcontext); if (parse->onConflict) + { parse->onConflict->onConflictSet = (List *) - pullup_replace_vars((Node *) parse->onConflict->onConflictSet, &rvcontext); + pullup_replace_vars((Node *) parse->onConflict->onConflictSet, + &rvcontext); + parse->onConflict->onConflictWhere = + pullup_replace_vars(parse->onConflict->onConflictWhere, + &rvcontext); + + /* + * We assume ON CONFLICT's arbiterElems, arbiterWhere, exclRelTlist + * can't contain any references to a subquery + */ + } replace_vars_in_jointree((Node *) parse->jointree, &rvcontext, NULL); Assert(parse->setOperations == NULL); parse->havingQual = pullup_replace_vars(parse->havingQual, &rvcontext); diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 9c11b09cbcc..4f399a5b854 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -623,7 +623,6 @@ infer_arbiter_indexes(PlannerInfo *root) Bitmapset *indexedAttrs = NULL; List *idxExprs; List *predExprs; - List *whereExplicit; AttrNumber natt; ListCell *el; @@ -685,6 +684,7 @@ infer_arbiter_indexes(PlannerInfo *root) { int attno = idxRel->rd_index->indkey.values[natt]; + /* XXX broken */ if (attno < 0) elog(ERROR, "system column in index"); @@ -745,13 +745,12 @@ infer_arbiter_indexes(PlannerInfo *root) goto next; /* - * Any user-supplied ON CONFLICT unique index inference WHERE clause - * need only be implied by the cataloged index definitions predicate. + * If it's a partial index, its predicate must be implied by the ON + * CONFLICT's WHERE clause. */ predExprs = RelationGetIndexPredicate(idxRel); - whereExplicit = make_ands_implicit((Expr *) onconflict->arbiterWhere); - if (!predicate_implied_by(predExprs, whereExplicit)) + if (!predicate_implied_by(predExprs, (List *) onconflict->arbiterWhere)) goto next; results = lappend_oid(results, idxForm->indexrelid); diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 6dfa6b9a319..8cb3075e785 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -5570,12 +5570,15 @@ get_insert_query_def(Query *query, deparse_context *context) context->varprefix = save_varprefix; } } - else if (confl->constraint != InvalidOid) + else if (OidIsValid(confl->constraint)) { char *constraint = get_constraint_name(confl->constraint); + if (!constraint) + elog(ERROR, "cache lookup failed for constraint %u", + confl->constraint); appendStringInfo(buf, " ON CONSTRAINT %s", - quote_qualified_identifier(NULL, constraint)); + quote_identifier(constraint)); } if (confl->action == ONCONFLICT_NOTHING) |