diff options
Diffstat (limited to 'src/backend/parser')
-rw-r--r-- | src/backend/parser/gram.y | 182 | ||||
-rw-r--r-- | src/backend/parser/parse_expr.c | 17 | ||||
-rw-r--r-- | src/backend/parser/parse_func.c | 4 | ||||
-rw-r--r-- | src/backend/parser/parse_relation.c | 3 | ||||
-rw-r--r-- | src/backend/parser/parse_type.c | 166 | ||||
-rw-r--r-- | src/backend/parser/parse_utilcmd.c | 46 |
6 files changed, 265 insertions, 153 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 5b96b5b0df5..373d2adc71c 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -132,6 +132,9 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, static List *mergeTableFuncParameters(List *func_args, List *columns); static TypeName *TableFuncTypeName(List *columns); static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner); +static void SplitColQualList(List *qualList, + List **constraintList, CollateClause **collClause, + core_yyscan_t yyscanner); %} @@ -221,7 +224,7 @@ static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_ %type <node> alter_column_default opclass_item opclass_drop alter_using %type <ival> add_drop opt_asc_desc opt_nulls_order -%type <node> alter_table_cmd alter_type_cmd +%type <node> alter_table_cmd alter_type_cmd opt_collate_clause %type <list> alter_table_cmds alter_type_cmds %type <dbehavior> opt_drop_behavior @@ -400,8 +403,7 @@ static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_ %type <list> copy_generic_opt_list copy_generic_opt_arg_list %type <list> copy_options -%type <typnam> Typename SimpleTypename SimpleTypenameWithoutCollation - ConstTypename +%type <typnam> Typename SimpleTypename ConstTypename GenericType Numeric opt_float Character ConstCharacter CharacterWithLength CharacterWithoutLength @@ -619,6 +621,7 @@ static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_ %left '^' /* Unary Operators */ %left AT ZONE /* sets precedence for AT TIME ZONE */ +%left COLLATE %right UMINUS %left '[' ']' %left '(' ')' @@ -1746,13 +1749,17 @@ alter_table_cmd: * ALTER TABLE <name> ALTER [COLUMN] <colname> [SET DATA] TYPE <typename> * [ USING <expression> ] */ - | ALTER opt_column ColId opt_set_data TYPE_P Typename alter_using + | ALTER opt_column ColId opt_set_data TYPE_P Typename opt_collate_clause alter_using { AlterTableCmd *n = makeNode(AlterTableCmd); + ColumnDef *def = makeNode(ColumnDef); n->subtype = AT_AlterColumnType; n->name = $3; - n->def = (Node *) $6; - n->transform = $7; + n->def = (Node *) def; + /* We only use these three fields of the ColumnDef node */ + def->typeName = $6; + def->collClause = (CollateClause *) $7; + def->raw_default = $8; $$ = (Node *)n; } /* ALTER TABLE <name> ADD CONSTRAINT ... */ @@ -1981,6 +1988,19 @@ opt_drop_behavior: | /* EMPTY */ { $$ = DROP_RESTRICT; /* default */ } ; +opt_collate_clause: + COLLATE any_name + { + CollateClause *n = makeNode(CollateClause); + n->arg = NULL; + n->collnames = $2; + n->collOid = InvalidOid; + n->location = @1; + $$ = (Node *) n; + } + | /* EMPTY */ { $$ = NULL; } + ; + alter_using: USING a_expr { $$ = $2; } | /* EMPTY */ { $$ = NULL; } @@ -2077,13 +2097,18 @@ alter_type_cmd: $$ = (Node *)n; } /* ALTER TYPE <name> ALTER ATTRIBUTE <attname> [SET DATA] TYPE <typename> [RESTRICT|CASCADE] */ - | ALTER ATTRIBUTE ColId opt_set_data TYPE_P Typename opt_drop_behavior + | ALTER ATTRIBUTE ColId opt_set_data TYPE_P Typename opt_collate_clause opt_drop_behavior { AlterTableCmd *n = makeNode(AlterTableCmd); + ColumnDef *def = makeNode(ColumnDef); n->subtype = AT_AlterColumnType; n->name = $3; - n->def = (Node *) $6; - n->behavior = $7; + n->def = (Node *) def; + n->behavior = $8; + /* We only use these three fields of the ColumnDef node */ + def->typeName = $6; + def->collClause = (CollateClause *) $7; + def->raw_default = NULL; $$ = (Node *)n; } ; @@ -2454,8 +2479,16 @@ columnDef: ColId Typename ColQualList ColumnDef *n = makeNode(ColumnDef); n->colname = $1; n->typeName = $2; - n->constraints = $3; + n->inhcount = 0; n->is_local = true; + n->is_not_null = false; + n->is_from_type = false; + n->storage = 0; + n->raw_default = NULL; + n->cooked_default = NULL; + n->collOid = InvalidOid; + SplitColQualList($3, &n->constraints, &n->collClause, + yyscanner); $$ = (Node *)n; } ; @@ -2464,8 +2497,17 @@ columnOptions: ColId WITH OPTIONS ColQualList { ColumnDef *n = makeNode(ColumnDef); n->colname = $1; - n->constraints = $4; + n->typeName = NULL; + n->inhcount = 0; n->is_local = true; + n->is_not_null = false; + n->is_from_type = false; + n->storage = 0; + n->raw_default = NULL; + n->cooked_default = NULL; + n->collOid = InvalidOid; + SplitColQualList($4, &n->constraints, &n->collClause, + yyscanner); $$ = (Node *)n; } ; @@ -2486,6 +2528,20 @@ ColConstraint: } | ColConstraintElem { $$ = $1; } | ConstraintAttr { $$ = $1; } + | COLLATE any_name + { + /* + * Note: the CollateClause is momentarily included in + * the list built by ColQualList, but we split it out + * again in SplitColQualList. + */ + CollateClause *n = makeNode(CollateClause); + n->arg = NULL; + n->collnames = $2; + n->collOid = InvalidOid; + n->location = @1; + $$ = (Node *) n; + } ; /* DEFAULT NULL is already the default for Postgres. @@ -2973,8 +3029,12 @@ CreateAsElement: n->inhcount = 0; n->is_local = true; n->is_not_null = false; + n->is_from_type = false; + n->storage = 0; n->raw_default = NULL; n->cooked_default = NULL; + n->collClause = NULL; + n->collOid = InvalidOid; n->constraints = NIL; $$ = (Node *)n; } @@ -6577,7 +6637,7 @@ opt_column: COLUMN { $$ = COLUMN; } | /*EMPTY*/ { $$ = 0; } ; -opt_set_data: SET DATA_P { $$ = 1; } +opt_set_data: SET DATA_P { $$ = 1; } | /*EMPTY*/ { $$ = 0; } ; @@ -7443,7 +7503,8 @@ CreateDomainStmt: CreateDomainStmt *n = makeNode(CreateDomainStmt); n->domainname = $3; n->typeName = $5; - n->constraints = $6; + SplitColQualList($6, &n->constraints, &n->collClause, + yyscanner); $$ = (Node *)n; } ; @@ -9084,13 +9145,21 @@ TableFuncElementList: } ; -TableFuncElement: ColId Typename +TableFuncElement: ColId Typename opt_collate_clause { ColumnDef *n = makeNode(ColumnDef); n->colname = $1; n->typeName = $2; - n->constraints = NIL; + n->inhcount = 0; n->is_local = true; + n->is_not_null = false; + n->is_from_type = false; + n->storage = 0; + n->raw_default = NULL; + n->cooked_default = NULL; + n->collClause = (CollateClause *) $3; + n->collOid = InvalidOid; + n->constraints = NIL; $$ = (Node *)n; } ; @@ -9151,13 +9220,6 @@ opt_array_bounds: ; SimpleTypename: - SimpleTypenameWithoutCollation opt_collate - { - $$ = $1; - $$->collnames = $2; - } - -SimpleTypenameWithoutCollation: GenericType { $$ = $1; } | Numeric { $$ = $1; } | Bit { $$ = $1; } @@ -9625,6 +9687,14 @@ interval_second: a_expr: c_expr { $$ = $1; } | a_expr TYPECAST Typename { $$ = makeTypeCast($1, $3, @2); } + | a_expr COLLATE any_name + { + CollateClause *n = makeNode(CollateClause); + n->arg = (Expr *) $1; + n->collnames = $3; + n->location = @2; + $$ = (Node *) n; + } | a_expr AT TIME ZONE a_expr { FuncCall *n = makeNode(FuncCall); @@ -10193,14 +10263,6 @@ c_expr: columnref { $$ = $1; } r->location = @1; $$ = (Node *)r; } - | c_expr COLLATE any_name - { - CollateClause *n = makeNode(CollateClause); - n->arg = (Expr *) $1; - n->collnames = $3; - n->location = @2; - $$ = (Node *)n; - } ; /* @@ -12678,15 +12740,6 @@ makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, return (Node *) x; } -/* parser_init() - * Initialize to parse one query string - */ -void -parser_init(base_yy_extra_type *yyext) -{ - yyext->parsetree = NIL; /* in case grammar forgets to set it */ -} - /* * Merge the input and output parameters of a table function. */ @@ -12774,6 +12827,57 @@ makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner) return r; } +/* Separate Constraint nodes from COLLATE clauses in a ColQualList */ +static void +SplitColQualList(List *qualList, + List **constraintList, CollateClause **collClause, + core_yyscan_t yyscanner) +{ + ListCell *cell; + ListCell *prev; + ListCell *next; + + *collClause = NULL; + prev = NULL; + for (cell = list_head(qualList); cell; cell = next) + { + Node *n = (Node *) lfirst(cell); + + next = lnext(cell); + if (IsA(n, Constraint)) + { + /* keep it in list */ + prev = cell; + continue; + } + if (IsA(n, CollateClause)) + { + CollateClause *c = (CollateClause *) n; + + if (*collClause) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("multiple COLLATE clauses not allowed"), + parser_errposition(c->location))); + *collClause = c; + } + else + elog(ERROR, "unexpected node type %d", (int) n->type); + /* remove non-Constraint nodes from qualList */ + qualList = list_delete_cell(qualList, cell, prev); + } + *constraintList = qualList; +} + +/* parser_init() + * Initialize to parse one query string + */ +void +parser_init(base_yy_extra_type *yyext) +{ + yyext->parsetree = NIL; /* in case grammar forgets to set it */ +} + /* * Must undefine this stuff before including scan.c, since it has different * definitions for these macros. diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index ae565325928..7a4f8cc2497 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -147,12 +147,6 @@ 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 @@ -2116,13 +2110,16 @@ transformCollateClause(ParseState *pstate, CollateClause *c) 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. */ + /* + * 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), + (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("collations are not supported by type %s", - format_type_be(argtype)))); + format_type_be(argtype)), + parser_errposition(pstate, c->location))); newc->collOid = LookupCollation(pstate, c->collnames, c->location); newc->collnames = c->collnames; diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 0af9cbd92b3..a2d6c598104 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -1313,7 +1313,7 @@ FuncNameAsType(List *funcname) Oid result; Type typtup; - typtup = LookupTypeName(NULL, makeTypeNameFromNameList(funcname), NULL, NULL); + typtup = LookupTypeName(NULL, makeTypeNameFromNameList(funcname), NULL); if (typtup == NULL) return InvalidOid; @@ -1500,7 +1500,7 @@ LookupTypeNameOid(const TypeName *typename) Oid result; Type typtup; - typtup = LookupTypeName(NULL, typename, NULL, NULL); + typtup = LookupTypeName(NULL, typename, NULL); if (typtup == NULL) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index c7000b99153..488b1425a35 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -1169,7 +1169,8 @@ addRangeTableEntryForFunction(ParseState *pstate, errmsg("column \"%s\" cannot be declared SETOF", attrname), parser_errposition(pstate, n->typeName->location))); - typenameTypeIdModColl(pstate, n->typeName, &attrtype, &attrtypmod, &attrcollation); + typenameTypeIdAndMod(pstate, n->typeName, &attrtype, &attrtypmod); + attrcollation = GetColumnDefCollation(pstate, n, attrtype); eref->colnames = lappend(eref->colnames, makeString(attrname)); rte->funccoltypes = lappend_oid(rte->funccoltypes, attrtype); rte->funccoltypmods = lappend_int(rte->funccoltypmods, attrtypmod); diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c index 20cb47e712f..2ba9bf51816 100644 --- a/src/backend/parser/parse_type.c +++ b/src/backend/parser/parse_type.c @@ -29,8 +29,6 @@ static int32 typenameTypeMod(ParseState *pstate, const TypeName *typeName, Type typ); -static Oid typenameCollation(ParseState *pstate, const TypeName *typeName, - Type typ); /* @@ -38,8 +36,7 @@ static Oid typenameCollation(ParseState *pstate, const TypeName *typeName, * Given a TypeName object, lookup the pg_type syscache entry of the type. * Returns NULL if no such type can be found. If the type is found, * the typmod value represented in the TypeName struct is computed and - * stored into *typmod_p, and the collation is looked up and stored into - * *colloid_p. + * stored into *typmod_p. * * NB: on success, the caller must ReleaseSysCache the type tuple when done * with it. @@ -54,18 +51,15 @@ static Oid typenameCollation(ParseState *pstate, const TypeName *typeName, * found but is a shell, and there is typmod decoration, an error will be * thrown --- this is intentional. * - * colloid_p can also be null. - * * pstate is only used for error location info, and may be NULL. */ Type LookupTypeName(ParseState *pstate, const TypeName *typeName, - int32 *typmod_p, Oid *collid_p) + int32 *typmod_p) { Oid typoid; HeapTuple tup; int32 typmod; - Oid collid; if (typeName->names == NIL) { @@ -180,28 +174,22 @@ LookupTypeName(ParseState *pstate, const TypeName *typeName, if (typmod_p) *typmod_p = typmod; - collid = typenameCollation(pstate, typeName, (Type) tup); - - if (collid_p) - *collid_p = collid; - return (Type) tup; } /* - * typenameType - given a TypeName, return a Type structure, typmod, and - * collation + * typenameType - given a TypeName, return a Type structure and typmod * * This is equivalent to LookupTypeName, except that this will report * a suitable error message if the type cannot be found or is not defined. * Callers of this can therefore assume the result is a fully valid type. */ Type -typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p, Oid *collid_p) +typenameType(ParseState *pstate, const TypeName *typeName, int32 *typmod_p) { Type tup; - tup = LookupTypeName(pstate, typeName, typmod_p, collid_p); + tup = LookupTypeName(pstate, typeName, typmod_p); if (tup == NULL) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), @@ -229,7 +217,7 @@ typenameTypeId(ParseState *pstate, const TypeName *typeName) Oid typoid; Type tup; - tup = typenameType(pstate, typeName, NULL, NULL); + tup = typenameType(pstate, typeName, NULL); typoid = HeapTupleGetOid(tup); ReleaseSysCache(tup); @@ -248,25 +236,7 @@ typenameTypeIdAndMod(ParseState *pstate, const TypeName *typeName, { Type tup; - tup = typenameType(pstate, typeName, typmod_p, NULL); - *typeid_p = HeapTupleGetOid(tup); - ReleaseSysCache(tup); -} - -/* - * typenameTypeIdModColl - given a TypeName, return the type's OID, - * typmod, and collation - * - * This is equivalent to typenameType, but we only hand back the type OID, - * typmod, and collation, not the syscache entry. - */ -void -typenameTypeIdModColl(ParseState *pstate, const TypeName *typeName, - Oid *typeid_p, int32 *typmod_p, Oid *collid_p) -{ - Type tup; - - tup = typenameType(pstate, typeName, typmod_p, collid_p); + tup = typenameType(pstate, typeName, typmod_p); *typeid_p = HeapTupleGetOid(tup); ReleaseSysCache(tup); } @@ -381,62 +351,6 @@ typenameTypeMod(ParseState *pstate, const TypeName *typeName, Type typ) } /* - * typenameCollation - given a TypeName, return the collation OID - * - * This will throw an error if the TypeName includes a collation but - * the data type does not support collations. - * - * The actual type OID represented by the TypeName must already have been - * looked up, and is passed as "typ". - * - * pstate is only used for error location info, and may be NULL. - */ -static Oid -typenameCollation(ParseState *pstate, const TypeName *typeName, Type typ) -{ - Oid typcollation = ((Form_pg_type) GETSTRUCT(typ))->typcollation; - - /* return prespecified collation OID if no collation name specified */ - if (typeName->collnames == NIL) - { - if (typeName->collOid == InvalidOid) - return typcollation; - else - return typeName->collOid; - } - - if (!OidIsValid(typcollation)) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("collations are not supported by type %s", - format_type_be(HeapTupleGetOid(typ))), - parser_errposition(pstate, typeName->location))); - - return LookupCollation(pstate, typeName->collnames, typeName->location); -} - -/* - * LookupCollation - * - * Look up collation by name, return OID, with support for error - * location. - */ -Oid -LookupCollation(ParseState *pstate, List *collnames, int location) -{ - Oid colloid; - ParseCallbackState pcbstate; - - setup_parser_errposition_callback(&pcbstate, pstate, location); - - colloid = get_collation_oid(collnames, false); - - cancel_parser_errposition_callback(&pcbstate); - - return colloid; -} - -/* * appendTypeNameToBuffer * Append a string representing the name of a TypeName to a StringInfo. * This is the shared guts of TypeNameToString and TypeNameListToString. @@ -516,6 +430,72 @@ TypeNameListToString(List *typenames) return string.data; } +/* + * LookupCollation + * + * Look up collation by name, return OID, with support for error location. + */ +Oid +LookupCollation(ParseState *pstate, List *collnames, int location) +{ + Oid colloid; + ParseCallbackState pcbstate; + + if (pstate) + setup_parser_errposition_callback(&pcbstate, pstate, location); + + colloid = get_collation_oid(collnames, false); + + if (pstate) + cancel_parser_errposition_callback(&pcbstate); + + return colloid; +} + +/* + * GetColumnDefCollation + * + * Get the collation to be used for a column being defined, given the + * ColumnDef node and the previously-determined column type OID. + * + * pstate is only used for error location purposes, and can be NULL. + */ +Oid +GetColumnDefCollation(ParseState *pstate, ColumnDef *coldef, Oid typeOid) +{ + Oid result; + Oid typcollation = get_typcollation(typeOid); + int location = -1; + + if (coldef->collClause) + { + /* We have a raw COLLATE clause, so look up the collation */ + location = coldef->collClause->location; + result = LookupCollation(pstate, coldef->collClause->collnames, + location); + } + else if (OidIsValid(coldef->collOid)) + { + /* Precooked collation spec, use that */ + result = coldef->collOid; + } + else + { + /* Use the type's default collation if any */ + result = typcollation; + } + + /* Complain if COLLATE is applied to an uncollatable type */ + if (OidIsValid(result) && !OidIsValid(typcollation)) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("collations are not supported by type %s", + format_type_be(typeOid)), + parser_errposition(pstate, location))); + + return result; +} + /* return a Type structure, given a type id */ /* NB: caller must ReleaseSysCache the type tuple when done with it */ Type diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index 61ce840a5e5..e876853af02 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -627,13 +627,16 @@ transformInhRelation(CreateStmtContext *cxt, InhRelation *inhRelation) def = makeNode(ColumnDef); def->colname = pstrdup(attributeName); def->typeName = makeTypeNameFromOid(attribute->atttypid, - attribute->atttypmod, - attribute->attcollation); + attribute->atttypmod); def->inhcount = 0; def->is_local = true; def->is_not_null = attribute->attnotnull; + def->is_from_type = false; + def->storage = 0; def->raw_default = NULL; def->cooked_default = NULL; + def->collClause = NULL; + def->collOid = attribute->attcollation; def->constraints = NIL; /* @@ -822,7 +825,7 @@ transformOfType(CreateStmtContext *cxt, TypeName *ofTypename) AssertArg(ofTypename); - tuple = typenameType(NULL, ofTypename, NULL, NULL); + tuple = typenameType(NULL, ofTypename, NULL); typ = (Form_pg_type) GETSTRUCT(tuple); ofTypeId = HeapTupleGetOid(tuple); ofTypename->typeOid = ofTypeId; /* cached for later */ @@ -837,16 +840,24 @@ transformOfType(CreateStmtContext *cxt, TypeName *ofTypename) for (i = 0; i < tupdesc->natts; i++) { Form_pg_attribute attr = tupdesc->attrs[i]; - ColumnDef *n = makeNode(ColumnDef); + ColumnDef *n; if (attr->attisdropped) continue; + n = makeNode(ColumnDef); n->colname = pstrdup(NameStr(attr->attname)); - n->typeName = makeTypeNameFromOid(attr->atttypid, attr->atttypmod, attr->attcollation); - n->constraints = NULL; + n->typeName = makeTypeNameFromOid(attr->atttypid, attr->atttypmod); + n->inhcount = 0; n->is_local = true; + n->is_not_null = false; n->is_from_type = true; + n->storage = 0; + n->raw_default = NULL; + n->cooked_default = NULL; + n->collClause = NULL; + n->collOid = attr->attcollation; + n->constraints = NIL; cxt->columns = lappend(cxt->columns, n); } DecrTupleDescRefCount(tupdesc); @@ -2445,9 +2456,28 @@ static void transformColumnType(CreateStmtContext *cxt, ColumnDef *column) { /* - * All we really need to do here is verify that the type is valid. + * All we really need to do here is verify that the type is valid, + * including any collation spec that might be present. */ - Type ctype = typenameType(cxt->pstate, column->typeName, NULL, NULL); + Type ctype = typenameType(cxt->pstate, column->typeName, NULL); + + if (column->collClause) + { + Form_pg_type typtup = (Form_pg_type) GETSTRUCT(ctype); + Oid collOid; + + collOid = LookupCollation(cxt->pstate, + column->collClause->collnames, + column->collClause->location); + /* Complain if COLLATE is applied to an uncollatable type */ + if (!OidIsValid(typtup->typcollation)) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("collations are not supported by type %s", + format_type_be(HeapTupleGetOid(ctype))), + parser_errposition(cxt->pstate, + column->collClause->location))); + } ReleaseSysCache(ctype); } |