diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/bootstrap/bootparse.y | 3 | ||||
-rw-r--r-- | src/backend/catalog/heap.c | 19 | ||||
-rw-r--r-- | src/backend/catalog/information_schema.sql | 16 | ||||
-rw-r--r-- | src/backend/catalog/toasting.c | 3 | ||||
-rw-r--r-- | src/backend/commands/cluster.c | 3 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 65 | ||||
-rw-r--r-- | src/backend/executor/execMain.c | 3 | ||||
-rw-r--r-- | src/backend/nodes/copyfuncs.c | 3 | ||||
-rw-r--r-- | src/backend/nodes/equalfuncs.c | 3 | ||||
-rw-r--r-- | src/backend/nodes/outfuncs.c | 3 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 56 | ||||
-rw-r--r-- | src/backend/parser/parse_utilcmd.c | 58 |
12 files changed, 194 insertions, 41 deletions
diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y index f2155c1b64a..a6c1243b958 100644 --- a/src/backend/bootstrap/bootparse.y +++ b/src/backend/bootstrap/bootparse.y @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.103 2010/01/02 16:57:36 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.104 2010/01/28 23:21:11 petere Exp $ * *------------------------------------------------------------------------- */ @@ -217,6 +217,7 @@ Boot_CreateStmt: $5 ? GLOBALTABLESPACE_OID : 0, $3, $7, + InvalidOid, BOOTSTRAP_SUPERUSERID, tupdesc, NIL, diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 920e00f1012..f86747e149e 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.367 2010/01/22 16:40:18 rhaas Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.368 2010/01/28 23:21:11 petere Exp $ * * * INTERFACE ROUTINES @@ -72,7 +72,9 @@ static void AddNewRelationTuple(Relation pg_class_desc, Relation new_rel_desc, - Oid new_rel_oid, Oid new_type_oid, + Oid new_rel_oid, + Oid new_type_oid, + Oid reloftype, Oid relowner, char relkind, Datum relacl, @@ -669,6 +671,7 @@ InsertPgClassTuple(Relation pg_class_desc, values[Anum_pg_class_relname - 1] = NameGetDatum(&rd_rel->relname); values[Anum_pg_class_relnamespace - 1] = ObjectIdGetDatum(rd_rel->relnamespace); values[Anum_pg_class_reltype - 1] = ObjectIdGetDatum(rd_rel->reltype); + values[Anum_pg_class_reloftype - 1] = ObjectIdGetDatum(rd_rel->reloftype); values[Anum_pg_class_relowner - 1] = ObjectIdGetDatum(rd_rel->relowner); values[Anum_pg_class_relam - 1] = ObjectIdGetDatum(rd_rel->relam); values[Anum_pg_class_relfilenode - 1] = ObjectIdGetDatum(rd_rel->relfilenode); @@ -727,6 +730,7 @@ AddNewRelationTuple(Relation pg_class_desc, Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid, + Oid reloftype, Oid relowner, char relkind, Datum relacl, @@ -785,6 +789,7 @@ AddNewRelationTuple(Relation pg_class_desc, new_rel_reltup->relowner = relowner; new_rel_reltup->reltype = new_type_oid; + new_rel_reltup->reloftype = reloftype; new_rel_reltup->relkind = relkind; new_rel_desc->rd_att->tdtypeid = new_type_oid; @@ -876,6 +881,7 @@ heap_create_with_catalog(const char *relname, Oid reltablespace, Oid relid, Oid reltypeid, + Oid reloftypeid, Oid ownerid, TupleDesc tupdesc, List *cooked_constraints, @@ -1097,6 +1103,7 @@ heap_create_with_catalog(const char *relname, new_rel_desc, relid, new_type_oid, + reloftypeid, ownerid, relkind, PointerGetDatum(relacl), @@ -1139,6 +1146,14 @@ heap_create_with_catalog(const char *relname, recordDependencyOnOwner(RelationRelationId, relid, ownerid); + if (reloftypeid) + { + referenced.classId = TypeRelationId; + referenced.objectId = reloftypeid; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + if (relacl != NULL) { int nnewmembers; diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql index 64417b3ba8f..453953306a6 100644 --- a/src/backend/catalog/information_schema.sql +++ b/src/backend/catalog/information_schema.sql @@ -4,7 +4,7 @@ * * Copyright (c) 2003-2010, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.64 2010/01/17 22:56:21 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.65 2010/01/28 23:21:11 petere Exp $ */ /* @@ -1799,25 +1799,25 @@ CREATE VIEW tables AS CAST(null AS sql_identifier) AS self_referencing_column_name, CAST(null AS character_data) AS reference_generation, - CAST(null AS sql_identifier) AS user_defined_type_catalog, - CAST(null AS sql_identifier) AS user_defined_type_schema, - CAST(null AS sql_identifier) AS user_defined_type_name, + CAST(CASE WHEN t.typname IS NOT NULL THEN current_database() ELSE null END AS sql_identifier) AS user_defined_type_catalog, + CAST(nt.nspname AS sql_identifier) AS user_defined_type_schema, + CAST(t.typname AS sql_identifier) AS user_defined_type_name, CAST(CASE WHEN c.relkind = 'r' OR (c.relkind = 'v' AND EXISTS (SELECT 1 FROM pg_rewrite WHERE ev_class = c.oid AND ev_type = '3' AND is_instead)) THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_insertable_into, - CAST('NO' AS yes_or_no) AS is_typed, + CAST(CASE WHEN t.typname IS NOT NULL THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_typed, CAST( CASE WHEN nc.oid = pg_my_temp_schema() THEN 'PRESERVE' -- FIXME ELSE null END AS character_data) AS commit_action - FROM pg_namespace nc, pg_class c + FROM pg_namespace nc JOIN pg_class c ON (nc.oid = c.relnamespace) + LEFT JOIN (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid)) ON (c.reloftype = t.oid) - WHERE c.relnamespace = nc.oid - AND c.relkind IN ('r', 'v') + WHERE c.relkind IN ('r', 'v') AND (NOT pg_is_other_temp_schema(nc.oid)) AND (pg_has_role(c.relowner, 'USAGE') OR has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER') diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c index b1faccfbf96..58890aa6a0a 100644 --- a/src/backend/catalog/toasting.c +++ b/src/backend/catalog/toasting.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/toasting.c,v 1.27 2010/01/06 03:03:58 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/toasting.c,v 1.28 2010/01/28 23:21:11 petere Exp $ * *------------------------------------------------------------------------- */ @@ -203,6 +203,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, Datum reloptio rel->rd_rel->reltablespace, toastOid, toast_typid, + InvalidOid, rel->rd_rel->relowner, tupdesc, NIL, diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 56d040590ba..dc967390ba6 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.194 2010/01/20 19:43:40 heikki Exp $ + * $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.195 2010/01/28 23:21:11 petere Exp $ * *------------------------------------------------------------------------- */ @@ -720,6 +720,7 @@ make_new_heap(Oid OIDOldHeap, const char *NewName, Oid NewTableSpace) NewTableSpace, InvalidOid, InvalidOid, + InvalidOid, OldHeap->rd_rel->relowner, tupdesc, NIL, diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 89447d36782..134b217d829 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.319 2010/01/28 07:31:42 heikki Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.320 2010/01/28 23:21:11 petere Exp $ * *------------------------------------------------------------------------- */ @@ -361,6 +361,7 @@ DefineRelation(CreateStmt *stmt, char relkind) ListCell *listptr; AttrNumber attnum; static char *validnsps[] = HEAP_RELOPT_NAMESPACES; + Oid ofTypeId; /* * Truncate relname to appropriate length (probably a waste of time, as @@ -443,6 +444,11 @@ DefineRelation(CreateStmt *stmt, char relkind) (void) heap_reloptions(relkind, reloptions, true); + if (stmt->ofTypename) + ofTypeId = typenameTypeId(NULL, stmt->ofTypename, NULL); + else + ofTypeId = InvalidOid; + /* * Look up inheritance ancestors and generate relation schema, including * inherited attributes. @@ -521,6 +527,7 @@ DefineRelation(CreateStmt *stmt, char relkind) tablespaceId, InvalidOid, InvalidOid, + ofTypeId, GetUserId(), descriptor, list_concat(cookedDefaults, @@ -1230,17 +1237,46 @@ MergeAttributes(List *schema, List *supers, bool istemp, foreach(entry, schema) { ColumnDef *coldef = lfirst(entry); - ListCell *rest; + ListCell *rest = lnext(entry); + ListCell *prev = entry; + + if (coldef->typeName == NULL) + /* + * Typed table column option that does not belong to a + * column from the type. This works because the columns + * from the type come first in the list. + */ + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("column \"%s\" does not exist", + coldef->colname))); - for_each_cell(rest, lnext(entry)) + while (rest != NULL) { ColumnDef *restdef = lfirst(rest); + ListCell *next = lnext(rest); /* need to save it in case we delete it */ if (strcmp(coldef->colname, restdef->colname) == 0) - ereport(ERROR, - (errcode(ERRCODE_DUPLICATE_COLUMN), - errmsg("column \"%s\" specified more than once", - coldef->colname))); + { + if (coldef->is_from_type) + { + /* merge the column options into the column from + * the type */ + coldef->is_not_null = restdef->is_not_null; + coldef->raw_default = restdef->raw_default; + coldef->cooked_default = restdef->cooked_default; + coldef->constraints = restdef->constraints; + coldef->is_from_type = false; + list_delete_cell(schema, rest, prev); + } + else + ereport(ERROR, + (errcode(ERRCODE_DUPLICATE_COLUMN), + errmsg("column \"%s\" specified more than once", + coldef->colname))); + } + prev = rest; + rest = next; } } @@ -1921,6 +1957,11 @@ renameatt(Oid myrelid, */ targetrelation = relation_open(myrelid, AccessExclusiveLock); + if (targetrelation->rd_rel->reloftype) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot rename column of typed table"))); + /* * permissions checking. this would normally be done in utility.c, but * this particular routine is recursive. @@ -3586,6 +3627,11 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel, Form_pg_type tform; Expr *defval; + if (rel->rd_rel->reloftype) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot add column to typed table"))); + attrdesc = heap_open(AttributeRelationId, RowExclusiveLock); /* @@ -4307,6 +4353,11 @@ ATExecDropColumn(List **wqueue, Relation rel, const char *colName, List *children; ObjectAddress object; + if (rel->rd_rel->reloftype) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot drop column from typed table"))); + /* At top level, permission check was done in ATPrepCmd, else do it */ if (recursing) ATSimplePermissions(rel, false); diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 557ecc7e15c..b0698489c41 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.342 2010/01/15 09:19:02 heikki Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.343 2010/01/28 23:21:11 petere Exp $ * *------------------------------------------------------------------------- */ @@ -2162,6 +2162,7 @@ OpenIntoRel(QueryDesc *queryDesc) tablespaceId, InvalidOid, InvalidOid, + InvalidOid, GetUserId(), tupdesc, NIL, diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 8d1f1641d7c..4de0f7c87e9 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.459 2010/01/05 21:53:58 rhaas Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.460 2010/01/28 23:21:11 petere Exp $ * *------------------------------------------------------------------------- */ @@ -2507,6 +2507,7 @@ _copyCreateStmt(CreateStmt *from) COPY_NODE_FIELD(relation); COPY_NODE_FIELD(tableElts); COPY_NODE_FIELD(inhRelations); + COPY_NODE_FIELD(ofTypename); COPY_NODE_FIELD(constraints); COPY_NODE_FIELD(options); COPY_SCALAR_FIELD(oncommit); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 24e53773077..319070add11 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -22,7 +22,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.380 2010/01/05 21:53:58 rhaas Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.381 2010/01/28 23:21:11 petere Exp $ * *------------------------------------------------------------------------- */ @@ -1099,6 +1099,7 @@ _equalCreateStmt(CreateStmt *a, CreateStmt *b) COMPARE_NODE_FIELD(relation); COMPARE_NODE_FIELD(tableElts); COMPARE_NODE_FIELD(inhRelations); + COMPARE_NODE_FIELD(ofTypename); COMPARE_NODE_FIELD(constraints); COMPARE_NODE_FIELD(options); COMPARE_SCALAR_FIELD(oncommit); diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 5bd092eae25..70950807908 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.380 2010/01/05 21:53:58 rhaas Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.381 2010/01/28 23:21:12 petere Exp $ * * NOTES * Every node type that can appear in stored rules' parsetrees *must* @@ -1784,6 +1784,7 @@ _outCreateStmt(StringInfo str, CreateStmt *node) WRITE_NODE_FIELD(relation); WRITE_NODE_FIELD(tableElts); WRITE_NODE_FIELD(inhRelations); + WRITE_NODE_FIELD(ofTypename); WRITE_NODE_FIELD(constraints); WRITE_NODE_FIELD(options); WRITE_ENUM_FIELD(oncommit, OnCommitAction); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 981d2614042..d7bbbbd1bef 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.705 2010/01/25 20:55:32 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.706 2010/01/28 23:21:12 petere Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -277,6 +277,7 @@ static TypeName *TableFuncTypeName(List *columns); %type <list> stmtblock stmtmulti OptTableElementList TableElementList OptInherit definition + OptTypedTableElementList TypedTableElementList reloptions opt_reloptions OptWith opt_distinct opt_definition func_args func_args_list func_args_with_defaults func_args_with_defaults_list @@ -347,8 +348,8 @@ static TypeName *TableFuncTypeName(List *columns); %type <vsetstmt> set_rest SetResetClause -%type <node> TableElement ConstraintElem TableFuncElement -%type <node> columnDef +%type <node> TableElement TypedTableElement ConstraintElem TableFuncElement +%type <node> columnDef columnOptions %type <defelt> def_elem reloption_elem old_aggr_elem %type <node> def_arg columnElem where_clause where_or_current_clause a_expr b_expr c_expr func_expr AexprConst indirection_el @@ -2203,21 +2204,19 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' n->tablespacename = $11; $$ = (Node *)n; } - | CREATE OptTemp TABLE qualified_name OF qualified_name - '(' OptTableElementList ')' OptWith OnCommitOption OptTableSpace + | CREATE OptTemp TABLE qualified_name OF any_name + OptTypedTableElementList OptWith OnCommitOption OptTableSpace { - /* SQL99 CREATE TABLE OF <UDT> (cols) seems to be satisfied - * by our inheritance capabilities. Let's try it... - */ CreateStmt *n = makeNode(CreateStmt); $4->istemp = $2; n->relation = $4; - n->tableElts = $8; - n->inhRelations = list_make1($6); + n->tableElts = $7; + n->ofTypename = makeTypeNameFromNameList($6); + n->ofTypename->location = @6; n->constraints = NIL; - n->options = $10; - n->oncommit = $11; - n->tablespacename = $12; + n->options = $8; + n->oncommit = $9; + n->tablespacename = $10; $$ = (Node *)n; } ; @@ -2243,6 +2242,11 @@ OptTableElementList: | /*EMPTY*/ { $$ = NIL; } ; +OptTypedTableElementList: + '(' TypedTableElementList ')' { $$ = $2; } + | /*EMPTY*/ { $$ = NIL; } + ; + TableElementList: TableElement { @@ -2254,12 +2258,28 @@ TableElementList: } ; +TypedTableElementList: + TypedTableElement + { + $$ = list_make1($1); + } + | TypedTableElementList ',' TypedTableElement + { + $$ = lappend($1, $3); + } + ; + TableElement: columnDef { $$ = $1; } | TableLikeClause { $$ = $1; } | TableConstraint { $$ = $1; } ; +TypedTableElement: + columnOptions { $$ = $1; } + | TableConstraint { $$ = $1; } + ; + columnDef: ColId Typename ColQualList { ColumnDef *n = makeNode(ColumnDef); @@ -2271,6 +2291,16 @@ columnDef: ColId Typename ColQualList } ; +columnOptions: ColId WITH OPTIONS ColQualList + { + ColumnDef *n = makeNode(ColumnDef); + n->colname = $1; + n->constraints = $4; + n->is_local = true; + $$ = (Node *)n; + } + ; + ColQualList: ColQualList ColConstraint { $$ = lappend($1, $2); } | /*EMPTY*/ { $$ = NIL; } diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index a1ed7e48e37..bf455701e33 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -19,7 +19,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.36 2010/01/02 16:57:50 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.37 2010/01/28 23:21:12 petere Exp $ * *------------------------------------------------------------------------- */ @@ -58,6 +58,7 @@ #include "utils/lsyscache.h" #include "utils/relcache.h" #include "utils/syscache.h" +#include "utils/typcache.h" /* State shared by transformCreateStmt and its subroutines */ @@ -104,6 +105,8 @@ static void transformTableConstraint(ParseState *pstate, Constraint *constraint); static void transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, InhRelation *inhrelation); +static void transformOfType(ParseState *pstate, CreateStmtContext *cxt, + TypeName *ofTypename); static char *chooseIndexName(const RangeVar *relation, IndexStmt *index_stmt); static IndexStmt *generateClonedIndexStmt(CreateStmtContext *cxt, Relation parent_index, AttrNumber *attmap); @@ -183,6 +186,11 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString) cxt.pkey = NULL; cxt.hasoids = interpretOidsOption(stmt->options); + Assert(!stmt->ofTypename || !stmt->inhRelations); /* grammar enforces */ + + if (stmt->ofTypename) + transformOfType(pstate, &cxt, stmt->ofTypename); + /* * Run through each primary element in the table creation clause. Separate * column defs from constraints, and do preliminary analysis. @@ -266,8 +274,9 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, /* Check for SERIAL pseudo-types */ is_serial = false; - if (list_length(column->typeName->names) == 1 && - !column->typeName->pct_type) + if (column->typeName + && list_length(column->typeName->names) == 1 + && !column->typeName->pct_type) { char *typname = strVal(linitial(column->typeName->names)); @@ -299,7 +308,8 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt, } /* Do necessary work on the column type declaration */ - transformColumnType(pstate, column); + if (column->typeName) + transformColumnType(pstate, column); /* Special actions for SERIAL pseudo-types */ if (is_serial) @@ -787,6 +797,46 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt, heap_close(relation, NoLock); } +static void +transformOfType(ParseState *pstate, CreateStmtContext *cxt, TypeName *ofTypename) +{ + HeapTuple tuple; + Form_pg_type typ; + TupleDesc tupdesc; + int i; + Oid ofTypeId; + + AssertArg(ofTypename); + + tuple = typenameType(NULL, ofTypename, NULL); + typ = (Form_pg_type) GETSTRUCT(tuple); + ofTypeId = HeapTupleGetOid(tuple); + ofTypename->typeOid = ofTypeId; /* cached for later */ + + if (typ->typtype != TYPTYPE_COMPOSITE) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("type %s is not a composite type", + format_type_be(ofTypeId)))); + + tupdesc = lookup_rowtype_tupdesc(ofTypeId, -1); + for (i = 0; i < tupdesc->natts; i++) + { + ColumnDef *n = makeNode(ColumnDef); + Form_pg_attribute attr = tupdesc->attrs[i]; + + n->colname = NameStr(attr->attname); + n->typeName = makeTypeNameFromOid(attr->atttypid, attr->atttypmod); + n->constraints = NULL; + n->is_local = true; + n->is_from_type = true; + cxt->columns = lappend(cxt->columns, n); + } + DecrTupleDescRefCount(tupdesc); + + ReleaseSysCache(tuple); +} + /* * chooseIndexName * |