diff options
Diffstat (limited to 'src/backend/parser/analyze.c')
-rw-r--r-- | src/backend/parser/analyze.c | 65 |
1 files changed, 57 insertions, 8 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 29c8c4e94c7..eac86cce3ee 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -51,7 +51,8 @@ post_parse_analyze_hook_type post_parse_analyze_hook = NULL; static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt); static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt); static List *transformInsertRow(ParseState *pstate, List *exprlist, - List *stmtcols, List *icolumns, List *attrnos); + List *stmtcols, List *icolumns, List *attrnos, + bool strip_indirection); static OnConflictExpr *transformOnConflictClause(ParseState *pstate, OnConflictClause *onConflictClause); static int count_rowexpr_columns(ParseState *pstate, Node *expr); @@ -619,7 +620,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) /* Prepare row for assignment to target table */ exprList = transformInsertRow(pstate, exprList, stmt->cols, - icolumns, attrnos); + icolumns, attrnos, + false); } else if (list_length(selectStmt->valuesLists) > 1) { @@ -663,10 +665,20 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) exprLocation((Node *) sublist)))); } - /* Prepare row for assignment to target table */ + /* + * Prepare row for assignment to target table. We process any + * indirection on the target column specs normally but then strip + * off the resulting field/array assignment nodes, since we don't + * want the parsed statement to contain copies of those in each + * VALUES row. (It's annoying to have to transform the + * indirection specs over and over like this, but avoiding it + * would take some really messy refactoring of + * transformAssignmentIndirection.) + */ sublist = transformInsertRow(pstate, sublist, stmt->cols, - icolumns, attrnos); + icolumns, attrnos, + true); /* * We must assign collations now because assign_query_collations @@ -717,6 +729,14 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) * Generate list of Vars referencing the RTE */ expandRTE(rte, rtr->rtindex, 0, -1, false, NULL, &exprList); + + /* + * Re-apply any indirection on the target column specs to the Vars + */ + exprList = transformInsertRow(pstate, exprList, + stmt->cols, + icolumns, attrnos, + false); } else { @@ -739,7 +759,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) /* Prepare row for assignment to target table */ exprList = transformInsertRow(pstate, exprList, stmt->cols, - icolumns, attrnos); + icolumns, attrnos, + false); } /* @@ -808,12 +829,17 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) /* * Prepare an INSERT row for assignment to the target table. * - * The row might be either a VALUES row, or variables referencing a - * sub-SELECT output. + * exprlist: transformed expressions for source values; these might come from + * a VALUES row, or be Vars referencing a sub-SELECT or VALUES RTE output. + * stmtcols: original target-columns spec for INSERT (we just test for NIL) + * icolumns: effective target-columns spec (list of ResTarget) + * attrnos: integer column numbers (must be same length as icolumns) + * strip_indirection: if true, remove any field/array assignment nodes */ static List * transformInsertRow(ParseState *pstate, List *exprlist, - List *stmtcols, List *icolumns, List *attrnos) + List *stmtcols, List *icolumns, List *attrnos, + bool strip_indirection) { List *result; ListCell *lc; @@ -879,6 +905,29 @@ transformInsertRow(ParseState *pstate, List *exprlist, col->indirection, col->location); + if (strip_indirection) + { + while (expr) + { + if (IsA(expr, FieldStore)) + { + FieldStore *fstore = (FieldStore *) expr; + + expr = (Expr *) linitial(fstore->newvals); + } + else if (IsA(expr, ArrayRef)) + { + ArrayRef *aref = (ArrayRef *) expr; + + if (aref->refassgnexpr == NULL) + break; + expr = aref->refassgnexpr; + } + else + break; + } + } + result = lappend(result, expr); icols = lnext(icols); |