diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 182181f3a60e1d73bf38e68b3ef0dda399a17240..2c66a4ead5f5644d705282de75b6100aab93a106 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.198 2010/02/26 02:00:50 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.199 2010/07/18 19:37:48 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,6 +21,7 @@
 #include "commands/defrem.h"
 #include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
+#include "optimizer/clauses.h"
 #include "optimizer/tlist.h"
 #include "optimizer/var.h"
 #include "parser/analyze.h"
@@ -1430,8 +1431,20 @@ findTargetlistEntrySQL99(ParseState *pstate, Node *node, List **tlist)
 	foreach(tl, *tlist)
 	{
 		TargetEntry *tle = (TargetEntry *) lfirst(tl);
+		Node	   *texpr;
 
-		if (equal(expr, tle->expr))
+		/*
+		 * Ignore any implicit cast on the existing tlist expression.
+		 *
+		 * This essentially allows the ORDER/GROUP/etc item to adopt the same
+		 * datatype previously selected for a textually-equivalent tlist item.
+		 * There can't be any implicit cast at top level in an ordinary SELECT
+		 * tlist at this stage, but the case does arise with ORDER BY in an
+		 * aggregate function.
+		 */
+		texpr = strip_implicit_coercions((Node *) tle->expr);
+
+		if (equal(expr, texpr))
 			return tle;
 	}
 
diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out
index 2460d9dfd626ad493ec889527eba06f13cba5f39..087b4679d4d826e362a09b3bcf28a9ca4fcc08f9 100644
--- a/src/test/regress/expected/aggregates.out
+++ b/src/test/regress/expected/aggregates.out
@@ -830,3 +830,24 @@ select string_agg(a,',') from (values(null),(null)) g(a);
  
 (1 row)
 
+-- check some implicit casting cases, as per bug #5564
+select string_agg(distinct f1 order by f1) from varchar_tbl;  -- ok
+ string_agg 
+------------
+ aababcd
+(1 row)
+
+select string_agg(distinct f1::text order by f1) from varchar_tbl;  -- not ok
+ERROR:  in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list
+LINE 1: select string_agg(distinct f1::text order by f1) from varcha...
+                                                     ^
+select string_agg(distinct f1 order by f1::text) from varchar_tbl;  -- not ok
+ERROR:  in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list
+LINE 1: select string_agg(distinct f1 order by f1::text) from varcha...
+                                               ^
+select string_agg(distinct f1::text order by f1::text) from varchar_tbl;  -- ok
+ string_agg 
+------------
+ aababcd
+(1 row)
+
diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql
index daa89167a20f43fbca5165e6d14143c8168e634a..b2199d1ce94353df9669ba351931cc62cdc2e3ce 100644
--- a/src/test/regress/sql/aggregates.sql
+++ b/src/test/regress/sql/aggregates.sql
@@ -362,3 +362,9 @@ select string_agg(a,',') from (values('aaaa'),('bbbb'),('cccc')) g(a);
 select string_agg(a,',') from (values('aaaa'),(null),('bbbb'),('cccc')) g(a);
 select string_agg(a,',') from (values(null),(null),('bbbb'),('cccc')) g(a);
 select string_agg(a,',') from (values(null),(null)) g(a);
+
+-- check some implicit casting cases, as per bug #5564
+select string_agg(distinct f1 order by f1) from varchar_tbl;  -- ok
+select string_agg(distinct f1::text order by f1) from varchar_tbl;  -- not ok
+select string_agg(distinct f1 order by f1::text) from varchar_tbl;  -- not ok
+select string_agg(distinct f1::text order by f1::text) from varchar_tbl;  -- ok