mirror of
https://github.com/postgres/postgres.git
synced 2025-06-08 22:02:03 +03:00
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.
This commit is contained in:
parent
a712570880
commit
27edff700e
@ -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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
|
|
||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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,
|
|||||||
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,
|
|||||||
* 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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
* 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)
|
|||||||
/*
|
/*
|
||||||
* 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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
/*
|
/*
|
||||||
* 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,
|
|||||||
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,
|
|||||||
* 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,
|
|||||||
*/
|
*/
|
||||||
*sortClause = addAllTargetsToSortList(pstate,
|
*sortClause = addAllTargetsToSortList(pstate,
|
||||||
*sortClause,
|
*sortClause,
|
||||||
targetlist,
|
*targetlist,
|
||||||
true);
|
true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -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,
|
|||||||
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 @@
|
|||||||
* 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,
|
|||||||
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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user