mirror of
https://github.com/postgres/postgres.git
synced 2025-06-19 04:21:08 +03:00
Per-column collation support
This adds collation support for columns and domains, a COLLATE clause to override it per expression, and B-tree index support. Peter Eisentraut reviewed by Pavel Stehule, Itagaki Takahiro, Robert Haas, Noah Misch
This commit is contained in:
@ -65,6 +65,7 @@ static Node *transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte,
|
||||
static Node *transformIndirection(ParseState *pstate, Node *basenode,
|
||||
List *indirection);
|
||||
static Node *transformTypeCast(ParseState *pstate, TypeCast *tc);
|
||||
static Node *transformCollateClause(ParseState *pstate, CollateClause *c);
|
||||
static Node *make_row_comparison_op(ParseState *pstate, List *opname,
|
||||
List *largs, List *rargs, int location);
|
||||
static Node *make_row_distinct_op(ParseState *pstate, List *opname,
|
||||
@ -146,6 +147,12 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
{
|
||||
TypeCast *tc = (TypeCast *) expr;
|
||||
|
||||
if (tc->typeName->collnames)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("COLLATE clause not allowed in cast target"),
|
||||
parser_errposition(pstate, tc->typeName->location)));
|
||||
|
||||
/*
|
||||
* If the subject of the typecast is an ARRAY[] construct and
|
||||
* the target type is an array type, we invoke
|
||||
@ -185,6 +192,10 @@ transformExpr(ParseState *pstate, Node *expr)
|
||||
break;
|
||||
}
|
||||
|
||||
case T_CollateClause:
|
||||
result = transformCollateClause(pstate, (CollateClause *) expr);
|
||||
break;
|
||||
|
||||
case T_A_Expr:
|
||||
{
|
||||
A_Expr *a = (A_Expr *) expr;
|
||||
@ -423,6 +434,7 @@ transformIndirection(ParseState *pstate, Node *basenode, List *indirection)
|
||||
exprType(result),
|
||||
InvalidOid,
|
||||
exprTypmod(result),
|
||||
exprCollation(result),
|
||||
subscripts,
|
||||
NULL);
|
||||
subscripts = NIL;
|
||||
@ -444,6 +456,7 @@ transformIndirection(ParseState *pstate, Node *basenode, List *indirection)
|
||||
exprType(result),
|
||||
InvalidOid,
|
||||
exprTypmod(result),
|
||||
exprCollation(result),
|
||||
subscripts,
|
||||
NULL);
|
||||
|
||||
@ -1267,6 +1280,7 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c)
|
||||
placeholder = makeNode(CaseTestExpr);
|
||||
placeholder->typeId = exprType(arg);
|
||||
placeholder->typeMod = exprTypmod(arg);
|
||||
placeholder->collation = exprCollation(arg);
|
||||
}
|
||||
else
|
||||
placeholder = NULL;
|
||||
@ -1351,6 +1365,8 @@ transformCaseExpr(ParseState *pstate, CaseExpr *c)
|
||||
"CASE/WHEN");
|
||||
}
|
||||
|
||||
newc->casecollation = select_common_collation(pstate, resultexprs, true);
|
||||
|
||||
newc->location = c->location;
|
||||
|
||||
return (Node *) newc;
|
||||
@ -1461,6 +1477,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
|
||||
param->paramid = tent->resno;
|
||||
param->paramtype = exprType((Node *) tent->expr);
|
||||
param->paramtypmod = exprTypmod((Node *) tent->expr);
|
||||
param->paramcollation = exprCollation((Node *) tent->expr);
|
||||
param->location = -1;
|
||||
|
||||
right_list = lappend(right_list, param);
|
||||
@ -1704,6 +1721,7 @@ transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c)
|
||||
}
|
||||
|
||||
newc->args = newcoercedargs;
|
||||
newc->coalescecollation = select_common_collation(pstate, newcoercedargs, true);
|
||||
newc->location = c->location;
|
||||
return (Node *) newc;
|
||||
}
|
||||
@ -1728,6 +1746,7 @@ transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m)
|
||||
}
|
||||
|
||||
newm->minmaxtype = select_common_type(pstate, newargs, funcname, NULL);
|
||||
newm->collid = select_common_collation(pstate, newargs, false);
|
||||
|
||||
/* Convert arguments if necessary */
|
||||
foreach(args, newargs)
|
||||
@ -2082,6 +2101,36 @@ transformTypeCast(ParseState *pstate, TypeCast *tc)
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle an explicit COLLATE clause.
|
||||
*
|
||||
* Transform the argument, and look up the collation name.
|
||||
*/
|
||||
static Node *
|
||||
transformCollateClause(ParseState *pstate, CollateClause *c)
|
||||
{
|
||||
CollateClause *newc;
|
||||
Oid argtype;
|
||||
|
||||
newc = makeNode(CollateClause);
|
||||
newc->arg = (Expr *) transformExpr(pstate, (Node *) c->arg);
|
||||
|
||||
argtype = exprType((Node *) newc->arg);
|
||||
/* The unknown type is not collatable, but coerce_type() takes
|
||||
* care of it separately, so we'll let it go here. */
|
||||
if (!type_is_collatable(argtype) && argtype != UNKNOWNOID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("collations are not supported by type %s",
|
||||
format_type_be(argtype))));
|
||||
|
||||
newc->collOid = LookupCollation(pstate, c->collnames, c->location);
|
||||
newc->collnames = c->collnames;
|
||||
newc->location = c->location;
|
||||
|
||||
return (Node *) newc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Transform a "row compare-op row" construct
|
||||
*
|
||||
@ -2103,6 +2152,7 @@ make_row_comparison_op(ParseState *pstate, List *opname,
|
||||
List *opexprs;
|
||||
List *opnos;
|
||||
List *opfamilies;
|
||||
List *collids;
|
||||
ListCell *l,
|
||||
*r;
|
||||
List **opfamily_lists;
|
||||
@ -2273,6 +2323,7 @@ make_row_comparison_op(ParseState *pstate, List *opname,
|
||||
* possibility that make_op inserted coercion operations.
|
||||
*/
|
||||
opnos = NIL;
|
||||
collids = NIL;
|
||||
largs = NIL;
|
||||
rargs = NIL;
|
||||
foreach(l, opexprs)
|
||||
@ -2280,6 +2331,7 @@ make_row_comparison_op(ParseState *pstate, List *opname,
|
||||
OpExpr *cmp = (OpExpr *) lfirst(l);
|
||||
|
||||
opnos = lappend_oid(opnos, cmp->opno);
|
||||
collids = lappend_oid(collids, cmp->collid);
|
||||
largs = lappend(largs, linitial(cmp->args));
|
||||
rargs = lappend(rargs, lsecond(cmp->args));
|
||||
}
|
||||
@ -2288,6 +2340,7 @@ make_row_comparison_op(ParseState *pstate, List *opname,
|
||||
rcexpr->rctype = rctype;
|
||||
rcexpr->opnos = opnos;
|
||||
rcexpr->opfamilies = opfamilies;
|
||||
rcexpr->collids = collids;
|
||||
rcexpr->largs = largs;
|
||||
rcexpr->rargs = rargs;
|
||||
|
||||
|
Reference in New Issue
Block a user