Index: src/backend/parser/parse_clause.c =================================================================== RCS file: /opt/src/cvs/pgsql-server/src/backend/parser/parse_clause.c,v retrieving revision 1.103 diff -c -r1.103 parse_clause.c *** src/backend/parser/parse_clause.c 16 Dec 2002 18:39:22 -0000 1.103 --- src/backend/parser/parse_clause.c 12 Jan 2003 19:23:57 -0000 *************** *** 1121,1127 **** * the end of the target list. This target is given resjunk = TRUE so * that it will not be projected into the final tuple. */ ! target_result = transformTargetEntry(pstate, node, expr, NULL, true); lappend(tlist, target_result); return target_result; --- 1121,1127 ---- * the end of the target list. This target is given resjunk = TRUE so * that it will not be projected into the final tuple. */ ! target_result = transformTargetEntry(pstate, node, expr, NULL, true, NULL); lappend(tlist, target_result); return target_result; Index: src/backend/parser/parse_target.c =================================================================== RCS file: /opt/src/cvs/pgsql-server/src/backend/parser/parse_target.c,v retrieving revision 1.94 diff -c -r1.94 parse_target.c *** src/backend/parser/parse_target.c 12 Dec 2002 20:35:13 -0000 1.94 --- src/backend/parser/parse_target.c 12 Jan 2003 19:25:16 -0000 *************** *** 42,54 **** * colname the column name to be assigned, or NULL if none yet set. * resjunk true if the target should be marked resjunk, ie, it is not * wanted in the final projected tuple. */ TargetEntry * transformTargetEntry(ParseState *pstate, Node *node, Node *expr, char *colname, ! bool resjunk) { Oid type_id; int32 type_mod; --- 42,57 ---- * colname the column name to be assigned, or NULL if none yet set. * resjunk true if the target should be marked resjunk, ie, it is not * wanted in the final projected tuple. + * retset if non-NULL, and the entry is a function expression, pass back + * expr->funcretset */ TargetEntry * transformTargetEntry(ParseState *pstate, Node *node, Node *expr, char *colname, ! bool resjunk, ! bool *retset) { Oid type_id; int32 type_mod; *************** *** 61,66 **** --- 64,72 ---- if (IsA(expr, RangeVar)) elog(ERROR, "You can't use relation names alone in the target list, try relation.*."); + if (retset && IsA(expr, FuncExpr)) + *retset = ((FuncExpr *) expr)->funcretset; + type_id = exprType(expr); type_mod = exprTypmod(expr); *************** *** 93,102 **** --- 99,110 ---- List * transformTargetList(ParseState *pstate, List *targetlist) { + bool retset = false; List *p_target = NIL; while (targetlist != NIL) { + bool entry_retset = false; ResTarget *res = (ResTarget *) lfirst(targetlist); if (IsA(res->val, ColumnRef)) *************** *** 173,179 **** res->val, NULL, res->name, ! false)); } } else if (IsA(res->val, InsertDefault)) --- 181,188 ---- res->val, NULL, res->name, ! false, ! &entry_retset)); } } else if (IsA(res->val, InsertDefault)) *************** *** 194,201 **** res->val, NULL, res->name, ! false)); } targetlist = lnext(targetlist); } --- 203,217 ---- res->val, NULL, res->name, ! false, ! &entry_retset)); } + + if (retset && entry_retset) + elog(ERROR, "Only one target list entry may return a set result"); + + if (entry_retset) + retset = true; targetlist = lnext(targetlist); } Index: src/include/parser/parse_target.h =================================================================== RCS file: /opt/src/cvs/pgsql-server/src/include/parser/parse_target.h,v retrieving revision 1.27 diff -c -r1.27 parse_target.h *** src/include/parser/parse_target.h 18 Sep 2002 21:35:24 -0000 1.27 --- src/include/parser/parse_target.h 12 Jan 2003 19:08:56 -0000 *************** *** 20,26 **** extern List *transformTargetList(ParseState *pstate, List *targetlist); extern TargetEntry *transformTargetEntry(ParseState *pstate, Node *node, Node *expr, ! char *colname, bool resjunk); extern void updateTargetListEntry(ParseState *pstate, TargetEntry *tle, char *colname, int attrno, List *indirection); --- 20,26 ---- extern List *transformTargetList(ParseState *pstate, List *targetlist); extern TargetEntry *transformTargetEntry(ParseState *pstate, Node *node, Node *expr, ! char *colname, bool resjunk, bool *retset); extern void updateTargetListEntry(ParseState *pstate, TargetEntry *tle, char *colname, int attrno, List *indirection);