aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/analyze.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/analyze.c')
-rw-r--r--src/backend/parser/analyze.c136
1 files changed, 81 insertions, 55 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 05f57591e48..c601b6d40d1 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -1022,9 +1022,6 @@ transformOnConflictClause(ParseState *pstate,
if (onConflictClause->action == ONCONFLICT_UPDATE)
{
Relation targetrel = pstate->p_target_relation;
- Var *var;
- TargetEntry *te;
- int attno;
/*
* All INSERT expressions have been parsed, get ready for potentially
@@ -1033,75 +1030,36 @@ transformOnConflictClause(ParseState *pstate,
pstate->p_is_insert = false;
/*
- * Add range table entry for the EXCLUDED pseudo relation; relkind is
+ * Add range table entry for the EXCLUDED pseudo relation. relkind is
* set to composite to signal that we're not dealing with an actual
- * relation.
+ * relation, and no permission checks are required on it. (We'll
+ * check the actual target relation, instead.)
*/
exclRte = addRangeTableEntryForRelation(pstate,
targetrel,
makeAlias("excluded", NIL),
false, false);
exclRte->relkind = RELKIND_COMPOSITE_TYPE;
- exclRelIndex = list_length(pstate->p_rtable);
-
- /*
- * Build a targetlist representing the columns of the EXCLUDED pseudo
- * relation. Have to be careful to use resnos that correspond to
- * attnos of the underlying relation.
- */
- for (attno = 0; attno < RelationGetNumberOfAttributes(targetrel); attno++)
- {
- Form_pg_attribute attr = TupleDescAttr(targetrel->rd_att, attno);
- char *name;
-
- if (attr->attisdropped)
- {
- /*
- * can't use atttypid here, but it doesn't really matter what
- * type the Const claims to be.
- */
- var = (Var *) makeNullConst(INT4OID, -1, InvalidOid);
- name = "";
- }
- else
- {
- var = makeVar(exclRelIndex, attno + 1,
- attr->atttypid, attr->atttypmod,
- attr->attcollation,
- 0);
- name = pstrdup(NameStr(attr->attname));
- }
+ exclRte->requiredPerms = 0;
+ /* other permissions fields in exclRte are already empty */
- te = makeTargetEntry((Expr *) var,
- attno + 1,
- name,
- false);
-
- /* don't require select access yet */
- exclRelTlist = lappend(exclRelTlist, te);
- }
+ exclRelIndex = list_length(pstate->p_rtable);
- /*
- * Add a whole-row-Var entry to support references to "EXCLUDED.*".
- * Like the other entries in exclRelTlist, its resno must match the
- * Var's varattno, else the wrong things happen while resolving
- * references in setrefs.c. This is against normal conventions for
- * targetlists, but it's okay since we don't use this as a real tlist.
- */
- var = makeVar(exclRelIndex, InvalidAttrNumber,
- targetrel->rd_rel->reltype,
- -1, InvalidOid, 0);
- te = makeTargetEntry((Expr *) var, InvalidAttrNumber, NULL, true);
- exclRelTlist = lappend(exclRelTlist, te);
+ /* Create EXCLUDED rel's targetlist for use by EXPLAIN */
+ exclRelTlist = BuildOnConflictExcludedTargetlist(targetrel,
+ exclRelIndex);
/*
* Add EXCLUDED and the target RTE to the namespace, so that they can
- * be used in the UPDATE statement.
+ * be used in the UPDATE subexpressions.
*/
addRTEtoQuery(pstate, exclRte, false, true, true);
addRTEtoQuery(pstate, pstate->p_target_rangetblentry,
false, true, true);
+ /*
+ * Now transform the UPDATE subexpressions.
+ */
onConflictSet =
transformUpdateTargetList(pstate, onConflictClause->targetList);
@@ -1127,6 +1085,74 @@ transformOnConflictClause(ParseState *pstate,
/*
+ * BuildOnConflictExcludedTargetlist
+ * Create target list for the EXCLUDED pseudo-relation of ON CONFLICT,
+ * representing the columns of targetrel with varno exclRelIndex.
+ *
+ * Note: Exported for use in the rewriter.
+ */
+List *
+BuildOnConflictExcludedTargetlist(Relation targetrel,
+ Index exclRelIndex)
+{
+ List *result = NIL;
+ int attno;
+ Var *var;
+ TargetEntry *te;
+
+ /*
+ * Note that resnos of the tlist must correspond to attnos of the
+ * underlying relation, hence we need entries for dropped columns too.
+ */
+ for (attno = 0; attno < RelationGetNumberOfAttributes(targetrel); attno++)
+ {
+ Form_pg_attribute attr = TupleDescAttr(targetrel->rd_att, attno);
+ char *name;
+
+ if (attr->attisdropped)
+ {
+ /*
+ * can't use atttypid here, but it doesn't really matter what type
+ * the Const claims to be.
+ */
+ var = (Var *) makeNullConst(INT4OID, -1, InvalidOid);
+ name = "";
+ }
+ else
+ {
+ var = makeVar(exclRelIndex, attno + 1,
+ attr->atttypid, attr->atttypmod,
+ attr->attcollation,
+ 0);
+ name = pstrdup(NameStr(attr->attname));
+ }
+
+ te = makeTargetEntry((Expr *) var,
+ attno + 1,
+ name,
+ false);
+
+ result = lappend(result, te);
+ }
+
+ /*
+ * Add a whole-row-Var entry to support references to "EXCLUDED.*". Like
+ * the other entries in the EXCLUDED tlist, its resno must match the Var's
+ * varattno, else the wrong things happen while resolving references in
+ * setrefs.c. This is against normal conventions for targetlists, but
+ * it's okay since we don't use this as a real tlist.
+ */
+ var = makeVar(exclRelIndex, InvalidAttrNumber,
+ targetrel->rd_rel->reltype,
+ -1, InvalidOid, 0);
+ te = makeTargetEntry((Expr *) var, InvalidAttrNumber, NULL, true);
+ result = lappend(result, te);
+
+ return result;
+}
+
+
+/*
* count_rowexpr_columns -
* get number of columns contained in a ROW() expression;
* return -1 if expression isn't a RowExpr or a Var referencing one.