Commit 64505ed5 authored by Tom Lane's avatar Tom Lane

Code review for standalone composite types, query-specified composite

types, SRFs.  Not happy with memory management yet, but I'll commit these
other changes.
parent 7483749d
...@@ -112,7 +112,7 @@ relation_size(PG_FUNCTION_ARGS) ...@@ -112,7 +112,7 @@ relation_size(PG_FUNCTION_ARGS)
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname, relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname,
"relation_size")); "relation_size"));
relation = relation_openrv(relrv, AccessShareLock); relation = heap_openrv(relrv, AccessShareLock);
relnode = relation->rd_rel->relfilenode; relnode = relation->rd_rel->relfilenode;
...@@ -140,7 +140,7 @@ relation_size(PG_FUNCTION_ARGS) ...@@ -140,7 +140,7 @@ relation_size(PG_FUNCTION_ARGS)
segcount++; segcount++;
} }
relation_close(relation, AccessShareLock); heap_close(relation, AccessShareLock);
PG_RETURN_INT64(totalsize); PG_RETURN_INT64(totalsize);
} }
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_type.sgml,v 1.33 2002/08/23 00:33:24 tgl Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_type.sgml,v 1.34 2002/08/29 00:17:01 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -32,11 +32,7 @@ CREATE TYPE <replaceable class="parameter">typename</replaceable> ( INPUT = <rep ...@@ -32,11 +32,7 @@ CREATE TYPE <replaceable class="parameter">typename</replaceable> ( INPUT = <rep
) )
CREATE TYPE <replaceable class="parameter">typename</replaceable> AS CREATE TYPE <replaceable class="parameter">typename</replaceable> AS
( <replaceable class="PARAMETER">column_definition_list</replaceable> ) ( <replaceable class="PARAMETER">column_name</replaceable> <replaceable class="PARAMETER">data_type</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">
...@@ -216,8 +212,12 @@ CREATE TYPE ...@@ -216,8 +212,12 @@ CREATE TYPE
type names also must not conflict with table names in the same schema.) type names also must not conflict with table names in the same schema.)
</para> </para>
<refsect2>
<title>Base Types</title>
<para> <para>
The first form of <command>CREATE TYPE</command> requires the The first form of <command>CREATE TYPE</command> creates a new base type
(scalar type). It requires the
registration of two functions (using CREATE FUNCTION) before defining the registration of two functions (using CREATE FUNCTION) before defining the
type. 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
...@@ -338,20 +338,27 @@ CREATE TYPE ...@@ -338,20 +338,27 @@ CREATE TYPE
a row fit, but they will be kept in the main table preferentially over a row fit, but they will be kept in the main table preferentially over
<literal>extended</literal> and <literal>external</literal> items.) <literal>extended</literal> and <literal>external</literal> items.)
</para> </para>
</refsect2>
<refsect2>
<title>Composite Types</title>
<para> <para>
The second form of <command>CREATE TYPE</command> requires a column The second form of <command>CREATE TYPE</command>
definition list in the form ( <replaceable class="PARAMETER">column_name</replaceable> creates a composite type.
<replaceable class="PARAMETER">data_type</replaceable> [, ... ] ). This The composite type is specified by a list of column names and datatypes.
creates a composite type, similar to that of a TABLE or VIEW relation. This is essentially the same as the row type
A stand-alone composite type is useful as the return type of FUNCTION. of a table, but using <command>CREATE TYPE</command> avoids the need to
create an actual table when all that is wanted is to define a type.
A stand-alone composite type is useful as the return type of a function.
</para> </para>
</refsect2>
<refsect2> <refsect2>
<title>Array Types</title> <title>Array Types</title>
<para> <para>
Whenever a user-defined data type is created, Whenever a user-defined base data type is created,
<productname>PostgreSQL</productname> automatically creates an <productname>PostgreSQL</productname> automatically creates an
associated array type, whose name consists of the base type's associated array type, whose name consists of the base type's
name prepended with an underscore. The parser understands this name prepended with an underscore. The parser understands this
...@@ -436,8 +443,8 @@ CREATE TABLE big_objs (id int4, obj bigobj); ...@@ -436,8 +443,8 @@ CREATE TABLE big_objs (id int4, obj bigobj);
This example creates a composite type and uses it in This example creates a composite type and uses it in
a table function definition: a table function definition:
<programlisting> <programlisting>
CREATE TYPE compfoo AS (f1 int, f2 int); CREATE TYPE compfoo AS (f1 int, f2 text);
CREATE FUNCTION getfoo() RETURNS SETOF compfoo AS 'SELECT fooid, foorefid FROM foo' LANGUAGE SQL; CREATE FUNCTION getfoo() RETURNS SETOF compfoo AS 'SELECT fooid, fooname FROM foo' LANGUAGE SQL;
</programlisting> </programlisting>
</para> </para>
</refsect1> </refsect1>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/select.sgml,v 1.57 2002/08/28 14:35:37 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/select.sgml,v 1.58 2002/08/29 00:17:01 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -40,10 +40,10 @@ where <replaceable class="PARAMETER">from_item</replaceable> can be: ...@@ -40,10 +40,10 @@ where <replaceable class="PARAMETER">from_item</replaceable> can be:
( <replaceable class="PARAMETER">select</replaceable> ) ( <replaceable class="PARAMETER">select</replaceable> )
[ AS ] <replaceable class="PARAMETER">alias</replaceable> [ ( <replaceable class="PARAMETER">column_alias_list</replaceable> ) ] [ AS ] <replaceable class="PARAMETER">alias</replaceable> [ ( <replaceable class="PARAMETER">column_alias_list</replaceable> ) ]
| |
<replaceable class="PARAMETER">table_function_name</replaceable> ( [ <replaceable class="parameter">argtype</replaceable> [, ...] ] ) <replaceable class="PARAMETER">table_function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] )
[ AS ] <replaceable class="PARAMETER">alias</replaceable> [ ( <replaceable class="PARAMETER">column_alias_list</replaceable> | <replaceable class="PARAMETER">column_definition_list</replaceable> ) ] [ AS ] <replaceable class="PARAMETER">alias</replaceable> [ ( <replaceable class="PARAMETER">column_alias_list</replaceable> | <replaceable class="PARAMETER">column_definition_list</replaceable> ) ]
| |
<replaceable class="PARAMETER">table_function_name</replaceable> ( [ <replaceable class="parameter">argtype</replaceable> [, ...] ] ) <replaceable class="PARAMETER">table_function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] )
AS ( <replaceable class="PARAMETER">column_definition_list</replaceable> ) AS ( <replaceable class="PARAMETER">column_definition_list</replaceable> )
| |
<replaceable class="PARAMETER">from_item</replaceable> [ NATURAL ] <replaceable class="PARAMETER">join_type</replaceable> <replaceable class="PARAMETER">from_item</replaceable> <replaceable class="PARAMETER">from_item</replaceable> [ NATURAL ] <replaceable class="PARAMETER">join_type</replaceable> <replaceable class="PARAMETER">from_item</replaceable>
...@@ -142,10 +142,14 @@ where <replaceable class="PARAMETER">from_item</replaceable> can be: ...@@ -142,10 +142,14 @@ where <replaceable class="PARAMETER">from_item</replaceable> can be:
<term><replaceable class="PARAMETER">alias</replaceable></term> <term><replaceable class="PARAMETER">alias</replaceable></term>
<listitem> <listitem>
<para> <para>
A substitute name for the preceding A substitute name for the FROM item containing the alias.
<replaceable class="PARAMETER">table_name</replaceable>.
An alias is used for brevity or to eliminate ambiguity for self-joins An alias is used for brevity or to eliminate ambiguity for self-joins
(where the same table is scanned multiple times). If an alias is (where the same table is scanned multiple times). When an alias
is provided, it completely hides the actual name of the table or
table function; for example given <literal>FROM foo AS f</>, the
remainder of the SELECT must refer to this FROM item as <literal>f</>
not <literal>foo</>.
If an alias is
written, a column alias list can also be written to provide written, a column alias list can also be written to provide
substitute names for one or more columns of the table. substitute names for one or more columns of the table.
</para> </para>
...@@ -172,12 +176,15 @@ where <replaceable class="PARAMETER">from_item</replaceable> can be: ...@@ -172,12 +176,15 @@ where <replaceable class="PARAMETER">from_item</replaceable> can be:
A table function can appear in the FROM clause. This acts as though A table function can appear in the FROM clause. This acts as though
its output were created as a temporary table for the duration of its output were created as a temporary table for the duration of
this single SELECT command. An alias may also be used. If an alias is this single SELECT command. An alias may also be used. If an alias is
written, a column alias list can also be written to provide substitute names written, a column alias list can also be written to provide substitute
for one or more columns of the table function. If the table function has been names for one or more columns of the table function. If the table
defined as returning the RECORD data type, an alias, or the keyword AS, must function has been defined as returning the <type>record</> data type,
also be present, followed by a column definition list in the form an alias, or the keyword <literal>AS</>, must be present, followed by
( <replaceable class="PARAMETER">column_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [, ... ] ). a column definition list in the form ( <replaceable
The column definition list must match the actual number and types returned by the function. class="PARAMETER">column_name</replaceable> <replaceable
class="PARAMETER">data_type</replaceable> [, ... ] ).
The column definition list must match the actual number and types
of columns returned by the function.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -395,7 +402,7 @@ where <replaceable class="PARAMETER">from_item</replaceable> can be: ...@@ -395,7 +402,7 @@ where <replaceable class="PARAMETER">from_item</replaceable> can be:
this was the default result, and adding sub-tables was done this was the default result, and adding sub-tables was done
by appending <command>*</command> to the table name. by appending <command>*</command> to the table name.
This old behavior is available via the command This old behavior is available via the command
<command>SET SQL_Inheritance TO OFF;</command> <command>SET SQL_Inheritance TO OFF</command>.
</para> </para>
<para> <para>
...@@ -406,16 +413,22 @@ where <replaceable class="PARAMETER">from_item</replaceable> can be: ...@@ -406,16 +413,22 @@ where <replaceable class="PARAMETER">from_item</replaceable> can be:
</para> </para>
<para> <para>
A FROM item can be a table function (i.e. a function that returns A FROM item can be a table function (typically, a function that returns
multiple rows and columns). When a table function is created, it may multiple rows and/or columns, though actually any function can be used).
be defined to return a named scalar or composite data type (an existing The function is invoked with the given argument value(s), and then its
scalar data type, or a table or view name), or it may be defined to return output is scanned as though it were a table.
a RECORD data type. When a table function is defined to return RECORD, it </para>
must be followed in the FROM clause by an alias, or the keyword AS alone,
and then by a parenthesized list of column names and types. This provides <para>
a query-time composite type definition. The FROM clause composite type In some cases it is useful to define table functions that can return
must match the actual composite type returned from the function or an different column sets depending on how they are invoked. To support this,
ERROR will be generated. the table function can be declared as returning the pseudo-type
<type>record</>. When such a function is used in FROM, it must be
followed by an alias, or the keyword <literal>AS</> alone,
and then by a parenthesized list of column names and types. This provides
a query-time composite type definition. The composite type definition
must match the actual composite type returned from the function, or an
error will be reported at run-time.
</para> </para>
<para> <para>
...@@ -827,6 +840,38 @@ SELECT name FROM distributors ORDER BY code; ...@@ -827,6 +840,38 @@ SELECT name FROM distributors ORDER BY code;
unless ORDER BY is used to constrain the order. unless ORDER BY is used to constrain the order.
</para> </para>
</refsect2> </refsect2>
<refsect2 id="SQL-FOR-UPDATE">
<refsect2info>
<date>2002-08-28</date>
</refsect2info>
<title id="sql-for-update-title">
FOR UPDATE Clause
</title>
<para>
<synopsis>
FOR UPDATE [ OF <replaceable class="PARAMETER">tablename</replaceable> [, ...] ]
</synopsis>
</para>
<para>
FOR UPDATE causes the rows retrieved by the query to be locked as though
for update. This prevents them from being modified or deleted by other
transactions until the current transaction ends.
</para>
<para>
If specific tables are named in FOR UPDATE, then only rows coming from
those tables are locked.
</para>
<para>
FOR UPDATE cannot be used in contexts where returned rows can't be clearly
identified with individual table rows; for example it can't be used with
aggregation.
</para>
</refsect2>
</refsect1> </refsect1>
<refsect1 id="R1-SQL-SELECT-2"> <refsect1 id="R1-SQL-SELECT-2">
...@@ -1019,8 +1064,7 @@ SELECT * FROM distributors_2(111) AS (f1 int, f2 text); ...@@ -1019,8 +1064,7 @@ SELECT * FROM distributors_2(111) AS (f1 int, f2 text);
<productname>PostgreSQL</productname> allows one to omit <productname>PostgreSQL</productname> allows one to omit
the <command>FROM</command> clause from a query. This feature the <command>FROM</command> clause from a query. This feature
was retained from the original PostQuel query language. It has was retained from the original PostQuel query language. It has
a straightforward use to compute the results of simple constant a straightforward use to compute the results of simple expressions:
expressions:
<programlisting> <programlisting>
SELECT 2+2; SELECT 2+2;
...@@ -1062,6 +1106,11 @@ and later will warn if the implicit-FROM feature is used in a query that also ...@@ -1062,6 +1106,11 @@ and later will warn if the implicit-FROM feature is used in a query that also
contains an explicit FROM clause. contains an explicit FROM clause.
</para> </para>
<para>
The table-function feature is a <productname>PostgreSQL</productname>
extension.
</para>
</refsect2> </refsect2>
<refsect2 id="R2-SQL-SELECT-5"> <refsect2 id="R2-SQL-SELECT-5">
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/select_into.sgml,v 1.19 2002/08/28 14:35:37 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/select_into.sgml,v 1.20 2002/08/29 00:17:01 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -29,20 +29,9 @@ SELECT [ ALL | DISTINCT [ ON ( <replaceable class="PARAMETER">expression</replac ...@@ -29,20 +29,9 @@ SELECT [ ALL | DISTINCT [ ON ( <replaceable class="PARAMETER">expression</replac
[ HAVING <replaceable class="PARAMETER">condition</replaceable> [, ...] ] [ HAVING <replaceable class="PARAMETER">condition</replaceable> [, ...] ]
[ { UNION | INTERSECT | EXCEPT } [ ALL ] <replaceable class="PARAMETER">select</replaceable> ] [ { UNION | INTERSECT | EXCEPT } [ ALL ] <replaceable class="PARAMETER">select</replaceable> ]
[ ORDER BY <replaceable class="PARAMETER">expression</replaceable> [ ASC | DESC | USING <replaceable class="PARAMETER">operator</replaceable> ] [, ...] ] [ ORDER BY <replaceable class="PARAMETER">expression</replaceable> [ ASC | DESC | USING <replaceable class="PARAMETER">operator</replaceable> ] [, ...] ]
[ LIMIT [ <replaceable class="PARAMETER">start</replaceable> , ] { <replaceable class="PARAMETER">count</replaceable> | ALL } ] [ LIMIT { <replaceable class="PARAMETER">count</replaceable> | ALL } ]
[ OFFSET <replaceable class="PARAMETER">start</replaceable> ] [ OFFSET <replaceable class="PARAMETER">start</replaceable> ]
[ FOR UPDATE [ OF <replaceable class="PARAMETER">tablename</replaceable> [, ...] ] ] [ FOR UPDATE [ OF <replaceable class="PARAMETER">tablename</replaceable> [, ...] ] ]
where <replaceable class="PARAMETER">from_item</replaceable> can be:
[ ONLY ] <replaceable class="PARAMETER">table_name</replaceable> [ * ]
[ [ AS ] <replaceable class="PARAMETER">alias</replaceable> [ ( <replaceable class="PARAMETER">column_alias_list</replaceable> ) ] ]
|
( <replaceable class="PARAMETER">select</replaceable> )
[ AS ] <replaceable class="PARAMETER">alias</replaceable> [ ( <replaceable class="PARAMETER">column_alias_list</replaceable> ) ]
|
<replaceable class="PARAMETER">from_item</replaceable> [ NATURAL ] <replaceable class="PARAMETER">join_type</replaceable> <replaceable class="PARAMETER">from_item</replaceable>
[ ON <replaceable class="PARAMETER">join_condition</replaceable> | USING ( <replaceable class="PARAMETER">join_column_list</replaceable> ) ]
</synopsis> </synopsis>
<refsect2 id="R2-SQL-SELECTINTO-1"> <refsect2 id="R2-SQL-SELECTINTO-1">
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.152 2002/08/27 04:55:07 tgl Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.153 2002/08/29 00:17:01 tgl Exp $
--> -->
<appendix id="release"> <appendix id="release">
...@@ -26,6 +26,7 @@ worries about funny characters. ...@@ -26,6 +26,7 @@ worries about funny characters.
<literallayout><![CDATA[ <literallayout><![CDATA[
PREPARE statement allows caching query plans for interactive statements PREPARE statement allows caching query plans for interactive statements
Type OPAQUE is now deprecated in favor of pseudo-types cstring, trigger, etc Type OPAQUE is now deprecated in favor of pseudo-types cstring, trigger, etc
Standalone composite types can now be created with CREATE TYPE
Files larger than 2 GB are now supported (if supported by the operating system) Files larger than 2 GB are now supported (if supported by the operating system)
SERIAL no longer implies UNIQUE; specify explicitly if index is wanted SERIAL no longer implies UNIQUE; specify explicitly if index is wanted
pg_dump -n and -N options have been removed. The new behavior is like -n but knows about key words. pg_dump -n and -N options have been removed. The new behavior is like -n but knows about key words.
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.85 2002/08/05 02:30:49 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.86 2002/08/29 00:17:02 tgl Exp $
* *
* NOTES * NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be * some of the executor utility code such as "ExecTypeFromTL" should be
...@@ -570,7 +570,7 @@ BuildDescForRelation(List *schema) ...@@ -570,7 +570,7 @@ BuildDescForRelation(List *schema)
* Given a (possibly qualified) relation name, build a TupleDesc. * Given a (possibly qualified) relation name, build a TupleDesc.
*/ */
TupleDesc TupleDesc
RelationNameGetTupleDesc(char *relname) RelationNameGetTupleDesc(const char *relname)
{ {
RangeVar *relvar; RangeVar *relvar;
Relation rel; Relation rel;
...@@ -580,7 +580,7 @@ RelationNameGetTupleDesc(char *relname) ...@@ -580,7 +580,7 @@ RelationNameGetTupleDesc(char *relname)
/* Open relation and get the tuple description */ /* Open relation and get the tuple description */
relname_list = stringToQualifiedNameList(relname, "RelationNameGetTupleDesc"); relname_list = stringToQualifiedNameList(relname, "RelationNameGetTupleDesc");
relvar = makeRangeVarFromNameList(relname_list); relvar = makeRangeVarFromNameList(relname_list);
rel = heap_openrv(relvar, AccessShareLock); rel = relation_openrv(relvar, AccessShareLock);
tupdesc = CreateTupleDescCopy(RelationGetDescr(rel)); tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
relation_close(rel, AccessShareLock); relation_close(rel, AccessShareLock);
...@@ -611,50 +611,46 @@ TypeGetTupleDesc(Oid typeoid, List *colaliases) ...@@ -611,50 +611,46 @@ TypeGetTupleDesc(Oid typeoid, List *colaliases)
{ {
/* Composite data type, i.e. a table's row type */ /* Composite data type, i.e. a table's row type */
Oid relid = typeidTypeRelid(typeoid); Oid relid = typeidTypeRelid(typeoid);
Relation rel;
int natts;
if (OidIsValid(relid)) if (!OidIsValid(relid))
{ elog(ERROR, "Invalid typrelid for complex type %u", typeoid);
Relation rel;
int natts;
rel = relation_open(relid, AccessShareLock); rel = relation_open(relid, AccessShareLock);
tupdesc = CreateTupleDescCopy(RelationGetDescr(rel)); tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
natts = tupdesc->natts; natts = tupdesc->natts;
relation_close(rel, AccessShareLock); relation_close(rel, AccessShareLock);
/* XXX should we hold the lock to ensure table doesn't change? */
/* check to see if we've given column aliases */ if (colaliases != NIL)
if(colaliases != NIL) {
{ int varattno;
char *label;
int varattno;
/* does the List length match the number of attributes */ /* does the list length match the number of attributes? */
if (length(colaliases) != natts) if (length(colaliases) != natts)
elog(ERROR, "TypeGetTupleDesc: number of aliases does not match number of attributes"); elog(ERROR, "TypeGetTupleDesc: number of aliases does not match number of attributes");
/* OK, use the aliases instead */ /* OK, use the aliases instead */
for (varattno = 0; varattno < natts; varattno++) for (varattno = 0; varattno < natts; varattno++)
{ {
label = strVal(nth(varattno, colaliases)); char *label = strVal(nth(varattno, colaliases));
if (label != NULL) if (label != NULL)
namestrcpy(&(tupdesc->attrs[varattno]->attname), label); namestrcpy(&(tupdesc->attrs[varattno]->attname), label);
}
} }
} }
else
elog(ERROR, "Invalid return relation specified for function");
} }
else if (functyptype == 'b' || functyptype == 'd') else if (functyptype == 'b' || functyptype == 'd')
{ {
/* Must be a base data type, i.e. scalar */ /* Must be a base data type, i.e. scalar */
char *attname; char *attname;
/* the alias List is required for base types */ /* the alias list is required for base types */
if (colaliases == NIL) if (colaliases == NIL)
elog(ERROR, "TypeGetTupleDesc: no column alias was provided"); elog(ERROR, "TypeGetTupleDesc: no column alias was provided");
/* the alias List length must be 1 */ /* the alias list length must be 1 */
if (length(colaliases) != 1) if (length(colaliases) != 1)
elog(ERROR, "TypeGetTupleDesc: number of aliases does not match number of attributes"); elog(ERROR, "TypeGetTupleDesc: number of aliases does not match number of attributes");
...@@ -671,8 +667,7 @@ TypeGetTupleDesc(Oid typeoid, List *colaliases) ...@@ -671,8 +667,7 @@ TypeGetTupleDesc(Oid typeoid, List *colaliases)
false); false);
} }
else if (functyptype == 'p' && typeoid == RECORDOID) else if (functyptype == 'p' && typeoid == RECORDOID)
elog(ERROR, "Unable to determine tuple description for function" elog(ERROR, "Unable to determine tuple description for function returning \"record\"");
" returning \"record\"");
else else
elog(ERROR, "Unknown kind of return type specified for function"); elog(ERROR, "Unknown kind of return type specified for function");
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.145 2002/08/13 20:11:03 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.146 2002/08/29 00:17:02 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -607,6 +607,9 @@ heap_open(Oid relationId, LOCKMODE lockmode) ...@@ -607,6 +607,9 @@ heap_open(Oid relationId, LOCKMODE lockmode)
else if (r->rd_rel->relkind == RELKIND_SPECIAL) else if (r->rd_rel->relkind == RELKIND_SPECIAL)
elog(ERROR, "%s is a special relation", elog(ERROR, "%s is a special relation",
RelationGetRelationName(r)); RelationGetRelationName(r));
else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
elog(ERROR, "%s is a composite type",
RelationGetRelationName(r));
pgstat_initstats(&r->pgstat_info, r); pgstat_initstats(&r->pgstat_info, r);
...@@ -633,6 +636,9 @@ heap_openrv(const RangeVar *relation, LOCKMODE lockmode) ...@@ -633,6 +636,9 @@ heap_openrv(const RangeVar *relation, LOCKMODE lockmode)
else if (r->rd_rel->relkind == RELKIND_SPECIAL) else if (r->rd_rel->relkind == RELKIND_SPECIAL)
elog(ERROR, "%s is a special relation", elog(ERROR, "%s is a special relation",
RelationGetRelationName(r)); RelationGetRelationName(r));
else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
elog(ERROR, "%s is a composite type",
RelationGetRelationName(r));
pgstat_initstats(&r->pgstat_info, r); pgstat_initstats(&r->pgstat_info, r);
...@@ -659,6 +665,9 @@ heap_openr(const char *sysRelationName, LOCKMODE lockmode) ...@@ -659,6 +665,9 @@ heap_openr(const char *sysRelationName, LOCKMODE lockmode)
else if (r->rd_rel->relkind == RELKIND_SPECIAL) else if (r->rd_rel->relkind == RELKIND_SPECIAL)
elog(ERROR, "%s is a special relation", elog(ERROR, "%s is a special relation",
RelationGetRelationName(r)); RelationGetRelationName(r));
else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
elog(ERROR, "%s is a composite type",
RelationGetRelationName(r));
pgstat_initstats(&r->pgstat_info, r); pgstat_initstats(&r->pgstat_info, r);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.221 2002/08/15 16:36:00 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.222 2002/08/29 00:17:02 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -69,6 +69,7 @@ static void AddNewRelationTuple(Relation pg_class_desc, ...@@ -69,6 +69,7 @@ static void AddNewRelationTuple(Relation pg_class_desc,
static void AddNewRelationType(const char *typeName, static void AddNewRelationType(const char *typeName,
Oid typeNamespace, Oid typeNamespace,
Oid new_rel_oid, Oid new_rel_oid,
char new_rel_kind,
Oid new_type_oid); Oid new_type_oid);
static void RelationRemoveInheritance(Relation relation); static void RelationRemoveInheritance(Relation relation);
static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin); static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin);
...@@ -357,7 +358,7 @@ CheckAttributeNames(TupleDesc tupdesc, bool relhasoids, char relkind) ...@@ -357,7 +358,7 @@ 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 and type relation, since it doesn't have system * Skip this for a view or type relation, since those don't have system
* attributes. * attributes.
*/ */
if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE) if (relkind != RELKIND_VIEW && relkind != RELKIND_COMPOSITE_TYPE)
...@@ -618,6 +619,7 @@ static void ...@@ -618,6 +619,7 @@ static void
AddNewRelationType(const char *typeName, AddNewRelationType(const char *typeName,
Oid typeNamespace, Oid typeNamespace,
Oid new_rel_oid, Oid new_rel_oid,
char new_rel_kind,
Oid new_type_oid) Oid new_type_oid)
{ {
/* /*
...@@ -633,6 +635,7 @@ AddNewRelationType(const char *typeName, ...@@ -633,6 +635,7 @@ AddNewRelationType(const char *typeName,
typeNamespace, /* type namespace */ typeNamespace, /* type namespace */
new_type_oid, /* preassigned oid for type */ new_type_oid, /* preassigned oid for type */
new_rel_oid, /* relation oid */ new_rel_oid, /* relation oid */
new_rel_kind, /* relation kind */
sizeof(Oid), /* internal size */ sizeof(Oid), /* internal size */
'c', /* type-type (complex) */ 'c', /* type-type (complex) */
',', /* default array delimiter */ ',', /* default array delimiter */
...@@ -728,7 +731,11 @@ heap_create_with_catalog(const char *relname, ...@@ -728,7 +731,11 @@ heap_create_with_catalog(const char *relname,
* NOTE: we could get a unique-index failure here, in case the same name * NOTE: we could get a unique-index failure here, in case the same name
* has already been used for a type. * has already been used for a type.
*/ */
AddNewRelationType(relname, relnamespace, new_rel_oid, new_type_oid); AddNewRelationType(relname,
relnamespace,
new_rel_oid,
relkind,
new_type_oid);
/* /*
* now add tuples to pg_attribute for the attributes in our new * now add tuples to pg_attribute for the attributes in our new
...@@ -904,7 +911,7 @@ RemoveAttributeById(Oid relid, AttrNumber attnum) ...@@ -904,7 +911,7 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
* did this ... but when cascading from a drop of some other object, * did this ... but when cascading from a drop of some other object,
* we may not have any lock.) * we may not have any lock.)
*/ */
rel = heap_open(relid, AccessExclusiveLock); rel = relation_open(relid, AccessExclusiveLock);
attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock); attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);
...@@ -943,7 +950,7 @@ RemoveAttributeById(Oid relid, AttrNumber attnum) ...@@ -943,7 +950,7 @@ RemoveAttributeById(Oid relid, AttrNumber attnum)
heap_close(attr_rel, RowExclusiveLock); heap_close(attr_rel, RowExclusiveLock);
heap_close(rel, NoLock); relation_close(rel, NoLock);
} }
/* /*
...@@ -1036,7 +1043,7 @@ RemoveAttrDefaultById(Oid attrdefId) ...@@ -1036,7 +1043,7 @@ RemoveAttrDefaultById(Oid attrdefId)
myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum; myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
/* Get an exclusive lock on the relation owning the attribute */ /* Get an exclusive lock on the relation owning the attribute */
myrel = heap_open(myrelid, AccessExclusiveLock); myrel = relation_open(myrelid, AccessExclusiveLock);
/* Now we can delete the pg_attrdef row */ /* Now we can delete the pg_attrdef row */
simple_heap_delete(attrdef_rel, &tuple->t_self); simple_heap_delete(attrdef_rel, &tuple->t_self);
...@@ -1069,7 +1076,7 @@ RemoveAttrDefaultById(Oid attrdefId) ...@@ -1069,7 +1076,7 @@ RemoveAttrDefaultById(Oid attrdefId)
heap_close(attr_rel, RowExclusiveLock); heap_close(attr_rel, RowExclusiveLock);
/* Keep lock on attribute's rel until end of xact */ /* Keep lock on attribute's rel until end of xact */
heap_close(myrel, NoLock); relation_close(myrel, NoLock);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -1099,7 +1106,7 @@ heap_drop_with_catalog(Oid rid) ...@@ -1099,7 +1106,7 @@ heap_drop_with_catalog(Oid rid)
/* /*
* Open and lock the relation. * Open and lock the relation.
*/ */
rel = heap_open(rid, AccessExclusiveLock); rel = relation_open(rid, AccessExclusiveLock);
/* /*
* Release all buffers that belong to this relation, after writing any * Release all buffers that belong to this relation, after writing any
...@@ -1134,7 +1141,7 @@ heap_drop_with_catalog(Oid rid) ...@@ -1134,7 +1141,7 @@ 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) rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE)
smgrunlink(DEFAULT_SMGR, rel); smgrunlink(DEFAULT_SMGR, rel);
/* /*
...@@ -1142,7 +1149,7 @@ heap_drop_with_catalog(Oid rid) ...@@ -1142,7 +1149,7 @@ heap_drop_with_catalog(Oid rid)
* relation until transaction commit. This ensures no one else will * relation until transaction commit. This ensures no one else will
* try to do something with the doomed relation. * try to do something with the doomed relation.
*/ */
heap_close(rel, NoLock); relation_close(rel, NoLock);
/* /*
* flush the relation from the relcache * flush the relation from the relcache
......
...@@ -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.31 2002/08/15 16:36:01 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.32 2002/08/29 00:17:02 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1585,7 +1585,6 @@ RemoveTempRelations(Oid tempNamespaceId) ...@@ -1585,7 +1585,6 @@ 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_proc.c,v 1.90 2002/08/23 16:41:37 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.91 2002/08/29 00:17:03 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -400,7 +400,7 @@ checkretval(Oid rettype, char fn_typtype, List *queryTreeList) ...@@ -400,7 +400,7 @@ checkretval(Oid rettype, char fn_typtype, List *queryTreeList)
* attributes to ensure that they match the datatypes of the * attributes to ensure that they match the datatypes of the
* non-resjunk columns. * non-resjunk columns.
*/ */
reln = heap_open(typerelid, AccessShareLock); reln = relation_open(typerelid, AccessShareLock);
relnatts = reln->rd_rel->relnatts; relnatts = reln->rd_rel->relnatts;
rellogcols = 0; /* we'll count nondeleted cols as we go */ rellogcols = 0; /* we'll count nondeleted cols as we go */
colindex = 0; colindex = 0;
...@@ -447,7 +447,7 @@ checkretval(Oid rettype, char fn_typtype, List *queryTreeList) ...@@ -447,7 +447,7 @@ checkretval(Oid rettype, char fn_typtype, List *queryTreeList)
elog(ERROR, "function declared to return %s does not SELECT the right number of columns (%d)", elog(ERROR, "function declared to return %s does not SELECT the right number of columns (%d)",
format_type_be(rettype), rellogcols); format_type_be(rettype), rellogcols);
heap_close(reln, AccessShareLock); relation_close(reln, AccessShareLock);
} }
else if (fn_typtype == 'p' && rettype == RECORDOID) else if (fn_typtype == 'p' && rettype == RECORDOID)
{ {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.79 2002/08/24 15:00:46 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.80 2002/08/29 00:17:03 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -129,7 +129,8 @@ Oid ...@@ -129,7 +129,8 @@ Oid
TypeCreate(const char *typeName, TypeCreate(const char *typeName,
Oid typeNamespace, Oid typeNamespace,
Oid assignedTypeOid, Oid assignedTypeOid,
Oid relationOid, /* only for 'c'atalog typeTypes */ Oid relationOid, /* only for 'c'atalog typeType */
char relationKind, /* ditto */
int16 internalSize, int16 internalSize,
char typeType, char typeType,
char typDelim, char typDelim,
...@@ -332,15 +333,11 @@ TypeCreate(const char *typeName, ...@@ -332,15 +333,11 @@ TypeCreate(const char *typeName,
*/ */
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;
if (relkind != RELKIND_COMPOSITE_TYPE) if (relationKind != RELKIND_COMPOSITE_TYPE)
recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL); recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL);
else else
recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL); recordDependencyOn(&referenced, &myself, DEPENDENCY_INTERNAL);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 1996-2001, PostgreSQL Global Development Group * Copyright (c) 1996-2001, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.57 2002/08/22 00:01:41 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.58 2002/08/29 00:17:03 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -362,7 +362,7 @@ CommentAttribute(List *qualname, char *comment) ...@@ -362,7 +362,7 @@ CommentAttribute(List *qualname, char *comment)
/* Open the containing relation to ensure it won't go away meanwhile */ /* Open the containing relation to ensure it won't go away meanwhile */
rel = makeRangeVarFromNameList(relname); rel = makeRangeVarFromNameList(relname);
relation = heap_openrv(rel, AccessShareLock); relation = relation_openrv(rel, AccessShareLock);
/* Check object security */ /* Check object security */
...@@ -383,7 +383,7 @@ CommentAttribute(List *qualname, char *comment) ...@@ -383,7 +383,7 @@ CommentAttribute(List *qualname, char *comment)
/* Done, but hold lock until commit */ /* Done, but hold lock until commit */
heap_close(relation, NoLock); relation_close(relation, NoLock);
} }
/* /*
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.167 2002/08/24 15:00:46 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.168 2002/08/29 00:17:03 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -399,9 +399,6 @@ DoCopy(const CopyStmt *stmt) ...@@ -399,9 +399,6 @@ 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));
...@@ -447,9 +444,6 @@ DoCopy(const CopyStmt *stmt) ...@@ -447,9 +444,6 @@ 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));
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California * Portions Copyright (c) 1994-5, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.84 2002/07/20 15:12:55 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.85 2002/08/29 00:17:03 tgl Exp $
* *
*/ */
...@@ -79,7 +79,7 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest) ...@@ -79,7 +79,7 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest)
if (query->commandType == CMD_UTILITY) if (query->commandType == CMD_UTILITY)
{ {
/* rewriter will not cope with utility statements */ /* rewriter will not cope with utility statements */
PROJECT_LINE_OF_TEXT(tstate, "Utility statements have no plan structure"); do_text_output_oneline(tstate, "Utility statements have no plan structure");
} }
else else
{ {
...@@ -89,7 +89,7 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest) ...@@ -89,7 +89,7 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest)
if (rewritten == NIL) if (rewritten == NIL)
{ {
/* In the case of an INSTEAD NOTHING, tell at least that */ /* In the case of an INSTEAD NOTHING, tell at least that */
PROJECT_LINE_OF_TEXT(tstate, "Query rewrites to nothing"); do_text_output_oneline(tstate, "Query rewrites to nothing");
} }
else else
{ {
...@@ -99,7 +99,7 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest) ...@@ -99,7 +99,7 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest)
ExplainOneQuery(lfirst(l), stmt, tstate); ExplainOneQuery(lfirst(l), stmt, tstate);
/* put a blank line between plans */ /* put a blank line between plans */
if (lnext(l) != NIL) if (lnext(l) != NIL)
PROJECT_LINE_OF_TEXT(tstate, ""); do_text_output_oneline(tstate, "");
} }
} }
} }
...@@ -122,9 +122,9 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate) ...@@ -122,9 +122,9 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
if (query->commandType == CMD_UTILITY) if (query->commandType == CMD_UTILITY)
{ {
if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt)) if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
PROJECT_LINE_OF_TEXT(tstate, "NOTIFY"); do_text_output_oneline(tstate, "NOTIFY");
else else
PROJECT_LINE_OF_TEXT(tstate, "UTILITY"); do_text_output_oneline(tstate, "UTILITY");
return; return;
} }
...@@ -189,7 +189,7 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate) ...@@ -189,7 +189,7 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
do_text_output_multiline(tstate, f); do_text_output_multiline(tstate, f);
pfree(f); pfree(f);
if (es->printCost) if (es->printCost)
PROJECT_LINE_OF_TEXT(tstate, ""); /* separator line */ do_text_output_oneline(tstate, ""); /* separator line */
} }
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.35 2002/08/28 20:18:29 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.36 2002/08/29 00:17:03 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -228,7 +228,7 @@ DefineRelation(CreateStmt *stmt, char relkind) ...@@ -228,7 +228,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
* see the new rel anyway until we commit), but it keeps the lock * see the new rel anyway until we commit), but it keeps the lock
* manager from complaining about deadlock risks. * manager from complaining about deadlock risks.
*/ */
rel = heap_open(relationId, AccessExclusiveLock); rel = relation_open(relationId, AccessExclusiveLock);
/* /*
* Now add any newly specified column default values and CHECK * Now add any newly specified column default values and CHECK
...@@ -293,7 +293,7 @@ DefineRelation(CreateStmt *stmt, char relkind) ...@@ -293,7 +293,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
* Clean up. We keep lock on new relation (although it shouldn't be * Clean up. We keep lock on new relation (although it shouldn't be
* visible to anyone else anyway, until commit). * visible to anyone else anyway, until commit).
*/ */
heap_close(rel, NoLock); relation_close(rel, NoLock);
return relationId; return relationId;
} }
...@@ -1064,7 +1064,7 @@ renameatt(Oid relid, ...@@ -1064,7 +1064,7 @@ renameatt(Oid relid,
* Grab an exclusive lock on the target table, which we will NOT * Grab an exclusive lock on the target table, which we will NOT
* release until end of transaction. * release until end of transaction.
*/ */
targetrelation = heap_open(relid, AccessExclusiveLock); targetrelation = relation_open(relid, AccessExclusiveLock);
/* /*
* permissions checking. this would normally be done in utility.c, * permissions checking. this would normally be done in utility.c,
...@@ -1210,7 +1210,7 @@ renameatt(Oid relid, ...@@ -1210,7 +1210,7 @@ renameatt(Oid relid,
true, false); true, false);
} }
heap_close(targetrelation, NoLock); /* close rel but keep lock! */ relation_close(targetrelation, NoLock); /* close rel but keep lock! */
} }
/* /*
...@@ -3247,13 +3247,12 @@ CheckTupleType(Form_pg_class tuple_class) ...@@ -3247,13 +3247,12 @@ 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, type, or sequence", elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table, TOAST table, index, view, 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.11 2002/08/23 16:41:37 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.12 2002/08/29 00:17:03 tgl 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
...@@ -233,6 +233,7 @@ DefineType(List *names, List *parameters) ...@@ -233,6 +233,7 @@ DefineType(List *names, List *parameters)
typeNamespace, /* namespace */ typeNamespace, /* namespace */
InvalidOid, /* preassigned type oid (not done here) */ InvalidOid, /* preassigned type oid (not done here) */
InvalidOid, /* relation oid (n/a here) */ InvalidOid, /* relation oid (n/a here) */
0, /* relation kind (ditto) */
internalLength, /* internal size */ internalLength, /* internal size */
'b', /* type-type (base type) */ 'b', /* type-type (base type) */
delimiter, /* array element delimiter */ delimiter, /* array element delimiter */
...@@ -262,6 +263,7 @@ DefineType(List *names, List *parameters) ...@@ -262,6 +263,7 @@ DefineType(List *names, List *parameters)
typeNamespace, /* namespace */ typeNamespace, /* namespace */
InvalidOid, /* preassigned type oid (not done here) */ InvalidOid, /* preassigned type oid (not done here) */
InvalidOid, /* relation oid (n/a here) */ InvalidOid, /* relation oid (n/a here) */
0, /* relation kind (ditto) */
-1, /* internal size */ -1, /* internal size */
'b', /* type-type (base type) */ 'b', /* type-type (base type) */
DEFAULT_TYPDELIM, /* array element delimiter */ DEFAULT_TYPDELIM, /* array element delimiter */
...@@ -562,6 +564,7 @@ DefineDomain(CreateDomainStmt *stmt) ...@@ -562,6 +564,7 @@ DefineDomain(CreateDomainStmt *stmt)
domainNamespace, /* namespace */ domainNamespace, /* namespace */
InvalidOid, /* preassigned type oid (none here) */ InvalidOid, /* preassigned type oid (none here) */
InvalidOid, /* relation oid (n/a here) */ InvalidOid, /* relation oid (n/a here) */
0, /* relation kind (ditto) */
internalLength, /* internal size */ internalLength, /* internal size */
'd', /* type-type (domain type) */ 'd', /* type-type (domain type) */
delimiter, /* array element delimiter */ delimiter, /* array element delimiter */
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.175 2002/08/28 20:46:22 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.176 2002/08/29 00:17:03 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -786,10 +786,6 @@ initResultRelInfo(ResultRelInfo *resultRelInfo, ...@@ -786,10 +786,6 @@ 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 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.56 2002/07/20 05:49:27 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.57 2002/08/29 00:17:03 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -109,8 +109,9 @@ ...@@ -109,8 +109,9 @@
#include "funcapi.h" #include "funcapi.h"
#include "access/heapam.h" #include "access/heapam.h"
#include "catalog/pg_type.h"
#include "executor/executor.h" #include "executor/executor.h"
#include "utils/lsyscache.h"
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* tuple table create/delete functions * tuple table create/delete functions
...@@ -676,8 +677,7 @@ ExecTypeFromTL(List *targetList, hasoid_t withoid) ...@@ -676,8 +677,7 @@ ExecTypeFromTL(List *targetList, hasoid_t withoid)
} }
/* /*
* TupleDescGetSlot - Initialize a slot based on the supplied * TupleDescGetSlot - Initialize a slot based on the supplied tupledesc
* tupledesc
*/ */
TupleTableSlot * TupleTableSlot *
TupleDescGetSlot(TupleDesc tupdesc) TupleDescGetSlot(TupleDesc tupdesc)
...@@ -695,40 +695,36 @@ TupleDescGetSlot(TupleDesc tupdesc) ...@@ -695,40 +695,36 @@ TupleDescGetSlot(TupleDesc tupdesc)
} }
/* /*
* TupleDescGetAttInMetadata - Get a pointer to AttInMetadata based on the * TupleDescGetAttInMetadata - Build an AttInMetadata structure based on the
* supplied TupleDesc. AttInMetadata can be used in conjunction with C strings * supplied TupleDesc. AttInMetadata can be used in conjunction with C strings
* to produce a properly formed tuple. * to produce a properly formed tuple.
*/ */
AttInMetadata * AttInMetadata *
TupleDescGetAttInMetadata(TupleDesc tupdesc) TupleDescGetAttInMetadata(TupleDesc tupdesc)
{ {
int natts; int natts = tupdesc->natts;
int i; int i;
Oid atttypeid; Oid atttypeid;
Oid attinfuncid; Oid attinfuncid;
Oid attelem;
FmgrInfo *attinfuncinfo; FmgrInfo *attinfuncinfo;
Oid *attelems; Oid *attelems;
int4 *atttypmods; int32 *atttypmods;
AttInMetadata *attinmeta; AttInMetadata *attinmeta;
attinmeta = (AttInMetadata *) palloc(sizeof(AttInMetadata)); attinmeta = (AttInMetadata *) palloc(sizeof(AttInMetadata));
natts = tupdesc->natts;
/* /*
* Gather info needed later to call the "in" function for each attribute * Gather info needed later to call the "in" function for each attribute
*/ */
attinfuncinfo = (FmgrInfo *) palloc(natts * sizeof(FmgrInfo)); attinfuncinfo = (FmgrInfo *) palloc(natts * sizeof(FmgrInfo));
attelems = (Oid *) palloc(natts * sizeof(Oid)); attelems = (Oid *) palloc(natts * sizeof(Oid));
atttypmods = (int4 *) palloc(natts * sizeof(int4)); atttypmods = (int32 *) palloc(natts * sizeof(int32));
for (i = 0; i < natts; i++) for (i = 0; i < natts; i++)
{ {
atttypeid = tupdesc->attrs[i]->atttypid; atttypeid = tupdesc->attrs[i]->atttypid;
get_type_metadata(atttypeid, &attinfuncid, &attelem); getTypeInputInfo(atttypeid, &attinfuncid, &attelems[i]);
fmgr_info(attinfuncid, &attinfuncinfo[i]); fmgr_info(attinfuncid, &attinfuncinfo[i]);
attelems[i] = attelem;
atttypmods[i] = tupdesc->attrs[i]->atttypmod; atttypmods[i] = tupdesc->attrs[i]->atttypmod;
} }
attinmeta->tupdesc = tupdesc; attinmeta->tupdesc = tupdesc;
...@@ -746,39 +742,35 @@ TupleDescGetAttInMetadata(TupleDesc tupdesc) ...@@ -746,39 +742,35 @@ TupleDescGetAttInMetadata(TupleDesc tupdesc)
HeapTuple HeapTuple
BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values) BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
{ {
TupleDesc tupdesc; TupleDesc tupdesc = attinmeta->tupdesc;
int natts; int natts = tupdesc->natts;
HeapTuple tuple; Datum *dvalues;
char *nulls; char *nulls;
int i; int i;
Datum *dvalues;
FmgrInfo attinfuncinfo;
Oid attelem; Oid attelem;
int4 atttypmod; int32 atttypmod;
HeapTuple tuple;
tupdesc = attinmeta->tupdesc;
natts = tupdesc->natts;
dvalues = (Datum *) palloc(natts * sizeof(Datum)); dvalues = (Datum *) palloc(natts * sizeof(Datum));
nulls = (char *) palloc(natts * sizeof(char)); nulls = (char *) palloc(natts * sizeof(char));
/* Call the "in" function for each attribute */ /* Call the "in" function for each non-null attribute */
for (i = 0; i < natts; i++) for (i = 0; i < natts; i++)
{ {
if (values[i] != NULL) if (values[i] != NULL)
{ {
attinfuncinfo = attinmeta->attinfuncs[i];
attelem = attinmeta->attelems[i]; attelem = attinmeta->attelems[i];
atttypmod = attinmeta->atttypmods[i]; atttypmod = attinmeta->atttypmods[i];
dvalues[i] = FunctionCall3(&attinfuncinfo, CStringGetDatum(values[i]), dvalues[i] = FunctionCall3(&attinmeta->attinfuncs[i],
ObjectIdGetDatum(attelem), CStringGetDatum(values[i]),
Int32GetDatum(atttypmod)); ObjectIdGetDatum(attelem),
Int32GetDatum(atttypmod));
nulls[i] = ' '; nulls[i] = ' ';
} }
else else
{ {
dvalues[i] = PointerGetDatum(NULL); dvalues[i] = (Datum) 0;
nulls[i] = 'n'; nulls[i] = 'n';
} }
} }
...@@ -788,6 +780,13 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values) ...@@ -788,6 +780,13 @@ BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
*/ */
tuple = heap_formtuple(tupdesc, dvalues, nulls); tuple = heap_formtuple(tupdesc, dvalues, nulls);
/*
* Release locally palloc'd space. XXX would probably be good to
* pfree values of pass-by-reference datums, as well.
*/
pfree(dvalues);
pfree(nulls);
return tuple; return tuple;
} }
...@@ -804,7 +803,7 @@ begin_tup_output_tupdesc(CommandDest dest, TupleDesc tupdesc) ...@@ -804,7 +803,7 @@ begin_tup_output_tupdesc(CommandDest dest, TupleDesc tupdesc)
tstate = (TupOutputState *) palloc(sizeof(TupOutputState)); tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
tstate->tupdesc = tupdesc; tstate->metadata = TupleDescGetAttInMetadata(tupdesc);
tstate->destfunc = DestToFunction(dest); tstate->destfunc = DestToFunction(dest);
(*tstate->destfunc->setup) (tstate->destfunc, (int) CMD_SELECT, (*tstate->destfunc->setup) (tstate->destfunc, (int) CMD_SELECT,
...@@ -823,20 +822,22 @@ void ...@@ -823,20 +822,22 @@ void
do_tup_output(TupOutputState *tstate, char **values) do_tup_output(TupOutputState *tstate, char **values)
{ {
/* build a tuple from the input strings using the tupdesc */ /* build a tuple from the input strings using the tupdesc */
AttInMetadata *attinmeta = TupleDescGetAttInMetadata(tstate->tupdesc); HeapTuple tuple = BuildTupleFromCStrings(tstate->metadata, values);
HeapTuple tuple = BuildTupleFromCStrings(attinmeta, values);
/* send the tuple to the receiver */ /* send the tuple to the receiver */
(*tstate->destfunc->receiveTuple) (tuple, (*tstate->destfunc->receiveTuple) (tuple,
tstate->tupdesc, tstate->metadata->tupdesc,
tstate->destfunc); tstate->destfunc);
/* clean up */ /* clean up */
heap_freetuple(tuple); heap_freetuple(tuple);
} }
/* write a chunk of text, breaking at newline characters /*
* write a chunk of text, breaking at newline characters
*
* NB: scribbles on its input! * NB: scribbles on its input!
* Should only be used for a single TEXT attribute tupdesc. *
* Should only be used with a single-TEXT-attribute tupdesc.
*/ */
void void
do_text_output_multiline(TupOutputState *tstate, char *text) do_text_output_multiline(TupOutputState *tstate, char *text)
...@@ -859,5 +860,6 @@ void ...@@ -859,5 +860,6 @@ void
end_tup_output(TupOutputState *tstate) end_tup_output(TupOutputState *tstate)
{ {
(*tstate->destfunc->cleanup) (tstate->destfunc); (*tstate->destfunc->cleanup) (tstate->destfunc);
/* XXX worth cleaning up the attinmetadata? */
pfree(tstate); pfree(tstate);
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.55 2002/08/23 16:41:37 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.56 2002/08/29 00:17:04 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -193,9 +193,10 @@ init_sql_fcache(FmgrInfo *finfo) ...@@ -193,9 +193,10 @@ init_sql_fcache(FmgrInfo *finfo)
*/ */
fcache->typlen = typeStruct->typlen; fcache->typlen = typeStruct->typlen;
if (typeStruct->typtype != 'c') if (typeStruct->typtype != 'c' &&
procedureStruct->prorettype != RECORDOID)
{ {
/* The return type is not a relation, so just use byval */ /* The return type is not a composite type, so just use byval */
fcache->typbyval = typeStruct->typbyval; fcache->typbyval = typeStruct->typbyval;
fcache->returnsTuple = false; fcache->returnsTuple = false;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.5 2002/08/05 02:30:50 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.6 2002/08/29 00:17:04 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -130,10 +130,10 @@ FunctionNext(FunctionScan *node) ...@@ -130,10 +130,10 @@ FunctionNext(FunctionScan *node)
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecFunctionScan(node) * ExecFunctionScan(node)
* *
* Scans the Function sequentially and returns the next qualifying * Scans the function sequentially and returns the next qualifying
* tuple. * tuple.
* It calls the ExecScan() routine and passes it the access method * It calls the ExecScan() routine and passes it the access method
* which retrieve tuples sequentially. * which retrieves tuples sequentially.
* *
*/ */
...@@ -156,7 +156,6 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent) ...@@ -156,7 +156,6 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent)
FunctionScanState *scanstate; FunctionScanState *scanstate;
RangeTblEntry *rte; RangeTblEntry *rte;
Oid funcrettype; Oid funcrettype;
Oid funcrelid;
char functyptype; char functyptype;
TupleDesc tupdesc = NULL; TupleDesc tupdesc = NULL;
...@@ -201,31 +200,26 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent) ...@@ -201,31 +200,26 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent)
/* /*
* Now determine if the function returns a simple or composite type, * Now determine if the function returns a simple or composite type,
* and check/add column aliases. * and build an appropriate tupdesc.
*/ */
functyptype = get_typtype(funcrettype); functyptype = get_typtype(funcrettype);
/*
* Build a suitable tupledesc representing the output rows
*/
if (functyptype == 'c') if (functyptype == 'c')
{ {
funcrelid = typeidTypeRelid(funcrettype); /*
if (OidIsValid(funcrelid)) * Composite data type, i.e. a table's row type
{ */
/* Oid funcrelid;
* Composite data type, i.e. a table's row type Relation rel;
* Same as ordinary relation RTE
*/
Relation rel;
rel = relation_open(funcrelid, AccessShareLock); funcrelid = typeidTypeRelid(funcrettype);
tupdesc = CreateTupleDescCopy(RelationGetDescr(rel)); if (!OidIsValid(funcrelid))
relation_close(rel, AccessShareLock); elog(ERROR, "Invalid typrelid for complex type %u",
scanstate->returnsTuple = true; funcrettype);
} rel = relation_open(funcrelid, AccessShareLock);
else tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
elog(ERROR, "Invalid return relation specified for function"); relation_close(rel, AccessShareLock);
scanstate->returnsTuple = true;
} }
else if (functyptype == 'b' || functyptype == 'd') else if (functyptype == 'b' || functyptype == 'd')
{ {
...@@ -461,8 +455,7 @@ function_getonetuple(FunctionScanState *scanstate, ...@@ -461,8 +455,7 @@ function_getonetuple(FunctionScanState *scanstate,
*/ */
if (fn_typtype == 'p' && fn_typeid == RECORDOID) if (fn_typtype == 'p' && fn_typeid == RECORDOID)
if (tupledesc_mismatch(tupdesc, slot->ttc_tupleDescriptor)) if (tupledesc_mismatch(tupdesc, slot->ttc_tupleDescriptor))
elog(ERROR, "Query-specified return tuple and actual" elog(ERROR, "Query-specified return tuple and actual function return tuple do not match");
" function return tuple do not match");
} }
else else
{ {
...@@ -480,7 +473,7 @@ function_getonetuple(FunctionScanState *scanstate, ...@@ -480,7 +473,7 @@ function_getonetuple(FunctionScanState *scanstate,
slot, /* slot to store in */ slot, /* slot to store in */
InvalidBuffer, /* buffer associated with InvalidBuffer, /* buffer associated with
* this tuple */ * this tuple */
true); /* pfree this pointer */ true); /* pfree this tuple */
} }
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,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
* *
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.169 2002/08/26 17:53:58 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.170 2002/08/29 00:17:04 tgl Exp $
* *
* NOTES * NOTES
* Every (plan) node in POSTGRES has an associated "out" routine which * Every (plan) node in POSTGRES has an associated "out" routine which
...@@ -145,7 +145,7 @@ _outIndexStmt(StringInfo str, IndexStmt *node) ...@@ -145,7 +145,7 @@ _outIndexStmt(StringInfo str, IndexStmt *node)
static void static void
_outNotifyStmt(StringInfo str, NotifyStmt *node) _outNotifyStmt(StringInfo str, NotifyStmt *node)
{ {
appendStringInfo(str, "NOTIFY :relation "); appendStringInfo(str, " NOTIFY :relation ");
_outNode(str, node->relation); _outNode(str, node->relation);
} }
...@@ -153,14 +153,14 @@ static void ...@@ -153,14 +153,14 @@ static void
_outSelectStmt(StringInfo str, SelectStmt *node) _outSelectStmt(StringInfo str, SelectStmt *node)
{ {
/* XXX this is pretty durn incomplete */ /* XXX this is pretty durn incomplete */
appendStringInfo(str, "SELECT :where "); appendStringInfo(str, " SELECT :where ");
_outNode(str, node->whereClause); _outNode(str, node->whereClause);
} }
static void static void
_outFuncCall(StringInfo str, FuncCall *node) _outFuncCall(StringInfo str, FuncCall *node)
{ {
appendStringInfo(str, "FUNCTION "); appendStringInfo(str, " FUNCCALL ");
_outNode(str, node->funcname); _outNode(str, node->funcname);
appendStringInfo(str, " :args "); appendStringInfo(str, " :args ");
_outNode(str, node->args); _outNode(str, node->args);
...@@ -1006,7 +1006,7 @@ _outRangeTblEntry(StringInfo str, RangeTblEntry *node) ...@@ -1006,7 +1006,7 @@ _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
case RTE_FUNCTION: case RTE_FUNCTION:
appendStringInfo(str, ":funcexpr "); appendStringInfo(str, ":funcexpr ");
_outNode(str, node->funcexpr); _outNode(str, node->funcexpr);
appendStringInfo(str, ":coldeflist "); appendStringInfo(str, " :coldeflist ");
_outNode(str, node->coldeflist); _outNode(str, node->coldeflist);
break; break;
case RTE_JOIN: case RTE_JOIN:
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.363 2002/08/28 20:46:23 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.364 2002/08/29 00:17:04 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -204,8 +204,8 @@ static void doNegateFloat(Value *v); ...@@ -204,8 +204,8 @@ 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, rowdefinition opt_distinct, opt_definition, func_args,
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,
sort_clause, opt_sort_clause, sortby_list, index_params, sort_clause, opt_sort_clause, sortby_list, index_params,
...@@ -216,7 +216,7 @@ static void doNegateFloat(Value *v); ...@@ -216,7 +216,7 @@ static void doNegateFloat(Value *v);
insert_target_list, def_list, opt_indirection, insert_target_list, def_list, opt_indirection,
group_clause, TriggerFuncArgs, select_limit, group_clause, TriggerFuncArgs, select_limit,
opt_select_limit, opclass_item_list, trans_options, opt_select_limit, opclass_item_list, trans_options,
TableFuncElementList, OptTableFuncElementList, TableFuncElementList,
convert_args, prep_type_clause, prep_type_list, convert_args, prep_type_clause, prep_type_list,
execute_param_clause, execute_param_list execute_param_clause, execute_param_list
...@@ -1424,13 +1424,13 @@ OptTableElementList: ...@@ -1424,13 +1424,13 @@ OptTableElementList:
; ;
TableElementList: TableElementList:
TableElementList ',' TableElement TableElement
{ {
$$ = lappend($1, $3); $$ = makeList1($1);
} }
| TableElement | TableElementList ',' TableElement
{ {
$$ = makeList1($1); $$ = lappend($1, $3);
} }
; ;
...@@ -2234,11 +2234,12 @@ DefineStmt: ...@@ -2234,11 +2234,12 @@ DefineStmt:
n->definition = $4; n->definition = $4;
$$ = (Node *)n; $$ = (Node *)n;
} }
| CREATE TYPE_P any_name AS rowdefinition | CREATE TYPE_P any_name AS '(' TableFuncElementList ')'
{ {
CompositeTypeStmt *n = makeNode(CompositeTypeStmt); CompositeTypeStmt *n = makeNode(CompositeTypeStmt);
RangeVar *r = makeNode(RangeVar); RangeVar *r = makeNode(RangeVar);
/* can't use qualified_name, sigh */
switch (length($3)) switch (length($3))
{ {
case 1: case 1:
...@@ -2258,13 +2259,12 @@ DefineStmt: ...@@ -2258,13 +2259,12 @@ DefineStmt:
break; break;
default: default:
elog(ERROR, elog(ERROR,
"Improper qualified name " "Improper qualified name (too many dotted names): %s",
"(too many dotted names): %s",
NameListToString($3)); NameListToString($3));
break; break;
} }
n->typevar = r; n->typevar = r;
n->coldeflist = $5; n->coldeflist = $6;
$$ = (Node *)n; $$ = (Node *)n;
} }
| CREATE CHARACTER SET opt_as any_name GET definition opt_collate | CREATE CHARACTER SET opt_as any_name GET definition opt_collate
...@@ -2277,9 +2277,6 @@ DefineStmt: ...@@ -2277,9 +2277,6 @@ DefineStmt:
} }
; ;
rowdefinition: '(' TableFuncElementList ')' { $$ = $2; }
;
definition: '(' def_list ')' { $$ = $2; } definition: '(' def_list ')' { $$ = $2; }
; ;
...@@ -4539,14 +4536,22 @@ table_ref: relation_expr ...@@ -4539,14 +4536,22 @@ table_ref: relation_expr
n->coldeflist = NIL; n->coldeflist = NIL;
$$ = (Node *) n; $$ = (Node *) n;
} }
| func_table AS '(' OptTableFuncElementList ')' | func_table alias_clause
{
RangeFunction *n = makeNode(RangeFunction);
n->funccallnode = $1;
n->alias = $2;
n->coldeflist = NIL;
$$ = (Node *) n;
}
| func_table AS '(' TableFuncElementList ')'
{ {
RangeFunction *n = makeNode(RangeFunction); RangeFunction *n = makeNode(RangeFunction);
n->funccallnode = $1; n->funccallnode = $1;
n->coldeflist = $4; n->coldeflist = $4;
$$ = (Node *) n; $$ = (Node *) n;
} }
| func_table AS ColId '(' OptTableFuncElementList ')' | func_table AS ColId '(' TableFuncElementList ')'
{ {
RangeFunction *n = makeNode(RangeFunction); RangeFunction *n = makeNode(RangeFunction);
Alias *a = makeNode(Alias); Alias *a = makeNode(Alias);
...@@ -4556,7 +4561,7 @@ table_ref: relation_expr ...@@ -4556,7 +4561,7 @@ table_ref: relation_expr
n->coldeflist = $5; n->coldeflist = $5;
$$ = (Node *) n; $$ = (Node *) n;
} }
| func_table ColId '(' OptTableFuncElementList ')' | func_table ColId '(' TableFuncElementList ')'
{ {
RangeFunction *n = makeNode(RangeFunction); RangeFunction *n = makeNode(RangeFunction);
Alias *a = makeNode(Alias); Alias *a = makeNode(Alias);
...@@ -4566,14 +4571,6 @@ table_ref: relation_expr ...@@ -4566,14 +4571,6 @@ table_ref: relation_expr
n->coldeflist = $4; n->coldeflist = $4;
$$ = (Node *) n; $$ = (Node *) n;
} }
| func_table alias_clause
{
RangeFunction *n = makeNode(RangeFunction);
n->funccallnode = $1;
n->alias = $2;
n->coldeflist = NIL;
$$ = (Node *) n;
}
| select_with_parens | select_with_parens
{ {
/* /*
...@@ -4815,24 +4812,18 @@ func_table: func_name '(' ')' ...@@ -4815,24 +4812,18 @@ func_table: func_name '(' ')'
where_clause: where_clause:
WHERE a_expr { $$ = $2; } WHERE a_expr { $$ = $2; }
/* no qualifiers */
| /*EMPTY*/ { $$ = NULL; } | /*EMPTY*/ { $$ = NULL; }
; ;
OptTableFuncElementList:
TableFuncElementList { $$ = $1; }
| /*EMPTY*/ { $$ = NIL; }
;
TableFuncElementList: TableFuncElementList:
TableFuncElementList ',' TableFuncElement TableFuncElement
{ {
$$ = lappend($1, $3); $$ = makeList1($1);
} }
| TableFuncElement | TableFuncElementList ',' TableFuncElement
{ {
$$ = makeList1($1); $$ = lappend($1, $3);
} }
; ;
...@@ -4842,7 +4833,6 @@ TableFuncElement: ColId Typename ...@@ -4842,7 +4833,6 @@ TableFuncElement: ColId Typename
n->colname = $1; n->colname = $1;
n->typename = $2; n->typename = $2;
n->constraints = NIL; n->constraints = NIL;
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
......
This diff is collapsed.
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.173 2002/08/27 04:55:11 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.174 2002/08/29 00:17:04 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -583,14 +583,9 @@ ProcessUtility(Node *parsetree, ...@@ -583,14 +583,9 @@ ProcessUtility(Node *parsetree,
case T_CompositeTypeStmt: /* CREATE TYPE (composite) */ case T_CompositeTypeStmt: /* CREATE TYPE (composite) */
{ {
Oid relid;
CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree; CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
/* DefineCompositeType(stmt->typevar, stmt->coldeflist);
* DefineCompositeType returns relid for use when creating
* an implicit composite type during function creation
*/
relid = DefineCompositeType(stmt->typevar, stmt->coldeflist);
} }
break; break;
......
...@@ -5,22 +5,22 @@ ...@@ -5,22 +5,22 @@
* Copyright (c) 2002, PostgreSQL Global Development Group * Copyright (c) 2002, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/lockfuncs.c,v 1.2 2002/08/27 04:00:28 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/lockfuncs.c,v 1.3 2002/08/29 00:17:05 tgl Exp $
*/ */
#include "postgres.h" #include "postgres.h"
#include "fmgr.h"
#include "funcapi.h" #include "funcapi.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "storage/lmgr.h" #include "storage/lmgr.h"
#include "storage/lock.h" #include "storage/lock.h"
#include "storage/lwlock.h" #include "storage/lwlock.h"
#include "storage/proc.h" #include "storage/proc.h"
#include "utils/builtins.h"
Datum pg_lock_status(PG_FUNCTION_ARGS);
static int next_lock(int locks[]); static int next_lock(int locks[]);
Datum Datum
pg_lock_status(PG_FUNCTION_ARGS) pg_lock_status(PG_FUNCTION_ARGS)
{ {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.34 2002/08/28 20:46:24 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.35 2002/08/29 00:17:05 tgl Exp $
* *
* NOTES * NOTES
* input routine largely stolen from boxin(). * input routine largely stolen from boxin().
...@@ -226,9 +226,6 @@ currtid_byreloid(PG_FUNCTION_ARGS) ...@@ -226,9 +226,6 @@ 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);
...@@ -252,9 +249,6 @@ currtid_byrelname(PG_FUNCTION_ARGS) ...@@ -252,9 +249,6 @@ 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);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,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/utils/cache/lsyscache.c,v 1.80 2002/08/26 17:53:59 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.81 2002/08/29 00:17:05 tgl Exp $
* *
* NOTES * NOTES
* Eventually, the index information should go through here, too. * Eventually, the index information should go through here, too.
...@@ -1190,6 +1190,33 @@ get_typtype(Oid typid) ...@@ -1190,6 +1190,33 @@ get_typtype(Oid typid)
return '\0'; return '\0';
} }
/*
* getTypeInputInfo
*
* Get info needed for converting values of a type to internal form
*/
void
getTypeInputInfo(Oid type, Oid *typInput, Oid *typElem)
{
HeapTuple typeTuple;
Form_pg_type pt;
typeTuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(type),
0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
elog(ERROR, "getTypeInputInfo: Cache lookup of type %u failed", type);
pt = (Form_pg_type) GETSTRUCT(typeTuple);
if (!pt->typisdefined)
elog(ERROR, "Type \"%s\" is only a shell", NameStr(pt->typname));
*typInput = pt->typinput;
*typElem = pt->typelem;
ReleaseSysCache(typeTuple);
}
/* /*
* getTypeOutputInfo * getTypeOutputInfo
* *
......
...@@ -6,13 +6,18 @@ ...@@ -6,13 +6,18 @@
* *
* Copyright (c) 2002, PostgreSQL Global Development Group * Copyright (c) 2002, PostgreSQL Global Development Group
* *
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/funcapi.c,v 1.3 2002/08/29 00:17:05 tgl Exp $
*
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h"
#include "funcapi.h" #include "funcapi.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "utils/syscache.h" #include "utils/syscache.h"
/* /*
* init_MultiFuncCall * init_MultiFuncCall
* Create an empty FuncCallContext data structure * Create an empty FuncCallContext data structure
...@@ -99,8 +104,6 @@ per_MultiFuncCall(PG_FUNCTION_ARGS) ...@@ -99,8 +104,6 @@ per_MultiFuncCall(PG_FUNCTION_ARGS)
void void
end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx) end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
{ {
MemoryContext oldcontext;
/* unbind from fcinfo */ /* unbind from fcinfo */
fcinfo->flinfo->fn_extra = NULL; fcinfo->flinfo->fn_extra = NULL;
...@@ -108,32 +111,8 @@ end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx) ...@@ -108,32 +111,8 @@ end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx)
* Caller is responsible to free up memory for individual * Caller is responsible to free up memory for individual
* struct elements other than att_in_funcinfo and elements. * struct elements other than att_in_funcinfo and elements.
*/ */
oldcontext = MemoryContextSwitchTo(funcctx->fmctx);
if (funcctx->attinmeta != NULL) if (funcctx->attinmeta != NULL)
pfree(funcctx->attinmeta); pfree(funcctx->attinmeta);
pfree(funcctx); pfree(funcctx);
MemoryContextSwitchTo(oldcontext);
}
void
get_type_metadata(Oid typeid, Oid *attinfuncid, Oid *attelem)
{
HeapTuple typeTuple;
Form_pg_type typtup;
typeTuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typeid),
0, 0, 0);
if (!HeapTupleIsValid(typeTuple))
elog(ERROR, "get_type_metadata: Cache lookup of type %u failed", typeid);
typtup = (Form_pg_type) GETSTRUCT(typeTuple);
*attinfuncid = typtup->typinput;
*attelem = typtup->typelem;
ReleaseSysCache(typeTuple);
} }
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* command, configuration file, and command line options. * command, configuration file, and command line options.
* See src/backend/utils/misc/README for more information. * See src/backend/utils/misc/README for more information.
* *
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.84 2002/08/26 17:53:59 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.85 2002/08/29 00:17:05 tgl Exp $
* *
* Copyright 2000 by PostgreSQL Global Development Group * Copyright 2000 by PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>. * Written by Peter Eisentraut <peter_e@gmx.net>.
...@@ -2284,7 +2284,7 @@ ShowGUCConfigOption(const char *name) ...@@ -2284,7 +2284,7 @@ ShowGUCConfigOption(const char *name)
tstate = begin_tup_output_tupdesc(dest, tupdesc); tstate = begin_tup_output_tupdesc(dest, tupdesc);
/* Send it */ /* Send it */
PROJECT_LINE_OF_TEXT(tstate, value); do_text_output_oneline(tstate, value);
end_tup_output(tstate); end_tup_output(tstate);
} }
...@@ -2462,7 +2462,7 @@ show_all_settings(PG_FUNCTION_ARGS) ...@@ -2462,7 +2462,7 @@ show_all_settings(PG_FUNCTION_ARGS)
if (call_cntr < max_calls) /* do when there is more left to send */ if (call_cntr < max_calls) /* do when there is more left to send */
{ {
char **values; char *values[2];
char *varname; char *varname;
char *varval; char *varval;
bool noshow; bool noshow;
...@@ -2474,7 +2474,9 @@ show_all_settings(PG_FUNCTION_ARGS) ...@@ -2474,7 +2474,9 @@ show_all_settings(PG_FUNCTION_ARGS)
*/ */
do do
{ {
varval = GetConfigOptionByNum(call_cntr, (const char **) &varname, &noshow); varval = GetConfigOptionByNum(call_cntr,
(const char **) &varname,
&noshow);
if (noshow) if (noshow)
{ {
/* varval is a palloc'd copy, so free it */ /* varval is a palloc'd copy, so free it */
...@@ -2495,9 +2497,8 @@ show_all_settings(PG_FUNCTION_ARGS) ...@@ -2495,9 +2497,8 @@ show_all_settings(PG_FUNCTION_ARGS)
* This should be an array of C strings which will * This should be an array of C strings which will
* be processed later by the appropriate "in" functions. * be processed later by the appropriate "in" functions.
*/ */
values = (char **) palloc(2 * sizeof(char *)); values[0] = varname;
values[0] = pstrdup(varname); values[1] = varval;
values[1] = varval; /* varval is already a palloc'd copy */
/* build a tuple */ /* build a tuple */
tuple = BuildTupleFromCStrings(attinmeta, values); tuple = BuildTupleFromCStrings(attinmeta, values);
...@@ -2506,10 +2507,8 @@ show_all_settings(PG_FUNCTION_ARGS) ...@@ -2506,10 +2507,8 @@ show_all_settings(PG_FUNCTION_ARGS)
result = TupleGetDatum(slot, tuple); result = TupleGetDatum(slot, tuple);
/* Clean up */ /* Clean up */
pfree(values[0]);
if (varval != NULL) if (varval != NULL)
pfree(values[1]); pfree(varval);
pfree(values);
SRF_RETURN_NEXT(funcctx, result); SRF_RETURN_NEXT(funcctx, result);
} }
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.68 2002/08/15 16:36:06 momjian Exp $ * $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.69 2002/08/29 00:17:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -215,10 +215,9 @@ flagInhTables(TableInfo *tblinfo, int numTables, ...@@ -215,10 +215,9 @@ flagInhTables(TableInfo *tblinfo, int numTables,
for (i = 0; i < numTables; i++) for (i = 0; i < numTables; i++)
{ {
/* Sequences, views, and types never have parents */ /* Sequences and views 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 */
...@@ -270,10 +269,9 @@ flagInhAttrs(TableInfo *tblinfo, int numTables, ...@@ -270,10 +269,9 @@ flagInhAttrs(TableInfo *tblinfo, int numTables,
for (i = 0; i < numTables; i++) for (i = 0; i < numTables; i++)
{ {
/* Sequences, views, and types never have parents */ /* Sequences and views 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.294 2002/08/28 20:57:22 petere Exp $ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.295 2002/08/29 00:17:05 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1148,10 +1148,6 @@ dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout, ...@@ -1148,10 +1148,6 @@ 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;
...@@ -1581,7 +1577,8 @@ getTypes(int *numTypes) ...@@ -1581,7 +1577,8 @@ getTypes(int *numTypes)
"typnamespace, " "typnamespace, "
"(select usename from pg_user where typowner = usesysid) as usename, " "(select usename from pg_user where typowner = usesysid) as usename, "
"typelem, typrelid, " "typelem, typrelid, "
"(select relkind from pg_class where oid = typrelid) as typrelkind, " "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
"ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, "
"typtype, typisdefined " "typtype, typisdefined "
"FROM pg_type"); "FROM pg_type");
} }
...@@ -1591,7 +1588,8 @@ getTypes(int *numTypes) ...@@ -1591,7 +1588,8 @@ getTypes(int *numTypes)
"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, " "typelem, typrelid, "
"''::char as typrelkind, " "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
"ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END as typrelkind, "
"typtype, typisdefined " "typtype, typisdefined "
"FROM pg_type"); "FROM pg_type");
} }
...@@ -2120,7 +2118,6 @@ getTables(int *numTables) ...@@ -2120,7 +2118,6 @@ 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, "
...@@ -2392,10 +2389,6 @@ getTableAttrs(TableInfo *tblinfo, int numTables) ...@@ -2392,10 +2389,6 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
if (tbinfo->relkind == RELKIND_SEQUENCE) if (tbinfo->relkind == RELKIND_SEQUENCE)
continue; continue;
/* Don't bother to collect info for type relations */
if (tbinfo->relkind == RELKIND_COMPOSITE_TYPE)
continue;
/* Don't bother with uninteresting tables, either */ /* Don't bother with uninteresting tables, either */
if (!tbinfo->interesting) if (!tbinfo->interesting)
continue; continue;
...@@ -3210,7 +3203,7 @@ dumpOneDomain(Archive *fout, TypeInfo *tinfo) ...@@ -3210,7 +3203,7 @@ dumpOneDomain(Archive *fout, TypeInfo *tinfo)
/* DROP must be fully qualified in case same name appears in pg_catalog */ /* DROP must be fully qualified in case same name appears in pg_catalog */
appendPQExpBuffer(delq, "DROP DOMAIN %s.", appendPQExpBuffer(delq, "DROP DOMAIN %s.",
fmtId(tinfo->typnamespace->nspname)); fmtId(tinfo->typnamespace->nspname));
appendPQExpBuffer(delq, "%s RESTRICT;\n", appendPQExpBuffer(delq, "%s;\n",
fmtId(tinfo->typname)); fmtId(tinfo->typname));
appendPQExpBuffer(q, appendPQExpBuffer(q,
...@@ -3263,15 +3256,10 @@ dumpOneCompositeType(Archive *fout, TypeInfo *tinfo) ...@@ -3263,15 +3256,10 @@ dumpOneCompositeType(Archive *fout, TypeInfo *tinfo)
PQExpBuffer query = createPQExpBuffer(); PQExpBuffer query = createPQExpBuffer();
PGresult *res; PGresult *res;
int ntups; int ntups;
char *attname; int i_attname;
char *atttypdefn; int i_atttypdefn;
char *attbasetype;
const char *((*deps)[]);
int depIdx = 0;
int i; int i;
deps = malloc(sizeof(char *) * 10);
/* Set proper schema search path so type references list correctly */ /* Set proper schema search path so type references list correctly */
selectSourceSchema(tinfo->typnamespace->nspname); selectSourceSchema(tinfo->typnamespace->nspname);
...@@ -3279,11 +3267,12 @@ dumpOneCompositeType(Archive *fout, TypeInfo *tinfo) ...@@ -3279,11 +3267,12 @@ dumpOneCompositeType(Archive *fout, TypeInfo *tinfo)
/* We assume here that remoteVersion must be at least 70300 */ /* We assume here that remoteVersion must be at least 70300 */
appendPQExpBuffer(query, "SELECT a.attname, " appendPQExpBuffer(query, "SELECT a.attname, "
"pg_catalog.format_type(a.atttypid, a.atttypmod) as atttypdefn, " "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 " "FROM pg_catalog.pg_type t, pg_catalog.pg_attribute a "
"WHERE t.oid = '%s'::pg_catalog.oid " "WHERE t.oid = '%s'::pg_catalog.oid "
"AND a.attrelid = t.typrelid", "AND a.attrelid = t.typrelid "
"AND NOT a.attisdropped "
"ORDER BY a.attnum ",
tinfo->oid); tinfo->oid);
res = PQexec(g_conn, query->data); res = PQexec(g_conn, query->data);
...@@ -3302,37 +3291,35 @@ dumpOneCompositeType(Archive *fout, TypeInfo *tinfo) ...@@ -3302,37 +3291,35 @@ dumpOneCompositeType(Archive *fout, TypeInfo *tinfo)
exit_nicely(); exit_nicely();
} }
/* DROP must be fully qualified in case same name appears in pg_catalog */ i_attname = PQfnumber(res, "attname");
appendPQExpBuffer(delq, "DROP TYPE %s.", i_atttypdefn = PQfnumber(res, "atttypdefn");
fmtId(tinfo->typnamespace->nspname));
appendPQExpBuffer(delq, "%s RESTRICT;\n",
fmtId(tinfo->typname));
appendPQExpBuffer(q, appendPQExpBuffer(q, "CREATE TYPE %s AS (",
"CREATE TYPE %s AS (",
fmtId(tinfo->typname)); fmtId(tinfo->typname));
for (i = 0; i < ntups; i++) for (i = 0; i < ntups; i++)
{ {
attname = PQgetvalue(res, i, PQfnumber(res, "attname")); char *attname;
atttypdefn = PQgetvalue(res, i, PQfnumber(res, "atttypdefn")); char *atttypdefn;
attbasetype = PQgetvalue(res, i, PQfnumber(res, "attbasetype"));
if (i > 0) attname = PQgetvalue(res, i, i_attname);
appendPQExpBuffer(q, ",\n\t %s %s", attname, atttypdefn); atttypdefn = PQgetvalue(res, i, i_atttypdefn);
else
appendPQExpBuffer(q, "%s %s", attname, atttypdefn);
/* Depends on the base type */ if (i > 0)
(*deps)[depIdx++] = strdup(attbasetype); appendPQExpBuffer(q, ",\n\t");
appendPQExpBuffer(q, "%s %s", fmtId(attname), atttypdefn);
} }
appendPQExpBuffer(q, ");\n"); appendPQExpBuffer(q, ");\n");
(*deps)[depIdx++] = NULL; /* End of List */ /* DROP must be fully qualified in case same name appears in pg_catalog */
appendPQExpBuffer(delq, "DROP TYPE %s.",
fmtId(tinfo->typnamespace->nspname));
appendPQExpBuffer(delq, "%s;\n",
fmtId(tinfo->typname));
ArchiveEntry(fout, tinfo->oid, tinfo->typname, ArchiveEntry(fout, tinfo->oid, tinfo->typname,
tinfo->typnamespace->nspname, tinfo->typnamespace->nspname,
tinfo->usename, "TYPE", deps, tinfo->usename, "TYPE", NULL,
q->data, delq->data, NULL, NULL, NULL); q->data, delq->data, NULL, NULL, NULL);
/*** Dump Type Comments ***/ /*** Dump Type Comments ***/
...@@ -3365,7 +3352,7 @@ dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs, ...@@ -3365,7 +3352,7 @@ dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs,
if (!tinfo[i].typnamespace->dump) if (!tinfo[i].typnamespace->dump)
continue; continue;
/* skip relation types for non-stand-alone type relations*/ /* skip complex types, except for standalone composite types */
if (atooid(tinfo[i].typrelid) != 0 && tinfo[i].typrelkind != 'c') if (atooid(tinfo[i].typrelid) != 0 && tinfo[i].typrelkind != 'c')
continue; continue;
...@@ -5046,8 +5033,6 @@ dumpTables(Archive *fout, TableInfo tblinfo[], int numTables, ...@@ -5046,8 +5033,6 @@ 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)
{ {
......
...@@ -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.66 2002/08/27 20:16:48 petere Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.67 2002/08/29 00:17:05 tgl Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "describe.h" #include "describe.h"
...@@ -196,8 +196,10 @@ describeTypes(const char *pattern, bool verbose) ...@@ -196,8 +196,10 @@ describeTypes(const char *pattern, bool verbose)
if (verbose) if (verbose)
appendPQExpBuffer(&buf, appendPQExpBuffer(&buf,
" t.typname AS \"%s\",\n" " t.typname AS \"%s\",\n"
" CASE WHEN t.typlen < 0\n" " CASE WHEN t.typrelid != 0\n"
" THEN CAST('var' AS pg_catalog.text)\n" " THEN CAST('tuple' AS pg_catalog.text)\n"
" WHEN t.typlen < 0\n"
" THEN CAST('var' AS pg_catalog.text)\n"
" ELSE CAST(t.typlen AS pg_catalog.text)\n" " ELSE CAST(t.typlen AS pg_catalog.text)\n"
" END AS \"%s\",\n", " END AS \"%s\",\n",
_("Internal name"), _("Size")); _("Internal name"), _("Size"));
...@@ -209,12 +211,12 @@ describeTypes(const char *pattern, bool verbose) ...@@ -209,12 +211,12 @@ describeTypes(const char *pattern, bool verbose)
" LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n"); " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n");
/* /*
* 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) unless they are type relations * complex types (typrelid!=0) unless they are standalone composite types
*/ */
appendPQExpBuffer(&buf, "WHERE (t.typrelid = 0 "); appendPQExpBuffer(&buf, "WHERE (t.typrelid = 0 ");
appendPQExpBuffer(&buf, "OR (SELECT c.relkind = 'c' FROM pg_class c " appendPQExpBuffer(&buf, "OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c "
"where c.oid = t.typrelid)) "); "WHERE c.oid = t.typrelid)) ");
appendPQExpBuffer(&buf, "AND t.typname !~ '^_'\n"); appendPQExpBuffer(&buf, "AND t.typname !~ '^_'\n");
/* Match name pattern against either internal or external name */ /* Match name pattern against either internal or external name */
...@@ -801,6 +803,10 @@ describeOneTableDetails(const char *schemaname, ...@@ -801,6 +803,10 @@ describeOneTableDetails(const char *schemaname,
printfPQExpBuffer(&title, _("TOAST table \"%s.%s\""), printfPQExpBuffer(&title, _("TOAST table \"%s.%s\""),
schemaname, relationname); schemaname, relationname);
break; break;
case 'c':
printfPQExpBuffer(&title, _("Composite type \"%s.%s\""),
schemaname, relationname);
break;
default: default:
printfPQExpBuffer(&title, _("?%c? \"%s.%s\""), printfPQExpBuffer(&title, _("?%c? \"%s.%s\""),
tableinfo.relkind, schemaname, relationname); tableinfo.relkind, schemaname, relationname);
......
...@@ -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_type.h,v 1.130 2002/08/26 17:54:01 tgl Exp $ * $Id: pg_type.h,v 1.131 2002/08/29 00:17:06 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -542,6 +542,7 @@ extern Oid TypeCreate(const char *typeName, ...@@ -542,6 +542,7 @@ extern Oid TypeCreate(const char *typeName,
Oid typeNamespace, Oid typeNamespace,
Oid assignedTypeOid, Oid assignedTypeOid,
Oid relationOid, Oid relationOid,
char relationKind,
int16 internalSize, int16 internalSize,
char typeType, char typeType,
char typDelim, char typDelim,
......
...@@ -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: executor.h,v 1.73 2002/08/02 18:15:09 tgl Exp $ * $Id: executor.h,v 1.74 2002/08/29 00:17:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -123,7 +123,8 @@ extern void SetChangedParamList(Plan *node, List *newchg); ...@@ -123,7 +123,8 @@ extern void SetChangedParamList(Plan *node, List *newchg);
typedef struct TupOutputState typedef struct TupOutputState
{ {
TupleDesc tupdesc; /* use "struct" here to allow forward reference */
struct AttInMetadata *metadata;
DestReceiver *destfunc; DestReceiver *destfunc;
} TupOutputState; } TupOutputState;
...@@ -132,10 +133,15 @@ extern void do_tup_output(TupOutputState *tstate, char **values); ...@@ -132,10 +133,15 @@ extern void do_tup_output(TupOutputState *tstate, char **values);
extern void do_text_output_multiline(TupOutputState *tstate, char *text); extern void do_text_output_multiline(TupOutputState *tstate, char *text);
extern void end_tup_output(TupOutputState *tstate); extern void end_tup_output(TupOutputState *tstate);
#define PROJECT_LINE_OF_TEXT(tstate, text_to_project) \ /*
* Write a single line of text given as a C string.
*
* Should only be used with a single-TEXT-attribute tupdesc.
*/
#define do_text_output_oneline(tstate, text_to_emit) \
do { \ do { \
char *values_[1]; \ char *values_[1]; \
values_[0] = (text_to_project); \ values_[0] = (text_to_emit); \
do_tup_output(tstate, values_); \ do_tup_output(tstate, values_); \
} while (0) } while (0)
......
...@@ -9,26 +9,18 @@ ...@@ -9,26 +9,18 @@
* *
* Copyright (c) 2002, PostgreSQL Global Development Group * Copyright (c) 2002, PostgreSQL Global Development Group
* *
* $Id: funcapi.h,v 1.5 2002/08/29 00:17:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef FUNCAPI_H #ifndef FUNCAPI_H
#define FUNCAPI_H #define FUNCAPI_H
#include "postgres.h"
#include "fmgr.h" #include "fmgr.h"
#include "access/htup.h"
#include "access/tupdesc.h" #include "access/tupdesc.h"
#include "executor/executor.h" #include "executor/executor.h"
#include "executor/tuptable.h" #include "executor/tuptable.h"
/*
* All functions that can be called directly by fmgr must have this signature.
* (Other functions can be called by using a handler that does have this
* signature.)
*/
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* Support to ease writing Functions returning composite types * Support to ease writing Functions returning composite types
...@@ -40,20 +32,19 @@ ...@@ -40,20 +32,19 @@
* is derived from the TupleDesc, but it is stored here to * is derived from the TupleDesc, but it is stored here to
* avoid redundant cpu cycles on each call to an SRF. * avoid redundant cpu cycles on each call to an SRF.
*/ */
typedef struct typedef struct AttInMetadata
{ {
/* full TupleDesc */ /* full TupleDesc */
TupleDesc tupdesc; TupleDesc tupdesc;
/* pointer to array of attribute "type"in finfo */ /* array of attribute type input function finfo */
FmgrInfo *attinfuncs; FmgrInfo *attinfuncs;
/* pointer to array of attribute type typelem */ /* array of attribute type typelem */
Oid *attelems; Oid *attelems;
/* pointer to array of attribute type typtypmod */ /* array of attribute typmod */
int4 *atttypmods; int32 *atttypmods;
} AttInMetadata; } AttInMetadata;
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
...@@ -63,7 +54,7 @@ typedef struct ...@@ -63,7 +54,7 @@ typedef struct
* This struct holds function context for Set Returning Functions. * This struct holds function context for Set Returning Functions.
* Use fn_extra to hold a pointer to it across calls * Use fn_extra to hold a pointer to it across calls
*/ */
typedef struct typedef struct FuncCallContext
{ {
/* /*
* Number of times we've been called before. * Number of times we've been called before.
...@@ -120,35 +111,34 @@ typedef struct ...@@ -120,35 +111,34 @@ typedef struct
} FuncCallContext; } FuncCallContext;
/*------------------------------------------------------------------------- /*----------
* Support to ease writing Functions returning composite types * Support to ease writing Functions returning composite types
* *
* External declarations: * External declarations:
* TupleDesc RelationNameGetTupleDesc(char *relname) - Use to get a TupleDesc * TupleDesc RelationNameGetTupleDesc(const char *relname) - Use to get a
* based on the function's return type relation. * TupleDesc based on a specified relation.
* TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases) - Use to get a * TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases) - Use to get a
* TupleDesc based on the function's type oid. This can be used to get * TupleDesc based on a type OID. This can be used to get
* a TupleDesc for a base (scalar), or composite (relation) type. * a TupleDesc for a base (scalar) or composite (relation) type.
* TupleTableSlot *TupleDescGetSlot(TupleDesc tupdesc) - Initialize a slot * TupleTableSlot *TupleDescGetSlot(TupleDesc tupdesc) - Initialize a slot
* given a TupleDesc. * given a TupleDesc.
* AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc) - Get a pointer * AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc) - Build an
* to AttInMetadata based on the function's TupleDesc. AttInMetadata can * AttInMetadata struct based on the given TupleDesc. AttInMetadata can
* be used in conjunction with C strings to produce a properly formed * be used in conjunction with C strings to produce a properly formed
* tuple. Store the metadata here for use across calls to avoid redundant * tuple. Store the metadata here for use across calls to avoid redundant
* work. * work.
* HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values) - * HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values) -
* build a HeapTuple given user data in C string form. values is an array * build a HeapTuple given user data in C string form. values is an array
* of C strings, one for each attribute of the return tuple. * of C strings, one for each attribute of the return tuple.
* void get_type_metadata(Oid typeid, Oid *attinfuncid, Oid *attelem) - Get
* an attribute "in" function and typelem value given the typeid.
* *
* Macro declarations: * Macro declarations:
* TupleGetDatum(TupleTableSlot *slot, HeapTuple tuple) - get a Datum * TupleGetDatum(TupleTableSlot *slot, HeapTuple tuple) - get a Datum
* given a tuple and a slot. * given a tuple and a slot.
*----------
*/ */
/* from tupdesc.c */ /* from tupdesc.c */
extern TupleDesc RelationNameGetTupleDesc(char *relname); extern TupleDesc RelationNameGetTupleDesc(const char *relname);
extern TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases); extern TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases);
/* from execTuples.c */ /* from execTuples.c */
...@@ -156,13 +146,11 @@ extern TupleTableSlot *TupleDescGetSlot(TupleDesc tupdesc); ...@@ -156,13 +146,11 @@ extern TupleTableSlot *TupleDescGetSlot(TupleDesc tupdesc);
extern AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc); extern AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc);
extern HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values); extern HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values);
/* from funcapi.c */
extern void get_type_metadata(Oid typeid, Oid *attinfuncid, Oid *attelem);
#define TupleGetDatum(_slot, _tuple) \ #define TupleGetDatum(_slot, _tuple) \
PointerGetDatum(ExecStoreTuple(_tuple, _slot, InvalidBuffer, true)) PointerGetDatum(ExecStoreTuple(_tuple, _slot, InvalidBuffer, true))
/*-------------------------------------------------------------------------
/*----------
* Support for Set Returning Functions (SRFs) * Support for Set Returning Functions (SRFs)
* *
* The basic API for SRFs looks something like: * The basic API for SRFs looks something like:
...@@ -200,6 +188,7 @@ extern void get_type_metadata(Oid typeid, Oid *attinfuncid, Oid *attelem); ...@@ -200,6 +188,7 @@ extern void get_type_metadata(Oid typeid, Oid *attinfuncid, Oid *attelem);
* } * }
* } * }
* *
*----------
*/ */
/* from funcapi.c */ /* from funcapi.c */
...@@ -208,12 +197,15 @@ extern FuncCallContext *per_MultiFuncCall(PG_FUNCTION_ARGS); ...@@ -208,12 +197,15 @@ extern FuncCallContext *per_MultiFuncCall(PG_FUNCTION_ARGS);
extern void end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx); extern void end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx);
#define SRF_IS_FIRSTCALL() (fcinfo->flinfo->fn_extra == NULL) #define SRF_IS_FIRSTCALL() (fcinfo->flinfo->fn_extra == NULL)
#define SRF_FIRSTCALL_INIT() init_MultiFuncCall(fcinfo) #define SRF_FIRSTCALL_INIT() init_MultiFuncCall(fcinfo)
#define SRF_PERCALL_SETUP() per_MultiFuncCall(fcinfo) #define SRF_PERCALL_SETUP() per_MultiFuncCall(fcinfo)
#define SRF_RETURN_NEXT(_funcctx, _result) \ #define SRF_RETURN_NEXT(_funcctx, _result) \
do { \ do { \
ReturnSetInfo *rsi; \ ReturnSetInfo *rsi; \
_funcctx->call_cntr++; \ (_funcctx)->call_cntr++; \
rsi = (ReturnSetInfo *) fcinfo->resultinfo; \ rsi = (ReturnSetInfo *) fcinfo->resultinfo; \
rsi->isDone = ExprMultipleResult; \ rsi->isDone = ExprMultipleResult; \
PG_RETURN_DATUM(_result); \ PG_RETURN_DATUM(_result); \
...@@ -225,7 +217,6 @@ extern void end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx); ...@@ -225,7 +217,6 @@ extern void end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx);
end_MultiFuncCall(fcinfo, _funcctx); \ end_MultiFuncCall(fcinfo, _funcctx); \
rsi = (ReturnSetInfo *) fcinfo->resultinfo; \ rsi = (ReturnSetInfo *) fcinfo->resultinfo; \
rsi->isDone = ExprEndResult; \ rsi->isDone = ExprEndResult; \
_funcctx->slot = NULL; \
PG_RETURN_NULL(); \ PG_RETURN_NULL(); \
} while (0) } while (0)
......
...@@ -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: execnodes.h,v 1.71 2002/08/04 19:48:10 momjian Exp $ * $Id: execnodes.h,v 1.72 2002/08/29 00:17:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -509,17 +509,13 @@ typedef struct SubqueryScanState ...@@ -509,17 +509,13 @@ typedef struct SubqueryScanState
* Function nodes are used to scan the results of a * Function nodes are used to scan the results of a
* function appearing in FROM (typically a function returning set). * function appearing in FROM (typically a function returning set).
* *
* functionmode function operating mode: * functionmode function operating mode
* - repeated call
* - materialize
* - return query
* tupdesc function's return tuple description * tupdesc function's return tuple description
* tuplestorestate private state of tuplestore.c * tuplestorestate private state of tuplestore.c
* funcexpr function expression being evaluated * funcexpr function expression being evaluated
* returnsTuple does function return tuples? * returnsTuple does function return tuples?
* fn_typeid OID of function return type * fn_typeid OID of function return type
* fn_typtype return Datum type, i.e. 'b'ase, * fn_typtype return type's typtype
* 'c'atalog, or 'p'seudo
* ---------------- * ----------------
*/ */
typedef enum FunctionMode typedef enum FunctionMode
......
...@@ -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: builtins.h,v 1.195 2002/08/22 03:24:01 momjian Exp $ * $Id: builtins.h,v 1.196 2002/08/29 00:17:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -690,6 +690,9 @@ extern Datum show_config_by_name(PG_FUNCTION_ARGS); ...@@ -690,6 +690,9 @@ extern Datum show_config_by_name(PG_FUNCTION_ARGS);
extern Datum set_config_by_name(PG_FUNCTION_ARGS); extern Datum set_config_by_name(PG_FUNCTION_ARGS);
extern Datum show_all_settings(PG_FUNCTION_ARGS); extern Datum show_all_settings(PG_FUNCTION_ARGS);
/* lockfuncs.c */
extern Datum pg_lock_status(PG_FUNCTION_ARGS);
/* catalog/pg_conversion.c */ /* catalog/pg_conversion.c */
extern Datum pg_convert3(PG_FUNCTION_ARGS); extern Datum pg_convert3(PG_FUNCTION_ARGS);
......
...@@ -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: lsyscache.h,v 1.59 2002/08/26 17:54:02 tgl Exp $ * $Id: lsyscache.h,v 1.60 2002/08/29 00:17:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -54,6 +54,7 @@ extern void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, ...@@ -54,6 +54,7 @@ extern void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval,
extern char get_typstorage(Oid typid); extern char get_typstorage(Oid typid);
extern Node *get_typdefault(Oid typid); extern Node *get_typdefault(Oid typid);
extern char get_typtype(Oid typid); extern char get_typtype(Oid typid);
extern void getTypeInputInfo(Oid type, Oid *typInput, Oid *typElem);
extern bool getTypeOutputInfo(Oid type, Oid *typOutput, Oid *typElem, extern bool getTypeOutputInfo(Oid type, Oid *typOutput, Oid *typElem,
bool *typIsVarlena); bool *typIsVarlena);
extern Oid getBaseType(Oid typid); extern Oid getBaseType(Oid typid);
......
...@@ -134,6 +134,44 @@ SELECT * FROM vw_getfoo; ...@@ -134,6 +134,44 @@ SELECT * FROM vw_getfoo;
1 | 2 | Ed 1 | 2 | Ed
(2 rows) (2 rows)
-- sql, proretset = f, prorettype = record
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
CREATE FUNCTION getfoo(int) RETURNS RECORD AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
SELECT * FROM getfoo(1) AS t1(fooid int, foosubid int, fooname text);
fooid | foosubid | fooname
-------+----------+---------
1 | 1 | Joe
(1 row)
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) AS
(fooid int, foosubid int, fooname text);
SELECT * FROM vw_getfoo;
fooid | foosubid | fooname
-------+----------+---------
1 | 1 | Joe
(1 row)
-- sql, proretset = t, prorettype = record
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
CREATE FUNCTION getfoo(int) RETURNS setof record AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
SELECT * FROM getfoo(1) AS t1(fooid int, foosubid int, fooname text);
fooid | foosubid | fooname
-------+----------+---------
1 | 1 | Joe
1 | 2 | Ed
(2 rows)
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) AS
(fooid int, foosubid int, fooname text);
SELECT * FROM vw_getfoo;
fooid | foosubid | fooname
-------+----------+---------
1 | 1 | Joe
1 | 2 | Ed
(2 rows)
-- plpgsql, proretset = f, prorettype = b -- plpgsql, proretset = f, prorettype = b
DROP VIEW vw_getfoo; DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int); DROP FUNCTION getfoo(int);
......
...@@ -63,6 +63,24 @@ SELECT * FROM getfoo(1) AS t1; ...@@ -63,6 +63,24 @@ SELECT * FROM getfoo(1) AS t1;
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1); CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1);
SELECT * FROM vw_getfoo; SELECT * FROM vw_getfoo;
-- sql, proretset = f, prorettype = record
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
CREATE FUNCTION getfoo(int) RETURNS RECORD AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
SELECT * FROM getfoo(1) AS t1(fooid int, foosubid int, fooname text);
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) AS
(fooid int, foosubid int, fooname text);
SELECT * FROM vw_getfoo;
-- sql, proretset = t, prorettype = record
DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int);
CREATE FUNCTION getfoo(int) RETURNS setof record AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL;
SELECT * FROM getfoo(1) AS t1(fooid int, foosubid int, fooname text);
CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) AS
(fooid int, foosubid int, fooname text);
SELECT * FROM vw_getfoo;
-- plpgsql, proretset = f, prorettype = b -- plpgsql, proretset = f, prorettype = b
DROP VIEW vw_getfoo; DROP VIEW vw_getfoo;
DROP FUNCTION getfoo(int); DROP FUNCTION getfoo(int);
......
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