提交 8acdb8bf 编写于 作者: T Tom Lane

Split CollateClause into separate raw and analyzed node types.

CollateClause is now used only in raw grammar output, and CollateExpr after
parse analysis.  This is for clarity and to avoid carrying collation names
in post-analysis parse trees: that's both wasteful and possibly misleading,
since the collation's name could be changed while the parsetree still
exists.

Also, clean up assorted infelicities and omissions in processing of the
node type.
上级 7a8f4396
......@@ -1357,6 +1357,9 @@ recordDependencyOnSingleRelExpr(const ObjectAddress *depender,
* on the datatype, and OpExpr nodes depend on the operator which depends on
* the datatype. However we do need a type dependency if there is no such
* indirect dependency, as for example in Const and CoerceToDomain nodes.
*
* Similarly, we don't need to create dependencies on collations except where
* the collation is being freshly introduced to the expression.
*/
static bool
find_expr_references_walker(Node *node,
......@@ -1425,7 +1428,15 @@ find_expr_references_walker(Node *node,
/* A constant must depend on the constant's datatype */
add_object_address(OCLASS_TYPE, con->consttype, 0,
context->addrs);
if (OidIsValid(con->constcollid))
/*
* We must also depend on the constant's collation: it could be
* different from the datatype's, if a CollateExpr was const-folded
* to a simple constant. However we can save work in the most common
* case where the collation is "default", since we know that's pinned.
*/
if (OidIsValid(con->constcollid) &&
con->constcollid != DEFAULT_COLLATION_OID)
add_object_address(OCLASS_COLLATION, con->constcollid, 0,
context->addrs);
......@@ -1494,7 +1505,9 @@ find_expr_references_walker(Node *node,
/* A parameter must depend on the parameter's datatype */
add_object_address(OCLASS_TYPE, param->paramtype, 0,
context->addrs);
if (OidIsValid(param->paramcollation))
/* and its collation, just as for Consts */
if (OidIsValid(param->paramcollation) &&
param->paramcollation != DEFAULT_COLLATION_OID)
add_object_address(OCLASS_COLLATION, param->paramcollation, 0,
context->addrs);
}
......@@ -1567,13 +1580,6 @@ find_expr_references_walker(Node *node,
add_object_address(OCLASS_TYPE, relab->resulttype, 0,
context->addrs);
}
else if (IsA(node, CollateClause))
{
CollateClause *coll = (CollateClause *) node;
add_object_address(OCLASS_COLLATION, coll->collOid, 0,
context->addrs);
}
else if (IsA(node, CoerceViaIO))
{
CoerceViaIO *iocoerce = (CoerceViaIO *) node;
......@@ -1601,6 +1607,13 @@ find_expr_references_walker(Node *node,
add_object_address(OCLASS_TYPE, cvt->resulttype, 0,
context->addrs);
}
else if (IsA(node, CollateExpr))
{
CollateExpr *coll = (CollateExpr *) node;
add_object_address(OCLASS_COLLATION, coll->collOid, 0,
context->addrs);
}
else if (IsA(node, RowExpr))
{
RowExpr *rowexpr = (RowExpr *) node;
......@@ -1652,10 +1665,11 @@ find_expr_references_walker(Node *node,
/*
* Add whole-relation refs for each plain relation mentioned in the
* subquery's rtable, as well as datatype refs for any datatypes used
* as a RECORD function's output. (Note: query_tree_walker takes care
* of recursing into RTE_FUNCTION RTEs, subqueries, etc, so no need to
* do that here. But keep it from looking at join alias lists.)
* subquery's rtable, as well as refs for any datatypes and collations
* used in a RECORD function's output. (Note: query_tree_walker takes
* care of recursing into RTE_FUNCTION RTEs, subqueries, etc, so no
* need to do that here. But keep it from looking at join alias
* lists.)
*/
foreach(lc, query->rtable)
{
......@@ -1678,7 +1692,8 @@ find_expr_references_walker(Node *node,
{
Oid collid = lfirst_oid(ct);
if (OidIsValid(collid))
if (OidIsValid(collid) &&
collid != DEFAULT_COLLATION_OID)
add_object_address(OCLASS_COLLATION, collid, 0,
context->addrs);
}
......
......@@ -831,7 +831,7 @@ DefineDomain(CreateDomainStmt *stmt)
*/
baseColl = baseType->typcollation;
if (stmt->collClause)
domaincoll = get_collation_oid(stmt->collClause->collnames, false);
domaincoll = get_collation_oid(stmt->collClause->collname, false);
else
domaincoll = baseColl;
......
......@@ -120,6 +120,9 @@ static Datum ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
static Datum ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalCollateExpr(GenericExprState *exprstate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalCaseTestExpr(ExprState *exprstate,
......@@ -166,9 +169,6 @@ static Datum ExecEvalFieldStore(FieldStoreState *fstate,
static Datum ExecEvalRelabelType(GenericExprState *exprstate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalCollateClause(GenericExprState *exprstate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalCoerceViaIO(CoerceViaIOState *iostate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
......@@ -2753,6 +2753,20 @@ ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
return HeapTupleGetDatum(result);
}
/* ----------------------------------------------------------------
* ExecEvalCollateExpr
*
* Evaluate a CollateExpr node.
* ----------------------------------------------------------------
*/
static Datum
ExecEvalCollateExpr(GenericExprState *exprstate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
{
return ExecEvalExpr(exprstate->arg, econtext, isNull, isDone);
}
/* ----------------------------------------------------------------
* ExecEvalCase
*
......@@ -4028,20 +4042,6 @@ ExecEvalRelabelType(GenericExprState *exprstate,
return ExecEvalExpr(exprstate->arg, econtext, isNull, isDone);
}
/* ----------------------------------------------------------------
* ExecEvalCollateClause
*
* Evaluate a CollateClause node.
* ----------------------------------------------------------------
*/
static Datum
ExecEvalCollateClause(GenericExprState *exprstate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
{
return ExecEvalExpr(exprstate->arg, econtext, isNull, isDone);
}
/* ----------------------------------------------------------------
* ExecEvalCoerceViaIO
*
......@@ -4501,16 +4501,6 @@ ExecInitExpr(Expr *node, PlanState *parent)
state = (ExprState *) gstate;
}
break;
case T_CollateClause:
{
CollateClause *collate = (CollateClause *) node;
GenericExprState *gstate = makeNode(GenericExprState);
gstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCollateClause;
gstate->arg = ExecInitExpr(collate->arg, parent);
state = (ExprState *) gstate;
}
break;
case T_CoerceViaIO:
{
CoerceViaIO *iocoerce = (CoerceViaIO *) node;
......@@ -4561,6 +4551,16 @@ ExecInitExpr(Expr *node, PlanState *parent)
state = (ExprState *) cstate;
}
break;
case T_CollateExpr:
{
CollateExpr *collate = (CollateExpr *) node;
GenericExprState *gstate = makeNode(GenericExprState);
gstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalCollateExpr;
gstate->arg = ExecInitExpr(collate->arg, parent);
state = (ExprState *) gstate;
}
break;
case T_CaseExpr:
{
CaseExpr *caseexpr = (CaseExpr *) node;
......
......@@ -1434,6 +1434,21 @@ _copyConvertRowtypeExpr(ConvertRowtypeExpr *from)
return newnode;
}
/*
* _copyCollateExpr
*/
static CollateExpr *
_copyCollateExpr(CollateExpr *from)
{
CollateExpr *newnode = makeNode(CollateExpr);
COPY_NODE_FIELD(arg);
COPY_SCALAR_FIELD(collOid);
COPY_LOCATION_FIELD(location);
return newnode;
}
/*
* _copyCaseExpr
*/
......@@ -2260,8 +2275,7 @@ _copyCollateClause(CollateClause *from)
CollateClause *newnode = makeNode(CollateClause);
COPY_NODE_FIELD(arg);
COPY_NODE_FIELD(collnames);
COPY_SCALAR_FIELD(collOid);
COPY_NODE_FIELD(collname);
COPY_LOCATION_FIELD(location);
return newnode;
......@@ -4017,6 +4031,9 @@ copyObject(void *from)
case T_ConvertRowtypeExpr:
retval = _copyConvertRowtypeExpr(from);
break;
case T_CollateExpr:
retval = _copyCollateExpr(from);
break;
case T_CaseExpr:
retval = _copyCaseExpr(from);
break;
......
......@@ -493,6 +493,16 @@ _equalConvertRowtypeExpr(ConvertRowtypeExpr *a, ConvertRowtypeExpr *b)
return true;
}
static bool
_equalCollateExpr(CollateExpr *a, CollateExpr *b)
{
COMPARE_NODE_FIELD(arg);
COMPARE_SCALAR_FIELD(collOid);
COMPARE_LOCATION_FIELD(location);
return true;
}
static bool
_equalCaseExpr(CaseExpr *a, CaseExpr *b)
{
......@@ -2149,8 +2159,7 @@ static bool
_equalCollateClause(CollateClause *a, CollateClause *b)
{
COMPARE_NODE_FIELD(arg);
COMPARE_NODE_FIELD(collnames);
COMPARE_SCALAR_FIELD(collOid);
COMPARE_NODE_FIELD(collname);
COMPARE_LOCATION_FIELD(location);
return true;
......@@ -2583,6 +2592,9 @@ equal(void *a, void *b)
case T_ConvertRowtypeExpr:
retval = _equalConvertRowtypeExpr(a, b);
break;
case T_CollateExpr:
retval = _equalCollateExpr(a, b);
break;
case T_CaseExpr:
retval = _equalCaseExpr(a, b);
break;
......
......@@ -162,9 +162,6 @@ exprType(Node *expr)
case T_RelabelType:
type = ((RelabelType *) expr)->resulttype;
break;
case T_CollateClause:
type = exprType((Node *) ((CollateClause *) expr)->arg);
break;
case T_CoerceViaIO:
type = ((CoerceViaIO *) expr)->resulttype;
break;
......@@ -174,6 +171,9 @@ exprType(Node *expr)
case T_ConvertRowtypeExpr:
type = ((ConvertRowtypeExpr *) expr)->resulttype;
break;
case T_CollateExpr:
type = exprType((Node *) ((CollateExpr *) expr)->arg);
break;
case T_CaseExpr:
type = ((CaseExpr *) expr)->casetype;
break;
......@@ -321,6 +321,8 @@ exprTypmod(Node *expr)
return ((RelabelType *) expr)->resulttypmod;
case T_ArrayCoerceExpr:
return ((ArrayCoerceExpr *) expr)->resulttypmod;
case T_CollateExpr:
return exprTypmod((Node *) ((CollateExpr *) expr)->arg);
case T_CaseExpr:
{
/*
......@@ -571,9 +573,6 @@ exprCollation(Node *expr)
case T_RelabelType:
coll = exprCollation((Node *) ((RelabelType *) expr)->arg);
break;
case T_CollateClause:
coll = ((CollateClause *) expr)->collOid;
break;
case T_CoerceViaIO:
{
CoerceViaIO *cvio = (CoerceViaIO *) expr;
......@@ -592,6 +591,9 @@ exprCollation(Node *expr)
coll = coercion_expression_result_collation(cre->resulttype, (Node *) cre->arg);
break;
}
case T_CollateExpr:
coll = ((CollateExpr *) expr)->collOid;
break;
case T_CaseExpr:
coll = ((CaseExpr *) expr)->casecollation;
break;
......@@ -989,6 +991,10 @@ exprLocation(Node *expr)
exprLocation((Node *) cexpr->arg));
}
break;
case T_CollateExpr:
/* just use argument's location */
loc = exprLocation((Node *) ((CollateExpr *) expr)->arg);
break;
case T_CaseExpr:
/* CASE keyword should always be the first thing */
loc = ((CaseExpr *) expr)->location;
......@@ -1122,7 +1128,8 @@ exprLocation(Node *expr)
}
break;
case T_CollateClause:
loc = ((CollateClause *) expr)->location;
/* just use argument's location */
loc = exprLocation(((CollateClause *) expr)->arg);
break;
case T_SortBy:
/* just use argument's location (ignore operator, if any) */
......@@ -1436,14 +1443,14 @@ expression_tree_walker(Node *node,
break;
case T_RelabelType:
return walker(((RelabelType *) node)->arg, context);
case T_CollateClause:
return walker(((CollateClause *) node)->arg, context);
case T_CoerceViaIO:
return walker(((CoerceViaIO *) node)->arg, context);
case T_ArrayCoerceExpr:
return walker(((ArrayCoerceExpr *) node)->arg, context);
case T_ConvertRowtypeExpr:
return walker(((ConvertRowtypeExpr *) node)->arg, context);
case T_CollateExpr:
return walker(((CollateExpr *) node)->arg, context);
case T_CaseExpr:
{
CaseExpr *caseexpr = (CaseExpr *) node;
......@@ -1993,16 +2000,6 @@ expression_tree_mutator(Node *node,
return (Node *) newnode;
}
break;
case T_CollateClause:
{
CollateClause *collate = (CollateClause *) node;
CollateClause *newnode;
FLATCOPY(newnode, collate, CollateClause);
MUTATE(newnode->arg, collate->arg, Expr *);
return (Node *) newnode;
}
break;
case T_CoerceViaIO:
{
CoerceViaIO *iocoerce = (CoerceViaIO *) node;
......@@ -2033,6 +2030,16 @@ expression_tree_mutator(Node *node,
return (Node *) newnode;
}
break;
case T_CollateExpr:
{
CollateExpr *collate = (CollateExpr *) node;
CollateExpr *newnode;
FLATCOPY(newnode, collate, CollateExpr);
MUTATE(newnode->arg, collate->arg, Expr *);
return (Node *) newnode;
}
break;
case T_CaseExpr:
{
CaseExpr *caseexpr = (CaseExpr *) node;
......
......@@ -1195,6 +1195,16 @@ _outConvertRowtypeExpr(StringInfo str, ConvertRowtypeExpr *node)
WRITE_LOCATION_FIELD(location);
}
static void
_outCollateExpr(StringInfo str, CollateExpr *node)
{
WRITE_NODE_TYPE("COLLATE");
WRITE_NODE_FIELD(arg);
WRITE_OID_FIELD(collOid);
WRITE_LOCATION_FIELD(location);
}
static void
_outCaseExpr(StringInfo str, CaseExpr *node)
{
......@@ -2104,11 +2114,10 @@ _outTypeCast(StringInfo str, TypeCast *node)
static void
_outCollateClause(StringInfo str, CollateClause *node)
{
WRITE_NODE_TYPE("COLLATE");
WRITE_NODE_TYPE("COLLATECLAUSE");
WRITE_NODE_FIELD(arg);
WRITE_NODE_FIELD(collnames);
WRITE_OID_FIELD(collOid);
WRITE_NODE_FIELD(collname);
WRITE_LOCATION_FIELD(location);
}
......@@ -2829,9 +2838,6 @@ _outNode(StringInfo str, void *obj)
case T_RelabelType:
_outRelabelType(str, obj);
break;
case T_CollateClause:
_outCollateClause(str, obj);
break;
case T_CoerceViaIO:
_outCoerceViaIO(str, obj);
break;
......@@ -2841,6 +2847,9 @@ _outNode(StringInfo str, void *obj)
case T_ConvertRowtypeExpr:
_outConvertRowtypeExpr(str, obj);
break;
case T_CollateExpr:
_outCollateExpr(str, obj);
break;
case T_CaseExpr:
_outCaseExpr(str, obj);
break;
......@@ -3020,6 +3029,9 @@ _outNode(StringInfo str, void *obj)
case T_TypeCast:
_outTypeCast(str, obj);
break;
case T_CollateClause:
_outCollateClause(str, obj);
break;
case T_IndexElem:
_outIndexElem(str, obj);
break;
......
......@@ -743,22 +743,6 @@ _readRelabelType(void)
READ_DONE();
}
/*
* _readCollateClause
*/
static CollateClause *
_readCollateClause(void)
{
READ_LOCALS(CollateClause);
READ_NODE_FIELD(arg);
READ_NODE_FIELD(collnames);
READ_OID_FIELD(collOid);
READ_LOCATION_FIELD(location);
READ_DONE();
}
/*
* _readCoerceViaIO
*/
......@@ -810,6 +794,21 @@ _readConvertRowtypeExpr(void)
READ_DONE();
}
/*
* _readCollateExpr
*/
static CollateExpr *
_readCollateExpr(void)
{
READ_LOCALS(CollateExpr);
READ_NODE_FIELD(arg);
READ_OID_FIELD(collOid);
READ_LOCATION_FIELD(location);
READ_DONE();
}
/*
* _readCaseExpr
*/
......@@ -1286,14 +1285,14 @@ parseNodeString(void)
return_value = _readFieldStore();
else if (MATCH("RELABELTYPE", 11))
return_value = _readRelabelType();
else if (MATCH("COLLATE", 7))
return_value = _readCollateClause();
else if (MATCH("COERCEVIAIO", 11))
return_value = _readCoerceViaIO();
else if (MATCH("ARRAYCOERCEEXPR", 15))
return_value = _readArrayCoerceExpr();
else if (MATCH("CONVERTROWTYPEEXPR", 18))
return_value = _readConvertRowtypeExpr();
else if (MATCH("COLLATE", 7))
return_value = _readCollateExpr();
else if (MATCH("CASE", 4))
return_value = _readCaseExpr();
else if (MATCH("WHEN", 4))
......
......@@ -1308,6 +1308,12 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
}
else if (IsA(node, CollateExpr))
{
CollateExpr *expr = (CollateExpr *) node;
result = find_nonnullable_rels_walker((Node *) expr->arg, top_level);
}
else if (IsA(node, NullTest))
{
/* IS NOT NULL can be considered strict, but only at top level */
......@@ -1510,6 +1516,12 @@ find_nonnullable_vars_walker(Node *node, bool top_level)
result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
}
else if (IsA(node, CollateExpr))
{
CollateExpr *expr = (CollateExpr *) node;
result = find_nonnullable_vars_walker((Node *) expr->arg, top_level);
}
else if (IsA(node, NullTest))
{
/* IS NOT NULL can be considered strict, but only at top level */
......@@ -2580,6 +2592,42 @@ eval_const_expressions_mutator(Node *node,
/* Else we must return the partially-simplified node */
return (Node *) newexpr;
}
if (IsA(node, CollateExpr))
{
/*
* If we can simplify the input to a constant, then we don't need the
* CollateExpr node anymore: just change the constcollid field of the
* Const node. Otherwise, must copy the CollateExpr node.
*/
CollateExpr *collate = (CollateExpr *) node;
Node *arg;
arg = eval_const_expressions_mutator((Node *) collate->arg,
context);
/*
* If we find stacked CollateExprs, we can discard all but the top one.
*/
while (arg && IsA(arg, CollateExpr))
arg = (Node *) ((CollateExpr *) arg)->arg;
if (arg && IsA(arg, Const))
{
Const *con = (Const *) arg;
con->constcollid = collate->collOid;
return (Node *) con;
}
else
{
CollateExpr *newcollate = makeNode(CollateExpr);
newcollate->arg = (Expr *) arg;
newcollate->collOid = collate->collOid;
newcollate->location = collate->location;
return (Node *) newcollate;
}
}
if (IsA(node, CaseExpr))
{
/*----------
......
......@@ -1993,8 +1993,7 @@ opt_collate_clause:
{
CollateClause *n = makeNode(CollateClause);
n->arg = NULL;
n->collnames = $2;
n->collOid = InvalidOid;
n->collname = $2;
n->location = @1;
$$ = (Node *) n;
}
......@@ -2537,8 +2536,7 @@ ColConstraint:
*/
CollateClause *n = makeNode(CollateClause);
n->arg = NULL;
n->collnames = $2;
n->collOid = InvalidOid;
n->collname = $2;
n->location = @1;
$$ = (Node *) n;
}
......@@ -9690,8 +9688,8 @@ a_expr: c_expr { $$ = $1; }
| a_expr COLLATE any_name
{
CollateClause *n = makeNode(CollateClause);
n->arg = (Expr *) $1;
n->collnames = $3;
n->arg = $1;
n->collname = $3;
n->location = @2;
$$ = (Node *) n;
}
......
......@@ -279,11 +279,17 @@ coerce_type(ParseState *pstate, Node *node,
if (result)
return result;
}
if (IsA(node, CollateClause))
if (IsA(node, CollateExpr))
{
CollateClause *cc = (CollateClause *) node;
/*
* 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.
*/
CollateExpr *cc = (CollateExpr *) node;
cc->arg = (Expr *) coerce_type(pstate, (Node *) cc->arg, inputTypeId, targetTypeId, targetTypeMod,
cc->arg = (Expr *) coerce_type(pstate, (Node *) cc->arg,
inputTypeId, targetTypeId, targetTypeMod,
ccontext, cformat, location);
return (Node *) cc;
}
......@@ -2121,7 +2127,7 @@ select_common_collation(ParseState *pstate, List *exprs, bool none_ok)
{
Node *pexpr = (Node *) lfirst(lc);
Oid pcoll = exprCollation(pexpr);
bool pexplicit = IsA(pexpr, CollateClause);
bool pexplicit = IsA(pexpr, CollateExpr);
if (pcoll && pexplicit)
{
......@@ -2130,7 +2136,7 @@ select_common_collation(ParseState *pstate, List *exprs, bool none_ok)
{
Node *nexpr = (Node *) lfirst(lc2);
Oid ncoll = exprCollation(nexpr);
bool nexplicit = IsA(nexpr, CollateClause);
bool nexplicit = IsA(nexpr, CollateExpr);
if (!ncoll || !nexplicit)
continue;
......
......@@ -318,6 +318,7 @@ transformExpr(ParseState *pstate, Node *expr)
case T_CoerceViaIO:
case T_ArrayCoerceExpr:
case T_ConvertRowtypeExpr:
case T_CollateExpr:
case T_CaseTestExpr:
case T_ArrayExpr:
case T_CoerceToDomain:
......@@ -2103,11 +2104,11 @@ transformTypeCast(ParseState *pstate, TypeCast *tc)
static Node *
transformCollateClause(ParseState *pstate, CollateClause *c)
{
CollateClause *newc;
CollateExpr *newc;
Oid argtype;
newc = makeNode(CollateClause);
newc->arg = (Expr *) transformExpr(pstate, (Node *) c->arg);
newc = makeNode(CollateExpr);
newc->arg = (Expr *) transformExpr(pstate, c->arg);
argtype = exprType((Node *) newc->arg);
/*
......@@ -2121,8 +2122,7 @@ transformCollateClause(ParseState *pstate, CollateClause *c)
format_type_be(argtype)),
parser_errposition(pstate, c->location)));
newc->collOid = LookupCollation(pstate, c->collnames, c->location);
newc->collnames = c->collnames;
newc->collOid = LookupCollation(pstate, c->collname, c->location);
newc->location = c->location;
return (Node *) newc;
......
......@@ -1583,7 +1583,7 @@ FigureColnameInternal(Node *node, char **name)
}
break;
case T_CollateClause:
return FigureColnameInternal((Node *) ((CollateClause *) node)->arg, name);
return FigureColnameInternal(((CollateClause *) node)->arg, name);
case T_CaseExpr:
strength = FigureColnameInternal((Node *) ((CaseExpr *) node)->defresult,
name);
......
......@@ -471,7 +471,7 @@ GetColumnDefCollation(ParseState *pstate, ColumnDef *coldef, Oid typeOid)
{
/* We have a raw COLLATE clause, so look up the collation */
location = coldef->collClause->location;
result = LookupCollation(pstate, coldef->collClause->collnames,
result = LookupCollation(pstate, coldef->collClause->collname,
location);
}
else if (OidIsValid(coldef->collOid))
......
......@@ -2467,7 +2467,7 @@ transformColumnType(CreateStmtContext *cxt, ColumnDef *column)
Oid collOid;
collOid = LookupCollation(cxt->pstate,
column->collClause->collnames,
column->collClause->collname,
column->collClause->location);
/* Complain if COLLATE is applied to an uncollatable type */
if (!OidIsValid(typtup->typcollation))
......
......@@ -226,6 +226,7 @@ static void get_coercion_expr(Node *arg, deparse_context *context,
Node *parentNode);
static void get_const_expr(Const *constval, deparse_context *context,
int showtype);
static void get_const_collation(Const *constval, deparse_context *context);
static void simple_quote_literal(StringInfo buf, const char *val);
static void get_sublink_expr(SubLink *sublink, deparse_context *context);
static void get_from_clause(Query *query, const char *prefix,
......@@ -5075,21 +5076,6 @@ get_rule_expr(Node *node, deparse_context *context,
}
break;
case T_CollateClause:
{
CollateClause *collate = (CollateClause *) node;
Node *arg = (Node *) collate->arg;
if (!PRETTY_PAREN(context))
appendStringInfoChar(buf, '(');
get_rule_expr_paren(arg, context, showimplicit, node);
appendStringInfo(buf, " COLLATE %s",
generate_collation_name(collate->collOid));
if (!PRETTY_PAREN(context))
appendStringInfoChar(buf, ')');
}
break;
case T_CoerceViaIO:
{
CoerceViaIO *iocoerce = (CoerceViaIO *) node;
......@@ -5152,6 +5138,21 @@ get_rule_expr(Node *node, deparse_context *context,
}
break;
case T_CollateExpr:
{
CollateExpr *collate = (CollateExpr *) node;
Node *arg = (Node *) collate->arg;
if (!PRETTY_PAREN(context))
appendStringInfoChar(buf, '(');
get_rule_expr_paren(arg, context, showimplicit, node);
appendStringInfo(buf, " COLLATE %s",
generate_collation_name(collate->collOid));
if (!PRETTY_PAREN(context))
appendStringInfoChar(buf, ')');
}
break;
case T_CaseExpr:
{
CaseExpr *caseexpr = (CaseExpr *) node;
......@@ -5974,6 +5975,10 @@ get_coercion_expr(Node *arg, deparse_context *context,
* showtype can be -1 to never show "::typename" decoration, or +1 to always
* show it, or 0 to show it only if the constant wouldn't be assumed to be
* the right type by default.
*
* If the Const's collation isn't default for its type, show that too.
* This can only happen in trees that have been through constant-folding.
* We assume we don't need to do this when showtype is -1.
* ----------
*/
static void
......@@ -5994,9 +5999,12 @@ get_const_expr(Const *constval, deparse_context *context, int showtype)
*/
appendStringInfo(buf, "NULL");
if (showtype >= 0)
{
appendStringInfo(buf, "::%s",
format_type_with_typemod(constval->consttype,
constval->consttypmod));
get_const_collation(constval, context);
}
return;
}
......@@ -6097,6 +6105,28 @@ get_const_expr(Const *constval, deparse_context *context, int showtype)
appendStringInfo(buf, "::%s",
format_type_with_typemod(constval->consttype,
constval->consttypmod));
get_const_collation(constval, context);
}
/*
* helper for get_const_expr: append COLLATE if needed
*/
static void
get_const_collation(Const *constval, deparse_context *context)
{
StringInfo buf = context->buf;
if (OidIsValid(constval->constcollid))
{
Oid typcollation = get_typcollation(constval->consttype);
if (constval->constcollid != typcollation)
{
appendStringInfo(buf, " COLLATE %s",
generate_collation_name(constval->constcollid));
}
}
}
/*
......
......@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 201103111
#define CATALOG_VERSION_NO 201103112
#endif
......@@ -148,6 +148,7 @@ typedef enum NodeTag
T_CoerceViaIO,
T_ArrayCoerceExpr,
T_ConvertRowtypeExpr,
T_CollateExpr,
T_CaseExpr,
T_CaseWhen,
T_CaseTestExpr,
......@@ -169,7 +170,6 @@ typedef enum NodeTag
T_JoinExpr,
T_FromExpr,
T_IntoClause,
T_CollateClause,
/*
* TAGS FOR EXPRESSION STATE NODES (execnodes.h)
......@@ -377,6 +377,7 @@ typedef enum NodeTag
T_A_ArrayExpr,
T_ResTarget,
T_TypeCast,
T_CollateClause,
T_SortBy,
T_WindowDef,
T_RangeSubselect,
......
......@@ -265,6 +265,17 @@ typedef struct TypeCast
int location; /* token location, or -1 if unknown */
} TypeCast;
/*
* CollateClause - a COLLATE expression
*/
typedef struct CollateClause
{
NodeTag type;
Node *arg; /* input expression */
List *collname; /* possibly-qualified collation name */
int location; /* token location, or -1 if unknown */
} CollateClause;
/*
* FuncCall - a function or aggregate invocation
*
......
......@@ -653,18 +653,6 @@ typedef struct RelabelType
int location; /* token location, or -1 if unknown */
} RelabelType;
/*
* CollateClause - COLLATE
*/
typedef struct CollateClause
{
Expr xpr;
Expr *arg; /* original expression */
List *collnames; /* assigned collation */
Oid collOid; /* resolved collation OID */
int location; /* token location, or -1 if unknown */
} CollateClause;
/* ----------------
* CoerceViaIO
*
......@@ -730,6 +718,18 @@ typedef struct ConvertRowtypeExpr
int location; /* token location, or -1 if unknown */
} ConvertRowtypeExpr;
/*----------
* CollateExpr - COLLATE
*----------
*/
typedef struct CollateExpr
{
Expr xpr;
Expr *arg; /* input expression */
Oid collOid; /* collation's OID */
int location; /* token location, or -1 if unknown */
} CollateExpr;
/*----------
* CaseExpr - a CASE expression
*
......
......@@ -5350,6 +5350,9 @@ exec_simple_check_node(Node *node)
case T_ConvertRowtypeExpr:
return exec_simple_check_node((Node *) ((ConvertRowtypeExpr *) node)->arg);
case T_CollateExpr:
return exec_simple_check_node((Node *) ((CollateExpr *) node)->arg);
case T_CaseExpr:
{
CaseExpr *expr = (CaseExpr *) node;
......
......@@ -107,11 +107,11 @@ SELECT * FROM collate_test1 WHERE b COLLATE "C" >= 'bbc' COLLATE "C";
SELECT * FROM collate_test1 WHERE b COLLATE "C" >= 'bbc' COLLATE "en_US.utf8";
ERROR: collation mismatch between explicit collations "C" and "en_US.utf8"
LINE 1: ...* FROM collate_test1 WHERE b COLLATE "C" >= 'bbc' COLLATE "e...
LINE 1: ...ELECT * FROM collate_test1 WHERE b COLLATE "C" >= 'bbc' COLL...
^
SELECT * FROM collate_test1 WHERE b COLLATE "C" >= 'bbc' COLLATE "en_US";
ERROR: collation mismatch between explicit collations "C" and "en_US"
LINE 1: ...* FROM collate_test1 WHERE b COLLATE "C" >= 'bbc' COLLATE "e...
LINE 1: ...ELECT * FROM collate_test1 WHERE b COLLATE "C" >= 'bbc' COLL...
^
CREATE DOMAIN testdomain_sv AS text COLLATE "sv_SE.utf8";
CREATE DOMAIN testdomain_i AS int COLLATE "sv_SE.utf8"; -- fails
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册