diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/collationcmds.c | 2 | ||||
-rw-r--r-- | src/backend/commands/functioncmds.c | 4 | ||||
-rw-r--r-- | src/backend/commands/sequence.c | 23 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 65 | ||||
-rw-r--r-- | src/backend/commands/typecmds.c | 27 | ||||
-rw-r--r-- | src/backend/commands/view.c | 13 |
6 files changed, 88 insertions, 46 deletions
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c index 18e88d2653f..a52cb351ac8 100644 --- a/src/backend/commands/collationcmds.c +++ b/src/backend/commands/collationcmds.c @@ -98,7 +98,7 @@ DefineCollation(List *names, List *parameters) Oid collid; HeapTuple tp; - collid = LookupCollation(NULL, defGetQualifiedName(fromEl), -1); + collid = get_collation_oid(defGetQualifiedName(fromEl), false); tp = SearchSysCache1(COLLOID, ObjectIdGetDatum(collid)); if (!HeapTupleIsValid(tp)) elog(ERROR, "cache lookup failed for collation %u", collid); diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 3f25b3bf02a..a8ef947240e 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -87,7 +87,7 @@ compute_return_type(TypeName *returnType, Oid languageOid, Oid rettype; Type typtup; - typtup = LookupTypeName(NULL, returnType, NULL, NULL); + typtup = LookupTypeName(NULL, returnType, NULL); if (typtup) { @@ -207,7 +207,7 @@ examine_parameter_list(List *parameters, Oid languageOid, Oid toid; Type typtup; - typtup = LookupTypeName(NULL, t, NULL, NULL); + typtup = LookupTypeName(NULL, t, NULL); if (typtup) { if (!((Form_pg_type) GETSTRUCT(typtup))->typisdefined) diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index e71c311faf7..5c6212c64cd 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -139,9 +139,12 @@ DefineSequence(CreateSeqStmt *seq) coldef->inhcount = 0; coldef->is_local = true; coldef->is_not_null = true; + coldef->is_from_type = false; coldef->storage = 0; coldef->raw_default = NULL; coldef->cooked_default = NULL; + coldef->collClause = NULL; + coldef->collOid = InvalidOid; coldef->constraints = NIL; null[i - 1] = false; @@ -149,53 +152,53 @@ DefineSequence(CreateSeqStmt *seq) switch (i) { case SEQ_COL_NAME: - coldef->typeName = makeTypeNameFromOid(NAMEOID, -1, InvalidOid); + coldef->typeName = makeTypeNameFromOid(NAMEOID, -1); coldef->colname = "sequence_name"; namestrcpy(&name, seq->sequence->relname); value[i - 1] = NameGetDatum(&name); break; case SEQ_COL_LASTVAL: - coldef->typeName = makeTypeNameFromOid(INT8OID, -1, InvalidOid); + coldef->typeName = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "last_value"; value[i - 1] = Int64GetDatumFast(new.last_value); break; case SEQ_COL_STARTVAL: - coldef->typeName = makeTypeNameFromOid(INT8OID, -1, InvalidOid); + coldef->typeName = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "start_value"; value[i - 1] = Int64GetDatumFast(new.start_value); break; case SEQ_COL_INCBY: - coldef->typeName = makeTypeNameFromOid(INT8OID, -1, InvalidOid); + coldef->typeName = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "increment_by"; value[i - 1] = Int64GetDatumFast(new.increment_by); break; case SEQ_COL_MAXVALUE: - coldef->typeName = makeTypeNameFromOid(INT8OID, -1, InvalidOid); + coldef->typeName = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "max_value"; value[i - 1] = Int64GetDatumFast(new.max_value); break; case SEQ_COL_MINVALUE: - coldef->typeName = makeTypeNameFromOid(INT8OID, -1, InvalidOid); + coldef->typeName = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "min_value"; value[i - 1] = Int64GetDatumFast(new.min_value); break; case SEQ_COL_CACHE: - coldef->typeName = makeTypeNameFromOid(INT8OID, -1, InvalidOid); + coldef->typeName = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "cache_value"; value[i - 1] = Int64GetDatumFast(new.cache_value); break; case SEQ_COL_LOG: - coldef->typeName = makeTypeNameFromOid(INT8OID, -1, InvalidOid); + coldef->typeName = makeTypeNameFromOid(INT8OID, -1); coldef->colname = "log_cnt"; value[i - 1] = Int64GetDatum((int64) 1); break; case SEQ_COL_CYCLE: - coldef->typeName = makeTypeNameFromOid(BOOLOID, -1, InvalidOid); + coldef->typeName = makeTypeNameFromOid(BOOLOID, -1); coldef->colname = "is_cycled"; value[i - 1] = BoolGetDatum(new.is_cycled); break; case SEQ_COL_CALLED: - coldef->typeName = makeTypeNameFromOid(BOOLOID, -1, InvalidOid); + coldef->typeName = makeTypeNameFromOid(BOOLOID, -1); coldef->colname = "is_called"; value[i - 1] = BoolGetDatum(false); break; diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 3be9a6f3481..f1264bfb66d 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -339,7 +339,7 @@ static void ATPrepAlterColumnType(List **wqueue, AlterTableCmd *cmd, LOCKMODE lockmode); static bool ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno); static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, - const char *colName, TypeName *typeName, LOCKMODE lockmode); + AlterTableCmd *cmd, LOCKMODE lockmode); static void ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode); static void ATPostAlterTypeParse(char *cmd, List **wqueue, LOCKMODE lockmode); static void change_owner_recurse_to_sequences(Oid relationOid, @@ -1433,7 +1433,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence, (errmsg("merging multiple inherited definitions of column \"%s\"", attributeName))); def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1); - typenameTypeIdModColl(NULL, def->typeName, &defTypeId, &deftypmod, &defCollId); + typenameTypeIdAndMod(NULL, def->typeName, &defTypeId, &deftypmod); if (defTypeId != attribute->atttypid || deftypmod != attribute->atttypmod) ereport(ERROR, @@ -1443,6 +1443,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence, errdetail("%s versus %s", TypeNameToString(def->typeName), format_type_be(attribute->atttypid)))); + defCollId = GetColumnDefCollation(NULL, def, defTypeId); if (defCollId != attribute->attcollation) ereport(ERROR, (errcode(ERRCODE_COLLATION_MISMATCH), @@ -1478,14 +1479,16 @@ MergeAttributes(List *schema, List *supers, char relpersistence, def = makeNode(ColumnDef); def->colname = pstrdup(attributeName); def->typeName = makeTypeNameFromOid(attribute->atttypid, - attribute->atttypmod, - attribute->attcollation); + attribute->atttypmod); def->inhcount = 1; def->is_local = false; def->is_not_null = attribute->attnotnull; + def->is_from_type = false; def->storage = attribute->attstorage; def->raw_default = NULL; def->cooked_default = NULL; + def->collClause = NULL; + def->collOid = attribute->attcollation; def->constraints = NIL; inhSchema = lappend(inhSchema, def); newattno[parent_attno - 1] = ++child_attno; @@ -1616,8 +1619,8 @@ MergeAttributes(List *schema, List *supers, char relpersistence, (errmsg("merging column \"%s\" with inherited definition", attributeName))); def = (ColumnDef *) list_nth(inhSchema, exist_attno - 1); - typenameTypeIdModColl(NULL, def->typeName, &defTypeId, &deftypmod, &defcollid); - typenameTypeIdModColl(NULL, newdef->typeName, &newTypeId, &newtypmod, &newcollid); + typenameTypeIdAndMod(NULL, def->typeName, &defTypeId, &deftypmod); + typenameTypeIdAndMod(NULL, newdef->typeName, &newTypeId, &newtypmod); if (defTypeId != newTypeId || deftypmod != newtypmod) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), @@ -1626,6 +1629,8 @@ MergeAttributes(List *schema, List *supers, char relpersistence, errdetail("%s versus %s", TypeNameToString(def->typeName), TypeNameToString(newdef->typeName)))); + defcollid = GetColumnDefCollation(NULL, def, defTypeId); + newcollid = GetColumnDefCollation(NULL, newdef, newTypeId); if (defcollid != newcollid) ereport(ERROR, (errcode(ERRCODE_COLLATION_MISMATCH), @@ -3092,7 +3097,7 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, cmd->missing_ok, lockmode); break; case AT_AlterColumnType: /* ALTER COLUMN TYPE */ - ATExecAlterColumnType(tab, rel, cmd->name, (TypeName *) cmd->def, lockmode); + ATExecAlterColumnType(tab, rel, cmd, lockmode); break; case AT_ChangeOwner: /* ALTER OWNER */ ATExecChangeOwner(RelationGetRelid(rel), @@ -4129,13 +4134,14 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel, Oid ccollid; /* Child column must match by type */ - typenameTypeIdModColl(NULL, colDef->typeName, &ctypeId, &ctypmod, &ccollid); + typenameTypeIdAndMod(NULL, colDef->typeName, &ctypeId, &ctypmod); if (ctypeId != childatt->atttypid || ctypmod != childatt->atttypmod) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("child table \"%s\" has different type for column \"%s\"", RelationGetRelationName(rel), colDef->colname))); + ccollid = GetColumnDefCollation(NULL, colDef, ctypeId); if (ccollid != childatt->attcollation) ereport(ERROR, (errcode(ERRCODE_COLLATION_MISMATCH), @@ -4201,9 +4207,10 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel, MaxHeapAttributeNumber))); } - typeTuple = typenameType(NULL, colDef->typeName, &typmod, &collOid); + typeTuple = typenameType(NULL, colDef->typeName, &typmod); tform = (Form_pg_type) GETSTRUCT(typeTuple); typeOid = HeapTupleGetOid(typeTuple); + collOid = GetColumnDefCollation(NULL, colDef, typeOid); /* make sure datatype is legal for a column */ CheckAttributeType(colDef->colname, typeOid, collOid, false); @@ -4413,7 +4420,7 @@ ATPrepAddOids(List **wqueue, Relation rel, bool recurse, AlterTableCmd *cmd, LOC ColumnDef *cdef = makeNode(ColumnDef); cdef->colname = pstrdup("oid"); - cdef->typeName = makeTypeNameFromOid(OIDOID, -1, InvalidOid); + cdef->typeName = makeTypeNameFromOid(OIDOID, -1); cdef->inhcount = 0; cdef->is_local = true; cdef->is_not_null = true; @@ -6471,14 +6478,15 @@ ATPrepAlterColumnType(List **wqueue, AlterTableCmd *cmd, LOCKMODE lockmode) { char *colName = cmd->name; - TypeName *typeName = (TypeName *) cmd->def; + ColumnDef *def = (ColumnDef *) cmd->def; + TypeName *typeName = def->typeName; + Node *transform = def->raw_default; HeapTuple tuple; Form_pg_attribute attTup; AttrNumber attnum; Oid targettype; int32 targettypmod; Oid targetcollid; - Node *transform; NewColumnValue *newval; ParseState *pstate = make_parsestate(NULL); @@ -6512,7 +6520,10 @@ ATPrepAlterColumnType(List **wqueue, colName))); /* Look up the target type */ - typenameTypeIdModColl(NULL, typeName, &targettype, &targettypmod, &targetcollid); + typenameTypeIdAndMod(NULL, typeName, &targettype, &targettypmod); + + /* And the collation */ + targetcollid = GetColumnDefCollation(NULL, def, targettype); /* make sure datatype is legal for a column */ CheckAttributeType(colName, targettype, targetcollid, false); @@ -6527,7 +6538,7 @@ ATPrepAlterColumnType(List **wqueue, * because we need the expression to be parsed against the original table * rowtype. */ - if (cmd->transform) + if (transform) { RangeTblEntry *rte; @@ -6539,7 +6550,7 @@ ATPrepAlterColumnType(List **wqueue, true); addRTEtoQuery(pstate, rte, false, true, true); - transform = transformExpr(pstate, cmd->transform); + transform = transformExpr(pstate, transform); /* It can't return a set */ if (expression_returns_set(transform)) @@ -6592,16 +6603,13 @@ ATPrepAlterColumnType(List **wqueue, if (ATColumnChangeRequiresRewrite(transform, attnum)) tab->rewrite = true; } - else if (tab->relkind == RELKIND_FOREIGN_TABLE) - { - if (cmd->transform) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("ALTER TYPE USING is not supported on foreign tables"))); - } + else if (transform) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("ALTER TYPE USING is only supported on plain tables"))); - if (tab->relkind == RELKIND_COMPOSITE_TYPE - || tab->relkind == RELKIND_FOREIGN_TABLE) + if (tab->relkind == RELKIND_COMPOSITE_TYPE || + tab->relkind == RELKIND_FOREIGN_TABLE) { /* * For composite types, do this check now. Tables will check @@ -6667,8 +6675,11 @@ ATColumnChangeRequiresRewrite(Node *expr, AttrNumber varattno) static void ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, - const char *colName, TypeName *typeName, LOCKMODE lockmode) + AlterTableCmd *cmd, LOCKMODE lockmode) { + char *colName = cmd->name; + ColumnDef *def = (ColumnDef *) cmd->def; + TypeName *typeName = def->typeName; HeapTuple heapTup; Form_pg_attribute attTup; AttrNumber attnum; @@ -6705,9 +6716,11 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel, colName))); /* Look up the target type (should not fail, since prep found it) */ - typeTuple = typenameType(NULL, typeName, &targettypmod, &targetcollid); + typeTuple = typenameType(NULL, typeName, &targettypmod); tform = (Form_pg_type) GETSTRUCT(typeTuple); targettype = HeapTupleGetOid(typeTuple); + /* And the collation */ + targetcollid = GetColumnDefCollation(NULL, def, targettype); /* * If there is a default expression for the column, get it and ensure we diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index be1f1d791fd..3513256b9a5 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -292,7 +292,7 @@ DefineType(List *names, List *parameters) Type likeType; Form_pg_type likeForm; - likeType = typenameType(NULL, defGetTypeName(likeTypeEl), NULL, NULL); + likeType = typenameType(NULL, defGetTypeName(likeTypeEl), NULL); likeForm = (Form_pg_type) GETSTRUCT(likeType); internalLength = likeForm->typlen; byValue = likeForm->typbyval; @@ -649,7 +649,7 @@ RemoveTypes(DropStmt *drop) typename = makeTypeNameFromNameList(names); /* Use LookupTypeName here so that shell types can be removed. */ - tup = LookupTypeName(NULL, typename, NULL, NULL); + tup = LookupTypeName(NULL, typename, NULL); if (tup == NULL) { if (!drop->missing_ok) @@ -774,6 +774,7 @@ DefineDomain(CreateDomainStmt *stmt) Oid basetypeoid; Oid domainoid; Oid old_type_oid; + Oid domaincoll; Form_pg_type baseType; int32 basetypeMod; Oid baseColl; @@ -807,7 +808,7 @@ DefineDomain(CreateDomainStmt *stmt) /* * Look up the base type. */ - typeTup = typenameType(NULL, stmt->typeName, &basetypeMod, &baseColl); + typeTup = typenameType(NULL, stmt->typeName, &basetypeMod); baseType = (Form_pg_type) GETSTRUCT(typeTup); basetypeoid = HeapTupleGetOid(typeTup); @@ -825,6 +826,22 @@ DefineDomain(CreateDomainStmt *stmt) errmsg("\"%s\" is not a valid base type for a domain", TypeNameToString(stmt->typeName)))); + /* + * Identify the collation if any + */ + baseColl = baseType->typcollation; + if (stmt->collClause) + domaincoll = get_collation_oid(stmt->collClause->collnames, false); + else + domaincoll = baseColl; + + /* Complain if COLLATE is applied to an uncollatable type */ + if (OidIsValid(domaincoll) && !OidIsValid(baseColl)) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("collations are not supported by type %s", + format_type_be(basetypeoid)))); + /* passed by value */ byValue = baseType->typbyval; @@ -1051,7 +1068,7 @@ DefineDomain(CreateDomainStmt *stmt) basetypeMod, /* typeMod value */ typNDims, /* Array dimensions for base type */ typNotNull, /* Type NOT NULL */ - baseColl); + domaincoll); /* * Process constraints which refer to the domain ID returned by TypeCreate @@ -2629,7 +2646,7 @@ AlterTypeOwner(List *names, Oid newOwnerId) typename = makeTypeNameFromNameList(names); /* Use LookupTypeName here so that shell types can be processed */ - tup = LookupTypeName(NULL, typename, NULL, NULL); + tup = LookupTypeName(NULL, typename, NULL); if (tup == NULL) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index 5576ea259f4..794a56e84de 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -120,14 +120,23 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace) def->colname = pstrdup(tle->resname); def->typeName = makeTypeNameFromOid(exprType((Node *) tle->expr), - exprTypmod((Node *) tle->expr), - exprCollation((Node *) tle->expr)); + exprTypmod((Node *) tle->expr)); def->inhcount = 0; def->is_local = true; def->is_not_null = false; + def->is_from_type = false; def->storage = 0; def->raw_default = NULL; def->cooked_default = NULL; + def->collClause = NULL; + /* + * XXX Temporary kluge to make regression tests pass. We should + * be able to trust the result of exprCollation more than this. + */ + if (type_is_collatable(exprType((Node *) tle->expr))) + def->collOid = exprCollation((Node *) tle->expr); + else + def->collOid = InvalidOid; def->constraints = NIL; attrList = lappend(attrList, def); |