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
This commit is contained in:
parent
4e46c97fde
commit
d43a619c60
@ -790,7 +790,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
|
|||||||
*/
|
*/
|
||||||
exprList = transformExpressionList(pstate,
|
exprList = transformExpressionList(pstate,
|
||||||
(List *) linitial(valuesLists),
|
(List *) linitial(valuesLists),
|
||||||
EXPR_KIND_VALUES,
|
EXPR_KIND_VALUES_SINGLE,
|
||||||
true);
|
true);
|
||||||
|
|
||||||
/* Prepare row for assignment to target table */
|
/* Prepare row for assignment to target table */
|
||||||
|
@ -447,6 +447,7 @@ check_agglevels_and_constraints(ParseState *pstate, Node *expr)
|
|||||||
errkind = true;
|
errkind = true;
|
||||||
break;
|
break;
|
||||||
case EXPR_KIND_VALUES:
|
case EXPR_KIND_VALUES:
|
||||||
|
case EXPR_KIND_VALUES_SINGLE:
|
||||||
errkind = true;
|
errkind = true;
|
||||||
break;
|
break;
|
||||||
case EXPR_KIND_CHECK_CONSTRAINT:
|
case EXPR_KIND_CHECK_CONSTRAINT:
|
||||||
@ -840,6 +841,7 @@ transformWindowFuncCall(ParseState *pstate, WindowFunc *wfunc,
|
|||||||
errkind = true;
|
errkind = true;
|
||||||
break;
|
break;
|
||||||
case EXPR_KIND_VALUES:
|
case EXPR_KIND_VALUES:
|
||||||
|
case EXPR_KIND_VALUES_SINGLE:
|
||||||
errkind = true;
|
errkind = true;
|
||||||
break;
|
break;
|
||||||
case EXPR_KIND_CHECK_CONSTRAINT:
|
case EXPR_KIND_CHECK_CONSTRAINT:
|
||||||
|
@ -1797,6 +1797,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
|
|||||||
case EXPR_KIND_OFFSET:
|
case EXPR_KIND_OFFSET:
|
||||||
case EXPR_KIND_RETURNING:
|
case EXPR_KIND_RETURNING:
|
||||||
case EXPR_KIND_VALUES:
|
case EXPR_KIND_VALUES:
|
||||||
|
case EXPR_KIND_VALUES_SINGLE:
|
||||||
/* okay */
|
/* okay */
|
||||||
break;
|
break;
|
||||||
case EXPR_KIND_CHECK_CONSTRAINT:
|
case EXPR_KIND_CHECK_CONSTRAINT:
|
||||||
@ -3410,6 +3411,7 @@ ParseExprKindName(ParseExprKind exprKind)
|
|||||||
case EXPR_KIND_RETURNING:
|
case EXPR_KIND_RETURNING:
|
||||||
return "RETURNING";
|
return "RETURNING";
|
||||||
case EXPR_KIND_VALUES:
|
case EXPR_KIND_VALUES:
|
||||||
|
case EXPR_KIND_VALUES_SINGLE:
|
||||||
return "VALUES";
|
return "VALUES";
|
||||||
case EXPR_KIND_CHECK_CONSTRAINT:
|
case EXPR_KIND_CHECK_CONSTRAINT:
|
||||||
case EXPR_KIND_DOMAIN_CHECK:
|
case EXPR_KIND_DOMAIN_CHECK:
|
||||||
|
@ -2141,7 +2141,12 @@ check_srf_call_placement(ParseState *pstate, int location)
|
|||||||
errkind = true;
|
errkind = true;
|
||||||
break;
|
break;
|
||||||
case EXPR_KIND_VALUES:
|
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;
|
break;
|
||||||
case EXPR_KIND_CHECK_CONSTRAINT:
|
case EXPR_KIND_CHECK_CONSTRAINT:
|
||||||
case EXPR_KIND_DOMAIN_CHECK:
|
case EXPR_KIND_DOMAIN_CHECK:
|
||||||
|
@ -55,6 +55,7 @@ typedef enum ParseExprKind
|
|||||||
EXPR_KIND_OFFSET, /* OFFSET */
|
EXPR_KIND_OFFSET, /* OFFSET */
|
||||||
EXPR_KIND_RETURNING, /* RETURNING */
|
EXPR_KIND_RETURNING, /* RETURNING */
|
||||||
EXPR_KIND_VALUES, /* VALUES */
|
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_CHECK_CONSTRAINT, /* CHECK constraint for a table */
|
||||||
EXPR_KIND_DOMAIN_CHECK, /* CHECK constraint for a domain */
|
EXPR_KIND_DOMAIN_CHECK, /* CHECK constraint for a domain */
|
||||||
EXPR_KIND_COLUMN_DEFAULT, /* default value for a table column */
|
EXPR_KIND_COLUMN_DEFAULT, /* default value for a table column */
|
||||||
|
@ -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?)
|
-- nor standalone VALUES (but surely this is a bug?)
|
||||||
VALUES(1, generate_series(1,2));
|
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
|
-- We allow tSRFs that are not at top level
|
||||||
SELECT int4mul(generate_series(1,2), 10);
|
SELECT int4mul(generate_series(1,2), 10);
|
||||||
int4mul
|
int4mul
|
||||||
|
Loading…
x
Reference in New Issue
Block a user