* 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,
/* 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);
/* 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);
}
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;
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;
/*
* 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)
{
{
Oid collid = lfirst_oid(ct);
- if (OidIsValid(collid))
+ if (OidIsValid(collid) &&
+ collid != DEFAULT_COLLATION_OID)
add_object_address(OCLASS_COLLATION, collid, 0,
context->addrs);
}
*/
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;
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,
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);
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
*
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
*
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;
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;
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
*/
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;
case T_ConvertRowtypeExpr:
retval = _copyConvertRowtypeExpr(from);
break;
+ case T_CollateExpr:
+ retval = _copyCollateExpr(from);
+ break;
case T_CaseExpr:
retval = _copyCaseExpr(from);
break;
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)
{
_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;
case T_ConvertRowtypeExpr:
retval = _equalConvertRowtypeExpr(a, b);
break;
+ case T_CollateExpr:
+ retval = _equalCollateExpr(a, b);
+ break;
case T_CaseExpr:
retval = _equalCaseExpr(a, b);
break;
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;
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;
return ((RelabelType *) expr)->resulttypmod;
case T_ArrayCoerceExpr:
return ((ArrayCoerceExpr *) expr)->resulttypmod;
+ case T_CollateExpr:
+ return exprTypmod((Node *) ((CollateExpr *) expr)->arg);
case T_CaseExpr:
{
/*
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;
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;
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;
}
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) */
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;
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;
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;
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)
{
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);
}
case T_RelabelType:
_outRelabelType(str, obj);
break;
- case T_CollateClause:
- _outCollateClause(str, obj);
- break;
case T_CoerceViaIO:
_outCoerceViaIO(str, obj);
break;
case T_ConvertRowtypeExpr:
_outConvertRowtypeExpr(str, obj);
break;
+ case T_CollateExpr:
+ _outCollateExpr(str, obj);
+ break;
case T_CaseExpr:
_outCaseExpr(str, obj);
break;
case T_TypeCast:
_outTypeCast(str, obj);
break;
+ case T_CollateClause:
+ _outCollateClause(str, obj);
+ break;
case T_IndexElem:
_outIndexElem(str, obj);
break;
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
*/
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
*/
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))
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 */
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 */
/* 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))
{
/*----------
{
CollateClause *n = makeNode(CollateClause);
n->arg = NULL;
- n->collnames = $2;
- n->collOid = InvalidOid;
+ n->collname = $2;
n->location = @1;
$$ = (Node *) n;
}
*/
CollateClause *n = makeNode(CollateClause);
n->arg = NULL;
- n->collnames = $2;
- n->collOid = InvalidOid;
+ n->collname = $2;
n->location = @1;
$$ = (Node *) n;
}
| 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;
}
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;
}
{
Node *pexpr = (Node *) lfirst(lc);
Oid pcoll = exprCollation(pexpr);
- bool pexplicit = IsA(pexpr, CollateClause);
+ bool pexplicit = IsA(pexpr, CollateExpr);
if (pcoll && pexplicit)
{
{
Node *nexpr = (Node *) lfirst(lc2);
Oid ncoll = exprCollation(nexpr);
- bool nexplicit = IsA(nexpr, CollateClause);
+ bool nexplicit = IsA(nexpr, CollateExpr);
if (!ncoll || !nexplicit)
continue;
case T_CoerceViaIO:
case T_ArrayCoerceExpr:
case T_ConvertRowtypeExpr:
+ case T_CollateExpr:
case T_CaseTestExpr:
case T_ArrayExpr:
case T_CoerceToDomain:
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);
/*
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;
}
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);
{
/* 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))
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))
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,
}
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;
}
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;
* 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
*/
appendStringInfo(buf, "NULL");
if (showtype >= 0)
+ {
appendStringInfo(buf, "::%s",
format_type_with_typemod(constval->consttype,
constval->consttypmod));
+ get_const_collation(constval, context);
+ }
return;
}
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));
+ }
+ }
}
/*
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201103111
+#define CATALOG_VERSION_NO 201103112
#endif
T_CoerceViaIO,
T_ArrayCoerceExpr,
T_ConvertRowtypeExpr,
+ T_CollateExpr,
T_CaseExpr,
T_CaseWhen,
T_CaseTestExpr,
T_JoinExpr,
T_FromExpr,
T_IntoClause,
- T_CollateClause,
/*
* TAGS FOR EXPRESSION STATE NODES (execnodes.h)
T_A_ArrayExpr,
T_ResTarget,
T_TypeCast,
+ T_CollateClause,
T_SortBy,
T_WindowDef,
T_RangeSubselect,
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
*
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
*
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
*
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;
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