Commit b1a5f872 authored by Bruce Momjian's avatar Bruce Momjian

Tom Lane wrote:

> There's no longer a separate call to heap_storage_create in that routine
> --- the right place to make the test is now in the storage_create
> boolean parameter being passed to heap_create.  A simple change, but
> it passeth patch's understanding ...

Thanks.

Attached is a patch against cvs tip as of 8:30 PM PST or so. Turned out
that even after fixing the failed hunks, there was a new spot in
bufmgr.c which needed to be fixed (related to temp relations;
RelationUpdateNumberOfBlocks). But thankfully the regression test code
caught it :-)

Joe Conway
parent 38294db6
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_type.sgml,v 1.30 2002/07/24 19:11:07 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_type.sgml,v 1.31 2002/08/15 16:36:00 momjian Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -30,6 +30,13 @@ CREATE TYPE <replaceable class="parameter">typename</replaceable> ( INPUT = <rep ...@@ -30,6 +30,13 @@ CREATE TYPE <replaceable class="parameter">typename</replaceable> ( INPUT = <rep
[ , ALIGNMENT = <replaceable class="parameter">alignment</replaceable> ] [ , ALIGNMENT = <replaceable class="parameter">alignment</replaceable> ]
[ , STORAGE = <replaceable class="parameter">storage</replaceable> ] [ , STORAGE = <replaceable class="parameter">storage</replaceable> ]
) )
CREATE TYPE <replaceable class="parameter">typename</replaceable> AS
( <replaceable class="PARAMETER">column_definition_list</replaceable> )
where <replaceable class="PARAMETER">column_definition_list</replaceable> can be:
( <replaceable class="PARAMETER">column_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [, ... ] )
</synopsis> </synopsis>
<refsect2 id="R2-SQL-CREATETYPE-1"> <refsect2 id="R2-SQL-CREATETYPE-1">
...@@ -138,6 +145,25 @@ CREATE TYPE <replaceable class="parameter">typename</replaceable> ( INPUT = <rep ...@@ -138,6 +145,25 @@ CREATE TYPE <replaceable class="parameter">typename</replaceable> ( INPUT = <rep
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><replaceable class="PARAMETER">column_name</replaceable></term>
<listitem>
<para>
The name of a column of the composite type.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="PARAMETER">data_type</replaceable></term>
<listitem>
<para>
The name of an existing data type.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</para> </para>
</refsect2> </refsect2>
...@@ -191,9 +217,9 @@ CREATE TYPE ...@@ -191,9 +217,9 @@ CREATE TYPE
</para> </para>
<para> <para>
<command>CREATE TYPE</command> requires the registration of two functions The first form of <command>CREATE TYPE</command> requires the
(using CREATE FUNCTION) before defining the type. The registration of two functions (using CREATE FUNCTION) before defining the
representation of a new base type is determined by type. The representation of a new base type is determined by
<replaceable class="parameter">input_function</replaceable>, which <replaceable class="parameter">input_function</replaceable>, which
converts the type's external representation to an internal converts the type's external representation to an internal
representation usable by the representation usable by the
...@@ -288,6 +314,14 @@ CREATE TYPE ...@@ -288,6 +314,14 @@ CREATE TYPE
<literal>extended</literal> and <literal>external</literal> items.) <literal>extended</literal> and <literal>external</literal> items.)
</para> </para>
<para>
The second form of <command>CREATE TYPE</command> requires a column
definition list in the form ( <replaceable class="PARAMETER">column_name</replaceable>
<replaceable class="PARAMETER">data_type</replaceable> [, ... ] ). This
creates a composite type, similar to that of a TABLE or VIEW relation.
A stand-alone composite type is useful as the return type of FUNCTION.
</para>
<refsect2> <refsect2>
<title>Array Types</title> <title>Array Types</title>
...@@ -370,6 +404,15 @@ CREATE TYPE box (INTERNALLENGTH = 16, ...@@ -370,6 +404,15 @@ CREATE TYPE box (INTERNALLENGTH = 16,
CREATE TYPE bigobj (INPUT = lo_filein, OUTPUT = lo_fileout, CREATE TYPE bigobj (INPUT = lo_filein, OUTPUT = lo_fileout,
INTERNALLENGTH = VARIABLE); INTERNALLENGTH = VARIABLE);
CREATE TABLE big_objs (id int4, obj bigobj); CREATE TABLE big_objs (id int4, obj bigobj);
</programlisting>
</para>
<para>
This example creates a composite type and uses it in
a table function definition:
<programlisting>
CREATE TYPE compfoo AS (f1 int, f2 int);
CREATE FUNCTION getfoo() RETURNS SETOF compfoo AS 'SELECT fooid, foorefid FROM foo' LANGUAGE SQL;
</programlisting> </programlisting>
</para> </para>
</refsect1> </refsect1>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * INTERFACE ROUTINES
...@@ -357,9 +357,10 @@ CheckAttributeNames(TupleDesc tupdesc, bool relhasoids, char relkind) ...@@ -357,9 +357,10 @@ CheckAttributeNames(TupleDesc tupdesc, bool relhasoids, char relkind)
/* /*
* first check for collision with system attribute names * 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++) for (i = 0; i < natts; i++)
{ {
...@@ -473,10 +474,10 @@ AddNewAttributeTuples(Oid new_rel_oid, ...@@ -473,10 +474,10 @@ AddNewAttributeTuples(Oid new_rel_oid,
/* /*
* Next we add the system attributes. Skip OID if rel has no OIDs. * 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 * Skip all for a view or type relation. We don't bother with making
* dependencies here, since presumably all these types are pinned. * datatype dependencies here, since presumably all these types are pinned.
*/ */
if (relkind != RELKIND_VIEW) if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
{ {
dpp = SysAtt; dpp = SysAtt;
for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++) for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
...@@ -689,13 +690,14 @@ heap_create_with_catalog(const char *relname, ...@@ -689,13 +690,14 @@ heap_create_with_catalog(const char *relname,
* physical disk file. (If we fail further down, it's the smgr's * physical disk file. (If we fail further down, it's the smgr's
* responsibility to remove the disk file again.) * 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, new_rel_desc = heap_create(relname,
relnamespace, relnamespace,
tupdesc, tupdesc,
shared_relation, shared_relation,
(relkind != RELKIND_VIEW), (relkind != RELKIND_VIEW &&
relkind != RELKIND_COMPOSITE_TYPE),
allow_system_table_mods); allow_system_table_mods);
/* Fetch the relation OID assigned by heap_create */ /* Fetch the relation OID assigned by heap_create */
...@@ -1131,7 +1133,8 @@ heap_drop_with_catalog(Oid rid) ...@@ -1131,7 +1133,8 @@ heap_drop_with_catalog(Oid rid)
/* /*
* unlink the relation's physical file and finish up. * 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); smgrunlink(DEFAULT_SMGR, rel);
/* /*
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) ...@@ -1585,6 +1585,7 @@ RemoveTempRelations(Oid tempNamespaceId)
case RELKIND_RELATION: case RELKIND_RELATION:
case RELKIND_SEQUENCE: case RELKIND_SEQUENCE:
case RELKIND_VIEW: case RELKIND_VIEW:
case RELKIND_COMPOSITE_TYPE:
AssertTupleDescHasOid(pgclass->rd_att); AssertTupleDescHasOid(pgclass->rd_att);
object.classId = RelOid_pg_class; object.classId = RelOid_pg_class;
object.objectId = HeapTupleGetOid(tuple); object.objectId = HeapTupleGetOid(tuple);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -311,15 +311,28 @@ TypeCreate(const char *typeName,
/* /*
* If the type is a rowtype for a relation, mark it as internally * If the type is a rowtype for a relation, mark it as internally
* dependent on the relation. This allows it to be auto-dropped * dependent on the relation, *unless* it is a stand-alone composite
* when the relation is, and not otherwise. * 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)) 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.classId = RelOid_pg_class;
referenced.objectId = relationOid; referenced.objectId = relationOid;
referenced.objectSubId = 0; referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
if (relkind != RELKIND_COMPOSITE_TYPE)
recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
else
recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
} }
/* /*
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -398,6 +398,9 @@ DoCopy(const CopyStmt *stmt)
if (rel->rd_rel->relkind == RELKIND_VIEW) if (rel->rd_rel->relkind == RELKIND_VIEW)
elog(ERROR, "You cannot copy view %s", elog(ERROR, "You cannot copy view %s",
RelationGetRelationName(rel)); 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) else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
elog(ERROR, "You cannot change sequence relation %s", elog(ERROR, "You cannot change sequence relation %s",
RelationGetRelationName(rel)); RelationGetRelationName(rel));
...@@ -443,6 +446,9 @@ DoCopy(const CopyStmt *stmt) ...@@ -443,6 +446,9 @@ DoCopy(const CopyStmt *stmt)
if (rel->rd_rel->relkind == RELKIND_VIEW) if (rel->rd_rel->relkind == RELKIND_VIEW)
elog(ERROR, "You cannot copy view %s", elog(ERROR, "You cannot copy view %s",
RelationGetRelationName(rel)); 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) else if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
elog(ERROR, "You cannot copy sequence %s", elog(ERROR, "You cannot copy sequence %s",
RelationGetRelationName(rel)); RelationGetRelationName(rel));
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -345,6 +345,10 @@ TruncateRelation(const RangeVar *relation)
elog(ERROR, "TRUNCATE cannot be used on views. '%s' is a view", elog(ERROR, "TRUNCATE cannot be used on views. '%s' is a view",
RelationGetRelationName(rel)); 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)) if (!allowSystemTableMods && IsSystemRelation(rel))
elog(ERROR, "TRUNCATE cannot be used on system tables. '%s' is a system table", elog(ERROR, "TRUNCATE cannot be used on system tables. '%s' is a system table",
RelationGetRelationName(rel)); RelationGetRelationName(rel));
...@@ -3210,12 +3214,13 @@ CheckTupleType(Form_pg_class tuple_class) ...@@ -3210,12 +3214,13 @@ CheckTupleType(Form_pg_class tuple_class)
case RELKIND_RELATION: case RELKIND_RELATION:
case RELKIND_INDEX: case RELKIND_INDEX:
case RELKIND_VIEW: case RELKIND_VIEW:
case RELKIND_COMPOSITE_TYPE:
case RELKIND_SEQUENCE: case RELKIND_SEQUENCE:
case RELKIND_TOASTVALUE: case RELKIND_TOASTVALUE:
/* ok to change owner */ /* ok to change owner */
break; break;
default: 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)); NameStr(tuple_class->relname));
} }
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "catalog/namespace.h" #include "catalog/namespace.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "commands/defrem.h" #include "commands/defrem.h"
#include "commands/tablecmds.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "parser/parse_func.h" #include "parser/parse_func.h"
#include "parser/parse_type.h" #include "parser/parse_type.h"
...@@ -50,7 +51,6 @@ ...@@ -50,7 +51,6 @@
static Oid findTypeIOFunction(List *procname, bool isOutput); static Oid findTypeIOFunction(List *procname, bool isOutput);
/* /*
* DefineType * DefineType
* Registers a new type. * Registers a new type.
...@@ -666,3 +666,42 @@ findTypeIOFunction(List *procname, bool isOutput) ...@@ -666,3 +666,42 @@ findTypeIOFunction(List *procname, bool isOutput)
return procOid; 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);
}
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -786,6 +786,10 @@ initResultRelInfo(ResultRelInfo *resultRelInfo,
elog(ERROR, "You can't change view relation %s", elog(ERROR, "You can't change view relation %s",
RelationGetRelationName(resultRelationDesc)); RelationGetRelationName(resultRelationDesc));
break; break;
case RELKIND_COMPOSITE_TYPE:
elog(ERROR, "You can't change type relation %s",
RelationGetRelationName(resultRelationDesc));
break;
} }
MemSet(resultRelInfo, 0, sizeof(ResultRelInfo)); MemSet(resultRelInfo, 0, sizeof(ResultRelInfo));
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) ...@@ -2233,6 +2233,17 @@ _copyTransactionStmt(TransactionStmt *from)
return newnode; 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 * static ViewStmt *
_copyViewStmt(ViewStmt *from) _copyViewStmt(ViewStmt *from)
{ {
...@@ -2939,6 +2950,9 @@ copyObject(void *from) ...@@ -2939,6 +2950,9 @@ copyObject(void *from)
case T_TransactionStmt: case T_TransactionStmt:
retval = _copyTransactionStmt(from); retval = _copyTransactionStmt(from);
break; break;
case T_CompositeTypeStmt:
retval = _copyCompositeTypeStmt(from);
break;
case T_ViewStmt: case T_ViewStmt:
retval = _copyViewStmt(from); retval = _copyViewStmt(from);
break; break;
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1061,6 +1061,17 @@ _equalTransactionStmt(TransactionStmt *a, TransactionStmt *b) ...@@ -1061,6 +1061,17 @@ _equalTransactionStmt(TransactionStmt *a, TransactionStmt *b)
return true; return true;
} }
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 static bool
_equalViewStmt(ViewStmt *a, ViewStmt *b) _equalViewStmt(ViewStmt *a, ViewStmt *b)
{ {
...@@ -2111,6 +2122,9 @@ equal(void *a, void *b) ...@@ -2111,6 +2122,9 @@ equal(void *a, void *b)
case T_TransactionStmt: case T_TransactionStmt:
retval = _equalTransactionStmt(a, b); retval = _equalTransactionStmt(a, b);
break; break;
case T_CompositeTypeStmt:
retval = _equalCompositeTypeStmt(a, b);
break;
case T_ViewStmt: case T_ViewStmt:
retval = _equalViewStmt(a, b); retval = _equalViewStmt(a, b);
break; break;
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * 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 * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -205,7 +205,7 @@ static void doNegateFloat(Value *v); ...@@ -205,7 +205,7 @@ static void doNegateFloat(Value *v);
%type <list> stmtblock, stmtmulti, %type <list> stmtblock, stmtmulti,
OptTableElementList, TableElementList, OptInherit, definition, 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 func_args_list, func_as, createfunc_opt_list
oper_argtypes, RuleActionList, RuleActionMulti, oper_argtypes, RuleActionList, RuleActionMulti,
opt_column_list, columnList, opt_name_list, opt_column_list, columnList, opt_name_list,
...@@ -2233,6 +2233,39 @@ DefineStmt: ...@@ -2233,6 +2233,39 @@ DefineStmt:
n->definition = $4; n->definition = $4;
$$ = (Node *)n; $$ = (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 | CREATE CHARACTER SET opt_as any_name GET definition opt_collate
{ {
DefineStmt *n = makeNode(DefineStmt); DefineStmt *n = makeNode(DefineStmt);
...@@ -2243,6 +2276,9 @@ DefineStmt: ...@@ -2243,6 +2276,9 @@ DefineStmt:
} }
; ;
rowdefinition: '(' TableFuncElementList ')' { $$ = $2; }
;
definition: '(' def_list ')' { $$ = $2; } definition: '(' def_list ')' { $$ = $2; }
; ;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -1051,6 +1051,8 @@ RelationGetNumberOfBlocks(Relation relation)
*/ */
if (relation->rd_rel->relkind == RELKIND_VIEW) if (relation->rd_rel->relkind == RELKIND_VIEW)
relation->rd_nblocks = 0; 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) else if (!relation->rd_isnew && !relation->rd_istemp)
relation->rd_nblocks = smgrnblocks(DEFAULT_SMGR, relation); relation->rd_nblocks = smgrnblocks(DEFAULT_SMGR, relation);
return relation->rd_nblocks; return relation->rd_nblocks;
...@@ -1069,6 +1071,8 @@ RelationUpdateNumberOfBlocks(Relation relation) ...@@ -1069,6 +1071,8 @@ RelationUpdateNumberOfBlocks(Relation relation)
{ {
if (relation->rd_rel->relkind == RELKIND_VIEW) if (relation->rd_rel->relkind == RELKIND_VIEW)
relation->rd_nblocks = 0; relation->rd_nblocks = 0;
else if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
relation->rd_nblocks = 0;
else else
relation->rd_nblocks = smgrnblocks(DEFAULT_SMGR, relation); relation->rd_nblocks = smgrnblocks(DEFAULT_SMGR, relation);
} }
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -263,6 +263,8 @@ smgropen(int16 which, Relation reln, bool failOK)
if (reln->rd_rel->relkind == RELKIND_VIEW) if (reln->rd_rel->relkind == RELKIND_VIEW)
return -1; return -1;
if (reln->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
return -1;
if ((fd = (*(smgrsw[which].smgr_open)) (reln)) < 0) if ((fd = (*(smgrsw[which].smgr_open)) (reln)) < 0)
if (!failOK) if (!failOK)
elog(ERROR, "cannot open %s: %m", RelationGetRelationName(reln)); elog(ERROR, "cannot open %s: %m", RelationGetRelationName(reln));
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* this is the "main" module of the postgres backend and * this is the "main" module of the postgres backend and
...@@ -1674,7 +1674,7 @@ PostgresMain(int argc, char *argv[], const char *username) ...@@ -1674,7 +1674,7 @@ PostgresMain(int argc, char *argv[], const char *username)
if (!IsUnderPostmaster) if (!IsUnderPostmaster)
{ {
puts("\nPOSTGRES backend interactive interface "); 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) ...@@ -2233,6 +2233,10 @@ CreateCommandTag(Node *parsetree)
} }
break; break;
case T_CompositeTypeStmt:
tag = "CREATE TYPE";
break;
case T_ViewStmt: case T_ViewStmt:
tag = "CREATE VIEW"; tag = "CREATE VIEW";
break; break;
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * 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[] = { ...@@ -70,6 +70,7 @@ static struct kindstrings kindstringarray[] = {
{RELKIND_SEQUENCE, "a", "sequence", "SEQUENCE"}, {RELKIND_SEQUENCE, "a", "sequence", "SEQUENCE"},
{RELKIND_VIEW, "a", "view", "VIEW"}, {RELKIND_VIEW, "a", "view", "VIEW"},
{RELKIND_INDEX, "an", "index", "INDEX"}, {RELKIND_INDEX, "an", "index", "INDEX"},
{RELKIND_COMPOSITE_TYPE, "a", "type", "TYPE"},
{'\0', "a", "???", "???"} {'\0', "a", "???", "???"}
}; };
...@@ -573,6 +574,19 @@ ProcessUtility(Node *parsetree, ...@@ -573,6 +574,19 @@ ProcessUtility(Node *parsetree,
} }
break; 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 */ case T_ViewStmt: /* CREATE VIEW */
{ {
ViewStmt *stmt = (ViewStmt *) parsetree; ViewStmt *stmt = (ViewStmt *) parsetree;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* input routine largely stolen from boxin(). * input routine largely stolen from boxin().
...@@ -226,6 +226,9 @@ currtid_byreloid(PG_FUNCTION_ARGS) ...@@ -226,6 +226,9 @@ currtid_byreloid(PG_FUNCTION_ARGS)
if (rel->rd_rel->relkind == RELKIND_VIEW) if (rel->rd_rel->relkind == RELKIND_VIEW)
return currtid_for_view(rel, tid); 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); ItemPointerCopy(tid, result);
heap_get_latest_tid(rel, SnapshotNow, result); heap_get_latest_tid(rel, SnapshotNow, result);
...@@ -249,6 +252,9 @@ currtid_byrelname(PG_FUNCTION_ARGS) ...@@ -249,6 +252,9 @@ currtid_byrelname(PG_FUNCTION_ARGS)
if (rel->rd_rel->relkind == RELKIND_VIEW) if (rel->rd_rel->relkind == RELKIND_VIEW)
return currtid_for_view(rel, tid); 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)); result = (ItemPointer) palloc(sizeof(ItemPointerData));
ItemPointerCopy(tid, result); ItemPointerCopy(tid, result);
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -215,9 +215,10 @@ flagInhTables(TableInfo *tblinfo, int numTables,
for (i = 0; i < numTables; i++) 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 || if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
tblinfo[i].relkind == RELKIND_VIEW) tblinfo[i].relkind == RELKIND_VIEW ||
tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
continue; continue;
/* Don't bother computing anything for non-target tables, either */ /* Don't bother computing anything for non-target tables, either */
...@@ -269,9 +270,10 @@ flagInhAttrs(TableInfo *tblinfo, int numTables, ...@@ -269,9 +270,10 @@ flagInhAttrs(TableInfo *tblinfo, int numTables,
for (i = 0; i < numTables; i++) 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 || if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
tblinfo[i].relkind == RELKIND_VIEW) tblinfo[i].relkind == RELKIND_VIEW ||
tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
continue; continue;
/* Don't bother computing anything for non-target tables, either */ /* Don't bother computing anything for non-target tables, either */
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -95,6 +95,7 @@ static void dumpOneBaseType(Archive *fout, TypeInfo *tinfo,
FuncInfo *g_finfo, int numFuncs, FuncInfo *g_finfo, int numFuncs,
TypeInfo *g_tinfo, int numTypes); TypeInfo *g_tinfo, int numTypes);
static void dumpOneDomain(Archive *fout, TypeInfo *tinfo); static void dumpOneDomain(Archive *fout, TypeInfo *tinfo);
static void dumpOneCompositeType(Archive *fout, TypeInfo *tinfo);
static void dumpOneTable(Archive *fout, TableInfo *tbinfo, static void dumpOneTable(Archive *fout, TableInfo *tbinfo,
TableInfo *g_tblinfo); TableInfo *g_tblinfo);
static void dumpOneSequence(Archive *fout, TableInfo *tbinfo, static void dumpOneSequence(Archive *fout, TableInfo *tbinfo,
...@@ -1171,6 +1172,10 @@ dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout, ...@@ -1171,6 +1172,10 @@ dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout,
if (tblinfo[i].relkind == RELKIND_VIEW) if (tblinfo[i].relkind == RELKIND_VIEW)
continue; continue;
/* Skip TYPE relations */
if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
continue;
if (tblinfo[i].relkind == RELKIND_SEQUENCE) /* already dumped */ if (tblinfo[i].relkind == RELKIND_SEQUENCE) /* already dumped */
continue; continue;
...@@ -1575,6 +1580,7 @@ getTypes(int *numTypes) ...@@ -1575,6 +1580,7 @@ getTypes(int *numTypes)
int i_usename; int i_usename;
int i_typelem; int i_typelem;
int i_typrelid; int i_typrelid;
int i_typrelkind;
int i_typtype; int i_typtype;
int i_typisdefined; int i_typisdefined;
...@@ -1595,7 +1601,9 @@ getTypes(int *numTypes) ...@@ -1595,7 +1601,9 @@ getTypes(int *numTypes)
appendPQExpBuffer(query, "SELECT pg_type.oid, typname, " appendPQExpBuffer(query, "SELECT pg_type.oid, typname, "
"typnamespace, " "typnamespace, "
"(select usename from pg_user where typowner = usesysid) as usename, " "(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"); "FROM pg_type");
} }
else else
...@@ -1603,7 +1611,9 @@ getTypes(int *numTypes) ...@@ -1603,7 +1611,9 @@ getTypes(int *numTypes)
appendPQExpBuffer(query, "SELECT pg_type.oid, typname, " appendPQExpBuffer(query, "SELECT pg_type.oid, typname, "
"0::oid as typnamespace, " "0::oid as typnamespace, "
"(select usename from pg_user where typowner = usesysid) as usename, " "(select usename from pg_user where typowner = usesysid) as usename, "
"typelem, typrelid, typtype, typisdefined " "typelem, typrelid, "
"''::char as typrelkind, "
"typtype, typisdefined "
"FROM pg_type"); "FROM pg_type");
} }
...@@ -1625,6 +1635,7 @@ getTypes(int *numTypes) ...@@ -1625,6 +1635,7 @@ getTypes(int *numTypes)
i_usename = PQfnumber(res, "usename"); i_usename = PQfnumber(res, "usename");
i_typelem = PQfnumber(res, "typelem"); i_typelem = PQfnumber(res, "typelem");
i_typrelid = PQfnumber(res, "typrelid"); i_typrelid = PQfnumber(res, "typrelid");
i_typrelkind = PQfnumber(res, "typrelkind");
i_typtype = PQfnumber(res, "typtype"); i_typtype = PQfnumber(res, "typtype");
i_typisdefined = PQfnumber(res, "typisdefined"); i_typisdefined = PQfnumber(res, "typisdefined");
...@@ -1637,6 +1648,7 @@ getTypes(int *numTypes) ...@@ -1637,6 +1648,7 @@ getTypes(int *numTypes)
tinfo[i].usename = strdup(PQgetvalue(res, i, i_usename)); tinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
tinfo[i].typelem = strdup(PQgetvalue(res, i, i_typelem)); tinfo[i].typelem = strdup(PQgetvalue(res, i, i_typelem));
tinfo[i].typrelid = strdup(PQgetvalue(res, i, i_typrelid)); 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); tinfo[i].typtype = *PQgetvalue(res, i, i_typtype);
/* /*
...@@ -2102,7 +2114,6 @@ getTables(int *numTables) ...@@ -2102,7 +2114,6 @@ getTables(int *numTables)
appendPQExpBuffer(query, appendPQExpBuffer(query,
"SELECT pg_class.oid, relname, relacl, relkind, " "SELECT pg_class.oid, relname, relacl, relkind, "
"relnamespace, " "relnamespace, "
"(select usename from pg_user where relowner = usesysid) as usename, " "(select usename from pg_user where relowner = usesysid) as usename, "
"relchecks, reltriggers, " "relchecks, reltriggers, "
"relhasindex, relhasrules, relhasoids " "relhasindex, relhasrules, relhasoids "
...@@ -2113,6 +2124,7 @@ getTables(int *numTables) ...@@ -2113,6 +2124,7 @@ getTables(int *numTables)
} }
else if (g_fout->remoteVersion >= 70200) else if (g_fout->remoteVersion >= 70200)
{ {
/* before 7.3 there were no type relations with relkind 'c' */
appendPQExpBuffer(query, appendPQExpBuffer(query,
"SELECT pg_class.oid, relname, relacl, relkind, " "SELECT pg_class.oid, relname, relacl, relkind, "
"0::oid as relnamespace, " "0::oid as relnamespace, "
...@@ -2356,6 +2368,10 @@ getTableAttrs(TableInfo *tblinfo, int numTables) ...@@ -2356,6 +2368,10 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
if (tblinfo[i].relkind == RELKIND_SEQUENCE) if (tblinfo[i].relkind == RELKIND_SEQUENCE)
continue; 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 */ /* Don't bother with uninteresting tables, either */
if (!tblinfo[i].interesting) if (!tblinfo[i].interesting)
continue; continue;
...@@ -3172,6 +3188,105 @@ dumpOneDomain(Archive *fout, TypeInfo *tinfo) ...@@ -3172,6 +3188,105 @@ dumpOneDomain(Archive *fout, TypeInfo *tinfo)
destroyPQExpBuffer(query); destroyPQExpBuffer(query);
} }
/*
* 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 * dumpTypes
* writes out to fout the queries to recreate all the user-defined types * writes out to fout the queries to recreate all the user-defined types
...@@ -3188,8 +3303,8 @@ dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs, ...@@ -3188,8 +3303,8 @@ dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs,
if (!tinfo[i].typnamespace->dump) if (!tinfo[i].typnamespace->dump)
continue; continue;
/* skip relation types */ /* skip relation types for non-stand-alone type relations*/
if (atooid(tinfo[i].typrelid) != 0) if (atooid(tinfo[i].typrelid) != 0 && tinfo[i].typrelkind != 'c')
continue; continue;
/* skip undefined placeholder types */ /* skip undefined placeholder types */
...@@ -3207,6 +3322,8 @@ dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs, ...@@ -3207,6 +3322,8 @@ dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs,
finfo, numFuncs, tinfo, numTypes); finfo, numFuncs, tinfo, numTypes);
else if (tinfo[i].typtype == 'd') else if (tinfo[i].typtype == 'd')
dumpOneDomain(fout, &tinfo[i]); 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, ...@@ -4832,6 +4949,7 @@ dumpTables(Archive *fout, TableInfo tblinfo[], int numTables,
if (tbinfo->relkind != RELKIND_SEQUENCE) if (tbinfo->relkind != RELKIND_SEQUENCE)
continue; continue;
if (tbinfo->dump) if (tbinfo->dump)
{ {
dumpOneSequence(fout, tbinfo, schemaOnly, dataOnly); dumpOneSequence(fout, tbinfo, schemaOnly, dataOnly);
...@@ -4848,6 +4966,8 @@ dumpTables(Archive *fout, TableInfo tblinfo[], int numTables, ...@@ -4848,6 +4966,8 @@ dumpTables(Archive *fout, TableInfo tblinfo[], int numTables,
if (tbinfo->relkind == RELKIND_SEQUENCE) /* already dumped */ if (tbinfo->relkind == RELKIND_SEQUENCE) /* already dumped */
continue; continue;
if (tbinfo->relkind == RELKIND_COMPOSITE_TYPE) /* dumped as a type */
continue;
if (tbinfo->dump) if (tbinfo->dump)
{ {
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 ...@@ -47,6 +47,7 @@ typedef struct _typeInfo
char *usename; /* name of owner, or empty string */ char *usename; /* name of owner, or empty string */
char *typelem; /* OID */ char *typelem; /* OID */
char *typrelid; /* OID */ char *typrelid; /* OID */
char typrelkind; /* 'r', 'v', 'c', etc */
char typtype; /* 'b', 'c', etc */ char typtype; /* 'b', 'c', etc */
bool isArray; /* true if user-defined array type */ bool isArray; /* true if user-defined array type */
bool isDefined; /* true if typisdefined */ bool isDefined; /* true if typisdefined */
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright 2000-2002 by PostgreSQL Global Development Group * 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 "postgres_fe.h"
#include "describe.h" #include "describe.h"
...@@ -210,9 +210,12 @@ describeTypes(const char *pattern, bool verbose) ...@@ -210,9 +210,12 @@ describeTypes(const char *pattern, bool verbose)
/* /*
* do not include array types (start with underscore), do not include * 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 */ /* Match name pattern against either internal or external name */
processNamePattern(&buf, pattern, true, false, processNamePattern(&buf, pattern, true, false,
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -169,5 +169,6 @@ DESCR(""); ...@@ -169,5 +169,6 @@ DESCR("");
#define RELKIND_UNCATALOGED 'u' /* temporary heap */ #define RELKIND_UNCATALOGED 'u' /* temporary heap */
#define RELKIND_TOASTVALUE 't' /* moved off huge values */ #define RELKIND_TOASTVALUE 't' /* moved off huge values */
#define RELKIND_VIEW 'v' /* view */ #define RELKIND_VIEW 'v' /* view */
#define RELKIND_COMPOSITE_TYPE 'c' /* composite type */
#endif /* PG_CLASS_H */ #endif /* PG_CLASS_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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); ...@@ -58,6 +58,7 @@ extern void RemoveType(List *names, DropBehavior behavior);
extern void RemoveTypeById(Oid typeOid); extern void RemoveTypeById(Oid typeOid);
extern void DefineDomain(CreateDomainStmt *stmt); extern void DefineDomain(CreateDomainStmt *stmt);
extern void RemoveDomain(List *names, DropBehavior behavior); extern void RemoveDomain(List *names, DropBehavior behavior);
extern Oid DefineCompositeType(const RangeVar *typevar, List *coldeflist);
extern void DefineOpClass(CreateOpClassStmt *stmt); extern void DefineOpClass(CreateOpClassStmt *stmt);
extern void RemoveOpClass(RemoveOpClassStmt *stmt); extern void RemoveOpClass(RemoveOpClassStmt *stmt);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 ...@@ -238,6 +238,7 @@ typedef enum NodeTag
T_PrivTarget, T_PrivTarget,
T_InsertDefault, T_InsertDefault,
T_CreateOpClassItem, T_CreateOpClassItem,
T_CompositeTypeStmt,
/* /*
* TAGS FOR FUNCTION-CALL CONTEXT AND RESULTINFO NODES (see fmgr.h) * TAGS FOR FUNCTION-CALL CONTEXT AND RESULTINFO NODES (see fmgr.h)
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1401,6 +1401,18 @@ typedef struct TransactionStmt ...@@ -1401,6 +1401,18 @@ typedef struct TransactionStmt
List *options; List *options;
} 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 * Create View Statement
* ---------------------- * ----------------------
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* procedural language * procedural language
* *
* IDENTIFICATION * 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. * This software is copyrighted by Jan Wieck - Hamburg.
* *
...@@ -1028,12 +1028,13 @@ plpgsql_parse_dblwordtype(char *word) ...@@ -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); classStruct = (Form_pg_class) GETSTRUCT(classtup);
if (classStruct->relkind != RELKIND_RELATION && if (classStruct->relkind != RELKIND_RELATION &&
classStruct->relkind != RELKIND_SEQUENCE && classStruct->relkind != RELKIND_SEQUENCE &&
classStruct->relkind != RELKIND_VIEW) classStruct->relkind != RELKIND_VIEW &&
classStruct->relkind != RELKIND_COMPOSITE_TYPE)
{ {
ReleaseSysCache(classtup); ReleaseSysCache(classtup);
pfree(cp[0]); pfree(cp[0]);
...@@ -1145,10 +1146,11 @@ build_rowtype(Oid classOid) ...@@ -1145,10 +1146,11 @@ build_rowtype(Oid classOid)
classStruct = (Form_pg_class) GETSTRUCT(classtup); classStruct = (Form_pg_class) GETSTRUCT(classtup);
relname = NameStr(classStruct->relname); 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 && if (classStruct->relkind != RELKIND_RELATION &&
classStruct->relkind != RELKIND_SEQUENCE && 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); elog(ERROR, "%s isn't a table", relname);
/* /*
......
...@@ -37,4 +37,17 @@ SELECT * FROM default_test; ...@@ -37,4 +37,17 @@ SELECT * FROM default_test;
zippo | 42 zippo | 42
(1 row) (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; DROP TABLE default_test;
...@@ -41,4 +41,16 @@ INSERT INTO default_test DEFAULT VALUES; ...@@ -41,4 +41,16 @@ INSERT INTO default_test DEFAULT VALUES;
SELECT * FROM default_test; 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; DROP TABLE default_test;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment