* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/equivclass.c,v 1.2 2007/01/22 20:00:39 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/equivclass.c,v 1.3 2007/07/07 20:46:45 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* No Vars, assume it's a pseudoconstant. This is correct for
* entries generated from process_equivalence(), because a WHERE
- * clause can't contain aggregates and non-volatility was checked
- * before process_equivalence() ever got called. But
+ * clause can't contain aggregates or SRFs, and non-volatility was
+ * checked before process_equivalence() ever got called. But
* get_eclass_for_sort_expr() has to work harder. We put the tests
* there not here to save cycles in the equivalence case.
*/
false, expr_datatype);
/*
- * add_eq_member doesn't check for volatile functions or aggregates,
- * but such could appear in sort expressions, so we have to check
- * whether its const-marking was correct.
+ * add_eq_member doesn't check for volatile functions, set-returning
+ * functions, or aggregates, but such could appear in sort expressions;
+ * so we have to check whether its const-marking was correct.
*/
if (newec->ec_has_const)
{
- if (newec->ec_has_volatile || contain_agg_clause((Node *) expr))
+ if (newec->ec_has_volatile ||
+ expression_returns_set((Node *) expr) ||
+ contain_agg_clause((Node *) expr))
{
newec->ec_has_const = false;
newem->em_is_const = false;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.101 2007/05/04 01:13:44 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.102 2007/07/07 20:46:45 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
if (parse->jointree->fromlist == NIL)
{
+ /* We need a trivial path result */
*cheapest_path = (Path *)
create_result_path((List *) parse->jointree->quals);
*sorted_path = NULL;
+ /*
+ * We still are required to canonicalize any pathkeys, in case
+ * it's something like "SELECT 2+2 ORDER BY 1".
+ */
+ root->canon_pathkeys = NIL;
+ root->query_pathkeys = canonicalize_pathkeys(root,
+ root->query_pathkeys);
+ root->group_pathkeys = canonicalize_pathkeys(root,
+ root->group_pathkeys);
+ root->sort_pathkeys = canonicalize_pathkeys(root,
+ root->sort_pathkeys);
return;
}
(7 rows)
+--
+-- Test some corner cases that have been known to confuse the planner
+--
+-- ORDER BY on a constant doesn't really need any sorting
+SELECT 1 AS x ORDER BY x;
+ x
+---
+ 1
+(1 row)
+
+-- But ORDER BY on a set-valued expression does
+create function sillysrf(int) returns setof int as
+ 'values (1),(10),(2),($1)' language sql immutable;
+select sillysrf(42);
+ sillysrf
+----------
+ 1
+ 10
+ 2
+ 42
+(4 rows)
+
+select sillysrf(-1) order by 1;
+ sillysrf
+----------
+ -1
+ 1
+ 2
+ 10
+(4 rows)
+
+drop function sillysrf(int);
SELECT * FROM foo ORDER BY f1 NULLS FIRST;
SELECT * FROM foo ORDER BY f1 DESC;
SELECT * FROM foo ORDER BY f1 DESC NULLS LAST;
+
+--
+-- Test some corner cases that have been known to confuse the planner
+--
+
+-- ORDER BY on a constant doesn't really need any sorting
+SELECT 1 AS x ORDER BY x;
+
+-- But ORDER BY on a set-valued expression does
+create function sillysrf(int) returns setof int as
+ 'values (1),(10),(2),($1)' language sql immutable;
+
+select sillysrf(42);
+select sillysrf(-1) order by 1;
+
+drop function sillysrf(int);