*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.145 2003/06/15 22:51:45 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.146 2003/06/16 02:03:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
List *sortList;
- sortList = addAllTargetsToSortList(NIL, my_tlist);
+ sortList = addAllTargetsToSortList(NULL, NIL, my_tlist, false);
plan = (Plan *) make_sort_from_sortclauses(root, my_tlist,
subplan, sortList);
plan = (Plan *) make_unique(my_tlist, plan, sortList);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.154 2003/06/06 15:04:02 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.155 2003/06/16 02:03:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
if (parse->groupClause)
{
List *groupExprs;
+ double cheapest_path_rows;
+ int cheapest_path_width;
+
+ /*
+ * Beware in this section of the possibility that
+ * cheapest_path->parent is NULL. This could happen if user
+ * does something silly like SELECT 'foo' GROUP BY 1;
+ */
+ if (cheapest_path->parent)
+ {
+ cheapest_path_rows = cheapest_path->parent->rows;
+ cheapest_path_width = cheapest_path->parent->width;
+ }
+ else
+ {
+ cheapest_path_rows = 1; /* assume non-set result */
+ cheapest_path_width = 100; /* arbitrary */
+ }
/*
* Always estimate the number of groups. We can't do this until
parse->targetList);
dNumGroups = estimate_num_groups(parse,
groupExprs,
- cheapest_path->parent->rows);
+ cheapest_path_rows);
/* Also want it as a long int --- but 'ware overflow! */
numGroups = (long) Min(dNumGroups, (double) LONG_MAX);
* assume it is 100 bytes. Also set the overhead per hashtable
* entry at 64 bytes.
*/
- int hashentrysize = cheapest_path->parent->width + 64 +
- numAggs * 100;
+ int hashentrysize = cheapest_path_width + 64 + numAggs * 100;
if (hashentrysize * dNumGroups <= SortMem * 1024L)
{
numGroupCols, dNumGroups,
cheapest_path->startup_cost,
cheapest_path->total_cost,
- cheapest_path->parent->rows);
+ cheapest_path_rows);
/* Result of hashed agg is always unsorted */
if (sort_pathkeys)
cost_sort(&hashed_p, parse, sort_pathkeys,
hashed_p.total_cost,
dNumGroups,
- cheapest_path->parent->width);
+ cheapest_path_width);
if (sorted_path)
{
{
cost_sort(&sorted_p, parse, group_pathkeys,
sorted_p.total_cost,
- cheapest_path->parent->rows,
- cheapest_path->parent->width);
+ cheapest_path_rows,
+ cheapest_path_width);
current_pathkeys = group_pathkeys;
}
if (parse->hasAggs)
numGroupCols, dNumGroups,
sorted_p.startup_cost,
sorted_p.total_cost,
- cheapest_path->parent->rows);
+ cheapest_path_rows);
else
cost_group(&sorted_p, parse,
numGroupCols, dNumGroups,
sorted_p.startup_cost,
sorted_p.total_cost,
- cheapest_path->parent->rows);
+ cheapest_path_rows);
/* The Agg or Group node will preserve ordering */
if (sort_pathkeys &&
!pathkeys_contained_in(sort_pathkeys,
cost_sort(&sorted_p, parse, sort_pathkeys,
sorted_p.total_cost,
dNumGroups,
- cheapest_path->parent->width);
+ cheapest_path_width);
}
/*
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.95 2003/05/06 00:20:32 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.96 2003/06/16 02:03:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
List *sortList;
tlist = copyObject(tlist);
- sortList = addAllTargetsToSortList(NIL, tlist);
+ sortList = addAllTargetsToSortList(NULL, NIL, tlist, false);
plan = (Plan *) make_sort_from_sortclauses(parse, tlist,
plan, sortList);
plan = (Plan *) make_unique(tlist, plan, sortList);
* correct output.
*/
tlist = copyObject(tlist);
- sortList = addAllTargetsToSortList(NIL, tlist);
+ sortList = addAllTargetsToSortList(NULL, NIL, tlist, false);
plan = (Plan *) make_sort_from_sortclauses(parse, tlist, plan, sortList);
switch (op->op)
{
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.274 2003/06/15 16:42:07 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.275 2003/06/16 02:03:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
qry->sortClause = transformSortClause(pstate,
stmt->sortClause,
- qry->targetList);
+ qry->targetList,
+ true /* fix unknowns */);
qry->groupClause = transformGroupClause(pstate,
stmt->groupClause,
qry->sortClause = transformSortClause(pstate,
sortClause,
- qry->targetList);
+ qry->targetList,
+ false /* no unknowns expected */);
pstate->p_namespace = sv_namespace;
pstate->p_rtable = sv_rtable;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.115 2003/06/15 16:42:07 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.116 2003/06/16 02:03:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Var *l_colvar, Var *r_colvar);
static TargetEntry *findTargetlistEntry(ParseState *pstate, Node *node,
List *tlist, int clause);
-static List *addTargetToSortList(TargetEntry *tle, List *sortlist,
- List *targetlist, List *opname);
+static List *addTargetToSortList(ParseState *pstate, TargetEntry *tle,
+ List *sortlist, List *targetlist,
+ List *opname, bool resolveUnknown);
/*
foreach(gl, grouplist)
{
TargetEntry *tle;
+ Oid restype;
Oid ordering_op;
GroupClause *grpcl;
if (targetIsInSortList(tle, glist))
continue;
+ /* if tlist item is an UNKNOWN literal, change it to TEXT */
+ restype = tle->resdom->restype;
+
+ if (restype == UNKNOWNOID)
+ {
+ tle->expr = (Expr *) coerce_type(pstate, (Node *) tle->expr,
+ restype, TEXTOID,
+ COERCION_IMPLICIT,
+ COERCE_IMPLICIT_CAST);
+ restype = tle->resdom->restype = TEXTOID;
+ tle->resdom->restypmod = -1;
+ }
+
/*
* If the GROUP BY clause matches the ORDER BY clause, we want to
* adopt the ordering operators from the latter rather than using
}
else
{
- ordering_op = ordering_oper_opid(tle->resdom->restype);
+ ordering_op = ordering_oper_opid(restype);
sortClause = NIL; /* disregard ORDER BY once match fails */
}
List *
transformSortClause(ParseState *pstate,
List *orderlist,
- List *targetlist)
+ List *targetlist,
+ bool resolveUnknown)
{
List *sortlist = NIL;
List *olitem;
tle = findTargetlistEntry(pstate, sortby->node,
targetlist, ORDER_CLAUSE);
- sortlist = addTargetToSortList(tle, sortlist, targetlist,
- sortby->useOp);
+ sortlist = addTargetToSortList(pstate, tle,
+ sortlist, targetlist,
+ sortby->useOp, resolveUnknown);
}
return sortlist;
* the user's ORDER BY spec alone, and just add additional sort
* keys to it to ensure that all targetlist items get sorted.)
*/
- *sortClause = addAllTargetsToSortList(*sortClause, targetlist);
+ *sortClause = addAllTargetsToSortList(pstate,
+ *sortClause,
+ targetlist,
+ true);
/*
* Now, DISTINCT list consists of all non-resjunk sortlist items.
}
else
{
- *sortClause = addTargetToSortList(tle, *sortClause,
- targetlist, NIL);
+ *sortClause = addTargetToSortList(pstate, tle,
+ *sortClause, targetlist,
+ NIL, true);
/*
* Probably, the tle should always have been added at the
* ORDER BY list, adding the not-yet-sorted ones to the end of the list.
* This is typically used to help implement SELECT DISTINCT.
*
+ * See addTargetToSortList for info about pstate and resolveUnknown inputs.
+ *
* Returns the updated ORDER BY list.
*/
List *
-addAllTargetsToSortList(List *sortlist, List *targetlist)
+addAllTargetsToSortList(ParseState *pstate, List *sortlist,
+ List *targetlist, bool resolveUnknown)
{
List *i;
TargetEntry *tle = (TargetEntry *) lfirst(i);
if (!tle->resdom->resjunk)
- sortlist = addTargetToSortList(tle, sortlist, targetlist, NIL);
+ sortlist = addTargetToSortList(pstate, tle,
+ sortlist, targetlist,
+ NIL, resolveUnknown);
}
return sortlist;
}
* add it to the end of the list, using the sortop with given name
* or the default sort operator if opname == NIL.
*
+ * If resolveUnknown is TRUE, convert TLEs of type UNKNOWN to TEXT. If not,
+ * do nothing (which implies the search for a sort operator will fail).
+ * pstate should be provided if resolveUnknown is TRUE, but can be NULL
+ * otherwise.
+ *
* Returns the updated ORDER BY list.
*/
static List *
-addTargetToSortList(TargetEntry *tle, List *sortlist, List *targetlist,
- List *opname)
+addTargetToSortList(ParseState *pstate, TargetEntry *tle,
+ List *sortlist, List *targetlist,
+ List *opname, bool resolveUnknown)
{
/* avoid making duplicate sortlist entries */
if (!targetIsInSortList(tle, sortlist))
{
SortClause *sortcl = makeNode(SortClause);
+ Oid restype = tle->resdom->restype;
+
+ /* if tlist item is an UNKNOWN literal, change it to TEXT */
+ if (restype == UNKNOWNOID && resolveUnknown)
+ {
+ tle->expr = (Expr *) coerce_type(pstate, (Node *) tle->expr,
+ restype, TEXTOID,
+ COERCION_IMPLICIT,
+ COERCE_IMPLICIT_CAST);
+ restype = tle->resdom->restype = TEXTOID;
+ tle->resdom->restypmod = -1;
+ }
sortcl->tleSortGroupRef = assignSortGroupRef(tle, targetlist);
if (opname)
sortcl->sortop = compatible_oper_opid(opname,
- tle->resdom->restype,
- tle->resdom->restype,
+ restype,
+ restype,
false);
else
- sortcl->sortop = ordering_oper_opid(tle->resdom->restype);
+ sortcl->sortop = ordering_oper_opid(restype);
sortlist = lappend(sortlist, sortcl);
}
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parse_clause.h,v 1.31 2003/06/15 16:42:08 tgl Exp $
+ * $Id: parse_clause.h,v 1.32 2003/06/16 02:03:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern int setTargetTable(ParseState *pstate, RangeVar *relation,
bool inh, bool alsoSource);
extern bool interpretInhOption(InhOption inhOpt);
+
extern Node *transformWhereClause(ParseState *pstate, Node *where);
extern List *transformGroupClause(ParseState *pstate, List *grouplist,
List *targetlist, List *sortClause);
extern List *transformSortClause(ParseState *pstate, List *orderlist,
- List *targetlist);
+ List *targetlist, bool resolveUnknown);
extern List *transformDistinctClause(ParseState *pstate, List *distinctlist,
List *targetlist, List **sortClause);
-extern List *addAllTargetsToSortList(List *sortlist, List *targetlist);
+extern List *addAllTargetsToSortList(ParseState *pstate,
+ List *sortlist, List *targetlist,
+ bool resolveUnknown);
extern Index assignSortGroupRef(TargetEntry *tle, List *tlist);
extern bool targetIsInSortList(TargetEntry *tle, List *sortList);