* resolve_unique_index_expr * Infer a unique index from a list of indexElems, for ON * CONFLICT clause * * Perform parse analysis of expressions and columns appearing within ON * CONFLICT clause. During planning, the returned list of expressions is used * to infer which unique index to use. */
| 3381 | * to infer which unique index to use. |
| 3382 | */ |
| 3383 | static List * |
| 3384 | resolve_unique_index_expr(ParseState *pstate, InferClause *infer, |
| 3385 | Relation heapRel) |
| 3386 | { |
| 3387 | List *result = NIL; |
| 3388 | ListCell *l; |
| 3389 | |
| 3390 | foreach(l, infer->indexElems) |
| 3391 | { |
| 3392 | IndexElem *ielem = (IndexElem *) lfirst(l); |
| 3393 | InferenceElem *pInfer = makeNode(InferenceElem); |
| 3394 | Node *parse; |
| 3395 | |
| 3396 | /* |
| 3397 | * Raw grammar re-uses CREATE INDEX infrastructure for unique index |
| 3398 | * inference clause, and so will accept opclasses by name and so on. |
| 3399 | * |
| 3400 | * Make no attempt to match ASC or DESC ordering or NULLS FIRST/NULLS |
| 3401 | * LAST ordering, since those are not significant for inference |
| 3402 | * purposes (any unique index matching the inference specification in |
| 3403 | * other regards is accepted indifferently). Actively reject this as |
| 3404 | * wrong-headed. |
| 3405 | */ |
| 3406 | if (ielem->ordering != SORTBY_DEFAULT) |
| 3407 | ereport(ERROR, |
| 3408 | (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), |
| 3409 | errmsg("ASC/DESC is not allowed in ON CONFLICT clause"), |
| 3410 | parser_errposition(pstate, |
| 3411 | exprLocation((Node *) infer)))); |
| 3412 | if (ielem->nulls_ordering != SORTBY_NULLS_DEFAULT) |
| 3413 | ereport(ERROR, |
| 3414 | (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), |
| 3415 | errmsg("NULLS FIRST/LAST is not allowed in ON CONFLICT clause"), |
| 3416 | parser_errposition(pstate, |
| 3417 | exprLocation((Node *) infer)))); |
| 3418 | |
| 3419 | if (!ielem->expr) |
| 3420 | { |
| 3421 | /* Simple index attribute */ |
| 3422 | ColumnRef *n; |
| 3423 | |
| 3424 | /* |
| 3425 | * Grammar won't have built raw expression for us in event of |
| 3426 | * plain column reference. Create one directly, and perform |
| 3427 | * expression transformation. Planner expects this, and performs |
| 3428 | * its own normalization for the purposes of matching against |
| 3429 | * pg_index. |
| 3430 | */ |
| 3431 | n = makeNode(ColumnRef); |
| 3432 | n->fields = list_make1(makeString(ielem->name)); |
| 3433 | /* Location is approximately that of inference specification */ |
| 3434 | n->location = infer->location; |
| 3435 | parse = (Node *) n; |
| 3436 | } |
| 3437 | else |
| 3438 | { |
| 3439 | /* Do parse transformation of the raw expression */ |
| 3440 | parse = (Node *) ielem->expr; |
no test coverage detected