summaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_coerce.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_coerce.c')
-rw-r--r--src/backend/parser/parse_coerce.c152
1 files changed, 21 insertions, 131 deletions
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index 6aff34dd90d..9b59b032976 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -16,7 +16,6 @@
#include "catalog/pg_cast.h"
#include "catalog/pg_class.h"
-#include "catalog/pg_collation.h"
#include "catalog/pg_inherits_fn.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
@@ -123,6 +122,9 @@ coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype,
* pstate is only used in the case that we are able to resolve the type of
* a previously UNKNOWN Param. It is okay to pass pstate = NULL if the
* caller does not want type information updated for Params.
+ *
+ * Note: this function must not modify the given expression tree, only add
+ * decoration on top of it. See transformSetOperationTree, for example.
*/
Node *
coerce_type(ParseState *pstate, Node *node,
@@ -282,16 +284,21 @@ coerce_type(ParseState *pstate, Node *node,
if (IsA(node, CollateExpr))
{
/*
- * XXX very ugly kluge to push the coercion underneath the CollateExpr.
- * This needs to be rethought, as it almost certainly doesn't cover
- * all cases.
+ * If we have a COLLATE clause, we have to push the coercion
+ * underneath the COLLATE. This is really ugly, but there is little
+ * choice because the above hacks on Consts and Params wouldn't happen
+ * otherwise.
*/
- CollateExpr *cc = (CollateExpr *) node;
-
- cc->arg = (Expr *) coerce_type(pstate, (Node *) cc->arg,
- inputTypeId, targetTypeId, targetTypeMod,
- ccontext, cformat, location);
- return (Node *) cc;
+ CollateExpr *coll = (CollateExpr *) node;
+ CollateExpr *newcoll = makeNode(CollateExpr);
+
+ newcoll->arg = (Expr *)
+ coerce_type(pstate, (Node *) coll->arg,
+ inputTypeId, targetTypeId, targetTypeMod,
+ ccontext, cformat, location);
+ newcoll->collOid = coll->collOid;
+ newcoll->location = coll->location;
+ return (Node *) newcoll;
}
pathtype = find_coercion_pathway(targetTypeId, inputTypeId, ccontext,
&funcId);
@@ -352,6 +359,7 @@ coerce_type(ParseState *pstate, Node *node,
*/
RelabelType *r = makeRelabelType((Expr *) result,
targetTypeId, -1,
+ InvalidOid,
cformat);
r->location = location;
@@ -591,6 +599,7 @@ coerce_to_domain(Node *arg, Oid baseTypeId, int32 baseTypeMod, Oid typeId,
result->arg = (Expr *) arg;
result->resulttype = typeId;
result->resulttypmod = -1; /* currently, always -1 for domains */
+ /* resultcollid will be set by parse_collate.c */
result->coercionformat = cformat;
result->location = location;
@@ -734,7 +743,6 @@ build_coercion_expression(Node *node,
FuncExpr *fexpr;
List *args;
Const *cons;
- Oid collation;
Assert(OidIsValid(funcId));
@@ -766,9 +774,8 @@ build_coercion_expression(Node *node,
args = lappend(args, cons);
}
- collation = coercion_expression_result_collation(targetTypeId, node);
-
- fexpr = makeFuncExpr(funcId, targetTypeId, args, collation, cformat);
+ fexpr = makeFuncExpr(funcId, targetTypeId, args,
+ InvalidOid, InvalidOid, cformat);
fexpr->location = location;
return (Node *) fexpr;
}
@@ -2100,120 +2107,3 @@ typeIsOfTypedTable(Oid reltypeId, Oid reloftypeId)
return result;
}
-
-
-/*
- * select_common_collation() -- determine one collation to apply for
- * an expression node, for evaluating the expression itself or to
- * label the result of the expression node.
- *
- * none_ok means that it is permitted to return "no" collation. It is
- * then not possible to sort the result value of whatever expression
- * is applying this. none_ok = true reflects the rules of SQL
- * standard clause "Result of data type combinations", none_ok = false
- * reflects the rules of clause "Collation determination" (in some
- * cases invoked via "Grouping operations").
- */
-Oid
-select_common_collation(ParseState *pstate, List *exprs, bool none_ok)
-{
- ListCell *lc;
-
- /*
- * Check if there are any explicit collation derivations. If so,
- * they must all be the same.
- */
- foreach(lc, exprs)
- {
- Node *pexpr = (Node *) lfirst(lc);
- Oid pcoll = exprCollation(pexpr);
- bool pexplicit = IsA(pexpr, CollateExpr);
-
- if (pcoll && pexplicit)
- {
- ListCell *lc2;
- for_each_cell(lc2, lnext(lc))
- {
- Node *nexpr = (Node *) lfirst(lc2);
- Oid ncoll = exprCollation(nexpr);
- bool nexplicit = IsA(nexpr, CollateExpr);
-
- if (!ncoll || !nexplicit)
- continue;
-
- if (ncoll != pcoll)
- ereport(ERROR,
- (errcode(ERRCODE_COLLATION_MISMATCH),
- errmsg("collation mismatch between explicit collations \"%s\" and \"%s\"",
- get_collation_name(pcoll),
- get_collation_name(ncoll)),
- parser_errposition(pstate, exprLocation(nexpr))));
- }
-
- return pcoll;
- }
- }
-
- /*
- * Check if there are any implicit collation derivations.
- */
- foreach(lc, exprs)
- {
- Node *pexpr = (Node *) lfirst(lc);
- Oid pcoll = exprCollation(pexpr);
-
- if (pcoll && pcoll != DEFAULT_COLLATION_OID)
- {
- ListCell *lc2;
- for_each_cell(lc2, lnext(lc))
- {
- Node *nexpr = (Node *) lfirst(lc2);
- Oid ncoll = exprCollation(nexpr);
-
- if (!ncoll || ncoll == DEFAULT_COLLATION_OID)
- continue;
-
- if (ncoll != pcoll)
- {
- if (none_ok)
- return InvalidOid;
- ereport(ERROR,
- (errcode(ERRCODE_COLLATION_MISMATCH),
- errmsg("collation mismatch between implicit collations \"%s\" and \"%s\"",
- get_collation_name(pcoll),
- get_collation_name(ncoll)),
- errhint("You can override the collation by applying the COLLATE clause to one or both expressions."),
- parser_errposition(pstate, exprLocation(nexpr))));
- }
- }
-
- return pcoll;
- }
- }
-
- foreach(lc, exprs)
- {
- Node *pexpr = (Node *) lfirst(lc);
- Oid pcoll = exprCollation(pexpr);
-
- if (pcoll == DEFAULT_COLLATION_OID)
- {
- ListCell *lc2;
- for_each_cell(lc2, lnext(lc))
- {
- Node *nexpr = (Node *) lfirst(lc2);
- Oid ncoll = exprCollation(nexpr);
-
- if (ncoll != pcoll)
- break;
- }
-
- return pcoll;
- }
- }
-
- /*
- * Else use default
- */
- return InvalidOid;
-}