aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2001-02-15 01:10:28 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2001-02-15 01:10:28 +0000
commitde434c2d5f2d666861408ca2c04e96939a19b368 (patch)
tree25bd543c40ac0dcc1aff04bba2892766b82c8ac4 /src
parentc7d2ce7bc6eb02eac0c10fae9caf2936a71ad25c (diff)
downloadpostgresql-de434c2d5f2d666861408ca2c04e96939a19b368.tar.gz
postgresql-de434c2d5f2d666861408ca2c04e96939a19b368.zip
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...
Diffstat (limited to 'src')
-rw-r--r--src/backend/parser/analyze.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index cf43da0d707..ba0a3cfa348 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: analyze.c,v 1.180 2001/02/14 23:32:38 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.181 2001/02/15 01:10:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1871,7 +1871,11 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
List *forUpdate;
Node *node;
List *lefttl,
- *dtlist;
+ *dtlist,
+ *targetvars,
+ *targetnames,
+ *sv_namespace;
+ JoinExpr *jnode;
int tllen;
qry->commandType = CMD_SELECT;
@@ -1934,22 +1938,26 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
Assert(leftmostQuery != NULL);
/*
* Generate dummy targetlist for outer query using column names of
- * leftmost select and common datatypes of topmost set operation
+ * leftmost select and common datatypes of topmost set operation.
+ * Also make lists of the dummy vars and their names for use in
+ * parsing ORDER BY.
*/
qry->targetList = NIL;
+ targetvars = NIL;
+ targetnames = NIL;
lefttl = leftmostQuery->targetList;
foreach(dtlist, sostmt->colTypes)
{
Oid colType = (Oid) lfirsti(dtlist);
Resdom *leftResdom = ((TargetEntry *) lfirst(lefttl))->resdom;
- char *colName = leftResdom->resname;
+ char *colName = pstrdup(leftResdom->resname);
Resdom *resdom;
Node *expr;
resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
colType,
-1,
- pstrdup(colName),
+ colName,
false);
expr = (Node *) makeVar(leftmostRTI,
leftResdom->resno,
@@ -1958,6 +1966,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
0);
qry->targetList = lappend(qry->targetList,
makeTargetEntry(resdom, expr));
+ targetvars = lappend(targetvars, expr);
+ targetnames = lappend(targetnames, makeString(colName));
lefttl = lnext(lefttl);
}
/*
@@ -1998,6 +2008,23 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
}
/*
+ * As a first step towards supporting sort clauses that are expressions
+ * using the output columns, generate a namespace entry that makes the
+ * output columns visible. A JoinExpr node is handy for this, since
+ * we can easily control the Vars generated upon matches.
+ *
+ * Note: we don't yet do anything useful with such cases, but at least
+ * "ORDER BY upper(foo)" will draw the right error message rather than
+ * "foo not found".
+ */
+ jnode = makeNode(JoinExpr);
+ jnode->colnames = targetnames;
+ jnode->colvars = targetvars;
+
+ sv_namespace = pstate->p_namespace;
+ pstate->p_namespace = makeList1(jnode);
+
+ /*
* For now, we don't support resjunk sort clauses on the output of a
* setOperation tree --- you can only use the SQL92-spec options of
* selecting an output column by name or number. Enforce by checking
@@ -2009,6 +2036,8 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
sortClause,
qry->targetList);
+ pstate->p_namespace = sv_namespace;
+
if (tllen != length(qry->targetList))
elog(ERROR, "ORDER BY on a UNION/INTERSECT/EXCEPT result must be on one of the result columns");