6
6
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7
7
* Portions Copyright (c) 1994, Regents of the University of California
8
8
*
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 $
10
10
*
11
11
*-------------------------------------------------------------------------
12
12
*/
@@ -1871,7 +1871,11 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
1871
1871
List * forUpdate ;
1872
1872
Node * node ;
1873
1873
List * lefttl ,
1874
- * dtlist ;
1874
+ * dtlist ,
1875
+ * targetvars ,
1876
+ * targetnames ,
1877
+ * sv_namespace ;
1878
+ JoinExpr * jnode ;
1875
1879
int tllen ;
1876
1880
1877
1881
qry -> commandType = CMD_SELECT ;
@@ -1934,22 +1938,26 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
1934
1938
Assert (leftmostQuery != NULL );
1935
1939
/*
1936
1940
* 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.
1938
1944
*/
1939
1945
qry -> targetList = NIL ;
1946
+ targetvars = NIL ;
1947
+ targetnames = NIL ;
1940
1948
lefttl = leftmostQuery -> targetList ;
1941
1949
foreach (dtlist , sostmt -> colTypes )
1942
1950
{
1943
1951
Oid colType = (Oid ) lfirsti (dtlist );
1944
1952
Resdom * leftResdom = ((TargetEntry * ) lfirst (lefttl ))-> resdom ;
1945
- char * colName = leftResdom -> resname ;
1953
+ char * colName = pstrdup ( leftResdom -> resname ) ;
1946
1954
Resdom * resdom ;
1947
1955
Node * expr ;
1948
1956
1949
1957
resdom = makeResdom ((AttrNumber ) pstate -> p_last_resno ++ ,
1950
1958
colType ,
1951
1959
-1 ,
1952
- pstrdup ( colName ) ,
1960
+ colName ,
1953
1961
false);
1954
1962
expr = (Node * ) makeVar (leftmostRTI ,
1955
1963
leftResdom -> resno ,
@@ -1958,6 +1966,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
1958
1966
0 );
1959
1967
qry -> targetList = lappend (qry -> targetList ,
1960
1968
makeTargetEntry (resdom , expr ));
1969
+ targetvars = lappend (targetvars , expr );
1970
+ targetnames = lappend (targetnames , makeString (colName ));
1961
1971
lefttl = lnext (lefttl );
1962
1972
}
1963
1973
/*
@@ -1997,6 +2007,23 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
1997
2007
qry -> isBinary = FALSE;
1998
2008
}
1999
2009
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
+
2000
2027
/*
2001
2028
* For now, we don't support resjunk sort clauses on the output of a
2002
2029
* setOperation tree --- you can only use the SQL92-spec options of
@@ -2009,6 +2036,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
2009
2036
sortClause ,
2010
2037
qry -> targetList );
2011
2038
2039
+ pstate -> p_namespace = sv_namespace ;
2040
+
2012
2041
if (tllen != length (qry -> targetList ))
2013
2042
elog (ERROR , "ORDER BY on a UNION/INTERSECT/EXCEPT result must be on one of the result columns" );
2014
2043
0 commit comments