Commit 27edff70 authored by Tom Lane's avatar Tom Lane

Still another place to make the world safe for zero-column tables:

remove the ancient (and always pretty dodgy) assumption in parse_clause.c
that a query can't have an empty targetlist.
parent a7125708
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.299 2004/05/05 04:48:46 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.300 2004/05/23 17:10:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1929,17 +1929,17 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) ...@@ -1929,17 +1929,17 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
*/ */
qry->sortClause = transformSortClause(pstate, qry->sortClause = transformSortClause(pstate,
stmt->sortClause, stmt->sortClause,
qry->targetList, &qry->targetList,
true /* fix unknowns */ ); true /* fix unknowns */ );
qry->groupClause = transformGroupClause(pstate, qry->groupClause = transformGroupClause(pstate,
stmt->groupClause, stmt->groupClause,
qry->targetList, &qry->targetList,
qry->sortClause); qry->sortClause);
qry->distinctClause = transformDistinctClause(pstate, qry->distinctClause = transformDistinctClause(pstate,
stmt->distinctClause, stmt->distinctClause,
qry->targetList, &qry->targetList,
&qry->sortClause); &qry->sortClause);
qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset, qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset,
...@@ -2145,7 +2145,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) ...@@ -2145,7 +2145,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
qry->sortClause = transformSortClause(pstate, qry->sortClause = transformSortClause(pstate,
sortClause, sortClause,
qry->targetList, &qry->targetList,
false /* no unknowns expected */ ); false /* no unknowns expected */ );
pstate->p_namespace = sv_namespace; pstate->p_namespace = sv_namespace;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.128 2004/04/18 18:12:57 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.129 2004/05/23 17:10:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -58,7 +58,7 @@ static Node *transformFromClauseItem(ParseState *pstate, Node *n, ...@@ -58,7 +58,7 @@ static Node *transformFromClauseItem(ParseState *pstate, Node *n,
static Node *buildMergedJoinVar(ParseState *pstate, JoinType jointype, static Node *buildMergedJoinVar(ParseState *pstate, JoinType jointype,
Var *l_colvar, Var *r_colvar); Var *l_colvar, Var *r_colvar);
static TargetEntry *findTargetlistEntry(ParseState *pstate, Node *node, static TargetEntry *findTargetlistEntry(ParseState *pstate, Node *node,
List *tlist, int clause); List **tlist, int clause);
/* /*
...@@ -1076,12 +1076,11 @@ transformLimitClause(ParseState *pstate, Node *clause, ...@@ -1076,12 +1076,11 @@ transformLimitClause(ParseState *pstate, Node *clause,
* list as a "resjunk" node. * list as a "resjunk" node.
* *
* node the ORDER BY, GROUP BY, or DISTINCT ON expression to be matched * node the ORDER BY, GROUP BY, or DISTINCT ON expression to be matched
* tlist the existing target list (NB: this will never be NIL, which is a * tlist the target list (passed by reference so we can append to it)
* good thing since we'd be unable to append to it if it were...) * clause identifies clause type being processed
* clause identifies clause type being processed.
*/ */
static TargetEntry * static TargetEntry *
findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause) findTargetlistEntry(ParseState *pstate, Node *node, List **tlist, int clause)
{ {
TargetEntry *target_result = NULL; TargetEntry *target_result = NULL;
List *tl; List *tl;
...@@ -1157,7 +1156,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause) ...@@ -1157,7 +1156,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
if (name != NULL) if (name != NULL)
{ {
foreach(tl, tlist) foreach(tl, *tlist)
{ {
TargetEntry *tle = (TargetEntry *) lfirst(tl); TargetEntry *tle = (TargetEntry *) lfirst(tl);
Resdom *resnode = tle->resdom; Resdom *resnode = tle->resdom;
...@@ -1196,7 +1195,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause) ...@@ -1196,7 +1195,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
errmsg("non-integer constant in %s", errmsg("non-integer constant in %s",
clauseText[clause]))); clauseText[clause])));
target_pos = intVal(val); target_pos = intVal(val);
foreach(tl, tlist) foreach(tl, *tlist)
{ {
TargetEntry *tle = (TargetEntry *) lfirst(tl); TargetEntry *tle = (TargetEntry *) lfirst(tl);
Resdom *resnode = tle->resdom; Resdom *resnode = tle->resdom;
...@@ -1224,7 +1223,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause) ...@@ -1224,7 +1223,7 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
*/ */
expr = transformExpr(pstate, node); expr = transformExpr(pstate, node);
foreach(tl, tlist) foreach(tl, *tlist)
{ {
TargetEntry *tle = (TargetEntry *) lfirst(tl); TargetEntry *tle = (TargetEntry *) lfirst(tl);
...@@ -1238,7 +1237,8 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause) ...@@ -1238,7 +1237,8 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
* that it will not be projected into the final tuple. * that it will not be projected into the final tuple.
*/ */
target_result = transformTargetEntry(pstate, node, expr, NULL, true); target_result = transformTargetEntry(pstate, node, expr, NULL, true);
lappend(tlist, target_result);
*tlist = lappend(*tlist, target_result);
return target_result; return target_result;
} }
...@@ -1247,10 +1247,13 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause) ...@@ -1247,10 +1247,13 @@ findTargetlistEntry(ParseState *pstate, Node *node, List *tlist, int clause)
/* /*
* transformGroupClause - * transformGroupClause -
* transform a GROUP BY clause * transform a GROUP BY clause
*
* GROUP BY items will be added to the targetlist (as resjunk columns)
* if not already present, so the targetlist must be passed by reference.
*/ */
List * List *
transformGroupClause(ParseState *pstate, List *grouplist, transformGroupClause(ParseState *pstate, List *grouplist,
List *targetlist, List *sortClause) List **targetlist, List *sortClause)
{ {
List *glist = NIL, List *glist = NIL,
*gl; *gl;
...@@ -1304,7 +1307,7 @@ transformGroupClause(ParseState *pstate, List *grouplist, ...@@ -1304,7 +1307,7 @@ transformGroupClause(ParseState *pstate, List *grouplist,
} }
grpcl = makeNode(GroupClause); grpcl = makeNode(GroupClause);
grpcl->tleSortGroupRef = assignSortGroupRef(tle, targetlist); grpcl->tleSortGroupRef = assignSortGroupRef(tle, *targetlist);
grpcl->sortop = ordering_op; grpcl->sortop = ordering_op;
glist = lappend(glist, grpcl); glist = lappend(glist, grpcl);
} }
...@@ -1315,11 +1318,14 @@ transformGroupClause(ParseState *pstate, List *grouplist, ...@@ -1315,11 +1318,14 @@ transformGroupClause(ParseState *pstate, List *grouplist,
/* /*
* transformSortClause - * transformSortClause -
* transform an ORDER BY clause * transform an ORDER BY clause
*
* ORDER BY items will be added to the targetlist (as resjunk columns)
* if not already present, so the targetlist must be passed by reference.
*/ */
List * List *
transformSortClause(ParseState *pstate, transformSortClause(ParseState *pstate,
List *orderlist, List *orderlist,
List *targetlist, List **targetlist,
bool resolveUnknown) bool resolveUnknown)
{ {
List *sortlist = NIL; List *sortlist = NIL;
...@@ -1334,7 +1340,7 @@ transformSortClause(ParseState *pstate, ...@@ -1334,7 +1340,7 @@ transformSortClause(ParseState *pstate,
targetlist, ORDER_CLAUSE); targetlist, ORDER_CLAUSE);
sortlist = addTargetToSortList(pstate, tle, sortlist = addTargetToSortList(pstate, tle,
sortlist, targetlist, sortlist, *targetlist,
sortby->sortby_kind, sortby->sortby_kind,
sortby->useOp, sortby->useOp,
resolveUnknown); resolveUnknown);
...@@ -1348,13 +1354,11 @@ transformSortClause(ParseState *pstate, ...@@ -1348,13 +1354,11 @@ transformSortClause(ParseState *pstate,
* transform a DISTINCT or DISTINCT ON clause * transform a DISTINCT or DISTINCT ON clause
* *
* Since we may need to add items to the query's sortClause list, that list * Since we may need to add items to the query's sortClause list, that list
* is passed by reference. We might also need to add items to the query's * is passed by reference. Likewise for the targetlist.
* targetlist, but we assume that cannot be empty initially, so we can
* lappend to it even though the pointer is passed by value.
*/ */
List * List *
transformDistinctClause(ParseState *pstate, List *distinctlist, transformDistinctClause(ParseState *pstate, List *distinctlist,
List *targetlist, List **sortClause) List **targetlist, List **sortClause)
{ {
List *result = NIL; List *result = NIL;
List *slitem; List *slitem;
...@@ -1377,7 +1381,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist, ...@@ -1377,7 +1381,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist,
*/ */
*sortClause = addAllTargetsToSortList(pstate, *sortClause = addAllTargetsToSortList(pstate,
*sortClause, *sortClause,
targetlist, *targetlist,
true); true);
/* /*
...@@ -1390,7 +1394,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist, ...@@ -1390,7 +1394,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist,
foreach(slitem, *sortClause) foreach(slitem, *sortClause)
{ {
SortClause *scl = (SortClause *) lfirst(slitem); SortClause *scl = (SortClause *) lfirst(slitem);
TargetEntry *tle = get_sortgroupclause_tle(scl, targetlist); TargetEntry *tle = get_sortgroupclause_tle(scl, *targetlist);
if (tle->resdom->resjunk) if (tle->resdom->resjunk)
ereport(ERROR, ereport(ERROR,
...@@ -1442,7 +1446,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist, ...@@ -1442,7 +1446,7 @@ transformDistinctClause(ParseState *pstate, List *distinctlist,
else else
{ {
*sortClause = addTargetToSortList(pstate, tle, *sortClause = addTargetToSortList(pstate, tle,
*sortClause, targetlist, *sortClause, *targetlist,
SORTBY_ASC, NIL, true); SORTBY_ASC, NIL, true);
/* /*
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/parser/parse_clause.h,v 1.40 2004/01/23 02:13:12 neilc Exp $ * $PostgreSQL: pgsql/src/include/parser/parse_clause.h,v 1.41 2004/05/23 17:10:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -27,11 +27,11 @@ extern Node *transformWhereClause(ParseState *pstate, Node *clause, ...@@ -27,11 +27,11 @@ extern Node *transformWhereClause(ParseState *pstate, Node *clause,
extern Node *transformLimitClause(ParseState *pstate, Node *clause, extern Node *transformLimitClause(ParseState *pstate, Node *clause,
const char *constructName); const char *constructName);
extern List *transformGroupClause(ParseState *pstate, List *grouplist, extern List *transformGroupClause(ParseState *pstate, List *grouplist,
List *targetlist, List *sortClause); List **targetlist, List *sortClause);
extern List *transformSortClause(ParseState *pstate, List *orderlist, extern List *transformSortClause(ParseState *pstate, List *orderlist,
List *targetlist, bool resolveUnknown); List **targetlist, bool resolveUnknown);
extern List *transformDistinctClause(ParseState *pstate, List *distinctlist, extern List *transformDistinctClause(ParseState *pstate, List *distinctlist,
List *targetlist, List **sortClause); List **targetlist, List **sortClause);
extern List *addAllTargetsToSortList(ParseState *pstate, extern List *addAllTargetsToSortList(ParseState *pstate,
List *sortlist, List *targetlist, List *sortlist, List *targetlist,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment