aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/catalog/heap.c21
-rw-r--r--src/backend/catalog/namespace.c3
-rw-r--r--src/backend/catalog/pg_type.c21
-rw-r--r--src/backend/commands/copy.c8
-rw-r--r--src/backend/commands/tablecmds.c9
-rw-r--r--src/backend/commands/typecmds.c43
-rw-r--r--src/backend/executor/execMain.c6
-rw-r--r--src/backend/nodes/copyfuncs.c16
-rw-r--r--src/backend/nodes/equalfuncs.c16
-rw-r--r--src/backend/parser/gram.y40
-rw-r--r--src/backend/storage/buffer/bufmgr.c6
-rw-r--r--src/backend/storage/smgr/smgr.c4
-rw-r--r--src/backend/tcop/postgres.c8
-rw-r--r--src/backend/tcop/utility.c16
-rw-r--r--src/backend/utils/adt/tid.c8
-rw-r--r--src/bin/pg_dump/common.c12
-rw-r--r--src/bin/pg_dump/pg_dump.c132
-rw-r--r--src/bin/pg_dump/pg_dump.h3
-rw-r--r--src/bin/psql/describe.c9
-rw-r--r--src/include/catalog/pg_class.h3
-rw-r--r--src/include/commands/defrem.h3
-rw-r--r--src/include/nodes/nodes.h3
-rw-r--r--src/include/nodes/parsenodes.h14
-rw-r--r--src/pl/plpgsql/src/pl_comp.c12
-rw-r--r--src/test/regress/expected/create_type.out13
-rw-r--r--src/test/regress/sql/create_type.sql12
26 files changed, 387 insertions, 54 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 747dcb9ae53..0c21400ca1d 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.220 2002/08/11 21:17:34 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.221 2002/08/15 16:36:00 momjian Exp $
*
*
* INTERFACE ROUTINES
@@ -357,9 +357,10 @@ CheckAttributeNames(TupleDesc tupdesc, bool relhasoids, char relkind)
/*
* first check for collision with system attribute names
*
- * Skip this for a view, since it doesn't have system attributes.
+ * Skip this for a view and type relation, since it doesn't have system
+ * attributes.
*/
- if (relkind != RELKIND_VIEW)
+ if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
{
for (i = 0; i < natts; i++)
{
@@ -473,10 +474,10 @@ AddNewAttributeTuples(Oid new_rel_oid,
/*
* Next we add the system attributes. Skip OID if rel has no OIDs.
- * Skip all for a view. We don't bother with making datatype
- * dependencies here, since presumably all these types are pinned.
+ * Skip all for a view or type relation. We don't bother with making
+ * datatype dependencies here, since presumably all these types are pinned.
*/
- if (relkind != RELKIND_VIEW)
+ if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
{
dpp = SysAtt;
for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
@@ -689,13 +690,14 @@ heap_create_with_catalog(const char *relname,
* physical disk file. (If we fail further down, it's the smgr's
* responsibility to remove the disk file again.)
*
- * NB: create a physical file only if it's not a view.
+ * NB: create a physical file only if it's not a view or type relation.
*/
new_rel_desc = heap_create(relname,
relnamespace,
tupdesc,
shared_relation,
- (relkind != RELKIND_VIEW),
+ (relkind != RELKIND_VIEW &&
+ relkind != RELKIND_COMPOSITE_TYPE),
allow_system_table_mods);
/* Fetch the relation OID assigned by heap_create */
@@ -1131,7 +1133,8 @@ heap_drop_with_catalog(Oid rid)
/*
* unlink the relation's physical file and finish up.
*/
- if (rel->rd_rel->relkind != RELKIND_VIEW)
+ if (rel->rd_rel->relkind != RELKIND_VIEW &&
+ rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE)
smgrunlink(DEFAULT_SMGR, rel);
/*
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 1aab73279fa..8f6caa5d4d9 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -13,7 +13,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.30 2002/08/09 16:45:14 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.31 2002/08/15 16:36:01 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1585,6 +1585,7 @@ RemoveTempRelations(Oid tempNamespaceId)
case RELKIND_RELATION:
case RELKIND_SEQUENCE:
case RELKIND_VIEW:
+ case RELKIND_COMPOSITE_TYPE:
AssertTupleDescHasOid(pgclass->rd_att);
object.classId = RelOid_pg_class;
object.objectId = HeapTupleGetOid(tuple);
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index d1e90c61732..8482c43ca27 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.77 2002/08/05 03:29:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.78 2002/08/15 16:36:01 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -311,15 +311,28 @@ TypeCreate(const char *typeName,
/*
* If the type is a rowtype for a relation, mark it as internally
- * dependent on the relation. This allows it to be auto-dropped
- * when the relation is, and not otherwise.
+ * dependent on the relation, *unless* it is a stand-alone composite
+ * type relation. For the latter case, we have to reverse the
+ * dependency.
+ *
+ * In the former case, this allows the type to be auto-dropped
+ * when the relation is, and not otherwise. And in the latter,
+ * of course we get the opposite effect.
*/
if (OidIsValid(relationOid))
{
+ Relation rel = relation_open(relationOid, AccessShareLock);
+ char relkind = rel->rd_rel->relkind;
+ relation_close(rel, AccessShareLock);
+
referenced.classId = RelOid_pg_class;
referenced.objectId = relationOid;
referenced.objectSubId = 0;
- recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
+
+ if (relkind != RELKIND_COMPOSITE_TYPE)
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
+ else
+ recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
}
/*
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 2529b728230..890ef6f6768 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.162 2002/08/02 18:15:06 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.163 2002/08/15 16:36:02 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -398,6 +398,9 @@ DoCopy(const CopyStmt *stmt)
if (rel->rd_rel->relkind == RELKIND_VIEW)
elog(ERROR, "You cannot copy view %s",
RelationGetRelationName(rel));
+ else if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+ elog(ERROR, "You cannot copy type relation %s",
+ RelationGetRelationName(rel));
else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
elog(ERROR, "You cannot change sequence relation %s",
RelationGetRelationName(rel));
@@ -443,6 +446,9 @@ DoCopy(const CopyStmt *stmt)
if (rel->rd_rel->relkind == RELKIND_VIEW)
elog(ERROR, "You cannot copy view %s",
RelationGetRelationName(rel));
+ else if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+ elog(ERROR, "You cannot copy type relation %s",
+ RelationGetRelationName(rel));
else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
elog(ERROR, "You cannot copy sequence %s",
RelationGetRelationName(rel));
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index d40122cdf54..72ecd6d0ce4 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.28 2002/08/07 21:45:01 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.29 2002/08/15 16:36:02 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -345,6 +345,10 @@ TruncateRelation(const RangeVar *relation)
elog(ERROR, "TRUNCATE cannot be used on views. '%s' is a view",
RelationGetRelationName(rel));
+ if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+ elog(ERROR, "TRUNCATE cannot be used on type relations. '%s' is a type",
+ RelationGetRelationName(rel));
+
if (!allowSystemTableMods && IsSystemRelation(rel))
elog(ERROR, "TRUNCATE cannot be used on system tables. '%s' is a system table",
RelationGetRelationName(rel));
@@ -3210,12 +3214,13 @@ CheckTupleType(Form_pg_class tuple_class)
case RELKIND_RELATION:
case RELKIND_INDEX:
case RELKIND_VIEW:
+ case RELKIND_COMPOSITE_TYPE:
case RELKIND_SEQUENCE:
case RELKIND_TOASTVALUE:
/* ok to change owner */
break;
default:
- elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table, TOAST table, index, view, or sequence",
+ elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table, TOAST table, index, view, type, or sequence",
NameStr(tuple_class->relname));
}
}
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index a27babb32e3..f9f27d58676 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.8 2002/07/24 19:11:09 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.9 2002/08/15 16:36:02 momjian Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -38,6 +38,7 @@
#include "catalog/namespace.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
+#include "commands/tablecmds.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "parser/parse_type.h"
@@ -50,7 +51,6 @@
static Oid findTypeIOFunction(List *procname, bool isOutput);
-
/*
* DefineType
* Registers a new type.
@@ -666,3 +666,42 @@ findTypeIOFunction(List *procname, bool isOutput)
return procOid;
}
+
+/*-------------------------------------------------------------------
+ * DefineCompositeType
+ *
+ * Create a Composite Type relation.
+ * `DefineRelation' does all the work, we just provide the correct
+ * arguments!
+ *
+ * If the relation already exists, then 'DefineRelation' will abort
+ * the xact...
+ *
+ * DefineCompositeType returns relid for use when creating
+ * an implicit composite type during function creation
+ *-------------------------------------------------------------------
+ */
+Oid
+DefineCompositeType(const RangeVar *typevar, List *coldeflist)
+{
+ CreateStmt *createStmt = makeNode(CreateStmt);
+
+ if (coldeflist == NIL)
+ elog(ERROR, "attempted to define composite type relation with"
+ " no attrs");
+
+ /*
+ * now create the parameters for keys/inheritance etc. All of them are
+ * nil...
+ */
+ createStmt->relation = (RangeVar *) typevar;
+ createStmt->tableElts = coldeflist;
+ createStmt->inhRelations = NIL;
+ createStmt->constraints = NIL;
+ createStmt->hasoids = false;
+
+ /*
+ * finally create the relation...
+ */
+ return DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE);
+}
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 7e50ca4f9e6..0b9bb86578a 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -27,7 +27,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.173 2002/08/07 21:45:02 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.174 2002/08/15 16:36:02 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -786,6 +786,10 @@ initResultRelInfo(ResultRelInfo *resultRelInfo,
elog(ERROR, "You can't change view relation %s",
RelationGetRelationName(resultRelationDesc));
break;
+ case RELKIND_COMPOSITE_TYPE:
+ elog(ERROR, "You can't change type relation %s",
+ RelationGetRelationName(resultRelationDesc));
+ break;
}
MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 954a372181a..6caceb7311c 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
- * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.200 2002/08/04 19:48:09 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.201 2002/08/15 16:36:02 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2233,6 +2233,17 @@ _copyTransactionStmt(TransactionStmt *from)
return newnode;
}
+static CompositeTypeStmt *
+_copyCompositeTypeStmt(CompositeTypeStmt *from)
+{
+ CompositeTypeStmt *newnode = makeNode(CompositeTypeStmt);
+
+ Node_Copy(from, newnode, typevar);
+ Node_Copy(from, newnode, coldeflist);
+
+ return newnode;
+}
+
static ViewStmt *
_copyViewStmt(ViewStmt *from)
{
@@ -2939,6 +2950,9 @@ copyObject(void *from)
case T_TransactionStmt:
retval = _copyTransactionStmt(from);
break;
+ case T_CompositeTypeStmt:
+ retval = _copyCompositeTypeStmt(from);
+ break;
case T_ViewStmt:
retval = _copyViewStmt(from);
break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index e87e9f4f94a..7eda9e377f0 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -20,7 +20,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.149 2002/08/04 23:49:59 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.150 2002/08/15 16:36:03 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1062,6 +1062,17 @@ _equalTransactionStmt(TransactionStmt *a, TransactionStmt *b)
}
static bool
+_equalCompositeTypeStmt(CompositeTypeStmt *a, CompositeTypeStmt *b)
+{
+ if (!equal(a->typevar, b->typevar))
+ return false;
+ if (!equal(a->coldeflist, b->coldeflist))
+ return false;
+
+ return true;
+}
+
+static bool
_equalViewStmt(ViewStmt *a, ViewStmt *b)
{
if (!equal(a->view, b->view))
@@ -2111,6 +2122,9 @@ equal(void *a, void *b)
case T_TransactionStmt:
retval = _equalTransactionStmt(a, b);
break;
+ case T_CompositeTypeStmt:
+ retval = _equalCompositeTypeStmt(a, b);
+ break;
case T_ViewStmt:
retval = _equalViewStmt(a, b);
break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 98acc050d56..a56f7d41b99 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.358 2002/08/10 19:01:53 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.359 2002/08/15 16:36:03 momjian Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -205,7 +205,7 @@ static void doNegateFloat(Value *v);
%type <list> stmtblock, stmtmulti,
OptTableElementList, TableElementList, OptInherit, definition,
- opt_distinct, opt_definition, func_args,
+ opt_distinct, opt_definition, func_args, rowdefinition
func_args_list, func_as, createfunc_opt_list
oper_argtypes, RuleActionList, RuleActionMulti,
opt_column_list, columnList, opt_name_list,
@@ -2233,6 +2233,39 @@ DefineStmt:
n->definition = $4;
$$ = (Node *)n;
}
+ | CREATE TYPE_P any_name AS rowdefinition
+ {
+ CompositeTypeStmt *n = makeNode(CompositeTypeStmt);
+ RangeVar *r = makeNode(RangeVar);
+
+ switch (length($3))
+ {
+ case 1:
+ r->catalogname = NULL;
+ r->schemaname = NULL;
+ r->relname = strVal(lfirst($3));
+ break;
+ case 2:
+ r->catalogname = NULL;
+ r->schemaname = strVal(lfirst($3));
+ r->relname = strVal(lsecond($3));
+ break;
+ case 3:
+ r->catalogname = strVal(lfirst($3));
+ r->schemaname = strVal(lsecond($3));
+ r->relname = strVal(lfirst(lnext(lnext($3))));
+ break;
+ default:
+ elog(ERROR,
+ "Improper qualified name "
+ "(too many dotted names): %s",
+ NameListToString($3));
+ break;
+ }
+ n->typevar = r;
+ n->coldeflist = $5;
+ $$ = (Node *)n;
+ }
| CREATE CHARACTER SET opt_as any_name GET definition opt_collate
{
DefineStmt *n = makeNode(DefineStmt);
@@ -2243,6 +2276,9 @@ DefineStmt:
}
;
+rowdefinition: '(' TableFuncElementList ')' { $$ = $2; }
+ ;
+
definition: '(' def_list ')' { $$ = $2; }
;
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 11df91c25cf..550bd6e70d5 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.129 2002/08/11 21:17:34 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.130 2002/08/15 16:36:04 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1051,6 +1051,8 @@ RelationGetNumberOfBlocks(Relation relation)
*/
if (relation->rd_rel->relkind == RELKIND_VIEW)
relation->rd_nblocks = 0;
+ else if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+ relation->rd_nblocks = 0;
else if (!relation->rd_isnew && !relation->rd_istemp)
relation->rd_nblocks = smgrnblocks(DEFAULT_SMGR, relation);
return relation->rd_nblocks;
@@ -1069,6 +1071,8 @@ RelationUpdateNumberOfBlocks(Relation relation)
{
if (relation->rd_rel->relkind == RELKIND_VIEW)
relation->rd_nblocks = 0;
+ else if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+ relation->rd_nblocks = 0;
else
relation->rd_nblocks = smgrnblocks(DEFAULT_SMGR, relation);
}
diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c
index 252781d9c3f..dab9b5dcbb2 100644
--- a/src/backend/storage/smgr/smgr.c
+++ b/src/backend/storage/smgr/smgr.c
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/smgr/smgr.c,v 1.58 2002/08/06 02:36:34 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/smgr/smgr.c,v 1.59 2002/08/15 16:36:04 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -263,6 +263,8 @@ smgropen(int16 which, Relation reln, bool failOK)
if (reln->rd_rel->relkind == RELKIND_VIEW)
return -1;
+ if (reln->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+ return -1;
if ((fd = (*(smgrsw[which].smgr_open)) (reln)) < 0)
if (!failOK)
elog(ERROR, "cannot open %s: %m", RelationGetRelationName(reln));
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 6c5e17b48f6..5c0a07bfaa9 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.281 2002/08/10 20:29:18 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.282 2002/08/15 16:36:05 momjian Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@@ -1674,7 +1674,7 @@ PostgresMain(int argc, char *argv[], const char *username)
if (!IsUnderPostmaster)
{
puts("\nPOSTGRES backend interactive interface ");
- puts("$Revision: 1.281 $ $Date: 2002/08/10 20:29:18 $\n");
+ puts("$Revision: 1.282 $ $Date: 2002/08/15 16:36:05 $\n");
}
/*
@@ -2233,6 +2233,10 @@ CreateCommandTag(Node *parsetree)
}
break;
+ case T_CompositeTypeStmt:
+ tag = "CREATE TYPE";
+ break;
+
case T_ViewStmt:
tag = "CREATE VIEW";
break;
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 2ef3ff8a3f4..e75b52b6702 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.169 2002/08/07 21:45:02 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.170 2002/08/15 16:36:05 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -70,6 +70,7 @@ static struct kindstrings kindstringarray[] = {
{RELKIND_SEQUENCE, "a", "sequence", "SEQUENCE"},
{RELKIND_VIEW, "a", "view", "VIEW"},
{RELKIND_INDEX, "an", "index", "INDEX"},
+ {RELKIND_COMPOSITE_TYPE, "a", "type", "TYPE"},
{'\0', "a", "???", "???"}
};
@@ -573,6 +574,19 @@ ProcessUtility(Node *parsetree,
}
break;
+ case T_CompositeTypeStmt: /* CREATE TYPE (composite) */
+ {
+ Oid relid;
+ CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
+
+ /*
+ * DefineCompositeType returns relid for use when creating
+ * an implicit composite type during function creation
+ */
+ relid = DefineCompositeType(stmt->typevar, stmt->coldeflist);
+ }
+ break;
+
case T_ViewStmt: /* CREATE VIEW */
{
ViewStmt *stmt = (ViewStmt *) parsetree;
diff --git a/src/backend/utils/adt/tid.c b/src/backend/utils/adt/tid.c
index e81248a6db0..5a784a44768 100644
--- a/src/backend/utils/adt/tid.c
+++ b/src/backend/utils/adt/tid.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.32 2002/07/16 17:55:25 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.33 2002/08/15 16:36:05 momjian Exp $
*
* NOTES
* input routine largely stolen from boxin().
@@ -226,6 +226,9 @@ currtid_byreloid(PG_FUNCTION_ARGS)
if (rel->rd_rel->relkind == RELKIND_VIEW)
return currtid_for_view(rel, tid);
+ if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+ elog(ERROR, "currtid can't handle type relations");
+
ItemPointerCopy(tid, result);
heap_get_latest_tid(rel, SnapshotNow, result);
@@ -249,6 +252,9 @@ currtid_byrelname(PG_FUNCTION_ARGS)
if (rel->rd_rel->relkind == RELKIND_VIEW)
return currtid_for_view(rel, tid);
+ if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+ elog(ERROR, "currtid can't handle type relations");
+
result = (ItemPointer) palloc(sizeof(ItemPointerData));
ItemPointerCopy(tid, result);
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 0e3ffe91e5c..4f33ff4e4fd 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.67 2002/07/30 21:56:04 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.68 2002/08/15 16:36:06 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -215,9 +215,10 @@ flagInhTables(TableInfo *tblinfo, int numTables,
for (i = 0; i < numTables; i++)
{
- /* Sequences and views never have parents */
+ /* Sequences, views, and types never have parents */
if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
- tblinfo[i].relkind == RELKIND_VIEW)
+ tblinfo[i].relkind == RELKIND_VIEW ||
+ tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
continue;
/* Don't bother computing anything for non-target tables, either */
@@ -269,9 +270,10 @@ flagInhAttrs(TableInfo *tblinfo, int numTables,
for (i = 0; i < numTables; i++)
{
- /* Sequences and views never have parents */
+ /* Sequences, views, and types never have parents */
if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
- tblinfo[i].relkind == RELKIND_VIEW)
+ tblinfo[i].relkind == RELKIND_VIEW ||
+ tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
continue;
/* Don't bother computing anything for non-target tables, either */
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 0397320a735..22dfa23a965 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -22,7 +22,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.281 2002/08/10 16:57:31 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.282 2002/08/15 16:36:06 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -95,6 +95,7 @@ static void dumpOneBaseType(Archive *fout, TypeInfo *tinfo,
FuncInfo *g_finfo, int numFuncs,
TypeInfo *g_tinfo, int numTypes);
static void dumpOneDomain(Archive *fout, TypeInfo *tinfo);
+static void dumpOneCompositeType(Archive *fout, TypeInfo *tinfo);
static void dumpOneTable(Archive *fout, TableInfo *tbinfo,
TableInfo *g_tblinfo);
static void dumpOneSequence(Archive *fout, TableInfo *tbinfo,
@@ -1171,6 +1172,10 @@ dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout,
if (tblinfo[i].relkind == RELKIND_VIEW)
continue;
+ /* Skip TYPE relations */
+ if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
+ continue;
+
if (tblinfo[i].relkind == RELKIND_SEQUENCE) /* already dumped */
continue;
@@ -1575,6 +1580,7 @@ getTypes(int *numTypes)
int i_usename;
int i_typelem;
int i_typrelid;
+ int i_typrelkind;
int i_typtype;
int i_typisdefined;
@@ -1595,7 +1601,9 @@ getTypes(int *numTypes)
appendPQExpBuffer(query, "SELECT pg_type.oid, typname, "
"typnamespace, "
"(select usename from pg_user where typowner = usesysid) as usename, "
- "typelem, typrelid, typtype, typisdefined "
+ "typelem, typrelid, "
+ "(select relkind from pg_class where oid = typrelid) as typrelkind, "
+ "typtype, typisdefined "
"FROM pg_type");
}
else
@@ -1603,7 +1611,9 @@ getTypes(int *numTypes)
appendPQExpBuffer(query, "SELECT pg_type.oid, typname, "
"0::oid as typnamespace, "
"(select usename from pg_user where typowner = usesysid) as usename, "
- "typelem, typrelid, typtype, typisdefined "
+ "typelem, typrelid, "
+ "''::char as typrelkind, "
+ "typtype, typisdefined "
"FROM pg_type");
}
@@ -1625,6 +1635,7 @@ getTypes(int *numTypes)
i_usename = PQfnumber(res, "usename");
i_typelem = PQfnumber(res, "typelem");
i_typrelid = PQfnumber(res, "typrelid");
+ i_typrelkind = PQfnumber(res, "typrelkind");
i_typtype = PQfnumber(res, "typtype");
i_typisdefined = PQfnumber(res, "typisdefined");
@@ -1637,6 +1648,7 @@ getTypes(int *numTypes)
tinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
tinfo[i].typelem = strdup(PQgetvalue(res, i, i_typelem));
tinfo[i].typrelid = strdup(PQgetvalue(res, i, i_typrelid));
+ tinfo[i].typrelkind = *PQgetvalue(res, i, i_typrelkind);
tinfo[i].typtype = *PQgetvalue(res, i, i_typtype);
/*
@@ -2102,7 +2114,6 @@ getTables(int *numTables)
appendPQExpBuffer(query,
"SELECT pg_class.oid, relname, relacl, relkind, "
"relnamespace, "
-
"(select usename from pg_user where relowner = usesysid) as usename, "
"relchecks, reltriggers, "
"relhasindex, relhasrules, relhasoids "
@@ -2113,6 +2124,7 @@ getTables(int *numTables)
}
else if (g_fout->remoteVersion >= 70200)
{
+ /* before 7.3 there were no type relations with relkind 'c' */
appendPQExpBuffer(query,
"SELECT pg_class.oid, relname, relacl, relkind, "
"0::oid as relnamespace, "
@@ -2356,6 +2368,10 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
if (tblinfo[i].relkind == RELKIND_SEQUENCE)
continue;
+ /* Don't bother to collect info for type relations */
+ if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
+ continue;
+
/* Don't bother with uninteresting tables, either */
if (!tblinfo[i].interesting)
continue;
@@ -3173,6 +3189,105 @@ dumpOneDomain(Archive *fout, TypeInfo *tinfo)
}
/*
+ * dumpOneCompositeType
+ * writes out to fout the queries to recreate a user-defined stand-alone
+ * composite type as requested by dumpTypes
+ */
+static void
+dumpOneCompositeType(Archive *fout, TypeInfo *tinfo)
+{
+ PQExpBuffer q = createPQExpBuffer();
+ PQExpBuffer delq = createPQExpBuffer();
+ PQExpBuffer query = createPQExpBuffer();
+ PGresult *res;
+ int ntups;
+ char *attname;
+ char *atttypdefn;
+ char *attbasetype;
+ const char *((*deps)[]);
+ int depIdx = 0;
+ int i;
+
+ deps = malloc(sizeof(char *) * 10);
+
+ /* Set proper schema search path so type references list correctly */
+ selectSourceSchema(tinfo->typnamespace->nspname);
+
+ /* Fetch type specific details */
+ /* We assume here that remoteVersion must be at least 70300 */
+
+ appendPQExpBuffer(query, "SELECT a.attname, "
+ "pg_catalog.format_type(a.atttypid, a.atttypmod) as atttypdefn, "
+ "a.atttypid as attbasetype "
+ "FROM pg_catalog.pg_type t, pg_catalog.pg_attribute a "
+ "WHERE t.oid = '%s'::pg_catalog.oid "
+ "AND a.attrelid = t.typrelid",
+ tinfo->oid);
+
+ res = PQexec(g_conn, query->data);
+ if (!res ||
+ PQresultStatus(res) != PGRES_TUPLES_OK)
+ {
+ write_msg(NULL, "query to obtain type information failed: %s", PQerrorMessage(g_conn));
+ exit_nicely();
+ }
+
+ /* Expecting at least a single result */
+ ntups = PQntuples(res);
+ if (ntups < 1)
+ {
+ write_msg(NULL, "Got no rows from: %s", query->data);
+ exit_nicely();
+ }
+
+ /* DROP must be fully qualified in case same name appears in pg_catalog */
+ appendPQExpBuffer(delq, "DROP TYPE %s.",
+ fmtId(tinfo->typnamespace->nspname, force_quotes));
+ appendPQExpBuffer(delq, "%s RESTRICT;\n",
+ fmtId(tinfo->typname, force_quotes));
+
+ appendPQExpBuffer(q,
+ "CREATE TYPE %s AS (",
+ fmtId(tinfo->typname, force_quotes));
+
+ for (i = 0; i < ntups; i++)
+ {
+ attname = PQgetvalue(res, i, PQfnumber(res, "attname"));
+ atttypdefn = PQgetvalue(res, i, PQfnumber(res, "atttypdefn"));
+ attbasetype = PQgetvalue(res, i, PQfnumber(res, "attbasetype"));
+
+ if (i > 0)
+ appendPQExpBuffer(q, ",\n\t %s %s", attname, atttypdefn);
+ else
+ appendPQExpBuffer(q, "%s %s", attname, atttypdefn);
+
+ /* Depends on the base type */
+ (*deps)[depIdx++] = strdup(attbasetype);
+ }
+ appendPQExpBuffer(q, ");\n");
+
+ (*deps)[depIdx++] = NULL; /* End of List */
+
+ ArchiveEntry(fout, tinfo->oid, tinfo->typname,
+ tinfo->typnamespace->nspname,
+ tinfo->usename, "TYPE", deps,
+ q->data, delq->data, NULL, NULL, NULL);
+
+ /*** Dump Type Comments ***/
+ resetPQExpBuffer(q);
+
+ appendPQExpBuffer(q, "TYPE %s", fmtId(tinfo->typname, force_quotes));
+ dumpComment(fout, q->data,
+ tinfo->typnamespace->nspname, tinfo->usename,
+ tinfo->oid, "pg_type", 0, NULL);
+
+ PQclear(res);
+ destroyPQExpBuffer(q);
+ destroyPQExpBuffer(delq);
+ destroyPQExpBuffer(query);
+}
+
+/*
* dumpTypes
* writes out to fout the queries to recreate all the user-defined types
*/
@@ -3188,8 +3303,8 @@ dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs,
if (!tinfo[i].typnamespace->dump)
continue;
- /* skip relation types */
- if (atooid(tinfo[i].typrelid) != 0)
+ /* skip relation types for non-stand-alone type relations*/
+ if (atooid(tinfo[i].typrelid) != 0 && tinfo[i].typrelkind != 'c')
continue;
/* skip undefined placeholder types */
@@ -3207,6 +3322,8 @@ dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs,
finfo, numFuncs, tinfo, numTypes);
else if (tinfo[i].typtype == 'd')
dumpOneDomain(fout, &tinfo[i]);
+ else if (tinfo[i].typtype == 'c')
+ dumpOneCompositeType(fout, &tinfo[i]);
}
}
@@ -4832,6 +4949,7 @@ dumpTables(Archive *fout, TableInfo tblinfo[], int numTables,
if (tbinfo->relkind != RELKIND_SEQUENCE)
continue;
+
if (tbinfo->dump)
{
dumpOneSequence(fout, tbinfo, schemaOnly, dataOnly);
@@ -4848,6 +4966,8 @@ dumpTables(Archive *fout, TableInfo tblinfo[], int numTables,
if (tbinfo->relkind == RELKIND_SEQUENCE) /* already dumped */
continue;
+ if (tbinfo->relkind == RELKIND_COMPOSITE_TYPE) /* dumped as a type */
+ continue;
if (tbinfo->dump)
{
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 9a208f1e147..02415a794de 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_dump.h,v 1.94 2002/08/02 18:15:08 tgl Exp $
+ * $Id: pg_dump.h,v 1.95 2002/08/15 16:36:06 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -47,6 +47,7 @@ typedef struct _typeInfo
char *usename; /* name of owner, or empty string */
char *typelem; /* OID */
char *typrelid; /* OID */
+ char typrelkind; /* 'r', 'v', 'c', etc */
char typtype; /* 'b', 'c', etc */
bool isArray; /* true if user-defined array type */
bool isDefined; /* true if typisdefined */
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index dc37b9b7ba4..5b446e673d7 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -3,7 +3,7 @@
*
* Copyright 2000-2002 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.60 2002/08/10 16:01:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.61 2002/08/15 16:36:06 momjian Exp $
*/
#include "postgres_fe.h"
#include "describe.h"
@@ -210,9 +210,12 @@ describeTypes(const char *pattern, bool verbose)
/*
* do not include array types (start with underscore), do not include
- * user relations (typrelid!=0)
+ * user relations (typrelid!=0) unless they are type relations
*/
- appendPQExpBuffer(&buf, "WHERE t.typrelid = 0 AND t.typname !~ '^_'\n");
+ appendPQExpBuffer(&buf, "WHERE (t.typrelid = 0 ");
+ appendPQExpBuffer(&buf, "OR (SELECT c.relkind = 'c' FROM pg_class c "
+ "where c.oid = t.typrelid)) ");
+ appendPQExpBuffer(&buf, "AND t.typname !~ '^_'\n");
/* Match name pattern against either internal or external name */
processNamePattern(&buf, pattern, true, false,
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 2d5011e6d62..fd4ffac9c07 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_class.h,v 1.70 2002/08/02 18:15:09 tgl Exp $
+ * $Id: pg_class.h,v 1.71 2002/08/15 16:36:07 momjian Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -169,5 +169,6 @@ DESCR("");
#define RELKIND_UNCATALOGED 'u' /* temporary heap */
#define RELKIND_TOASTVALUE 't' /* moved off huge values */
#define RELKIND_VIEW 'v' /* view */
+#define RELKIND_COMPOSITE_TYPE 'c' /* composite type */
#endif /* PG_CLASS_H */
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index a4af74ac5c5..3de3390dbf4 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: defrem.h,v 1.43 2002/07/29 22:14:11 tgl Exp $
+ * $Id: defrem.h,v 1.44 2002/08/15 16:36:07 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -58,6 +58,7 @@ extern void RemoveType(List *names, DropBehavior behavior);
extern void RemoveTypeById(Oid typeOid);
extern void DefineDomain(CreateDomainStmt *stmt);
extern void RemoveDomain(List *names, DropBehavior behavior);
+extern Oid DefineCompositeType(const RangeVar *typevar, List *coldeflist);
extern void DefineOpClass(CreateOpClassStmt *stmt);
extern void RemoveOpClass(RemoveOpClassStmt *stmt);
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 93a020a12e9..0e3922ec37a 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: nodes.h,v 1.114 2002/07/29 22:14:11 tgl Exp $
+ * $Id: nodes.h,v 1.115 2002/08/15 16:36:07 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -238,6 +238,7 @@ typedef enum NodeTag
T_PrivTarget,
T_InsertDefault,
T_CreateOpClassItem,
+ T_CompositeTypeStmt,
/*
* TAGS FOR FUNCTION-CALL CONTEXT AND RESULTINFO NODES (see fmgr.h)
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 765d1ca0514..8c356a55976 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parsenodes.h,v 1.198 2002/08/04 19:48:10 momjian Exp $
+ * $Id: parsenodes.h,v 1.199 2002/08/15 16:36:07 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1402,6 +1402,18 @@ typedef struct TransactionStmt
} TransactionStmt;
/* ----------------------
+ * Create Type Statement, composite types
+ * ----------------------
+ */
+typedef struct CompositeTypeStmt
+{
+ NodeTag type;
+ RangeVar *typevar; /* the composite type to be created */
+ List *coldeflist; /* list of ColumnDef nodes */
+} CompositeTypeStmt;
+
+
+/* ----------------------
* Create View Statement
* ----------------------
*/
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 00edb1abf93..ebb2312dae4 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.45 2002/08/12 14:25:07 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.46 2002/08/15 16:36:08 momjian Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -1028,12 +1028,13 @@ plpgsql_parse_dblwordtype(char *word)
}
/*
- * It must be a relation, sequence or view
+ * It must be a relation, sequence, view, or type
*/
classStruct = (Form_pg_class) GETSTRUCT(classtup);
if (classStruct->relkind != RELKIND_RELATION &&
classStruct->relkind != RELKIND_SEQUENCE &&
- classStruct->relkind != RELKIND_VIEW)
+ classStruct->relkind != RELKIND_VIEW &&
+ classStruct->relkind != RELKIND_COMPOSITE_TYPE)
{
ReleaseSysCache(classtup);
pfree(cp[0]);
@@ -1145,10 +1146,11 @@ build_rowtype(Oid classOid)
classStruct = (Form_pg_class) GETSTRUCT(classtup);
relname = NameStr(classStruct->relname);
- /* accept relation, sequence, or view pg_class entries */
+ /* accept relation, sequence, view, or type pg_class entries */
if (classStruct->relkind != RELKIND_RELATION &&
classStruct->relkind != RELKIND_SEQUENCE &&
- classStruct->relkind != RELKIND_VIEW)
+ classStruct->relkind != RELKIND_VIEW &&
+ classStruct->relkind != RELKIND_COMPOSITE_TYPE)
elog(ERROR, "%s isn't a table", relname);
/*
diff --git a/src/test/regress/expected/create_type.out b/src/test/regress/expected/create_type.out
index 06b992280b1..68dc8fbd5e5 100644
--- a/src/test/regress/expected/create_type.out
+++ b/src/test/regress/expected/create_type.out
@@ -37,4 +37,17 @@ SELECT * FROM default_test;
zippo | 42
(1 row)
+-- Test stand-alone composite type
+CREATE TYPE default_test_row AS (f1 text_w_default, f2 int42);
+CREATE FUNCTION get_default_test() RETURNS SETOF default_test_row AS '
+ SELECT * FROM default_test;
+' LANGUAGE SQL;
+SELECT * FROM get_default_test();
+ f1 | f2
+-------+----
+ zippo | 42
+(1 row)
+
+DROP TYPE default_test_row CASCADE;
+NOTICE: Drop cascades to function get_default_test()
DROP TABLE default_test;
diff --git a/src/test/regress/sql/create_type.sql b/src/test/regress/sql/create_type.sql
index a728bbd8b9d..9b37981bd49 100644
--- a/src/test/regress/sql/create_type.sql
+++ b/src/test/regress/sql/create_type.sql
@@ -41,4 +41,16 @@ INSERT INTO default_test DEFAULT VALUES;
SELECT * FROM default_test;
+-- Test stand-alone composite type
+
+CREATE TYPE default_test_row AS (f1 text_w_default, f2 int42);
+
+CREATE FUNCTION get_default_test() RETURNS SETOF default_test_row AS '
+ SELECT * FROM default_test;
+' LANGUAGE SQL;
+
+SELECT * FROM get_default_test();
+
+DROP TYPE default_test_row CASCADE;
+
DROP TABLE default_test;