diff options
Diffstat (limited to 'src/backend/parser/parse_clause.c')
-rw-r--r-- | src/backend/parser/parse_clause.c | 78 |
1 files changed, 61 insertions, 17 deletions
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c index 2e2beabddcb..4d08704da66 100644 --- a/src/backend/parser/parse_clause.c +++ b/src/backend/parser/parse_clause.c @@ -8,7 +8,7 @@ * * * 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 $ * *------------------------------------------------------------------------- */ @@ -59,8 +59,9 @@ static Node *buildMergedJoinVar(ParseState *pstate, JoinType jointype, 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); /* @@ -1133,6 +1134,7 @@ transformGroupClause(ParseState *pstate, List *grouplist, foreach(gl, grouplist) { TargetEntry *tle; + Oid restype; Oid ordering_op; GroupClause *grpcl; @@ -1143,6 +1145,19 @@ transformGroupClause(ParseState *pstate, List *grouplist, 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 @@ -1160,7 +1175,7 @@ transformGroupClause(ParseState *pstate, List *grouplist, } else { - ordering_op = ordering_oper_opid(tle->resdom->restype); + ordering_op = ordering_oper_opid(restype); sortClause = NIL; /* disregard ORDER BY once match fails */ } @@ -1180,7 +1195,8 @@ transformGroupClause(ParseState *pstate, List *grouplist, List * transformSortClause(ParseState *pstate, List *orderlist, - List *targetlist) + List *targetlist, + bool resolveUnknown) { List *sortlist = NIL; List *olitem; @@ -1193,8 +1209,9 @@ transformSortClause(ParseState *pstate, 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; @@ -1232,7 +1249,10 @@ transformDistinctClause(ParseState *pstate, List *distinctlist, * 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. @@ -1291,8 +1311,9 @@ transformDistinctClause(ParseState *pstate, List *distinctlist, } 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 @@ -1323,10 +1344,13 @@ transformDistinctClause(ParseState *pstate, List *distinctlist, * 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; @@ -1335,7 +1359,9 @@ addAllTargetsToSortList(List *sortlist, List *targetlist) 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; } @@ -1346,26 +1372,44 @@ addAllTargetsToSortList(List *sortlist, List *targetlist) * 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); } |