From d43a619c60405ecda275ca9e3ac9ead242e20ecb Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 16 Jan 2017 15:23:11 -0500 Subject: [PATCH] Fix check_srf_call_placement() to handle VALUES cases correctly. INSERT ... VALUES with a single VALUES row is implemented quite differently from the general VALUES case. A user-visible implication of that is that we accept SRFs in the single-row case, but not in the multi-row case. That's a historical artifact no doubt, but in view of the lack of field complaints, I'm not excited about fixing it right now. However, check_srf_call_placement() needs to know about this, first because it should throw an error in the unsupported case, and second because it should set p_hasTargetSRFs in the single-row case (because we treat that like a SELECT tlist). That's an oversight in commit a4c35ea1c. To fix, split EXPR_KIND_VALUES into two values. So far as I can see, this is the only place where we need to distinguish the two cases at present; but there might be more later. Patch by me, per report from Andres Freund. Discussion: https://postgr.es/m/20170116081548.zg63zltblwimpfgp@alap3.anarazel.de --- src/backend/parser/analyze.c | 2 +- src/backend/parser/parse_agg.c | 2 ++ src/backend/parser/parse_expr.c | 2 ++ src/backend/parser/parse_func.c | 7 ++++++- src/include/parser/parse_node.h | 1 + src/test/regress/expected/tsrf.out | 4 +++- 6 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 8278e742f8..a02a77a03a 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -790,7 +790,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) */ exprList = transformExpressionList(pstate, (List *) linitial(valuesLists), - EXPR_KIND_VALUES, + EXPR_KIND_VALUES_SINGLE, true); /* Prepare row for assignment to target table */ diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index d9777099aa..7be7fe9689 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -447,6 +447,7 @@ check_agglevels_and_constraints(ParseState *pstate, Node *expr) errkind = true; break; case EXPR_KIND_VALUES: + case EXPR_KIND_VALUES_SINGLE: errkind = true; break; case EXPR_KIND_CHECK_CONSTRAINT: @@ -840,6 +841,7 @@ transformWindowFuncCall(ParseState *pstate, WindowFunc *wfunc, errkind = true; break; case EXPR_KIND_VALUES: + case EXPR_KIND_VALUES_SINGLE: errkind = true; break; case EXPR_KIND_CHECK_CONSTRAINT: diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 73521b93fc..add3be6566 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -1797,6 +1797,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink) case EXPR_KIND_OFFSET: case EXPR_KIND_RETURNING: case EXPR_KIND_VALUES: + case EXPR_KIND_VALUES_SINGLE: /* okay */ break; case EXPR_KIND_CHECK_CONSTRAINT: @@ -3410,6 +3411,7 @@ ParseExprKindName(ParseExprKind exprKind) case EXPR_KIND_RETURNING: return "RETURNING"; case EXPR_KIND_VALUES: + case EXPR_KIND_VALUES_SINGLE: return "VALUES"; case EXPR_KIND_CHECK_CONSTRAINT: case EXPR_KIND_DOMAIN_CHECK: diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 12979602e5..a52261f2e9 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -2141,7 +2141,12 @@ check_srf_call_placement(ParseState *pstate, int location) errkind = true; break; case EXPR_KIND_VALUES: - /* okay */ + /* SRFs are presently not supported by nodeValuesscan.c */ + errkind = true; + break; + case EXPR_KIND_VALUES_SINGLE: + /* okay, since we process this like a SELECT tlist */ + pstate->p_hasTargetSRFs = true; break; case EXPR_KIND_CHECK_CONSTRAINT: case EXPR_KIND_DOMAIN_CHECK: diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index 7cdf142df6..bc3eea9ba5 100644 --- a/src/include/parser/parse_node.h +++ b/src/include/parser/parse_node.h @@ -55,6 +55,7 @@ typedef enum ParseExprKind EXPR_KIND_OFFSET, /* OFFSET */ EXPR_KIND_RETURNING, /* RETURNING */ EXPR_KIND_VALUES, /* VALUES */ + EXPR_KIND_VALUES_SINGLE, /* single-row VALUES (in INSERT only) */ EXPR_KIND_CHECK_CONSTRAINT, /* CHECK constraint for a table */ EXPR_KIND_DOMAIN_CHECK, /* CHECK constraint for a domain */ EXPR_KIND_COLUMN_DEFAULT, /* default value for a table column */ diff --git a/src/test/regress/expected/tsrf.out b/src/test/regress/expected/tsrf.out index 8c54f717df..7bb6d17fcb 100644 --- a/src/test/regress/expected/tsrf.out +++ b/src/test/regress/expected/tsrf.out @@ -374,7 +374,9 @@ LINE 1: INSERT INTO fewmore VALUES(1) RETURNING generate_series(1,3)... ^ -- nor standalone VALUES (but surely this is a bug?) VALUES(1, generate_series(1,2)); -ERROR: set-valued function called in context that cannot accept a set +ERROR: set-returning functions are not allowed in VALUES +LINE 1: VALUES(1, generate_series(1,2)); + ^ -- We allow tSRFs that are not at top level SELECT int4mul(generate_series(1,2), 10); int4mul -- 2.40.0