aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_collate.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-03-22 15:58:03 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2011-03-22 15:58:03 -0400
commit37d6d07dda28a5dffcad6ff195ab2c83aaebcc9e (patch)
tree2a864e45637478c4a4c385180c6cd4847860b249 /src/backend/parser/parse_collate.c
parent1192ba8b67df1446973c71aafde5f6f613dce0af (diff)
downloadpostgresql-37d6d07dda28a5dffcad6ff195ab2c83aaebcc9e.tar.gz
postgresql-37d6d07dda28a5dffcad6ff195ab2c83aaebcc9e.zip
Throw error for indeterminate collation of an ORDER/GROUP/DISTINCT target.
This restores a parse error that was thrown (though only in the ORDER BY case) by the original collation patch. I had removed it in my recent revisions because it was thrown at a place where collations now haven't been computed yet; but I thought of another way to handle it. Throwing the error at parse time, rather than leaving it to be done at runtime, is good because a syntax error pointer is helpful for localizing the problem. We can reasonably assume that the comparison function for a collatable datatype will complain if it doesn't have a collation to use. Now the planner might choose to implement GROUP or DISTINCT via hashing, in which case no runtime error would actually occur, but it seems better to throw error consistently rather than let the error depend on what the planner chooses to do. Another possible objection is that the user might specify a nondefault sort operator that doesn't care about collation ... but that's surely an uncommon usage, and it wouldn't hurt him to throw in a COLLATE clause anyway. This change also makes the ORDER BY/GROUP BY/DISTINCT case more consistent with the UNION/INTERSECT/EXCEPT case, which was already coded to throw this error even though the same objections could be raised there.
Diffstat (limited to 'src/backend/parser/parse_collate.c')
-rw-r--r--src/backend/parser/parse_collate.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/src/backend/parser/parse_collate.c b/src/backend/parser/parse_collate.c
index 0b77e3ea2b7..8860679ccb9 100644
--- a/src/backend/parser/parse_collate.c
+++ b/src/backend/parser/parse_collate.c
@@ -533,6 +533,30 @@ assign_collations_walker(Node *node, assign_collations_context *context)
collation = loccontext.collation;
strength = loccontext.strength;
location = loccontext.location;
+
+ /*
+ * Throw error if the collation is indeterminate for a TargetEntry
+ * that is a sort/group target. We prefer to do this now, instead
+ * of leaving the comparison functions to fail at runtime, because
+ * we can give a syntax error pointer to help locate the problem.
+ * There are some cases where there might not be a failure, for
+ * example if the planner chooses to use hash aggregation instead
+ * of sorting for grouping; but it seems better to predictably
+ * throw an error. (Compare transformSetOperationTree, which will
+ * throw error for indeterminate collation of set-op columns,
+ * even though the planner might be able to implement the set-op
+ * without sorting.)
+ */
+ if (strength == COLLATE_CONFLICT &&
+ ((TargetEntry *) node)->ressortgroupref != 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_COLLATION_MISMATCH),
+ errmsg("collation mismatch between implicit collations \"%s\" and \"%s\"",
+ get_collation_name(loccontext.collation),
+ get_collation_name(loccontext.collation2)),
+ errhint("You can choose the collation by applying the COLLATE clause to one or both expressions."),
+ parser_errposition(context->pstate,
+ loccontext.location2)));
break;
case T_RangeTblRef:
case T_JoinExpr: