aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/parser/parse_target.c59
-rw-r--r--src/test/regress/expected/update.out7
-rw-r--r--src/test/regress/sql/update.sql4
3 files changed, 46 insertions, 24 deletions
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index e6374c2eca5..27295291dff 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -113,17 +113,21 @@ transformTargetEntry(ParseState *pstate,
* transformTargetList()
* Turns a list of ResTarget's into a list of TargetEntry's.
*
- * At this point, we don't care whether we are doing SELECT, UPDATE,
- * or RETURNING; we just transform the given expressions (the "val" fields).
- * However, our subroutines care, so we need the exprKind parameter.
+ * This code acts mostly the same for SELECT, UPDATE, or RETURNING lists;
+ * the main thing is to transform the given expressions (the "val" fields).
+ * The exprKind parameter distinguishes these cases when necessary.
*/
List *
transformTargetList(ParseState *pstate, List *targetlist,
ParseExprKind exprKind)
{
List *p_target = NIL;
+ bool expand_star;
ListCell *o_target;
+ /* Expand "something.*" in SELECT and RETURNING, but not UPDATE */
+ expand_star = (exprKind != EXPR_KIND_UPDATE_SOURCE);
+
foreach(o_target, targetlist)
{
ResTarget *res = (ResTarget *) lfirst(o_target);
@@ -133,35 +137,42 @@ transformTargetList(ParseState *pstate, List *targetlist,
* "something", the star could appear as the last field in ColumnRef,
* or as the last indirection item in A_Indirection.
*/
- if (IsA(res->val, ColumnRef))
+ if (expand_star)
{
- ColumnRef *cref = (ColumnRef *) res->val;
-
- if (IsA(llast(cref->fields), A_Star))
+ if (IsA(res->val, ColumnRef))
{
- /* It is something.*, expand into multiple items */
- p_target = list_concat(p_target,
- ExpandColumnRefStar(pstate, cref,
- true));
- continue;
- }
- }
- else if (IsA(res->val, A_Indirection))
- {
- A_Indirection *ind = (A_Indirection *) res->val;
+ ColumnRef *cref = (ColumnRef *) res->val;
- if (IsA(llast(ind->indirection), A_Star))
+ if (IsA(llast(cref->fields), A_Star))
+ {
+ /* It is something.*, expand into multiple items */
+ p_target = list_concat(p_target,
+ ExpandColumnRefStar(pstate,
+ cref,
+ true));
+ continue;
+ }
+ }
+ else if (IsA(res->val, A_Indirection))
{
- /* It is something.*, expand into multiple items */
- p_target = list_concat(p_target,
- ExpandIndirectionStar(pstate, ind,
- true, exprKind));
- continue;
+ A_Indirection *ind = (A_Indirection *) res->val;
+
+ if (IsA(llast(ind->indirection), A_Star))
+ {
+ /* It is something.*, expand into multiple items */
+ p_target = list_concat(p_target,
+ ExpandIndirectionStar(pstate,
+ ind,
+ true,
+ exprKind));
+ continue;
+ }
}
}
/*
- * Not "something.*", so transform as a single expression
+ * Not "something.*", or we want to treat that as a plain whole-row
+ * variable, so transform as a single expression
*/
p_target = lappend(p_target,
transformTargetEntry(pstate,
diff --git a/src/test/regress/expected/update.out b/src/test/regress/expected/update.out
index 71b856f95c6..70b7f3a0b77 100644
--- a/src/test/regress/expected/update.out
+++ b/src/test/regress/expected/update.out
@@ -52,6 +52,13 @@ SELECT * FROM update_test;
100 | 20 |
(2 rows)
+-- fail, wrong data type:
+UPDATE update_test SET a = v.* FROM (VALUES(100, 20)) AS v(i, j)
+ WHERE update_test.b = v.j;
+ERROR: column "a" is of type integer but expression is of type record
+LINE 1: UPDATE update_test SET a = v.* FROM (VALUES(100, 20)) AS v(i...
+ ^
+HINT: You will need to rewrite or cast the expression.
--
-- Test multiple-set-clause syntax
--
diff --git a/src/test/regress/sql/update.sql b/src/test/regress/sql/update.sql
index a8a028f7101..a268a3bb307 100644
--- a/src/test/regress/sql/update.sql
+++ b/src/test/regress/sql/update.sql
@@ -35,6 +35,10 @@ UPDATE update_test SET a=v.i FROM (VALUES(100, 20)) AS v(i, j)
SELECT * FROM update_test;
+-- fail, wrong data type:
+UPDATE update_test SET a = v.* FROM (VALUES(100, 20)) AS v(i, j)
+ WHERE update_test.b = v.j;
+
--
-- Test multiple-set-clause syntax
--