diff options
Diffstat (limited to 'src/backend/optimizer')
-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 |
4 files changed, 43 insertions, 10 deletions
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); |