aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/src/sgml/catalogs.sgml49
-rw-r--r--doc/src/sgml/ref/allfiles.sgml4
-rw-r--r--doc/src/sgml/ref/comment.sgml15
-rw-r--r--doc/src/sgml/ref/create_domain.sgml231
-rw-r--r--doc/src/sgml/ref/drop_domain.sgml167
-rw-r--r--doc/src/sgml/reference.sgml6
-rw-r--r--src/backend/catalog/heap.c159
-rw-r--r--src/backend/catalog/pg_type.c70
-rw-r--r--src/backend/commands/creatinh.c71
-rw-r--r--src/backend/commands/define.c364
-rw-r--r--src/backend/commands/remove.c59
-rw-r--r--src/backend/nodes/copyfuncs.c19
-rw-r--r--src/backend/nodes/equalfuncs.c18
-rw-r--r--src/backend/optimizer/prep/preptlist.c54
-rw-r--r--src/backend/parser/gram.y81
-rw-r--r--src/backend/parser/keywords.c3
-rw-r--r--src/backend/parser/parse_coerce.c31
-rw-r--r--src/backend/parser/parse_expr.c7
-rw-r--r--src/backend/tcop/postgres.c7
-rw-r--r--src/backend/tcop/utility.c20
-rw-r--r--src/backend/utils/adt/format_type.c28
-rw-r--r--src/backend/utils/cache/lsyscache.c63
-rw-r--r--src/backend/utils/cache/relcache.c10
-rw-r--r--src/include/catalog/heap.h10
-rw-r--r--src/include/catalog/pg_attribute.h17
-rw-r--r--src/include/catalog/pg_class.h4
-rw-r--r--src/include/catalog/pg_type.h257
-rw-r--r--src/include/commands/defrem.h4
-rw-r--r--src/include/nodes/nodes.h3
-rw-r--r--src/include/nodes/parsenodes.h22
-rw-r--r--src/include/parser/parse_coerce.h3
-rw-r--r--src/include/utils/lsyscache.h4
-rw-r--r--src/test/regress/expected/domain.out114
-rw-r--r--src/test/regress/parallel_schedule2
-rw-r--r--src/test/regress/serial_schedule4
-rw-r--r--src/test/regress/sql/domain.sql111
36 files changed, 1805 insertions, 286 deletions
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index d785121a047..451c9dcaa8a 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -1,6 +1,6 @@
<!--
Documentation of the system catalogs, directed toward PostgreSQL developers
- $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.33 2002/03/07 16:35:32 momjian Exp $
+ $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.34 2002/03/19 02:18:10 momjian Exp $
-->
<chapter id="catalogs">
@@ -2511,6 +2511,53 @@
</row>
<row>
+ <entry>typbasetype</entry>
+ <entry><type>oid</type></entry>
+ <entry></entry>
+ <entry><para>
+ <structfield>typbasetype</structfield> is the type that this one is based
+ on. Normally references the domains parent type, and is 0 otherwise.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry>typnotnull</entry>
+ <entry><type>boolean</type></entry>
+ <entry></entry>
+ <entry><para>
+ <structfield>typnotnull</structfield> represents a NOT NULL
+ constraint on a type. Used for domains only.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry>typmod</entry>
+ <entry><type>integer</type></entry>
+ <entry></entry>
+ <entry><para>
+ <structfield>typmod</structfield> records type-specific data
+ supplied at table creation time (for example, the maximum
+ length of a <type>varchar</type> column). It is passed to
+ type-specific input and output functions as the third
+ argument. The value will generally be -1 for types that do not
+ need typmod. This data is copied to
+ <structfield>pg_attribute.atttypmod</structfield> on creation
+ of a table using a domain as it's field type.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry>typdefaultbin</entry>
+ <entry><type>text</type></entry>
+ <entry></entry>
+ <entry><para>
+ <structfield>typdefaultbin</structfield> is NULL for types without a
+ default value. If it's not NULL, it contains the internal string
+ representation of the default expression node.
+ </para></entry>
+ </row>
+
+ <row>
<entry>typdefault</entry>
<entry><type>text</type></entry>
<entry></entry>
diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
index 3ea658fd042..460f150bc89 100644
--- a/doc/src/sgml/ref/allfiles.sgml
+++ b/doc/src/sgml/ref/allfiles.sgml
@@ -1,5 +1,5 @@
<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.35 2002/03/07 16:35:32 momjian Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.36 2002/03/19 02:18:12 momjian Exp $
PostgreSQL documentation
Complete list of usable sgml source files in this directory.
-->
@@ -52,6 +52,7 @@ Complete list of usable sgml source files in this directory.
<!entity createAggregate system "create_aggregate.sgml">
<!entity createConstraint system "create_constraint.sgml">
<!entity createDatabase system "create_database.sgml">
+<!entity createDomain system "create_domain.sgml">
<!entity createFunction system "create_function.sgml">
<!entity createGroup system "create_group.sgml">
<!entity createIndex system "create_index.sgml">
@@ -69,6 +70,7 @@ Complete list of usable sgml source files in this directory.
<!entity delete system "delete.sgml">
<!entity dropAggregate system "drop_aggregate.sgml">
<!entity dropDatabase system "drop_database.sgml">
+<!entity dropDomain system "drop_domain.sgml">
<!entity dropFunction system "drop_function.sgml">
<!entity dropGroup system "drop_group.sgml">
<!entity dropIndex system "drop_index.sgml">
diff --git a/doc/src/sgml/ref/comment.sgml b/doc/src/sgml/ref/comment.sgml
index 026533de954..f3530b71ce6 100644
--- a/doc/src/sgml/ref/comment.sgml
+++ b/doc/src/sgml/ref/comment.sgml
@@ -1,5 +1,5 @@
<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/comment.sgml,v 1.14 2002/03/07 16:35:33 momjian Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/comment.sgml,v 1.15 2002/03/19 02:18:12 momjian Exp $
PostgreSQL documentation
-->
@@ -25,7 +25,7 @@ PostgreSQL documentation
<synopsis>
COMMENT ON
[
- [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] <replaceable class="PARAMETER">object_name</replaceable> |
+ [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] <replaceable class="PARAMETER">object_name</replaceable> |
COLUMN <replaceable class="PARAMETER">table_name</replaceable>.<replaceable class="PARAMETER">column_name</replaceable> |
AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable>) |
FUNCTION <replaceable class="PARAMETER">func_name</replaceable> (<replaceable class="PARAMETER">arg1</replaceable>, <replaceable class="PARAMETER">arg2</replaceable>, ...) |
@@ -33,7 +33,7 @@ COMMENT ON
TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable>
] IS <replaceable class="PARAMETER">'text'</replaceable>
</synopsis>
-
+
<refsect2 id="R2-SQL-COMMENT-1">
<refsect2info>
<date>1999-10-25</date>
@@ -64,7 +64,7 @@ COMMENT ON
</variablelist>
</para>
</refsect2>
-
+
<refsect2 id="R2-SQL-COMMENT-2">
<refsect2info>
<date>1998-09-08</date>
@@ -99,7 +99,7 @@ COMMENT
</title>
<para>
<command>COMMENT</command> stores a comment about a database object.
- Comments can be
+ Comments can be
easily retrieved with <command>psql</command>'s
<command>\dd</command>, <command>\d+</command>, or <command>\l+</command>
commands. Other user interfaces to retrieve comments can be built atop
@@ -141,6 +141,7 @@ COMMENT ON mytable IS 'This is my table.';
<programlisting>
COMMENT ON DATABASE my_database IS 'Development Database';
+COMMENT ON DOMAIN my_domain IS 'Email Address Domain';
COMMENT ON INDEX my_index IS 'Enforces uniqueness on employee id';
COMMENT ON RULE my_rule IS 'Logs UPDATES of employee records';
COMMENT ON SEQUENCE my_sequence IS 'Used to generate primary keys';
@@ -155,12 +156,12 @@ COMMENT ON TRIGGER my_trigger ON my_table IS 'Used for R.I.';
</programlisting>
</para>
</refsect1>
-
+
<refsect1 id="R1-SQL-COMMENT-3">
<title>
Compatibility
</title>
-
+
<refsect2 id="R2-SQL-COMMENT-4">
<refsect2info>
<date>1998-09-08</date>
diff --git a/doc/src/sgml/ref/create_domain.sgml b/doc/src/sgml/ref/create_domain.sgml
new file mode 100644
index 00000000000..5f79dc63b53
--- /dev/null
+++ b/doc/src/sgml/ref/create_domain.sgml
@@ -0,0 +1,231 @@
+<!--
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_domain.sgml,v 1.3 2002/03/19 02:18:13 momjian Exp $
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-CREATEDOMAIN">
+ <refmeta>
+ <refentrytitle id="sql-createdomian-title">
+ CREATE DOMAIN
+ </refentrytitle>
+ <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+ <refnamediv>
+ <refname>
+ CREATE DOMAIN
+ </refname>
+ <refpurpose>
+ define a new domain
+ </refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <refsynopsisdivinfo>
+ <date>2002-02-24</date>
+ </refsynopsisdivinfo>
+ <synopsis>
+CREATE DOMAIN <replaceable class="parameter">domainname</replaceable> <replaceable class="parameter">data_type</replaceable> [ DEFAULT <replaceable>default_expr</> ] [ <replaceable class="PARAMETER">column_constraint</replaceable> [, ... ] ]
+[ CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> ]
+{ NOT NULL | NULL <!-- | UNIQUE | PRIMARY KEY |
+ CHECK (<replaceable class="PARAMETER">expression</replaceable>) |
+ REFERENCES <replaceable class="PARAMETER">reftable</replaceable> [ ( <replaceable class="PARAMETER">refcolumn</replaceable> ) ] [ MATCH FULL | MATCH PARTIAL ]
+ [ ON DELETE <replaceable class="parameter">action</replaceable> ] [ ON UPDATE <replaceable class="parameter">action</replaceable> ] --> }
+<!-- [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] -->
+ </synopsis>
+
+ <refsect2 id="R2-SQL-CREATEDOMAIN-1">
+ <refsect2info>
+ <date>2002-02-24</date>
+ </refsect2info>
+ <title>
+ Parameters
+ </title>
+ <para>
+
+ <variablelist>
+ <varlistentry>
+ <term><replaceable class="parameter">domainname</replaceable></term>
+ <listitem>
+ <para>
+ The name of a domain to be created.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><replaceable class="PARAMETER">data_type</replaceable></term>
+ <listitem>
+ <para>
+ The data type of the domain. This may include array specifiers.
+ Refer to the <citetitle>User's Guide</citetitle> for further
+ information about data types and arrays.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>DEFAULT
+ <replaceable>default_expr</replaceable></literal></term>
+ <listitem>
+ <para>
+ The <literal>DEFAULT</> clause assigns a default data value for
+ the column whose column definition it appears within. The value
+ is any variable-free expression (subselects and cross-references
+ to other columns in the current table are not allowed). The
+ data type of the default expression must match the data type of the
+ domain.
+ </para>
+
+ <para>
+ The default expression will be used in any insert operation that
+ does not specify a value for the domain. If there is no default
+ for a domain, then the default is NULL.
+ </para>
+
+ <note>
+ <para>
+ The default of a column will be tested before that of the domain.
+ </para>
+ </note>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable></literal></term>
+ <listitem>
+ <para>
+ An optional name for a domain. If not specified,
+ the system generates a name.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>NOT NULL</></term>
+ <listitem>
+ <para>
+ The column is not allowed to contain NULL values. This is
+ equivalent to the column constraint <literal>CHECK (<replaceable
+ class="PARAMETER">column</replaceable> NOT NULL)</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>NULL</></term>
+ <listitem>
+ <para>
+ The column is allowed to contain NULL values. This is the default.
+ </para>
+
+ <para>
+ This clause is only available for compatibility with
+ non-standard SQL databases. Its use is discouraged in new
+ applications.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </para>
+ </refsect2>
+
+ <refsect2 id="R2-SQL-CREATEDOMAIN-2">
+ <refsect2info>
+ <date>2002-02-24</date>
+ </refsect2info>
+ <title>
+ Outputs
+ </title>
+ <para>
+
+ <variablelist>
+ <varlistentry>
+ <term><computeroutput>
+CREATE DOMAIN
+ </computeroutput></term>
+ <listitem>
+ <para>
+ Message returned if the domain is successfully created.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ </refsect2>
+ </refsynopsisdiv>
+
+ <refsect1 id="R1-SQL-CREATEDOMAIN-1">
+ <refsect1info>
+ <date>2002-02-24</date>
+ </refsect1info>
+ <title>
+ Description
+ </title>
+
+ <para>
+ <command>CREATE DOMAIN</command> allows the user to register a new user data
+ domain with PostgreSQL for use in the current data base. The
+ user who defines a domain becomes its owner.
+ <replaceable class="parameter">domainname</replaceable> is
+ the name of the new type and must be unique within the
+ types and domains defined for this database.
+ </para>
+
+ <para>
+ Domains are useful for abstracting common fields between tables into
+ a single location for maintenance. An email address column may be used
+ in several tables, all with the same properties. Define a domain and
+ use that rather than setting up each tables constraints individually.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Examples</title>
+ <para>
+ This example creates the <type>country_code</type> data type and then uses the
+ type in a table definition:
+<programlisting>
+CREATE DOMAIN country_code char(2) NOT NULL;
+CREATE TABLE countrylist (id INT4, country country_code);
+</programlisting>
+ </para>
+ </refsect1>
+
+ <refsect1 id="SQL-CREATEDOMAIN-compatibility">
+ <title>Compatibility</title>
+
+ <para>
+ This <command>CREATE DOMAIN</command> command is a
+ <productname>PostgreSQL</productname> extension. CHECK and FOREIGN KEY
+ constraints are currently unsupported.
+ </para>
+ </refsect1>
+
+ <refsect1 id="SQL-CREATEDOMAIN-see-also">
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-dropdomain"></member>
+ <member><citetitle>PostgreSQL Programmer's Guide</citetitle></member>
+ </simplelist>
+ </refsect1>
+
+</refentry>
+
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:"../reference.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:"/usr/lib/sgml/catalog"
+sgml-local-ecat-files:nil
+End:
+-->
diff --git a/doc/src/sgml/ref/drop_domain.sgml b/doc/src/sgml/ref/drop_domain.sgml
new file mode 100644
index 00000000000..e9bc38ad28c
--- /dev/null
+++ b/doc/src/sgml/ref/drop_domain.sgml
@@ -0,0 +1,167 @@
+<!--
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_domain.sgml,v 1.3 2002/03/19 02:18:13 momjian Exp $
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-DROPDOMAIN">
+ <refmeta>
+ <refentrytitle id="SQL-DROPDOMAIN-TITLE">
+ DROP DOMAIN
+ </refentrytitle>
+ <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+ <refnamediv>
+ <refname>
+ DROP DOMAIN
+ </refname>
+ <refpurpose>
+ remove a user-defined domain
+ </refpurpose>
+ </refnamediv>
+ <refsynopsisdiv>
+ <refsynopsisdivinfo>
+ <date>1999-07-20</date>
+ </refsynopsisdivinfo>
+ <synopsis>
+DROP DOMAIN <replaceable class="PARAMETER">domainname</replaceable> [, ...]
+ </synopsis>
+
+ <refsect2 id="R2-SQL-DROPDOMAIN-1">
+ <refsect2info>
+ <date>2002-02-24</date>
+ </refsect2info>
+ <title>
+ Inputs
+ </title>
+ <para>
+ <variablelist>
+ <varlistentry>
+ <term><replaceable class="PARAMETER">domainname</replaceable></term>
+ <listitem>
+ <para>
+ The name of an existing domain.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ </refsect2>
+
+ <refsect2 id="R2-SQL-DROPDOMAIN-2">
+ <refsect2info>
+ <date>2002-02-24</date>
+ </refsect2info>
+ <title>
+ Outputs
+ </title>
+ <para>
+ <variablelist>
+ <varlistentry>
+ <term><computeroutput>
+DROP
+ </computeroutput></term>
+ <listitem>
+ <para>
+ The message returned if the command is successful.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><computeroutput>
+ERROR: RemoveDomain: type '<replaceable class="parameter">domainname</replaceable>' does not exist
+ </computeroutput></term>
+ <listitem>
+ <para>
+ This message occurs if the specified domain (or type) is not found.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ </refsect2>
+ </refsynopsisdiv>
+
+ <refsect1 id="R1-SQL-DROPDOMAIN-1">
+ <refsect1info>
+ <date>2002-02-24</date>
+ </refsect1info>
+ <title>
+ Description
+ </title>
+ <para>
+ <command>DROP DOMAIN</command> will remove a user domain from the
+ system catalogs.
+ </para>
+ <para>
+ Only the owner of a domain can remove it.
+ </para>
+ </refsect1>
+
+ <refsect1 id="SQL-DROPDOMAIN-notes">
+ <title>Notes</title>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ It is the user's responsibility to remove any operators,
+ functions, aggregates, access methods, and tables that
+ use a deleted domain.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </refsect1>
+
+ <refsect1 id="SQL-DROPDOMAIN-examples">
+ <title>Examples</title>
+ <para>
+ To remove the <type>box</type> domain:
+
+<programlisting>
+DROP DOMAIN box RESTRICT;
+</programlisting>
+ </para>
+ </refsect1>
+
+ <refsect1 id="SQL-DROPDOMAIN-compatibility">
+ <title>Compatibility</title>
+
+ <para>
+ A <command>DROP DOMAIN</command> statement exists in SQL99. As with
+ most other <quote>drop</quote> commands, <command>DROP
+ DOMAIN</command> in SQL99 requires a <quote>drop behavior</quote>
+ clause to select between dropping all dependent objects or refusing
+ to drop if dependent objects exist:
+<synopsis>
+DROP DOMAIN <replaceable>name</replaceable> { CASCADE | RESTRICT }
+</synopsis>
+ <productname>PostgreSQL</productname> enforces the existance of
+ RESTRICT or CASCADE but ignores their enforcement against the
+ system tables.
+ </para>
+ </refsect1>
+
+ <refsect1 id="SQL-DROPDOMAIN-see-also">
+ <title>See Also</title>
+
+ <simplelist type="inline">
+ <member><xref linkend="sql-createdomain"></member>
+ </simplelist>
+ </refsect1>
+</refentry>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:"../reference.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:"/usr/lib/sgml/catalog"
+sgml-local-ecat-files:nil
+End:
+-->
diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
index 0ca0ea5a9c4..b6b63254462 100644
--- a/doc/src/sgml/reference.sgml
+++ b/doc/src/sgml/reference.sgml
@@ -1,5 +1,5 @@
<!-- reference.sgml
-$Header: /cvsroot/pgsql/doc/src/sgml/reference.sgml,v 1.23 2002/03/07 16:35:32 momjian Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/reference.sgml,v 1.24 2002/03/19 02:18:11 momjian Exp $
PostgreSQL Reference Manual
-->
@@ -61,6 +61,7 @@ PostgreSQL Reference Manual
&createAggregate;
&createConstraint;
&createDatabase;
+ &createDomain;
&createFunction;
&createGroup;
&createIndex;
@@ -78,6 +79,7 @@ PostgreSQL Reference Manual
&delete;
&dropAggregate;
&dropDatabase;
+ &dropDomain;
&dropFunction;
&dropGroup;
&dropIndex;
@@ -115,7 +117,7 @@ PostgreSQL Reference Manual
&unlisten;
&update;
&vacuum;
-
+
</reference>
<!--
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 4c35663e31c..9ec241e3ea3 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.186 2002/03/07 16:35:33 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.187 2002/03/19 02:18:14 momjian Exp $
*
*
* INTERFACE ROUTINES
@@ -49,6 +49,7 @@
#include "optimizer/planmain.h"
#include "optimizer/prep.h"
#include "optimizer/var.h"
+#include "parser/parse_coerce.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
@@ -698,10 +699,15 @@ AddNewRelationType(char *typeName, Oid new_rel_oid, Oid new_type_oid)
"oidin", /* receive procedure */
"oidout", /* send procedure */
NULL, /* array element type - irrelevant */
+ NULL, /* baseType Name -- typically for domains */
NULL, /* default type value - none */
+ NULL, /* default type binary representation */
true, /* passed by value */
'i', /* default alignment - same as for OID */
- 'p'); /* Not TOASTable */
+ 'p', /* Not TOASTable */
+ -1, /* Type mod length */
+ 0, /* array dimensions for typBaseType */
+ false); /* Type NOT NULL */
}
/* --------------------------------
@@ -1584,6 +1590,10 @@ AddRelationRawConstraints(Relation rel,
int numchecks;
List *listptr;
+ /* Probably shouldn't be null by default */
+ Node *expr = NULL;
+
+
/*
* Get info about existing constraints.
*/
@@ -1614,68 +1624,13 @@ AddRelationRawConstraints(Relation rel,
foreach(listptr, rawColDefaults)
{
RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr);
- Node *expr;
- Oid type_id;
-
- Assert(colDef->raw_default != NULL);
-
- /*
- * Transform raw parsetree to executable expression.
- */
- expr = transformExpr(pstate, colDef->raw_default, EXPR_COLUMN_FIRST);
-
- /*
- * Make sure default expr does not refer to any vars.
- */
- if (contain_var_clause(expr))
- elog(ERROR, "cannot use column references in DEFAULT clause");
-
- /*
- * No subplans or aggregates, either...
- */
- if (contain_subplans(expr))
- elog(ERROR, "cannot use subselects in DEFAULT clause");
- if (contain_agg_clause(expr))
- elog(ERROR, "cannot use aggregate functions in DEFAULT clause");
- /*
- * Check that it will be possible to coerce the expression to the
- * column's type. We store the expression without coercion,
- * however, to avoid premature coercion in cases like
- *
- * CREATE TABLE tbl (fld datetime DEFAULT 'now'::text);
- *
- * NB: this should match the code in optimizer/prep/preptlist.c that
- * will actually do the coercion, to ensure we don't accept an
- * unusable default expression.
- */
- type_id = exprType(expr);
- if (type_id != InvalidOid)
- {
- Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
- if (type_id != atp->atttypid)
- {
- if (CoerceTargetExpr(NULL, expr, type_id,
- atp->atttypid, atp->atttypmod) == NULL)
- elog(ERROR, "Column \"%s\" is of type %s"
- " but default expression is of type %s"
- "\n\tYou will need to rewrite or cast the expression",
- NameStr(atp->attname),
- format_type_be(atp->atttypid),
- format_type_be(type_id));
- }
- }
+ Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
- /*
- * Might as well try to reduce any constant expressions.
- */
- expr = eval_const_expressions(expr);
-
- /*
- * Must fix opids, in case any operators remain...
- */
- fix_opids(expr);
+ expr = cookDefault(pstate, colDef->raw_default
+ , atp->atttypid, atp->atttypmod
+ , NameStr(atp->attname));
/*
* OK, store it.
@@ -1892,6 +1847,88 @@ SetRelationNumChecks(Relation rel, int numchecks)
heap_close(relrel, RowExclusiveLock);
}
+/*
+ * Take a raw default and convert it to a cooked format ready for
+ * storage.
+ *
+ * Parse state, attypid, attypmod and attname are required for
+ * CoerceTargetExpr() and more importantly transformExpr().
+ */
+Node *
+cookDefault(ParseState *pstate,
+ Node *raw_default,
+ Oid atttypid,
+ int32 atttypmod,
+ char *attname) {
+
+ Oid type_id;
+ Node *expr;
+
+ Assert(raw_default != NULL);
+
+ /*
+ * Transform raw parsetree to executable expression.
+ */
+ expr = transformExpr(pstate, raw_default, EXPR_COLUMN_FIRST);
+
+ /*
+ * Make sure default expr does not refer to any vars.
+ */
+ if (contain_var_clause(expr))
+ elog(ERROR, "cannot use column references in DEFAULT clause");
+
+ /*
+ * No subplans or aggregates, either...
+ */
+ if (contain_subplans(expr))
+ elog(ERROR, "cannot use subselects in DEFAULT clause");
+ if (contain_agg_clause(expr))
+ elog(ERROR, "cannot use aggregate functions in DEFAULT clause");
+
+ /*
+ * Check that it will be possible to coerce the expression to the
+ * column's type. We store the expression without coercion,
+ * however, to avoid premature coercion in cases like
+ *
+ * CREATE TABLE tbl (fld datetime DEFAULT 'now'::text);
+ *
+ * NB: this should match the code in optimizer/prep/preptlist.c that
+ * will actually do the coercion, to ensure we don't accept an
+ * unusable default expression.
+ */
+ type_id = exprType(expr);
+ if (type_id != InvalidOid && atttypid != InvalidOid) {
+ if (type_id != atttypid) {
+
+ /* Try coercing to the base type of the domain if available */
+ if (CoerceTargetExpr(pstate, expr, type_id,
+ getBaseType(atttypid),
+ atttypmod) == NULL) {
+
+ elog(ERROR, "Column \"%s\" is of type %s"
+ " but default expression is of type %s"
+ "\n\tYou will need to rewrite or cast the expression",
+ attname,
+ format_type_be(atttypid),
+ format_type_be(type_id));
+ }
+ }
+ }
+
+ /*
+ * Might as well try to reduce any constant expressions.
+ */
+ expr = eval_const_expressions(expr);
+
+ /*
+ * Must fix opids, in case any operators remain...
+ */
+ fix_opids(expr);
+
+ return(expr);
+}
+
+
static void
RemoveAttrDefaults(Relation rel)
{
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index 3c5c9cd53e0..35164669190 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.67 2002/03/07 16:35:33 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.68 2002/03/19 02:18:14 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -176,10 +176,16 @@ TypeShellMakeWithOpenRelation(Relation pg_type_desc, char *typeName)
values[i++] = ObjectIdGetDatum(InvalidOid); /* 12 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 13 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 14 */
- values[i++] = CharGetDatum('i'); /* 15 */
- values[i++] = CharGetDatum('p'); /* 16 */
+ values[i++] = CharGetDatum('i'); /* 15 */
+ values[i++] = CharGetDatum('p'); /* 16 */
+ values[i++] = BoolGetDatum(false); /* 17 */
+ values[i++] = Int32GetDatum(-1); /* 18 */
+ values[i++] = ObjectIdGetDatum(InvalidOid); /* 19 */
+ values[i++] = Int32GetDatum(0); /* 20 */
values[i++] = DirectFunctionCall1(textin,
- CStringGetDatum(typeName)); /* 17 */
+ CStringGetDatum(typeName)); /* 21 */
+ values[i++] = DirectFunctionCall1(textin,
+ CStringGetDatum(typeName)); /* 22 */
/*
* create a new type tuple with FormHeapTuple
@@ -264,7 +270,7 @@ TypeShellMake(char *typeName)
Oid
TypeCreate(char *typeName,
Oid assignedTypeOid,
- Oid relationOid, /* only for 'c'atalog typeTypes */
+ Oid relationOid, /* only for 'c'atalog typeTypes */
int16 internalSize,
int16 externalSize,
char typeType,
@@ -274,10 +280,15 @@ TypeCreate(char *typeName,
char *receiveProcedure,
char *sendProcedure,
char *elementTypeName,
- char *defaultTypeValue, /* internal rep */
+ char *baseTypeName,
+ char *defaultTypeValue, /* human readable rep */
+ char *defaultTypeBin, /* cooked rep */
bool passedByValue,
char alignment,
- char storage)
+ char storage,
+ int32 typeMod,
+ int32 typNDims, /* Array dimensions for baseTypeName */
+ bool typeNotNull) /* binary default representation (cooked) */
{
int i,
j;
@@ -285,6 +296,7 @@ TypeCreate(char *typeName,
HeapScanDesc pg_type_scan;
Oid typeObjectId;
Oid elementObjectId = InvalidOid;
+ Oid baseObjectId = InvalidOid;
HeapTuple tup;
char nulls[Natts_pg_type];
char replaces[Natts_pg_type];
@@ -318,6 +330,17 @@ TypeCreate(char *typeName,
}
/*
+ * if this type has an associated baseType, then we check that it
+ * is defined.
+ */
+ if (baseTypeName)
+ {
+ baseObjectId = TypeGet(baseTypeName, &defined);
+ if (!defined)
+ elog(ERROR, "type %s does not exist", baseTypeName);
+ }
+
+ /*
* validate size specifications: either positive (fixed-length) or -1
* (variable-length).
*/
@@ -388,7 +411,7 @@ TypeCreate(char *typeName,
* signature is 0,OIDOID,INT4OID. The output procedures may
* take 2 args (data value, element OID).
*/
- if (OidIsValid(elementObjectId))
+ if (OidIsValid(elementObjectId) || OidIsValid(baseObjectId))
{
int nargs;
@@ -411,6 +434,7 @@ TypeCreate(char *typeName,
PointerGetDatum(argList),
0);
}
+
if (!OidIsValid(procOid))
func_error("TypeCreate", procname, 1, argList, NULL);
}
@@ -429,6 +453,34 @@ TypeCreate(char *typeName,
values[i++] = CharGetDatum(storage); /* 16 */
/*
+ * set the typenotnull value
+ */
+ values[i++] = BoolGetDatum(typeNotNull); /* 17 */
+
+ /*
+ * set the typemod value
+ */
+ values[i++] = Int32GetDatum(typeMod); /* 18 */
+
+ values[i++] = ObjectIdGetDatum(baseObjectId); /* 19 */
+
+ /*
+ * Dimension number for an array base type
+ */
+ values[i++] = Int32GetDatum(typNDims); /* 20 */
+
+ /*
+ * initialize the default binary value for this type. Check for
+ * nulls of course.
+ */
+ if (defaultTypeBin)
+ values[i] = DirectFunctionCall1(textin,
+ CStringGetDatum(defaultTypeBin));
+ else
+ nulls[i] = 'n';
+ i++; /* 21 */
+
+ /*
* initialize the default value for this type.
*/
if (defaultTypeValue)
@@ -436,7 +488,7 @@ TypeCreate(char *typeName,
CStringGetDatum(defaultTypeValue));
else
nulls[i] = 'n';
- i++; /* 17 */
+ i++; /* 22 */
/*
* open pg_type and begin a scan for the type name.
diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c
index bb80487dbb4..ae2a90c9311 100644
--- a/src/backend/commands/creatinh.c
+++ b/src/backend/commands/creatinh.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.85 2002/03/07 16:35:34 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.86 2002/03/19 02:18:15 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -39,7 +39,7 @@ static bool change_varattnos_of_a_node(Node *node, const AttrNumber *newattno);
static void StoreCatalogInheritance(Oid relationId, List *supers);
static int findAttrByName(const char *attributeName, List *schema);
static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
-
+static List *MergeDomainAttributes(List *schema);
/* ----------------------------------------------------------------
* DefineRelation
@@ -70,6 +70,13 @@ DefineRelation(CreateStmt *stmt, char relkind)
StrNCpy(relname, stmt->relname, NAMEDATALEN);
/*
+ * Inherit domain attributes into the known columns before table inheritance
+ * applies it's changes otherwise we risk adding double constraints
+ * to a domain thats inherited.
+ */
+ schema = MergeDomainAttributes(schema);
+
+ /*
* Look up inheritance ancestors and generate relation schema,
* including inherited attributes.
*/
@@ -237,6 +244,66 @@ TruncateRelation(char *name)
heap_truncate(name);
}
+
+/*
+ * MergeDomainAttributes
+ * Returns a new table schema with the constraints, types, and other
+ * attributes of the domain resolved for fields using the domain as
+ * their type.
+ *
+ * Defaults are pulled out by the table attribute as required, similar to
+ * how all types defaults are processed.
+ */
+static List *
+MergeDomainAttributes(List *schema)
+{
+ List *entry;
+
+ /*
+ * Loop through the table elements supplied. These should
+ * never include inherited domains else they'll be
+ * double (or more) processed.
+ */
+ foreach(entry, schema)
+ {
+ ColumnDef *coldef = lfirst(entry);
+ HeapTuple tuple;
+ Form_pg_type typeTup;
+
+
+ tuple = SearchSysCache(TYPENAME,
+ CStringGetDatum(coldef->typename->name),
+ 0,0,0);
+
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "MergeDomainAttributes: Type %s does not exist",
+ coldef->typename->name);
+
+ typeTup = (Form_pg_type) GETSTRUCT(tuple);
+ if (typeTup->typtype == 'd') {
+ /*
+ * This is a domain, lets force the properties of the domain on to
+ * the new column.
+ */
+
+ /* Enforce the typmod value */
+ coldef->typename->typmod = typeTup->typmod;
+
+ /* Enforce type NOT NULL || column definition NOT NULL -> NOT NULL */
+ coldef->is_not_null |= typeTup->typnotnull;
+
+ /* Enforce the element type in the event the domain is an array
+ *
+ * BUG: How do we fill out arrayBounds and attrname from typelem and typNDimms?
+ */
+
+ }
+ ReleaseSysCache(tuple);
+ }
+
+ return schema;
+}
+
/*----------
* MergeAttributes
* Returns new schema given initial schema and superclasses.
diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c
index f70b58d5c2e..72aa7a3a15f 100644
--- a/src/backend/commands/define.c
+++ b/src/backend/commands/define.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.69 2002/03/07 16:35:34 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.70 2002/03/19 02:18:15 momjian Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@@ -40,6 +40,7 @@
#include "access/heapam.h"
#include "catalog/catname.h"
+#include "catalog/heap.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_language.h"
#include "catalog/pg_operator.h"
@@ -476,6 +477,323 @@ DefineAggregate(char *aggName, List *parameters)
}
/*
+ * DefineDomain
+ * Registers a new domain.
+ */
+void
+DefineDomain(CreateDomainStmt *stmt)
+{
+ int16 internalLength = -1; /* int2 */
+ int16 externalLength = -1; /* int2 */
+ char *inputName = NULL;
+ char *outputName = NULL;
+ char *sendName = NULL;
+ char *receiveName = NULL;
+
+ /*
+ * Domains store the external representation in defaultValue
+ * and the interal Node representation in defaultValueBin
+ */
+ char *defaultValue = NULL;
+ char *defaultValueBin = NULL;
+
+ bool byValue = false;
+ char delimiter = DEFAULT_TYPDELIM;
+ char alignment = 'i'; /* default alignment */
+ char storage = 'p'; /* default TOAST storage method */
+ char typtype;
+ Datum datum;
+ bool typNotNull = false;
+ char *elemName = NULL;
+ int32 typNDims = 0; /* No array dimensions by default */
+
+ bool isnull;
+ Relation pg_type_rel;
+ TupleDesc pg_type_dsc;
+ HeapTuple typeTup;
+ char *typeName = stmt->typename->name;
+
+ List *listptr;
+ List *schema = stmt->constraints;
+
+ /*
+ * Domainnames, unlike typenames don't need to account for the '_'
+ * prefix. So they can be one character longer.
+ */
+ if (strlen(stmt->domainname) > (NAMEDATALEN - 1))
+ elog(ERROR, "CREATE DOMAIN: domain names must be %d characters or less",
+ NAMEDATALEN - 1);
+
+
+ /* Test for existing Domain (or type) of that name */
+ typeTup = SearchSysCache( TYPENAME
+ , PointerGetDatum(stmt->domainname)
+ , 0, 0, 0
+ );
+
+ if (HeapTupleIsValid(typeTup))
+ {
+ elog(ERROR, "CREATE DOMAIN: domain or type %s already exists",
+ stmt->domainname);
+ }
+
+ /*
+ * Get the information about old types
+ */
+ pg_type_rel = heap_openr(TypeRelationName, RowExclusiveLock);
+ pg_type_dsc = RelationGetDescr(pg_type_rel);
+
+
+ /*
+ * When the type is an array for some reason we don't actually receive
+ * the name here. We receive the base types name. Lets set Dims while
+ * were at it.
+ */
+ if (stmt->typename->arrayBounds > 0) {
+ typeName = makeArrayTypeName(stmt->typename->name);
+
+ typNDims = length(stmt->typename->arrayBounds);
+ }
+
+
+ typeTup = SearchSysCache( TYPENAME
+ , PointerGetDatum(typeName)
+ , 0, 0, 0
+ );
+
+ if (!HeapTupleIsValid(typeTup))
+ {
+ elog(ERROR, "CREATE DOMAIN: type %s does not exist",
+ stmt->typename->name);
+ }
+
+
+ /* Check that this is a basetype */
+ typtype = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typtype, pg_type_dsc, &isnull));
+ Assert(!isnull);
+
+ /*
+ * What we really don't want is domains of domains. This could cause all sorts
+ * of neat issues if we allow that.
+ *
+ * With testing, we may determine complex types should be allowed
+ */
+ if (typtype != 'b') {
+ elog(ERROR, "DefineDomain: %s is not a basetype", stmt->typename->name);
+ }
+
+ /* passed by value */
+ byValue = ((Form_pg_type) GETSTRUCT(typeTup))->typbyval;
+
+ /* Required Alignment */
+ alignment = ((Form_pg_type) GETSTRUCT(typeTup))->typalign;
+
+ /* Storage Length */
+ internalLength = ((Form_pg_type) GETSTRUCT(typeTup))->typlen;
+
+ /* External Length (unused) */
+ externalLength = ((Form_pg_type) GETSTRUCT(typeTup))->typprtlen;
+
+ /* Array element Delimiter */
+ delimiter = ((Form_pg_type) GETSTRUCT(typeTup))->typdelim;
+
+ /* Input Function Name */
+ datum = heap_getattr(typeTup, Anum_pg_type_typinput, pg_type_dsc, &isnull);
+ Assert(!isnull);
+
+ inputName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
+
+ /* Output Function Name */
+ datum = heap_getattr(typeTup, Anum_pg_type_typoutput, pg_type_dsc, &isnull);
+ Assert(!isnull);
+
+ outputName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
+
+ /* ReceiveName */
+ datum = heap_getattr(typeTup, Anum_pg_type_typreceive, pg_type_dsc, &isnull);
+ Assert(!isnull);
+
+ receiveName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
+
+ /* SendName */
+ datum = heap_getattr(typeTup, Anum_pg_type_typsend, pg_type_dsc, &isnull);
+ Assert(!isnull);
+
+ sendName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
+
+ /* TOAST Strategy */
+ storage = ((Form_pg_type) GETSTRUCT(typeTup))->typstorage;
+ Assert(!isnull);
+
+ /* Inherited default value */
+ datum = heap_getattr(typeTup, Anum_pg_type_typdefault, pg_type_dsc, &isnull);
+ if (!isnull) {
+ defaultValue = DatumGetCString(DirectFunctionCall1(textout, datum));
+ }
+
+ /* Inherited default binary value */
+ datum = heap_getattr(typeTup, Anum_pg_type_typdefaultbin, pg_type_dsc, &isnull);
+ if (!isnull) {
+ defaultValueBin = DatumGetCString(DirectFunctionCall1(textout, datum));
+ }
+
+ /*
+ * Pull out the typelem name of the parent OID.
+ *
+ * This is what enables us to make a domain of an array
+ */
+ datum = heap_getattr(typeTup, Anum_pg_type_typelem, pg_type_dsc, &isnull);
+ Assert(!isnull);
+
+ if (DatumGetObjectId(datum) != InvalidOid) {
+ HeapTuple tup;
+
+ tup = SearchSysCache( TYPEOID
+ , datum
+ , 0, 0, 0
+ );
+
+ elemName = NameStr(((Form_pg_type) GETSTRUCT(tup))->typname);
+
+ ReleaseSysCache(tup);
+ }
+
+
+ /*
+ * Run through constraints manually avoids the additional
+ * processing conducted by DefineRelation() and friends.
+ *
+ * Besides, we don't want any constraints to be cooked. We'll
+ * do that when the table is created via MergeDomainAttributes().
+ */
+ foreach(listptr, schema)
+ {
+ bool nullDefined = false;
+ Node *expr;
+ Constraint *colDef = lfirst(listptr);
+
+ /* Used for the statement transformation */
+ ParseState *pstate;
+
+ /*
+ * Create a dummy ParseState and insert the target relation as its
+ * sole rangetable entry. We need a ParseState for transformExpr.
+ */
+ pstate = make_parsestate(NULL);
+
+ switch(colDef->contype) {
+ /*
+ * The inherited default value may be overridden by the user
+ * with the DEFAULT <expr> statement.
+ *
+ * We have to search the entire constraint tree returned as we
+ * don't want to cook or fiddle too much.
+ */
+ case CONSTR_DEFAULT:
+
+ /*
+ * Cook the colDef->raw_expr into an expression to ensure
+ * that it can be done. We store the text version of the
+ * raw value.
+ *
+ * Note: Name is strictly for error message
+ */
+ expr = cookDefault(pstate, colDef->raw_expr
+ , typeTup->t_data->t_oid
+ , stmt->typename->typmod
+ , stmt->typename->name);
+
+ /* Binary default required */
+ defaultValue = deparse_expression(expr,
+ deparse_context_for(stmt->domainname,
+ InvalidOid),
+ false);
+
+ defaultValueBin = nodeToString(expr);
+
+ break;
+
+ /*
+ * Find the NULL constraint.
+ */
+ case CONSTR_NOTNULL:
+ if (nullDefined) {
+ elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
+ } else {
+ typNotNull = true;
+ nullDefined = true;
+ }
+
+ break;
+
+ case CONSTR_NULL:
+ if (nullDefined) {
+ elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
+ } else {
+ typNotNull = false;
+ nullDefined = true;
+ }
+
+ break;
+
+ case CONSTR_UNIQUE:
+ elog(ERROR, "CREATE DOMAIN / UNIQUE indecies not supported");
+ break;
+
+ case CONSTR_PRIMARY:
+ elog(ERROR, "CREATE DOMAIN / PRIMARY KEY indecies not supported");
+ break;
+
+
+ case CONSTR_CHECK:
+
+ elog(ERROR, "defineDomain: CHECK Constraints not supported");
+ break;
+
+ case CONSTR_ATTR_DEFERRABLE:
+ case CONSTR_ATTR_NOT_DEFERRABLE:
+ case CONSTR_ATTR_DEFERRED:
+ case CONSTR_ATTR_IMMEDIATE:
+ elog(ERROR, "defineDomain: DEFERRABLE, NON DEFERRABLE, DEFERRED and IMMEDIATE not supported");
+ break;
+ }
+
+ }
+
+ /*
+ * Have TypeCreate do all the real work.
+ */
+ TypeCreate(stmt->domainname, /* type name */
+ InvalidOid, /* preassigned type oid (not done here) */
+ InvalidOid, /* relation oid (n/a here) */
+ internalLength, /* internal size */
+ externalLength, /* external size */
+ 'd', /* type-type (domain type) */
+ delimiter, /* array element delimiter */
+ inputName, /* input procedure */
+ outputName, /* output procedure */
+ receiveName, /* receive procedure */
+ sendName, /* send procedure */
+ elemName, /* element type name */
+ typeName, /* base type name */
+ defaultValue, /* default type value */
+ defaultValueBin, /* default type value */
+ byValue, /* passed by value */
+ alignment, /* required alignment */
+ storage, /* TOAST strategy */
+ stmt->typename->typmod, /* typeMod value */
+ typNDims, /* Array dimensions for base type */
+ typNotNull); /* Type NOT NULL */
+
+ /*
+ * Now we can clean up.
+ */
+ ReleaseSysCache(typeTup);
+ heap_close(pg_type_rel, NoLock);
+}
+
+
+/*
* DefineType
* Registers a new type.
*/
@@ -490,6 +808,8 @@ DefineType(char *typeName, List *parameters)
char *sendName = NULL;
char *receiveName = NULL;
char *defaultValue = NULL;
+ char *defaultValueBin = NULL;
+ Node *defaultRaw = (Node *) NULL;
bool byValue = false;
char delimiter = DEFAULT_TYPDELIM;
char *shadow_type;
@@ -531,7 +851,7 @@ DefineType(char *typeName, List *parameters)
else if (strcasecmp(defel->defname, "element") == 0)
elemName = defGetString(defel);
else if (strcasecmp(defel->defname, "default") == 0)
- defaultValue = defGetString(defel);
+ defaultRaw = defel->arg;
else if (strcasecmp(defel->defname, "passedbyvalue") == 0)
byValue = true;
else if (strcasecmp(defel->defname, "alignment") == 0)
@@ -591,6 +911,32 @@ DefineType(char *typeName, List *parameters)
if (outputName == NULL)
elog(ERROR, "Define: \"output\" unspecified");
+
+ if (defaultRaw) {
+ Node *expr;
+ ParseState *pstate;
+
+ /*
+ * Create a dummy ParseState and insert the target relation as its
+ * sole rangetable entry. We need a ParseState for transformExpr.
+ */
+ pstate = make_parsestate(NULL);
+
+ expr = cookDefault(pstate, defaultRaw,
+ InvalidOid,
+ -1,
+ typeName);
+
+ /* Binary default required */
+ defaultValue = deparse_expression(expr,
+ deparse_context_for(typeName,
+ InvalidOid),
+ false);
+
+ defaultValueBin = nodeToString(expr);
+ }
+
+
/*
* now have TypeCreate do all the real work.
*/
@@ -606,10 +952,15 @@ DefineType(char *typeName, List *parameters)
receiveName, /* receive procedure */
sendName, /* send procedure */
elemName, /* element type name */
+ NULL, /* base type name (Non-zero for domains) */
defaultValue, /* default type value */
+ defaultValueBin, /* default type value (Binary form) */
byValue, /* passed by value */
alignment, /* required alignment */
- storage); /* TOAST strategy */
+ storage, /* TOAST strategy */
+ -1, /* typMod (Domains only) */
+ 0, /* Array Dimensions of typbasetype */
+ 'f'); /* Type NOT NULL */
/*
* When we create a base type (as opposed to a complex type) we need
@@ -632,10 +983,15 @@ DefineType(char *typeName, List *parameters)
"array_in", /* receive procedure */
"array_out", /* send procedure */
typeName, /* element type name */
+ NULL, /* base type name */
NULL, /* never a default type value */
+ NULL, /* binary default isn't sent either */
false, /* never passed by value */
alignment, /* see above */
- 'x'); /* ARRAY is always toastable */
+ 'x', /* ARRAY is always toastable */
+ -1, /* typMod (Domains only) */
+ 0, /* Array dimensions of typbasetype */
+ 'f'); /* Type NOT NULL */
pfree(shadow_type);
}
diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c
index 8c8634c18b4..297b351df83 100644
--- a/src/backend/commands/remove.c
+++ b/src/backend/commands/remove.c
@@ -1,14 +1,14 @@
/*-------------------------------------------------------------------------
*
* remove.c
- * POSTGRES remove (function | type | operator ) utilty code.
+ * POSTGRES remove (domain | function | type | operator ) utilty code.
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.68 2002/03/07 16:35:34 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.69 2002/03/19 02:18:16 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,6 +22,7 @@
#include "commands/comment.h"
#include "commands/defrem.h"
#include "miscadmin.h"
+#include "parser/parse.h"
#include "parser/parse_agg.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
@@ -276,6 +277,60 @@ RemoveType(char *typeName) /* type name to be removed */
}
/*
+ * RemoveDomain
+ * Removes the domain 'typeName' and all attributes and relations that
+ * use it.
+ */
+void
+RemoveDomain(char *domainName, int behavior) /* domain name to be removed */
+{
+ Relation relation;
+ HeapTuple tup;
+ TupleDesc description;
+ char typtype;
+ bool isnull;
+
+
+ /* Domains are stored as types. Check for permissions on the type */
+ if (!pg_ownercheck(GetUserId(), domainName, TYPENAME))
+ elog(ERROR, "RemoveDomain: type '%s': permission denied",
+ domainName);
+
+
+ relation = heap_openr(TypeRelationName, RowExclusiveLock);
+ description = RelationGetDescr(relation);
+
+ tup = SearchSysCache(TYPENAME,
+ PointerGetDatum(domainName),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "RemoveType: type '%s' does not exist", domainName);
+
+
+ /* Check that this is actually a domain */
+ typtype = DatumGetChar(heap_getattr(tup, Anum_pg_type_typtype, description, &isnull));
+ Assert(!isnull);
+
+ if (typtype != 'd') {
+ elog(ERROR, "%s is not a domain", domainName);
+ }
+
+ /* CASCADE unsupported */
+ if (behavior == CASCADE) {
+ elog(ERROR, "DROP DOMAIN does not support the CASCADE keyword");
+ }
+
+ /* Delete any comments associated with this type */
+ DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
+
+ simple_heap_delete(relation, &tup->t_self);
+
+ ReleaseSysCache(tup);
+
+ heap_close(relation, RowExclusiveLock);
+}
+
+/*
* RemoveFunction
* Deletes a function.
*
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 97eeb35ea38..070a6da5172 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.169 2002/03/12 00:51:37 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.170 2002/03/19 02:18:16 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2231,6 +2231,20 @@ _copyLoadStmt(LoadStmt *from)
return newnode;
}
+static CreateDomainStmt *
+_copyCreateDomainStmt(CreateDomainStmt *from)
+{
+ CreateDomainStmt *newnode = makeNode(CreateDomainStmt);
+
+ if (from->domainname)
+ newnode->domainname = pstrdup(from->domainname);
+
+ Node_Copy(from, newnode, typename);
+ Node_Copy(from, newnode, constraints);
+
+ return newnode;
+}
+
static CreatedbStmt *
_copyCreatedbStmt(CreatedbStmt *from)
{
@@ -3031,6 +3045,9 @@ copyObject(void *from)
case T_FuncWithArgs:
retval = _copyFuncWithArgs(from);
break;
+ case T_CreateDomainStmt:
+ retval = _copyCreateDomainStmt(from);
+ break;
default:
elog(ERROR, "copyObject: don't know how to copy node type %d",
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 760554dbb63..f6f39f2f247 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -20,7 +20,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.117 2002/03/12 00:51:37 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.118 2002/03/19 02:18:16 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1094,6 +1094,19 @@ _equalLoadStmt(LoadStmt *a, LoadStmt *b)
}
static bool
+_equalCreateDomainStmt(CreateDomainStmt *a, CreateDomainStmt *b)
+{
+ if (!equalstr(a->domainname, b->domainname))
+ return false;
+ if (!equal(a->typename, b->typename))
+ return false;
+ if (!equal(a->constraints, b->constraints))
+ return false;
+
+ return true;
+}
+
+static bool
_equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
{
if (!equalstr(a->dbname, b->dbname))
@@ -2021,6 +2034,9 @@ equal(void *a, void *b)
case T_LoadStmt:
retval = _equalLoadStmt(a, b);
break;
+ case T_CreateDomainStmt:
+ retval = _equalCreateDomainStmt(a, b);
+ break;
case T_CreatedbStmt:
retval = _equalCreatedbStmt(a, b);
break;
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index f6d574e9640..cc992c7f3a8 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.48 2002/03/07 16:35:35 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.49 2002/03/19 02:18:17 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -355,8 +355,6 @@ build_column_default(Relation rel, int attrno)
Form_pg_attribute att_tup = rd_att->attrs[attrno - 1];
Oid atttype = att_tup->atttypid;
int32 atttypmod = att_tup->atttypmod;
- bool hasdefault;
- Datum typedefault;
int16 typlen;
bool typbyval;
Node *expr;
@@ -392,7 +390,7 @@ build_column_default(Relation rel, int attrno)
if (type_id != atttype)
{
expr = CoerceTargetExpr(NULL, expr, type_id,
- atttype, atttypmod);
+ getBaseType(atttype), atttypmod);
/*
* This really shouldn't fail; should have checked the
@@ -430,41 +428,53 @@ build_column_default(Relation rel, int attrno)
* element type is, and the element type's default is irrelevant
* too.
*/
- hasdefault = false;
- typedefault = (Datum) 0;
typlen = sizeof(Oid);
typbyval = true;
+
+ expr = (Node *) makeConst(atttype,
+ typlen,
+ (Datum) 0,
+ true,
+ typbyval,
+ false, /* not a set */
+ false);
}
else
{
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(att_tup))
{
- hasdefault = false;
- typedefault = (Datum) 0;
+
+ expr = (Node *) makeConst(atttype,
+ typlen,
+ (Datum) 0,
+ true,
+ typbyval,
+ false, /* not a set */
+ false);
}
else
#endif /* _DROP_COLUMN_HACK__ */
- hasdefault = get_typdefault(atttype, &typedefault);
-
+ expr = get_typdefault(atttype, atttypmod);
+
+ if (expr == NULL) {
+ expr = (Node *) makeConst(atttype,
+ typlen,
+ (Datum) 0,
+ true,
+ typbyval,
+ false, /* not a set */
+ false);
+ }
get_typlenbyval(atttype, &typlen, &typbyval);
}
- expr = (Node *) makeConst(atttype,
- typlen,
- typedefault,
- !hasdefault,
- typbyval,
- false, /* not a set */
- false);
-
/*
* If the column is a fixed-length type, it may need a length coercion
- * as well as a type coercion. But NULLs don't need that.
+ * as well as a type coercion, as well as direction to the final type.
*/
- if (hasdefault)
- expr = coerce_type_typmod(NULL, expr,
- atttype, atttypmod);
+ expr = coerce_type_typmod(NULL, expr,
+ atttype, atttypmod);
return expr;
}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index ec20ce19065..58b9eeb89e5 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.291 2002/03/10 06:02:23 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.292 2002/03/19 02:18:18 momjian Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -98,7 +98,6 @@ static void doNegateFloat(Value *v);
%}
-
%union
{
int ival;
@@ -134,9 +133,10 @@ static void doNegateFloat(Value *v);
AlterDatabaseSetStmt, AlterGroupStmt, AlterSchemaStmt, AlterTableStmt,
AlterUserStmt, AlterUserSetStmt, AnalyzeStmt,
ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt,
- CopyStmt, CreateAsStmt, CreateGroupStmt, CreatePLangStmt,
+ CopyStmt, CreateAsStmt, CreateDomainStmt, CreateGroupStmt, CreatePLangStmt,
CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
- CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt,
+ CreateUserStmt, CreatedbStmt, CursorStmt,
+ DefineStmt, DeleteStmt,
DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
@@ -289,6 +289,8 @@ static void doNegateFloat(Value *v);
%type <list> constraints_set_list
%type <boolean> constraints_set_mode
+%type <boolean> opt_as
+
/*
* If you make any token changes, remember to:
* - use "yacc -d" and update parse.h
@@ -343,7 +345,7 @@ static void doNegateFloat(Value *v);
WITHOUT
/* Keywords (in SQL92 non-reserved words) */
-%token COMMITTED, SERIALIZABLE, TYPE_P
+%token COMMITTED, SERIALIZABLE, TYPE_P, DOMAIN_P
/* Keywords for Postgres support (not in SQL92 reserved words)
*
@@ -446,6 +448,7 @@ stmt : AlterDatabaseSetStmt
| CopyStmt
| CreateStmt
| CreateAsStmt
+ | CreateDomainStmt
| CreateSchemaStmt
| CreateGroupStmt
| CreateSeqStmt
@@ -776,8 +779,11 @@ DropSchemaStmt: DROP SCHEMA UserId
n->dbname = $3;
$$ = (Node *)n;
}
+ ;
+
+
/*****************************************************************************
*
* Set PG internal variable
@@ -1439,7 +1445,10 @@ ColConstraintElem:
n->name = NULL;
if (exprIsNullConstant($2))
{
- /* DEFAULT NULL should be reported as empty expr */
+ /*
+ * DEFAULT NULL should be reported as empty expr
+ * Required for NOT NULL Domain overrides
+ */
n->raw_expr = NULL;
}
else
@@ -2021,13 +2030,22 @@ def_list: def_elem { $$ = makeList1($1); }
| def_list ',' def_elem { $$ = lappend($1, $3); }
;
-def_elem: ColLabel '=' def_arg
+def_elem: DEFAULT '=' b_expr
+ {
+ $$ = makeNode(DefElem);
+ $$->defname = "default";
+ if (exprIsNullConstant($3))
+ $$->arg = (Node *)NULL;
+ else
+ $$->arg = $3;
+ }
+ | ColId '=' def_arg
{
$$ = makeNode(DefElem);
$$->defname = $1;
$$->arg = (Node *)$3;
}
- | ColLabel
+ | ColId
{
$$ = makeNode(DefElem);
$$->defname = $1;
@@ -2056,6 +2074,15 @@ DropStmt: DROP drop_type name_list
DropStmt *n = makeNode(DropStmt);
n->removeType = $2;
n->names = $3;
+ n->behavior = RESTRICT; /* Restricted by default */
+ $$ = (Node *)n;
+ }
+ | DROP DOMAIN_P name_list drop_behavior
+ {
+ DropStmt *n = makeNode(DropStmt);
+ n->removeType = DROP_DOMAIN_P;
+ n->names = $3;
+ n->behavior = $4;
$$ = (Node *)n;
}
;
@@ -2088,7 +2115,7 @@ TruncateStmt: TRUNCATE opt_table relation_name
* The COMMENT ON statement can take different forms based upon the type of
* the object associated with the comment. The form of the statement is:
*
- * COMMENT ON [ [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ]
+ * COMMENT ON [ [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ]
* <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION
* <funcname> (arg1, arg2, ...) | OPERATOR <op>
* (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
@@ -2174,6 +2201,7 @@ comment_type: DATABASE { $$ = DATABASE; }
| RULE { $$ = RULE; }
| SEQUENCE { $$ = SEQUENCE; }
| TABLE { $$ = TABLE; }
+ | DOMAIN_P { $$ = TYPE_P; }
| TYPE_P { $$ = TYPE_P; }
| VIEW { $$ = VIEW; }
;
@@ -3156,6 +3184,22 @@ createdb_opt_item: LOCATION opt_equal Sconst
{
$$ = lconsi(3, makeListi1(-1));
}
+ ;
+
+
+/*****************************************************************************
+ *
+ * DROP DATABASE
+ *
+ *
+ *****************************************************************************/
+
+DropdbStmt: DROP DATABASE database_name
+ {
+ DropdbStmt *n = makeNode(DropdbStmt);
+ n->dbname = $3;
+ $$ = (Node *)n;
+ }
| OWNER opt_equal name
{
$$ = lconsi(4, makeList1($3));
@@ -3200,22 +3244,30 @@ AlterDatabaseSetStmt: ALTER DATABASE database_name VariableSetStmt
}
;
-
/*****************************************************************************
*
- * DROP DATABASE
+ * Manipulate a domain
*
*
*****************************************************************************/
-DropdbStmt: DROP DATABASE database_name
+CreateDomainStmt: CREATE DOMAIN_P name opt_as Typename ColQualList opt_collate
{
- DropdbStmt *n = makeNode(DropdbStmt);
- n->dbname = $3;
+ CreateDomainStmt *n = makeNode(CreateDomainStmt);
+ n->domainname = $3;
+ n->typename = $5;
+ n->constraints = $6;
+
+ if ($7 != NULL)
+ elog(NOTICE,"CREATE DOMAIN / COLLATE %s not yet "
+ "implemented; clause ignored", $7);
$$ = (Node *)n;
}
;
+opt_as: AS {$$ = TRUE; }
+ | /* EMPTY */ {$$ = FALSE; }
+ ;
/*****************************************************************************
*
@@ -5857,6 +5909,7 @@ unreserved_keyword:
| DEFERRED { $$ = "deferred"; }
| DELETE { $$ = "delete"; }
| DELIMITERS { $$ = "delimiters"; }
+ | DOMAIN_P { $$ = "domain"; }
| DOUBLE { $$ = "double"; }
| DROP { $$ = "drop"; }
| EACH { $$ = "each"; }
diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c
index e1f53155c43..61e8744968e 100644
--- a/src/backend/parser/keywords.c
+++ b/src/backend/parser/keywords.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.103 2002/03/07 16:35:35 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.104 2002/03/19 02:18:19 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -97,6 +97,7 @@ static ScanKeyword ScanKeywords[] = {
{"desc", DESC},
{"distinct", DISTINCT},
{"do", DO},
+ {"domain", DOMAIN_P},
{"double", DOUBLE},
{"drop", DROP},
{"each", EACH},
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index 172142e33dc..7aaaa65c61b 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.66 2002/03/07 16:35:35 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.67 2002/03/19 02:18:20 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -605,3 +605,32 @@ PreferredType(CATEGORY category, Oid type)
}
return result;
} /* PreferredType() */
+
+
+/*
+ * If the targetTypeId is a domain, we really want to coerce
+ * the tuple to the domain type -- not the domain itself
+ */
+Oid
+getBaseType(Oid inType)
+{
+ HeapTuple tup;
+ Form_pg_type typTup;
+
+ tup = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(inType),
+ 0, 0, 0);
+
+ typTup = ((Form_pg_type) GETSTRUCT(tup));
+
+ /*
+ * Assume that typbasetype exists and is a base type, where inType
+ * was a domain
+ */
+ if (typTup->typtype == 'd')
+ inType = typTup->typbasetype;
+
+ ReleaseSysCache(tup);
+
+ return inType;
+}
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 9c32fac2314..5cbc26f5cbe 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.108 2002/03/12 00:51:54 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.109 2002/03/19 02:18:20 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1027,7 +1027,8 @@ parser_typecast_expression(ParseState *pstate,
if (inputType != targetType)
{
expr = CoerceTargetExpr(pstate, expr, inputType,
- targetType, typename->typmod);
+ getBaseType(targetType),
+ typename->typmod);
if (expr == NULL)
elog(ERROR, "Cannot cast type '%s' to '%s'",
format_type_be(inputType),
@@ -1039,7 +1040,7 @@ parser_typecast_expression(ParseState *pstate,
* as well as a type coercion.
*/
expr = coerce_type_typmod(pstate, expr,
- targetType, typename->typmod);
+ getBaseType(targetType), typename->typmod);
return expr;
}
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 7a3fa9f98b1..70665e114f9 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.254 2002/03/06 06:10:09 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.255 2002/03/19 02:18:20 momjian Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@@ -1722,7 +1722,7 @@ PostgresMain(int argc, char *argv[], const char *username)
if (!IsUnderPostmaster)
{
puts("\nPOSTGRES backend interactive interface ");
- puts("$Revision: 1.254 $ $Date: 2002/03/06 06:10:09 $\n");
+ puts("$Revision: 1.255 $ $Date: 2002/03/19 02:18:20 $\n");
}
/*
@@ -2212,8 +2212,9 @@ CreateCommandTag(Node *parsetree)
}
break;
+ case T_CreateDomainStmt:
case T_CreateStmt:
- tag = "CREATE";
+ tag = "CREATE DOMAIN";
break;
case T_DropStmt:
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 2a5f7b30ad6..a6400eabc35 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.132 2002/03/07 16:35:36 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.133 2002/03/19 02:18:20 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -282,6 +282,11 @@ ProcessUtility(Node *parsetree,
/* RemoveType does its own permissions checks */
RemoveType(relname);
break;
+
+ case DROP_DOMAIN_P:
+ /* RemoveDomain does its own permissions checks */
+ RemoveDomain(relname, stmt->behavior);
+ break;
}
/*
@@ -726,6 +731,19 @@ ProcessUtility(Node *parsetree,
DropProceduralLanguage((DropPLangStmt *) parsetree);
break;
+ /*
+ * ******************************** DOMAIN statements ****
+ *
+ */
+ case T_CreateDomainStmt:
+ DefineDomain((CreateDomainStmt *) parsetree);
+ break;
+
+ /*
+ * ******************************** USER statements ****
+ *
+ */
+
case T_CreateUserStmt:
CreateUser((CreateUserStmt *) parsetree);
break;
diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c
index edd9c314bbb..fc8733e960c 100644
--- a/src/backend/utils/adt/format_type.c
+++ b/src/backend/utils/adt/format_type.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.26 2002/03/07 16:35:36 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.27 2002/03/19 02:18:21 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -126,6 +126,7 @@ format_type_internal(Oid type_oid, int32 typemod,
bool is_array;
char *name;
char *buf;
+ char typtype;
if (type_oid == InvalidOid && allow_invalid)
return pstrdup("-");
@@ -144,6 +145,31 @@ format_type_internal(Oid type_oid, int32 typemod,
array_base_type = ((Form_pg_type) GETSTRUCT(tuple))->typelem;
typlen = ((Form_pg_type) GETSTRUCT(tuple))->typlen;
+ typtype = ((Form_pg_type) GETSTRUCT(tuple))->typtype;
+
+ /*
+ * Domains look alot like arrays, so lets process them first, and return
+ * back to avoid the array and 'standard' formatting procedures that are
+ * use for base types.
+ */
+ if (typtype == 'd') {
+ name = NameStr(((Form_pg_type) GETSTRUCT(tuple))->typname);
+
+ /*
+ * Double-quote the name if it's not a standard identifier.
+ * Note this is *necessary* for ruleutils.c's use.
+ */
+ if (strspn(name, "abcdefghijklmnopqrstuvwxyz0123456789_") != strlen(name)
+ || isdigit((unsigned char) name[0]))
+ buf = psnprintf(strlen(name) + 3, "\"%s\"", name);
+ else
+ buf = pstrdup(name);
+
+ ReleaseSysCache(tuple);
+
+ return buf;
+ }
+
if (array_base_type != InvalidOid && typlen < 0)
{
/* Switch our attention to the array element type */
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index d7b84b55fec..760e07ce5e6 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.62 2002/03/07 16:35:36 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.63 2002/03/19 02:18:21 momjian Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@@ -23,6 +23,7 @@
#include "catalog/pg_shadow.h"
#include "catalog/pg_statistic.h"
#include "catalog/pg_type.h"
+#include "parser/parse_coerce.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
@@ -822,16 +823,17 @@ get_typstorage(Oid typid)
* Returns FALSE if there is no default (effectively, default is NULL).
* The result points to palloc'd storage for pass-by-reference types.
*/
-bool
-get_typdefault(Oid typid, Datum *defaultValue)
+Node *
+get_typdefault(Oid typid, int32 atttypmod)
{
HeapTuple typeTuple;
Form_pg_type type;
- Oid typinput,
- typelem;
- Datum textDefaultVal;
+ Oid typinput;
+ Oid typbasetype;
+ char typtype;
+ Datum datum;
bool isNull;
- char *strDefaultVal;
+ Node *expr;
typeTuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typid),
@@ -843,38 +845,41 @@ get_typdefault(Oid typid, Datum *defaultValue)
type = (Form_pg_type) GETSTRUCT(typeTuple);
typinput = type->typinput;
- typelem = type->typelem;
+ typbasetype = type->typbasetype;
+ typtype = type->typtype;
/*
- * typdefault is potentially null, so don't try to access it as a
+ * typdefaultbin is potentially null, so don't try to access it as a
* struct field. Must do it the hard way with SysCacheGetAttr.
*/
- textDefaultVal = SysCacheGetAttr(TYPEOID,
- typeTuple,
- Anum_pg_type_typdefault,
- &isNull);
+ datum = SysCacheGetAttr(TYPEOID,
+ typeTuple,
+ Anum_pg_type_typdefaultbin,
+ &isNull);
+ ReleaseSysCache(typeTuple);
if (isNull)
- {
- ReleaseSysCache(typeTuple);
- *defaultValue = (Datum) 0;
- return false;
- }
+ return (Node *) NULL;
- /* Convert text datum to C string */
- strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
- textDefaultVal));
+ /* Convert Datum to a Node */
+ expr = stringToNode(DatumGetCString(
+ DirectFunctionCall1(textout, datum)));
- /* Convert C string to a value of the given type */
- *defaultValue = OidFunctionCall3(typinput,
- CStringGetDatum(strDefaultVal),
- ObjectIdGetDatum(typelem),
- Int32GetDatum(-1));
- pfree(strDefaultVal);
- ReleaseSysCache(typeTuple);
+ /*
+ * Ensure we goto the basetype before the domain type.
+ *
+ * Prevents scenarios like the below from failing:
+ * CREATE DOMAIN dom text DEFAULT random();
+ *
+ */
+ if (typbasetype != InvalidOid) {
+ expr = coerce_type(NULL, expr, typid,
+ typbasetype, atttypmod);
+ }
- return true;
+
+ return expr;
}
/*
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 1745e37ea49..d10569fd7ce 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.156 2002/03/07 16:35:36 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.157 2002/03/19 02:18:22 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -512,8 +512,12 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
(char *) attp,
ATTRIBUTE_TUPLE_SIZE);
- /* Update constraint/default info */
- if (attp->attnotnull)
+
+
+ /*
+ * Update constraint/default info
+ */
+ if (attp->attnotnull)
constr->has_not_null = true;
if (attp->atthasdef)
diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h
index 68c4c701aeb..368293148bb 100644
--- a/src/include/catalog/heap.h
+++ b/src/include/catalog/heap.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: heap.h,v 1.43 2002/03/07 16:35:38 momjian Exp $
+ * $Id: heap.h,v 1.44 2002/03/19 02:18:22 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -15,6 +15,8 @@
#define HEAP_H
#include "catalog/pg_attribute.h"
+#include "nodes/parsenodes.h"
+#include "parser/parse_node.h"
#include "utils/rel.h"
typedef struct RawColumnDefault
@@ -45,6 +47,12 @@ extern void AddRelationRawConstraints(Relation rel,
List *rawColDefaults,
List *rawConstraints);
+extern Node *cookDefault(ParseState *pstate
+ , Node *raw_default
+ , Oid atttypid
+ , int32 atttypmod
+ , char *attname);
+
extern int RemoveCheckConstraint(Relation rel, const char *constrName, bool inh);
extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno,
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index e7f788bacc5..6efbe3223a3 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_attribute.h,v 1.83 2002/03/07 16:35:38 momjian Exp $
+ * $Id: pg_attribute.h,v 1.84 2002/03/19 02:18:22 momjian Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -240,7 +240,13 @@ typedef FormData_pg_attribute *Form_pg_attribute;
{ 1247, {"typsend"}, 24, 0, 4, 14, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1247, {"typalign"}, 18, 0, 1, 15, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1247, {"typstorage"}, 18, 0, 1, 16, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1247, {"typdefault"}, 25, 0, -1, 17, 0, -1, -1, false , 'x', false, 'i', false, false }
+{ 1247, {"typnotnull"}, 16, 0, 1, 17, 0, -1, -1, true, 'p', false, 'c', false, false }, \
+{ 1247, {"typmod"}, 23, 0, 4, 18, 0, -1, -1, true, 'p', false, 'i', false, false }, \
+{ 1247, {"typbasetype"}, 26, 0, 4, 19, 0, -1, -1, true, 'p', false, 'i', false, false }, \
+{ 1247, {"typndims"}, 23, 0, 4, 20, 0, -1, -1, true, 'p', false, 'i', false, false }, \
+{ 1247, {"typdefaultbin"}, 25, 0, -1, 21, 0, -1, -1, false, 'x', false, 'i', false, false }, \
+{ 1247, {"typdefault"}, 25, 0, -1, 22, 0, -1, -1, false, 'x', false, 'i', false, false }
+
DATA(insert ( 1247 typname 19 DEFAULT_ATTSTATTARGET NAMEDATALEN 1 0 -1 -1 f p f i f f));
DATA(insert ( 1247 typowner 23 0 4 2 0 -1 -1 t p f i f f));
@@ -258,7 +264,12 @@ DATA(insert ( 1247 typreceive 24 0 4 13 0 -1 -1 t p f i f f));
DATA(insert ( 1247 typsend 24 0 4 14 0 -1 -1 t p f i f f));
DATA(insert ( 1247 typalign 18 0 1 15 0 -1 -1 t p f c f f));
DATA(insert ( 1247 typstorage 18 0 1 16 0 -1 -1 t p f c f f));
-DATA(insert ( 1247 typdefault 25 0 -1 17 0 -1 -1 f x f i f f));
+DATA(insert ( 1247 typnotnull 16 0 1 17 0 -1 -1 t p f c f f));
+DATA(insert ( 1247 typmod 23 0 4 18 0 -1 -1 t p f i f f));
+DATA(insert ( 1247 typbasetype 26 0 4 19 0 -1 -1 t p f i f f));
+DATA(insert ( 1247 typndims 23 0 4 20 0 -1 -1 t p f i f f));
+DATA(insert ( 1247 typdefaultbin 25 0 -1 21 0 -1 -1 f x f i f f));
+DATA(insert ( 1247 typdefault 25 0 -1 22 0 -1 -1 f x f i f f));
DATA(insert ( 1247 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
DATA(insert ( 1247 oid 26 0 4 -2 0 -1 -1 t p f i f f));
DATA(insert ( 1247 xmin 28 0 4 -3 0 -1 -1 t p f i f f));
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 0717bf33b74..ccfc0ceef91 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_class.h,v 1.61 2002/03/07 16:35:38 momjian Exp $
+ * $Id: pg_class.h,v 1.62 2002/03/19 02:18:22 momjian Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -132,7 +132,7 @@ typedef FormData_pg_class *Form_pg_class;
* ----------------
*/
-DATA(insert OID = 1247 ( pg_type 71 PGUID 0 1247 0 0 0 0 f f r 17 0 0 0 0 0 t f f f _null_ ));
+DATA(insert OID = 1247 ( pg_type 71 PGUID 0 1247 0 0 0 0 f f r 22 0 0 0 0 0 t f f f _null_ ));
DESCR("");
DATA(insert OID = 1249 ( pg_attribute 75 PGUID 0 1249 0 0 0 0 f f r 15 0 0 0 0 0 f f f f _null_ ));
DESCR("");
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index e270c41c03d..9aaea0cb3b1 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_type.h,v 1.116 2002/03/07 16:35:38 momjian Exp $
+ * $Id: pg_type.h,v 1.117 2002/03/19 02:18:23 momjian Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -141,12 +141,49 @@ CATALOG(pg_type) BOOTSTRAP
char typstorage;
/*
+ * This flag represents a "NOT NULL" constraint against this datatype.
+ *
+ * If true, the attnotnull column for a corresponding table column using
+ * this datatype will always enforce the NOT NULL constraint.
+ *
+ * Used primarily for domain types.
+ */
+ bool typnotnull;
+
+ /*
+ * typmod records type-specific data supplied at domain creation
+ * time (for example, the max length of a varchar field). It is
+ * passed to type-specific input and output functions as the third
+ * argument. The value will generally be -1 for types that do not need
+ * typmod. This value is copied to pg_attribute.atttypmod.
+ */
+ int4 typmod;
+
+ /*
+ * Domains use typbasetype to determine the base (or complex)type that
+ * the domain is based off. It must be non-zero if the type is a
+ * domain.
+ */
+ Oid typbasetype;
+
+ /*
+ * typndims is the declared number of dimensions, if an array typbasetype,
+ * otherwise zero.
+ */
+ int4 typndims;
+
+ /*
+ * typdefaultbin is the binary representation of typdefault
+ */
+ text typdefaultbin; /* VARIABLE LENGTH FIELD */
+
+ /*
* typdefault is NULL if the type has no associated default value. If
* it's not NULL, it contains the external representation of the
- * type's default value --- this default is used whenever no
- * per-column default is specified for a column of the datatype.
+ * type's default value
*/
text typdefault; /* VARIABLE LENGTH FIELD */
+
} FormData_pg_type;
/* ----------------
@@ -160,7 +197,7 @@ typedef FormData_pg_type *Form_pg_type;
* compiler constants for pg_type
* ----------------
*/
-#define Natts_pg_type 17
+#define Natts_pg_type 22
#define Anum_pg_type_typname 1
#define Anum_pg_type_typowner 2
#define Anum_pg_type_typlen 3
@@ -177,7 +214,13 @@ typedef FormData_pg_type *Form_pg_type;
#define Anum_pg_type_typsend 14
#define Anum_pg_type_typalign 15
#define Anum_pg_type_typstorage 16
-#define Anum_pg_type_typdefault 17
+#define Anum_pg_type_typnotnull 17
+#define Anum_pg_type_typmod 18
+#define Anum_pg_type_typbasetype 19
+#define Anum_pg_type_typndims 20
+#define Anum_pg_type_typdefaultbin 21
+#define Anum_pg_type_typdefault 22
+
/* ----------------
* initial contents of pg_type
@@ -192,82 +235,82 @@ typedef FormData_pg_type *Form_pg_type;
*/
/* OIDS 1 - 99 */
-DATA(insert OID = 16 ( bool PGUID 1 1 t b t \054 0 0 boolin boolout boolin boolout c p _null_ ));
+DATA(insert OID = 16 ( bool PGUID 1 1 t b t \054 0 0 boolin boolout boolin boolout c p f -1 0 0 _null_ _null_ ));
DESCR("boolean, 'true'/'false'");
#define BOOLOID 16
-DATA(insert OID = 17 ( bytea PGUID -1 -1 f b t \054 0 0 byteain byteaout byteain byteaout i x _null_ ));
+DATA(insert OID = 17 ( bytea PGUID -1 -1 f b t \054 0 0 byteain byteaout byteain byteaout i x f -1 0 0 _null_ _null_ ));
DESCR("variable-length string, binary values escaped");
#define BYTEAOID 17
-DATA(insert OID = 18 ( char PGUID 1 1 t b t \054 0 0 charin charout charin charout c p _null_ ));
+DATA(insert OID = 18 ( char PGUID 1 1 t b t \054 0 0 charin charout charin charout c p f -1 0 0 _null_ _null_ ));
DESCR("single character");
#define CHAROID 18
-DATA(insert OID = 19 ( name PGUID NAMEDATALEN NAMEDATALEN f b t \054 0 18 namein nameout namein nameout i p _null_ ));
+DATA(insert OID = 19 ( name PGUID NAMEDATALEN NAMEDATALEN f b t \054 0 18 namein nameout namein nameout i p f -1 0 0 _null_ _null_ ));
DESCR("31-character type for storing system identifiers");
#define NAMEOID 19
-DATA(insert OID = 20 ( int8 PGUID 8 20 f b t \054 0 0 int8in int8out int8in int8out d p _null_ ));
+DATA(insert OID = 20 ( int8 PGUID 8 20 f b t \054 0 0 int8in int8out int8in int8out d p f -1 0 0 _null_ _null_ ));
DESCR("~18 digit integer, 8-byte storage");
#define INT8OID 20
-DATA(insert OID = 21 ( int2 PGUID 2 5 t b t \054 0 0 int2in int2out int2in int2out s p _null_ ));
+DATA(insert OID = 21 ( int2 PGUID 2 5 t b t \054 0 0 int2in int2out int2in int2out s p f -1 0 0 _null_ _null_ ));
DESCR("-32 thousand to 32 thousand, 2-byte storage");
#define INT2OID 21
-DATA(insert OID = 22 ( int2vector PGUID INDEX_MAX_KEYS*2 -1 f b t \054 0 21 int2vectorin int2vectorout int2vectorin int2vectorout i p _null_ ));
+DATA(insert OID = 22 ( int2vector PGUID INDEX_MAX_KEYS*2 -1 f b t \054 0 21 int2vectorin int2vectorout int2vectorin int2vectorout i p f -1 0 0 _null_ _null_ ));
DESCR("array of INDEX_MAX_KEYS int2 integers, used in system tables");
#define INT2VECTOROID 22
-DATA(insert OID = 23 ( int4 PGUID 4 10 t b t \054 0 0 int4in int4out int4in int4out i p _null_ ));
+DATA(insert OID = 23 ( int4 PGUID 4 10 t b t \054 0 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
DESCR("-2 billion to 2 billion integer, 4-byte storage");
#define INT4OID 23
-DATA(insert OID = 24 ( regproc PGUID 4 16 t b t \054 0 0 regprocin regprocout regprocin regprocout i p _null_ ));
+DATA(insert OID = 24 ( regproc PGUID 4 16 t b t \054 0 0 regprocin regprocout regprocin regprocout i p f -1 0 0 _null_ _null_ ));
DESCR("registered procedure");
#define REGPROCOID 24
-DATA(insert OID = 25 ( text PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x _null_ ));
+DATA(insert OID = 25 ( text PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x f -1 0 0 _null_ _null_ ));
DESCR("variable-length string, no limit specified");
#define TEXTOID 25
-DATA(insert OID = 26 ( oid PGUID 4 10 t b t \054 0 0 oidin oidout oidin oidout i p _null_ ));
+DATA(insert OID = 26 ( oid PGUID 4 10 t b t \054 0 0 oidin oidout oidin oidout i p f -1 0 0 _null_ _null_ ));
DESCR("object identifier(oid), maximum 4 billion");
#define OIDOID 26
-DATA(insert OID = 27 ( tid PGUID 6 19 f b t \054 0 0 tidin tidout tidin tidout i p _null_ ));
+DATA(insert OID = 27 ( tid PGUID 6 19 f b t \054 0 0 tidin tidout tidin tidout i p f -1 0 0 _null_ _null_ ));
DESCR("(Block, offset), physical location of tuple");
#define TIDOID 27
-DATA(insert OID = 28 ( xid PGUID 4 12 t b t \054 0 0 xidin xidout xidin xidout i p _null_ ));
+DATA(insert OID = 28 ( xid PGUID 4 12 t b t \054 0 0 xidin xidout xidin xidout i p f -1 0 0 _null_ _null_ ));
DESCR("transaction id");
#define XIDOID 28
-DATA(insert OID = 29 ( cid PGUID 4 10 t b t \054 0 0 cidin cidout cidin cidout i p _null_ ));
+DATA(insert OID = 29 ( cid PGUID 4 10 t b t \054 0 0 cidin cidout cidin cidout i p f -1 0 0 _null_ _null_ ));
DESCR("command identifier type, sequence in transaction id");
#define CIDOID 29
-DATA(insert OID = 30 ( oidvector PGUID INDEX_MAX_KEYS*4 -1 f b t \054 0 26 oidvectorin oidvectorout oidvectorin oidvectorout i p _null_ ));
+DATA(insert OID = 30 ( oidvector PGUID INDEX_MAX_KEYS*4 -1 f b t \054 0 26 oidvectorin oidvectorout oidvectorin oidvectorout i p f -1 0 0 _null_ _null_ ));
DESCR("array of INDEX_MAX_KEYS oids, used in system tables");
#define OIDVECTOROID 30
-DATA(insert OID = 32 ( SET PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p _null_ ));
+DATA(insert OID = 32 ( SET PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p f -1 0 0 _null_ _null_ ));
DESCR("set of tuples");
-DATA(insert OID = 71 ( pg_type PGUID 4 4 t c t \054 1247 0 int4in int4out int4in int4out i p _null_));
-DATA(insert OID = 75 ( pg_attribute PGUID 4 4 t c t \054 1249 0 int4in int4out int4in int4out i p _null_));
-DATA(insert OID = 81 ( pg_proc PGUID 4 4 t c t \054 1255 0 int4in int4out int4in int4out i p _null_));
-DATA(insert OID = 83 ( pg_class PGUID 4 4 t c t \054 1259 0 int4in int4out int4in int4out i p _null_));
-DATA(insert OID = 86 ( pg_shadow PGUID 4 4 t c t \054 1260 0 int4in int4out int4in int4out i p _null_));
-DATA(insert OID = 87 ( pg_group PGUID 4 4 t c t \054 1261 0 int4in int4out int4in int4out i p _null_));
-DATA(insert OID = 88 ( pg_database PGUID 4 4 t c t \054 1262 0 int4in int4out int4in int4out i p _null_));
+DATA(insert OID = 71 ( pg_type PGUID 4 4 t c t \054 1247 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 75 ( pg_attribute PGUID 4 4 t c t \054 1249 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 81 ( pg_proc PGUID 4 4 t c t \054 1255 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 83 ( pg_class PGUID 4 4 t c t \054 1259 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 86 ( pg_shadow PGUID 4 4 t c t \054 1260 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 87 ( pg_group PGUID 4 4 t c t \054 1261 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 88 ( pg_database PGUID 4 4 t c t \054 1262 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
/* OIDS 100 - 199 */
/* OIDS 200 - 299 */
-DATA(insert OID = 210 ( smgr PGUID 2 12 t b t \054 0 0 smgrin smgrout smgrin smgrout s p _null_ ));
+DATA(insert OID = 210 ( smgr PGUID 2 12 t b t \054 0 0 smgrin smgrout smgrin smgrout s p f -1 0 0 _null_ _null_ ));
DESCR("storage manager");
/* OIDS 300 - 399 */
@@ -277,167 +320,167 @@ DESCR("storage manager");
/* OIDS 500 - 599 */
/* OIDS 600 - 699 */
-DATA(insert OID = 600 ( point PGUID 16 24 f b t \054 0 701 point_in point_out point_in point_out d p _null_ ));
+DATA(insert OID = 600 ( point PGUID 16 24 f b t \054 0 701 point_in point_out point_in point_out d p f -1 0 0 _null_ _null_ ));
DESCR("geometric point '(x, y)'");
#define POINTOID 600
-DATA(insert OID = 601 ( lseg PGUID 32 48 f b t \054 0 600 lseg_in lseg_out lseg_in lseg_out d p _null_ ));
+DATA(insert OID = 601 ( lseg PGUID 32 48 f b t \054 0 600 lseg_in lseg_out lseg_in lseg_out d p f -1 0 0 _null_ _null_ ));
DESCR("geometric line segment '(pt1,pt2)'");
#define LSEGOID 601
-DATA(insert OID = 602 ( path PGUID -1 -1 f b t \054 0 0 path_in path_out path_in path_out d x _null_ ));
+DATA(insert OID = 602 ( path PGUID -1 -1 f b t \054 0 0 path_in path_out path_in path_out d x f -1 0 0 _null_ _null_ ));
DESCR("geometric path '(pt1,...)'");
#define PATHOID 602
-DATA(insert OID = 603 ( box PGUID 32 100 f b t \073 0 600 box_in box_out box_in box_out d p _null_ ));
+DATA(insert OID = 603 ( box PGUID 32 100 f b t \073 0 600 box_in box_out box_in box_out d p f -1 0 0 _null_ _null_ ));
DESCR("geometric box '(lower left,upper right)'");
#define BOXOID 603
-DATA(insert OID = 604 ( polygon PGUID -1 -1 f b t \054 0 0 poly_in poly_out poly_in poly_out d x _null_ ));
+DATA(insert OID = 604 ( polygon PGUID -1 -1 f b t \054 0 0 poly_in poly_out poly_in poly_out d x f -1 0 0 _null_ _null_ ));
DESCR("geometric polygon '(pt1,...)'");
#define POLYGONOID 604
-DATA(insert OID = 628 ( line PGUID 32 48 f b t \054 0 701 line_in line_out line_in line_out d p _null_ ));
+DATA(insert OID = 628 ( line PGUID 32 48 f b t \054 0 701 line_in line_out line_in line_out d p f -1 0 0 _null_ _null_ ));
DESCR("geometric line '(pt1,pt2)'");
#define LINEOID 628
-DATA(insert OID = 629 ( _line PGUID -1 -1 f b t \054 0 628 array_in array_out array_in array_out d x _null_ ));
+DATA(insert OID = 629 ( _line PGUID -1 -1 f b t \054 0 628 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
DESCR("");
/* OIDS 700 - 799 */
-DATA(insert OID = 700 ( float4 PGUID 4 12 f b t \054 0 0 float4in float4out float4in float4out i p _null_ ));
+DATA(insert OID = 700 ( float4 PGUID 4 12 f b t \054 0 0 float4in float4out float4in float4out i p f -1 0 0 _null_ _null_ ));
DESCR("single-precision floating point number, 4-byte storage");
#define FLOAT4OID 700
-DATA(insert OID = 701 ( float8 PGUID 8 24 f b t \054 0 0 float8in float8out float8in float8out d p _null_ ));
+DATA(insert OID = 701 ( float8 PGUID 8 24 f b t \054 0 0 float8in float8out float8in float8out d p f -1 0 0 _null_ _null_ ));
DESCR("double-precision floating point number, 8-byte storage");
#define FLOAT8OID 701
-DATA(insert OID = 702 ( abstime PGUID 4 20 t b t \054 0 0 nabstimein nabstimeout nabstimein nabstimeout i p _null_ ));
+DATA(insert OID = 702 ( abstime PGUID 4 20 t b t \054 0 0 nabstimein nabstimeout nabstimein nabstimeout i p f -1 0 0 _null_ _null_ ));
DESCR("absolute, limited-range date and time (Unix system time)");
#define ABSTIMEOID 702
-DATA(insert OID = 703 ( reltime PGUID 4 20 t b t \054 0 0 reltimein reltimeout reltimein reltimeout i p _null_ ));
+DATA(insert OID = 703 ( reltime PGUID 4 20 t b t \054 0 0 reltimein reltimeout reltimein reltimeout i p f -1 0 0 _null_ _null_ ));
DESCR("relative, limited-range time interval (Unix delta time)");
#define RELTIMEOID 703
-DATA(insert OID = 704 ( tinterval PGUID 12 47 f b t \054 0 0 tintervalin tintervalout tintervalin tintervalout i p _null_ ));
+DATA(insert OID = 704 ( tinterval PGUID 12 47 f b t \054 0 0 tintervalin tintervalout tintervalin tintervalout i p f -1 0 0 _null_ _null_ ));
DESCR("(abstime,abstime), time interval");
#define TINTERVALOID 704
-DATA(insert OID = 705 ( unknown PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p _null_ ));
+DATA(insert OID = 705 ( unknown PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p f -1 0 0 _null_ _null_ ));
DESCR("");
#define UNKNOWNOID 705
-DATA(insert OID = 718 ( circle PGUID 24 47 f b t \054 0 0 circle_in circle_out circle_in circle_out d p _null_ ));
+DATA(insert OID = 718 ( circle PGUID 24 47 f b t \054 0 0 circle_in circle_out circle_in circle_out d p f -1 0 0 _null_ _null_ ));
DESCR("geometric circle '(center,radius)'");
#define CIRCLEOID 718
-DATA(insert OID = 719 ( _circle PGUID -1 -1 f b t \054 0 718 array_in array_out array_in array_out d x _null_ ));
-DATA(insert OID = 790 ( money PGUID 4 24 f b t \054 0 0 cash_in cash_out cash_in cash_out i p _null_ ));
+DATA(insert OID = 719 ( _circle PGUID -1 -1 f b t \054 0 718 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 790 ( money PGUID 4 24 f b t \054 0 0 cash_in cash_out cash_in cash_out i p f -1 0 0 _null_ _null_ ));
DESCR("$d,ddd.cc, money");
#define CASHOID 790
-DATA(insert OID = 791 ( _money PGUID -1 -1 f b t \054 0 790 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 791 ( _money PGUID -1 -1 f b t \054 0 790 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
/* OIDS 800 - 899 */
-DATA(insert OID = 829 ( macaddr PGUID 6 -1 f b t \054 0 0 macaddr_in macaddr_out macaddr_in macaddr_out i p _null_ ));
+DATA(insert OID = 829 ( macaddr PGUID 6 -1 f b t \054 0 0 macaddr_in macaddr_out macaddr_in macaddr_out i p f -1 0 0 _null_ _null_ ));
DESCR("XX:XX:XX:XX:XX:XX, MAC address");
#define MACADDROID 829
-DATA(insert OID = 869 ( inet PGUID -1 -1 f b t \054 0 0 inet_in inet_out inet_in inet_out i p _null_ ));
+DATA(insert OID = 869 ( inet PGUID -1 -1 f b t \054 0 0 inet_in inet_out inet_in inet_out i p f -1 0 0 _null_ _null_ ));
DESCR("IP address/netmask, host address, netmask optional");
#define INETOID 869
-DATA(insert OID = 650 ( cidr PGUID -1 -1 f b t \054 0 0 cidr_in cidr_out cidr_in cidr_out i p _null_ ));
+DATA(insert OID = 650 ( cidr PGUID -1 -1 f b t \054 0 0 cidr_in cidr_out cidr_in cidr_out i p f -1 0 0 _null_ _null_ ));
DESCR("network IP address/netmask, network address");
#define CIDROID 650
/* OIDS 900 - 999 */
/* OIDS 1000 - 1099 */
-DATA(insert OID = 1000 ( _bool PGUID -1 -1 f b t \054 0 16 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1001 ( _bytea PGUID -1 -1 f b t \054 0 17 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1002 ( _char PGUID -1 -1 f b t \054 0 18 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1003 ( _name PGUID -1 -1 f b t \054 0 19 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1005 ( _int2 PGUID -1 -1 f b t \054 0 21 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1006 ( _int2vector PGUID -1 -1 f b t \054 0 22 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1007 ( _int4 PGUID -1 -1 f b t \054 0 23 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1008 ( _regproc PGUID -1 -1 f b t \054 0 24 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1009 ( _text PGUID -1 -1 f b t \054 0 25 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1028 ( _oid PGUID -1 -1 f b t \054 0 26 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1010 ( _tid PGUID -1 -1 f b t \054 0 27 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1011 ( _xid PGUID -1 -1 f b t \054 0 28 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1012 ( _cid PGUID -1 -1 f b t \054 0 29 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1013 ( _oidvector PGUID -1 -1 f b t \054 0 30 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1014 ( _bpchar PGUID -1 -1 f b t \054 0 1042 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1015 ( _varchar PGUID -1 -1 f b t \054 0 1043 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1016 ( _int8 PGUID -1 -1 f b t \054 0 20 array_in array_out array_in array_out d x _null_ ));
-DATA(insert OID = 1017 ( _point PGUID -1 -1 f b t \054 0 600 array_in array_out array_in array_out d x _null_ ));
-DATA(insert OID = 1018 ( _lseg PGUID -1 -1 f b t \054 0 601 array_in array_out array_in array_out d x _null_ ));
-DATA(insert OID = 1019 ( _path PGUID -1 -1 f b t \054 0 602 array_in array_out array_in array_out d x _null_ ));
-DATA(insert OID = 1020 ( _box PGUID -1 -1 f b t \073 0 603 array_in array_out array_in array_out d x _null_ ));
-DATA(insert OID = 1021 ( _float4 PGUID -1 -1 f b t \054 0 700 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1022 ( _float8 PGUID -1 -1 f b t \054 0 701 array_in array_out array_in array_out d x _null_ ));
-DATA(insert OID = 1023 ( _abstime PGUID -1 -1 f b t \054 0 702 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1024 ( _reltime PGUID -1 -1 f b t \054 0 703 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1025 ( _tinterval PGUID -1 -1 f b t \054 0 704 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1027 ( _polygon PGUID -1 -1 f b t \054 0 604 array_in array_out array_in array_out d x _null_ ));
+DATA(insert OID = 1000 ( _bool PGUID -1 -1 f b t \054 0 16 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1001 ( _bytea PGUID -1 -1 f b t \054 0 17 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1002 ( _char PGUID -1 -1 f b t \054 0 18 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1003 ( _name PGUID -1 -1 f b t \054 0 19 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1005 ( _int2 PGUID -1 -1 f b t \054 0 21 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1006 ( _int2vector PGUID -1 -1 f b t \054 0 22 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1007 ( _int4 PGUID -1 -1 f b t \054 0 23 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1008 ( _regproc PGUID -1 -1 f b t \054 0 24 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1009 ( _text PGUID -1 -1 f b t \054 0 25 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1028 ( _oid PGUID -1 -1 f b t \054 0 26 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1010 ( _tid PGUID -1 -1 f b t \054 0 27 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1011 ( _xid PGUID -1 -1 f b t \054 0 28 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1012 ( _cid PGUID -1 -1 f b t \054 0 29 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1013 ( _oidvector PGUID -1 -1 f b t \054 0 30 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1014 ( _bpchar PGUID -1 -1 f b t \054 0 1042 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1015 ( _varchar PGUID -1 -1 f b t \054 0 1043 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1016 ( _int8 PGUID -1 -1 f b t \054 0 20 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1017 ( _point PGUID -1 -1 f b t \054 0 600 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1018 ( _lseg PGUID -1 -1 f b t \054 0 601 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1019 ( _path PGUID -1 -1 f b t \054 0 602 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1020 ( _box PGUID -1 -1 f b t \073 0 603 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1021 ( _float4 PGUID -1 -1 f b t \054 0 700 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1022 ( _float8 PGUID -1 -1 f b t \054 0 701 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1023 ( _abstime PGUID -1 -1 f b t \054 0 702 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1024 ( _reltime PGUID -1 -1 f b t \054 0 703 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1025 ( _tinterval PGUID -1 -1 f b t \054 0 704 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1027 ( _polygon PGUID -1 -1 f b t \054 0 604 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
/*
* Note: the size of aclitem needs to match sizeof(AclItem) in acl.h.
* Thanks to some padding, this will be 8 on all platforms.
* We also have an Assert to make sure.
*/
#define ACLITEMSIZE 8
-DATA(insert OID = 1033 ( aclitem PGUID 8 -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i p _null_ ));
+DATA(insert OID = 1033 ( aclitem PGUID 8 -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i p f -1 0 0 _null_ _null_ ));
DESCR("access control list");
-DATA(insert OID = 1034 ( _aclitem PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1040 ( _macaddr PGUID -1 -1 f b t \054 0 829 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1041 ( _inet PGUID -1 -1 f b t \054 0 869 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 651 ( _cidr PGUID -1 -1 f b t \054 0 650 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1042 ( bpchar PGUID -1 -1 f b t \054 0 0 bpcharin bpcharout bpcharin bpcharout i x _null_ ));
+DATA(insert OID = 1034 ( _aclitem PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1040 ( _macaddr PGUID -1 -1 f b t \054 0 829 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1041 ( _inet PGUID -1 -1 f b t \054 0 869 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 651 ( _cidr PGUID -1 -1 f b t \054 0 650 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1042 ( bpchar PGUID -1 -1 f b t \054 0 0 bpcharin bpcharout bpcharin bpcharout i x f -1 0 0 _null_ _null_ ));
DESCR("char(length), blank-padded string, fixed storage length");
#define BPCHAROID 1042
-DATA(insert OID = 1043 ( varchar PGUID -1 -1 f b t \054 0 0 varcharin varcharout varcharin varcharout i x _null_ ));
+DATA(insert OID = 1043 ( varchar PGUID -1 -1 f b t \054 0 0 varcharin varcharout varcharin varcharout i x f -1 0 0 _null_ _null_ ));
DESCR("varchar(length), non-blank-padded string, variable storage length");
#define VARCHAROID 1043
-DATA(insert OID = 1082 ( date PGUID 4 10 t b t \054 0 0 date_in date_out date_in date_out i p _null_ ));
+DATA(insert OID = 1082 ( date PGUID 4 10 t b t \054 0 0 date_in date_out date_in date_out i p f -1 0 0 _null_ _null_ ));
DESCR("ANSI SQL date");
#define DATEOID 1082
-DATA(insert OID = 1083 ( time PGUID 8 16 f b t \054 0 0 time_in time_out time_in time_out d p _null_ ));
+DATA(insert OID = 1083 ( time PGUID 8 16 f b t \054 0 0 time_in time_out time_in time_out d p f -1 0 0 _null_ _null_ ));
DESCR("hh:mm:ss, ANSI SQL time");
#define TIMEOID 1083
/* OIDS 1100 - 1199 */
-DATA(insert OID = 1114 ( timestamp PGUID 8 47 f b t \054 0 0 timestamp_in timestamp_out timestamp_in timestamp_out d p _null_ ));
+DATA(insert OID = 1114 ( timestamp PGUID 8 47 f b t \054 0 0 timestamp_in timestamp_out timestamp_in timestamp_out d p f -1 0 0 _null_ _null_ ));
DESCR("date and time");
#define TIMESTAMPOID 1114
-DATA(insert OID = 1115 ( _timestamp PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x _null_ ));
-DATA(insert OID = 1182 ( _date PGUID -1 -1 f b t \054 0 1082 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1183 ( _time PGUID -1 -1 f b t \054 0 1083 array_in array_out array_in array_out d x _null_ ));
-DATA(insert OID = 1184 ( timestamptz PGUID 8 47 f b t \054 0 0 timestamptz_in timestamptz_out timestamptz_in timestamptz_out d p _null_ ));
+DATA(insert OID = 1115 ( _timestamp PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1182 ( _date PGUID -1 -1 f b t \054 0 1082 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1183 ( _time PGUID -1 -1 f b t \054 0 1083 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1184 ( timestamptz PGUID 8 47 f b t \054 0 0 timestamptz_in timestamptz_out timestamptz_in timestamptz_out d p f -1 0 0 _null_ _null_ ));
DESCR("date and time with time zone");
#define TIMESTAMPTZOID 1184
-DATA(insert OID = 1185 ( _timestamptz PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x _null_ ));
-DATA(insert OID = 1186 ( interval PGUID 12 47 f b t \054 0 0 interval_in interval_out interval_in interval_out d p _null_ ));
+DATA(insert OID = 1185 ( _timestamptz PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1186 ( interval PGUID 12 47 f b t \054 0 0 interval_in interval_out interval_in interval_out d p f -1 0 0 _null_ _null_ ));
DESCR("@ <number> <units>, time interval");
#define INTERVALOID 1186
-DATA(insert OID = 1187 ( _interval PGUID -1 -1 f b t \054 0 1186 array_in array_out array_in array_out d x _null_ ));
+DATA(insert OID = 1187 ( _interval PGUID -1 -1 f b t \054 0 1186 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
/* OIDS 1200 - 1299 */
-DATA(insert OID = 1231 ( _numeric PGUID -1 -1 f b t \054 0 1700 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1266 ( timetz PGUID 12 22 f b t \054 0 0 timetz_in timetz_out timetz_in timetz_out d p _null_ ));
+DATA(insert OID = 1231 ( _numeric PGUID -1 -1 f b t \054 0 1700 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1266 ( timetz PGUID 12 22 f b t \054 0 0 timetz_in timetz_out timetz_in timetz_out d p f -1 0 0 _null_ _null_ ));
DESCR("hh:mm:ss, ANSI SQL time");
#define TIMETZOID 1266
-DATA(insert OID = 1270 ( _timetz PGUID -1 -1 f b t \054 0 1266 array_in array_out array_in array_out d x _null_ ));
+DATA(insert OID = 1270 ( _timetz PGUID -1 -1 f b t \054 0 1266 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
/* OIDS 1500 - 1599 */
-DATA(insert OID = 1560 ( bit PGUID -1 -1 f b t \054 0 0 bit_in bit_out bit_in bit_out i x _null_ ));
+DATA(insert OID = 1560 ( bit PGUID -1 -1 f b t \054 0 0 bit_in bit_out bit_in bit_out i x f -1 0 0 _null_ _null_ ));
DESCR("fixed-length bit string");
#define BITOID 1560
-DATA(insert OID = 1561 ( _bit PGUID -1 -1 f b t \054 0 1560 array_in array_out array_in array_out i x _null_ ));
-DATA(insert OID = 1562 ( varbit PGUID -1 -1 f b t \054 0 0 varbit_in varbit_out varbit_in varbit_out i x _null_ ));
+DATA(insert OID = 1561 ( _bit PGUID -1 -1 f b t \054 0 1560 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
+DATA(insert OID = 1562 ( varbit PGUID -1 -1 f b t \054 0 0 varbit_in varbit_out varbit_in varbit_out i x f -1 0 0 _null_ _null_ ));
DESCR("variable-length bit string");
#define VARBITOID 1562
-DATA(insert OID = 1563 ( _varbit PGUID -1 -1 f b t \054 0 1562 array_in array_out array_in array_out i x _null_ ));
+DATA(insert OID = 1563 ( _varbit PGUID -1 -1 f b t \054 0 1562 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
/* OIDS 1600 - 1699 */
/* OIDS 1700 - 1799 */
-DATA(insert OID = 1700 ( numeric PGUID -1 -1 f b t \054 0 0 numeric_in numeric_out numeric_in numeric_out i m _null_ ));
+DATA(insert OID = 1700 ( numeric PGUID -1 -1 f b t \054 0 0 numeric_in numeric_out numeric_in numeric_out i m f -1 0 0 _null_ _null_ ));
DESCR("numeric(precision, decimal), arbitrary precision number");
#define NUMERICOID 1700
/* OID 1790 */
-DATA(insert OID = 1790 ( refcursor PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x _null_ ));
+DATA(insert OID = 1790 ( refcursor PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x f -1 0 0 _null_ _null_ ));
DESCR("reference cursor (portal name)");
#define REFCURSOROID 1790
@@ -447,6 +490,7 @@ DESCR("reference cursor (portal name)");
*/
extern Oid TypeGet(char *typeName, bool *defined);
extern Oid TypeShellMake(char *typeName);
+
extern Oid TypeCreate(char *typeName,
Oid assignedTypeOid,
Oid relationOid,
@@ -459,10 +503,17 @@ extern Oid TypeCreate(char *typeName,
char *receiveProcedure,
char *sendProcedure,
char *elementTypeName,
+ char *baseTypeName,
char *defaultTypeValue,
+ char *defaultTypeBin,
bool passedByValue,
char alignment,
- char storage);
+ char storage,
+ int32 typeMod,
+ int32 typNDims,
+ bool typeNotNull);
+
+
extern void TypeRename(const char *oldTypeName, const char *newTypeName);
extern char *makeArrayTypeName(char *typeName);
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index b2dc3231d4f..78b34614d58 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: defrem.h,v 1.30 2002/03/07 16:35:38 momjian Exp $
+ * $Id: defrem.h,v 1.31 2002/03/19 02:18:23 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -39,10 +39,12 @@ extern void CreateFunction(ProcedureStmt *stmt);
extern void DefineOperator(char *name, List *parameters);
extern void DefineAggregate(char *name, List *parameters);
extern void DefineType(char *name, List *parameters);
+extern void DefineDomain(CreateDomainStmt *stmt);
/*
* prototypes in remove.c
*/
+extern void RemoveDomain(char *domainName, int behavior);
extern void RemoveFunction(char *functionName, List *argTypes);
extern void RemoveOperator(char *operatorName,
char *typeName1, char *typeName2);
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 87aceb2ff0c..d25bc5f1563 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: nodes.h,v 1.100 2002/03/07 16:35:40 momjian Exp $
+ * $Id: nodes.h,v 1.101 2002/03/19 02:18:23 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -172,6 +172,7 @@ typedef enum NodeTag
T_TransactionStmt,
T_ViewStmt,
T_LoadStmt,
+ T_CreateDomainStmt,
T_CreatedbStmt,
T_DropdbStmt,
T_VacuumStmt,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 9ae9feb739d..71552abbc76 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parsenodes.h,v 1.160 2002/03/12 00:52:01 tgl Exp $
+ * $Id: parsenodes.h,v 1.161 2002/03/19 02:18:24 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -408,6 +408,23 @@ typedef struct DefElem
/****************************************************************************
+ * Nodes for a Domain Creation tree
+ ****************************************************************************/
+/* ----------------------
+ * CreateDomain Statement
+ * ----------------------
+ * Down here as it required TypeName to be defined first.
+ */
+typedef struct CreateDomainStmt
+{
+ NodeTag type;
+ char *domainname; /* name of domain to create */
+ TypeName *typename; /* the typecast */
+ List *constraints; /* constraints (list of Constraint nodes) */
+} CreateDomainStmt;
+
+
+/****************************************************************************
* Nodes for a Query tree
****************************************************************************/
@@ -1055,12 +1072,14 @@ typedef struct DefineStmt
#define DROP_INDEX 4
#define DROP_RULE 5
#define DROP_TYPE_P 6
+#define DROP_DOMAIN_P 7
typedef struct DropStmt
{
NodeTag type;
List *names;
int removeType;
+ int behavior; /* CASCADE or RESTRICT drop behavior */
} DropStmt;
/* ----------------------
@@ -1269,6 +1288,7 @@ typedef struct LoadStmt
char *filename; /* file to load */
} LoadStmt;
+
/* ----------------------
* Createdb Statement
* ----------------------
diff --git a/src/include/parser/parse_coerce.h b/src/include/parser/parse_coerce.h
index 4d4767a6d04..d2c91ed25fa 100644
--- a/src/include/parser/parse_coerce.h
+++ b/src/include/parser/parse_coerce.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parse_coerce.h,v 1.39 2002/03/07 16:35:40 momjian Exp $
+ * $Id: parse_coerce.h,v 1.40 2002/03/19 02:18:24 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -81,5 +81,6 @@ extern Oid select_common_type(List *typeids, const char *context);
extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
Oid targetTypeId,
const char *context);
+extern Oid getBaseType(Oid inType);
#endif /* PARSE_COERCE_H */
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 957311985a4..9b0ff8514d8 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: lsyscache.h,v 1.42 2002/03/07 16:35:41 momjian Exp $
+ * $Id: lsyscache.h,v 1.43 2002/03/19 02:18:24 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -44,7 +44,7 @@ extern int16 get_typlen(Oid typid);
extern bool get_typbyval(Oid typid);
extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval);
extern char get_typstorage(Oid typid);
-extern bool get_typdefault(Oid typid, Datum *defaultValue);
+extern Node *get_typdefault(Oid typid, int32 atttypmod);
extern int32 get_typavgwidth(Oid typid, int32 typmod);
extern int32 get_attavgwidth(Oid relid, AttrNumber attnum);
extern bool get_attstatsslot(HeapTuple statstuple,
diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out
new file mode 100644
index 00000000000..4d8d13ec2d7
--- /dev/null
+++ b/src/test/regress/expected/domain.out
@@ -0,0 +1,114 @@
+-- Test Comment / Drop
+create domain domaindroptest int4;
+comment on domain domaindroptest is 'About to drop this..';
+create domain basetypetest domaindroptest;
+ERROR: DefineDomain: domaindroptest is not a basetype
+drop domain domaindroptest;
+ERROR: parser: parse error at or near ";"
+drop domain domaindroptest restrict;
+-- TEST Domains.
+create domain domainvarchar varchar(5);
+create domain domainnumeric numeric(8,2);
+create domain domainint4 int4;
+create domain domaintext text;
+-- Test tables using domains
+create table basictest
+ ( testint4 domainint4
+ , testtext domaintext
+ , testvarchar domainvarchar
+ , testnumeric domainnumeric
+ );
+INSERT INTO basictest values ('88', 'haha', 'short', '123.12'); -- Good
+INSERT INTO basictest values ('88', 'haha', 'short text', '123.12'); -- Bad varchar
+ERROR: value too long for type character varying(5)
+INSERT INTO basictest values ('88', 'haha', 'short', '123.1212'); -- Truncate numeric
+select * from basictest;
+ testint4 | testtext | testvarchar | testnumeric
+----------+----------+-------------+-------------
+ 88 | haha | short | 123.12
+ 88 | haha | short | 123.12
+(2 rows)
+
+drop table basictest;
+drop domain domainvarchar restrict;
+drop domain domainnumeric restrict;
+drop domain domainint4 restrict;
+drop domain domaintext restrict;
+-- Array Test
+create domain domainint4arr int4[1];
+create domain domaintextarr text[2][3];
+create table domarrtest
+ ( testint4arr domainint4arr
+ , testtextarr domaintextarr
+ );
+INSERT INTO domarrtest values ('{2,2}', '{{"a","b"}{"c","d"}}');
+INSERT INTO domarrtest values ('{{2,2}{2,2}}', '{{"a","b"}}');
+INSERT INTO domarrtest values ('{2,2}', '{{"a","b"}{"c","d"}{"e"}}');
+INSERT INTO domarrtest values ('{2,2}', '{{"a"}{"c"}}');
+INSERT INTO domarrtest values (NULL, '{{"a","b"}{"c","d","e"}}');
+drop table domarrtest;
+drop domain domainint4arr restrict;
+drop domain domaintextarr restrict;
+create domain dnotnull varchar(15) NOT NULL;
+create domain dnull varchar(15) NULL;
+create table nulltest
+ ( col1 dnotnull
+ , col2 dnotnull NULL -- NOT NULL in the domain cannot be overridden
+ , col3 dnull NOT NULL
+ , col4 dnull
+ );
+INSERT INTO nulltest DEFAULT VALUES;
+ERROR: ExecAppend: Fail to add null value in not null attribute col1
+INSERT INTO nulltest values ('a', 'b', 'c', 'd'); -- Good
+INSERT INTO nulltest values (NULL, 'b', 'c', 'd');
+ERROR: ExecAppend: Fail to add null value in not null attribute col1
+INSERT INTO nulltest values ('a', NULL, 'c', 'd');
+ERROR: ExecAppend: Fail to add null value in not null attribute col2
+INSERT INTO nulltest values ('a', 'b', NULL, 'd');
+ERROR: ExecAppend: Fail to add null value in not null attribute col3
+INSERT INTO nulltest values ('a', 'b', 'c', NULL); -- Good
+select * from nulltest;
+ col1 | col2 | col3 | col4
+------+------+------+------
+ a | b | c | d
+ a | b | c |
+(2 rows)
+
+drop table nulltest;
+drop domain dnotnull restrict;
+drop domain dnull restrict;
+create domain ddef1 int4 DEFAULT 3;
+create domain ddef2 oid DEFAULT '12';
+-- Type mixing, function returns int8
+create domain ddef3 text DEFAULT 5;
+create sequence ddef4_seq;
+create domain ddef4 int4 DEFAULT nextval(cast('ddef4_seq' as text));
+create domain ddef5 numeric(8,2) NOT NULL DEFAULT '12.12';
+create table defaulttest
+ ( col1 ddef1
+ , col2 ddef2
+ , col3 ddef3
+ , col4 ddef4
+ , col5 ddef1 NOT NULL DEFAULT NULL
+ , col6 ddef2 DEFAULT '88'
+ , col7 ddef4 DEFAULT 8000
+ , col8 ddef5
+ );
+insert into defaulttest default values;
+insert into defaulttest default values;
+insert into defaulttest default values;
+select * from defaulttest;
+ col1 | col2 | col3 | col4 | col5 | col6 | col7 | col8
+------+------+------+------+------+------+------+-------
+ 3 | 12 | 5 | 1 | 3 | 88 | 8000 | 12.12
+ 3 | 12 | 5 | 2 | 3 | 88 | 8000 | 12.12
+ 3 | 12 | 5 | 3 | 3 | 88 | 8000 | 12.12
+(3 rows)
+
+drop sequence ddef4_seq;
+drop table defaulttest;
+drop domain ddef1 restrict;
+drop domain ddef2 restrict;
+drop domain ddef3 restrict;
+drop domain ddef4 restrict;
+drop domain ddef5 restrict;
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 877a70f902b..cd9d2d5260a 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -73,4 +73,4 @@ test: select_views alter_table portals_p2 rules foreign_key
# The sixth group of parallel test
# ----------
# "plpgsql" cannot run concurrently with "rules"
-test: limit plpgsql temp
+test: limit plpgsql temp domain
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index 61a5d39b649..c56b3561c2f 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -1,4 +1,4 @@
-# $Header: /cvsroot/pgsql/src/test/regress/serial_schedule,v 1.7 2001/09/28 07:59:38 thomas Exp $
+# $Header: /cvsroot/pgsql/src/test/regress/serial_schedule,v 1.8 2002/03/19 02:18:24 momjian Exp $
# This should probably be in an order similar to parallel_schedule.
test: boolean
test: char
@@ -80,3 +80,5 @@ test: foreign_key
test: limit
test: plpgsql
test: temp
+test: domain
+
diff --git a/src/test/regress/sql/domain.sql b/src/test/regress/sql/domain.sql
new file mode 100644
index 00000000000..1417fe31896
--- /dev/null
+++ b/src/test/regress/sql/domain.sql
@@ -0,0 +1,111 @@
+
+
+-- Test Comment / Drop
+create domain domaindroptest int4;
+comment on domain domaindroptest is 'About to drop this..';
+
+create domain basetypetest domaindroptest;
+
+drop domain domaindroptest;
+drop domain domaindroptest restrict;
+
+
+-- TEST Domains.
+
+create domain domainvarchar varchar(5);
+create domain domainnumeric numeric(8,2);
+create domain domainint4 int4;
+create domain domaintext text;
+
+
+-- Test tables using domains
+create table basictest
+ ( testint4 domainint4
+ , testtext domaintext
+ , testvarchar domainvarchar
+ , testnumeric domainnumeric
+ );
+
+INSERT INTO basictest values ('88', 'haha', 'short', '123.12'); -- Good
+INSERT INTO basictest values ('88', 'haha', 'short text', '123.12'); -- Bad varchar
+INSERT INTO basictest values ('88', 'haha', 'short', '123.1212'); -- Truncate numeric
+select * from basictest;
+
+drop table basictest;
+drop domain domainvarchar restrict;
+drop domain domainnumeric restrict;
+drop domain domainint4 restrict;
+drop domain domaintext restrict;
+
+
+-- Array Test
+create domain domainint4arr int4[1];
+create domain domaintextarr text[2][3];
+
+create table domarrtest
+ ( testint4arr domainint4arr
+ , testtextarr domaintextarr
+ );
+INSERT INTO domarrtest values ('{2,2}', '{{"a","b"}{"c","d"}}');
+INSERT INTO domarrtest values ('{{2,2}{2,2}}', '{{"a","b"}}');
+INSERT INTO domarrtest values ('{2,2}', '{{"a","b"}{"c","d"}{"e"}}');
+INSERT INTO domarrtest values ('{2,2}', '{{"a"}{"c"}}');
+INSERT INTO domarrtest values (NULL, '{{"a","b"}{"c","d","e"}}');
+
+drop table domarrtest;
+drop domain domainint4arr restrict;
+drop domain domaintextarr restrict;
+
+
+create domain dnotnull varchar(15) NOT NULL;
+create domain dnull varchar(15) NULL;
+
+create table nulltest
+ ( col1 dnotnull
+ , col2 dnotnull NULL -- NOT NULL in the domain cannot be overridden
+ , col3 dnull NOT NULL
+ , col4 dnull
+ );
+INSERT INTO nulltest DEFAULT VALUES;
+INSERT INTO nulltest values ('a', 'b', 'c', 'd'); -- Good
+INSERT INTO nulltest values (NULL, 'b', 'c', 'd');
+INSERT INTO nulltest values ('a', NULL, 'c', 'd');
+INSERT INTO nulltest values ('a', 'b', NULL, 'd');
+INSERT INTO nulltest values ('a', 'b', 'c', NULL); -- Good
+select * from nulltest;
+
+drop table nulltest;
+drop domain dnotnull restrict;
+drop domain dnull restrict;
+
+
+create domain ddef1 int4 DEFAULT 3;
+create domain ddef2 oid DEFAULT '12';
+-- Type mixing, function returns int8
+create domain ddef3 text DEFAULT 5;
+create sequence ddef4_seq;
+create domain ddef4 int4 DEFAULT nextval(cast('ddef4_seq' as text));
+create domain ddef5 numeric(8,2) NOT NULL DEFAULT '12.12';
+
+create table defaulttest
+ ( col1 ddef1
+ , col2 ddef2
+ , col3 ddef3
+ , col4 ddef4
+ , col5 ddef1 NOT NULL DEFAULT NULL
+ , col6 ddef2 DEFAULT '88'
+ , col7 ddef4 DEFAULT 8000
+ , col8 ddef5
+ );
+insert into defaulttest default values;
+insert into defaulttest default values;
+insert into defaulttest default values;
+select * from defaulttest;
+
+drop sequence ddef4_seq;
+drop table defaulttest;
+drop domain ddef1 restrict;
+drop domain ddef2 restrict;
+drop domain ddef3 restrict;
+drop domain ddef4 restrict;
+drop domain ddef5 restrict;