Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit de434c2

Browse files
committed
Arrange for ORDER BY an expression on a UNION/INTERSECT/EXCEPT result,
such as SELECT f1 FROM foo UNION SELECT ... ORDER BY upper(f1) to draw 'ORDER BY on a UNION/INTERSECT/EXCEPT result must be on one of the result columns' rather than the uninformative 'f1 not found' we were producing before. Eventually this should actually work, but that looks much too hard to try to implement in late beta...
1 parent c7d2ce7 commit de434c2

File tree

1 file changed

+34
-5
lines changed

1 file changed

+34
-5
lines changed

src/backend/parser/analyze.c

+34-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Id: analyze.c,v 1.180 2001/02/14 23:32:38 tgl Exp $
9+
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.181 2001/02/15 01:10:28 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -1871,7 +1871,11 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
18711871
List *forUpdate;
18721872
Node *node;
18731873
List *lefttl,
1874-
*dtlist;
1874+
*dtlist,
1875+
*targetvars,
1876+
*targetnames,
1877+
*sv_namespace;
1878+
JoinExpr *jnode;
18751879
int tllen;
18761880

18771881
qry->commandType = CMD_SELECT;
@@ -1934,22 +1938,26 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
19341938
Assert(leftmostQuery != NULL);
19351939
/*
19361940
* Generate dummy targetlist for outer query using column names of
1937-
* leftmost select and common datatypes of topmost set operation
1941+
* leftmost select and common datatypes of topmost set operation.
1942+
* Also make lists of the dummy vars and their names for use in
1943+
* parsing ORDER BY.
19381944
*/
19391945
qry->targetList = NIL;
1946+
targetvars = NIL;
1947+
targetnames = NIL;
19401948
lefttl = leftmostQuery->targetList;
19411949
foreach(dtlist, sostmt->colTypes)
19421950
{
19431951
Oid colType = (Oid) lfirsti(dtlist);
19441952
Resdom *leftResdom = ((TargetEntry *) lfirst(lefttl))->resdom;
1945-
char *colName = leftResdom->resname;
1953+
char *colName = pstrdup(leftResdom->resname);
19461954
Resdom *resdom;
19471955
Node *expr;
19481956

19491957
resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
19501958
colType,
19511959
-1,
1952-
pstrdup(colName),
1960+
colName,
19531961
false);
19541962
expr = (Node *) makeVar(leftmostRTI,
19551963
leftResdom->resno,
@@ -1958,6 +1966,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
19581966
0);
19591967
qry->targetList = lappend(qry->targetList,
19601968
makeTargetEntry(resdom, expr));
1969+
targetvars = lappend(targetvars, expr);
1970+
targetnames = lappend(targetnames, makeString(colName));
19611971
lefttl = lnext(lefttl);
19621972
}
19631973
/*
@@ -1997,6 +2007,23 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
19972007
qry->isBinary = FALSE;
19982008
}
19992009

2010+
/*
2011+
* As a first step towards supporting sort clauses that are expressions
2012+
* using the output columns, generate a namespace entry that makes the
2013+
* output columns visible. A JoinExpr node is handy for this, since
2014+
* we can easily control the Vars generated upon matches.
2015+
*
2016+
* Note: we don't yet do anything useful with such cases, but at least
2017+
* "ORDER BY upper(foo)" will draw the right error message rather than
2018+
* "foo not found".
2019+
*/
2020+
jnode = makeNode(JoinExpr);
2021+
jnode->colnames = targetnames;
2022+
jnode->colvars = targetvars;
2023+
2024+
sv_namespace = pstate->p_namespace;
2025+
pstate->p_namespace = makeList1(jnode);
2026+
20002027
/*
20012028
* For now, we don't support resjunk sort clauses on the output of a
20022029
* setOperation tree --- you can only use the SQL92-spec options of
@@ -2009,6 +2036,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
20092036
sortClause,
20102037
qry->targetList);
20112038

2039+
pstate->p_namespace = sv_namespace;
2040+
20122041
if (tllen != length(qry->targetList))
20132042
elog(ERROR, "ORDER BY on a UNION/INTERSECT/EXCEPT result must be on one of the result columns");
20142043

0 commit comments

Comments
 (0)