Add DOMAIN support. Includes manual pages and regression tests, from
authorBruce Momjian <bruce@momjian.us>
Tue, 19 Mar 2002 02:18:25 +0000 (02:18 +0000)
committerBruce Momjian <bruce@momjian.us>
Tue, 19 Mar 2002 02:18:25 +0000 (02:18 +0000)
Rod Taylor.

36 files changed:
doc/src/sgml/catalogs.sgml
doc/src/sgml/ref/allfiles.sgml
doc/src/sgml/ref/comment.sgml
doc/src/sgml/ref/create_domain.sgml [new file with mode: 0644]
doc/src/sgml/ref/drop_domain.sgml [new file with mode: 0644]
doc/src/sgml/reference.sgml
src/backend/catalog/heap.c
src/backend/catalog/pg_type.c
src/backend/commands/creatinh.c
src/backend/commands/define.c
src/backend/commands/remove.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/optimizer/prep/preptlist.c
src/backend/parser/gram.y
src/backend/parser/keywords.c
src/backend/parser/parse_coerce.c
src/backend/parser/parse_expr.c
src/backend/tcop/postgres.c
src/backend/tcop/utility.c
src/backend/utils/adt/format_type.c
src/backend/utils/cache/lsyscache.c
src/backend/utils/cache/relcache.c
src/include/catalog/heap.h
src/include/catalog/pg_attribute.h
src/include/catalog/pg_class.h
src/include/catalog/pg_type.h
src/include/commands/defrem.h
src/include/nodes/nodes.h
src/include/nodes/parsenodes.h
src/include/parser/parse_coerce.h
src/include/utils/lsyscache.h
src/test/regress/expected/domain.out [new file with mode: 0644]
src/test/regress/parallel_schedule
src/test/regress/serial_schedule
src/test/regress/sql/domain.sql [new file with mode: 0644]

index d785121a0479f84069d7e34251775ea637b0e9d5..451c9dcaa8af08510434568ad8b36256b670ed76 100644 (file)
@@ -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">
       </para></entry>
      </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>
index 3ea658fd0427fc75b1fe21f52408d5fe2cd00cbd..460f150bc893036958acdb73a91d626e2d3d5c8b 100644 (file)
@@ -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">
index 026533de9542df6151dc2e69307c2155db14f164..f3530b71ce6cd80ab6c65ae55eb8695ff41d28f6 100644 (file)
@@ -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 (file)
index 0000000..5f79dc6
--- /dev/null
@@ -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 (file)
index 0000000..e9bc38a
--- /dev/null
@@ -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:
+-->
index 0ca0ea5a9c471f1056158b1c5dc835db164da179..b6b63254462addb3c97992f9fcac129dfc6c19c6 100644 (file)
@@ -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>
 
 <!--
index 4c35663e31c1da61dcc46ed8b9537ae8250431b3..9ec241e3ea3aae93db4321f093219375423dc175 100644 (file)
@@ -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)
 {
index 3c5c9cd53e07106ecfa0536ee34347d009be02c1..351646691906a25aa37f9c98967a81b1570a5819 100644 (file)
@@ -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];
@@ -317,6 +329,17 @@ TypeCreate(char *typeName,
                        elog(ERROR, "type %s does not exist", elementTypeName);
        }
 
+       /*
+        * 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);
                }
@@ -428,6 +452,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.
         */
@@ -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.
index bb80487dbb4306ed1aea31e9a782df60dbd2dab7..ae2a90c93113ad9db6b2f9d908d24c11d65a4799 100644 (file)
@@ -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
@@ -69,6 +69,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.
index f70b58d5c2eb3fb29c36bb773e16b4b88466c6d0..72aa7a3a15f092ce098a34f0a3a5edea57e3a0ae 100644 (file)
@@ -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"
@@ -475,6 +476,323 @@ DefineAggregate(char *aggName, List *parameters)
                                        initval);       /* initial condition */
 }
 
+/*
+ * 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);
 }
index 8c8634c18b4add9fec545a556b395a0314158d07..297b351df834a3ba945409770aff5835e5ab6f23 100644 (file)
@@ -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"
@@ -275,6 +276,60 @@ RemoveType(char *typeName)         /* type name to be removed */
        heap_close(relation, RowExclusiveLock);
 }
 
+/*
+ *     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.
index 97eeb35ea38303ff68ed809bde2b9399e6fd3605..070a6da5172a1b3f5f97dc5b1dbbc0cb42bdc0fe 100644 (file)
@@ -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",
index 760554dbb63f40d119a2ee1dd96694bc44e8b78b..f6f39f2f247eaf520221cfc2b2813e41ac41bba0 100644 (file)
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -1093,6 +1093,19 @@ _equalLoadStmt(LoadStmt *a, LoadStmt *b)
        return true;
 }
 
+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)
 {
@@ -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;
index f6d574e9640eed7cd4b5a238b33944c08aa7c0c5..cc992c7f3a8f92a0030621c18333975fb1453423 100644 (file)
@@ -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;
 }
index ec20ce190657de73aa4edc1cbe7b5b539be4a5cc..58b9eeb89e510435bfa6b6de4cc5c570cb9d99bc 100644 (file)
@@ -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"; }
index e1f53155c4381093c6e2c24ecb526430306c2595..61e8744968efa273d159e783bd85411e5d3a3d77 100644 (file)
@@ -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},
index 172142e33dc0f1d36f2ea66ed9f8e8c00fccf502..7aaaa65c61bfa0068818d128ef3f744495299b47 100644 (file)
@@ -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;
+}
index 9c32fac23147507055320efb015e0be91acf2315..5cbc26f5cbec3ab64cd93c7149559e97e57e85a8 100644 (file)
@@ -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;
 }
index 7a3fa9f98b1fbf649fd88af7d533eca00ea4d31f..70665e114f96e4d8685b10b5b6ff946319c52c69 100644 (file)
@@ -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:
index 2a5f7b30ad6b160f075f826cff7155d372bb6502..a6400eabc3572e62646134963d35acb5c10f5ba2 100644 (file)
@@ -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;
index edd9c314bbb48b86348ada59115f51b80d5fb19a..fc8733e960cf7a4d0b04957a18792685ea79cec3 100644 (file)
@@ -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 */
index d7b84b55fec36e5fec765de0646b84f5a6e9753d..760e07ce5e6b7b03b36f128d61ef234b93b28ac6 100644 (file)
@@ -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;
 }
 
 /*
index 1745e37ea495e61ca926dd0274614fa99f1cfeaf..d10569fd7ce981f194c9eeadfa591e40a79b4ae9 100644 (file)
@@ -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)
index 68c4c701aebcd6dc7fcd7d0c83e5225ba5f42519..368293148bb344f1057ed8878ffe050de113b1b8 100644 (file)
@@ -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,
index e7f788bacc59f64a09eb9ef091c112aca848904e..6efbe3223a36cf2cb68f31198f043541fc8429d8 100644 (file)
@@ -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));
index 0717bf33b74e1a781e93db155882d69da8488459..ccfc0ceef915a4a5db3897a35a44ef44ae8e60ba 100644 (file)
@@ -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("");
index e270c41c03d389a0ef80520dfe89d652552bac56..9aaea0cb3b1a9b0c3d351242a3f3afeb495fe805 100644 (file)
@@ -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
@@ -140,13 +140,50 @@ 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);
 
index b2dc3231d4f653b8392fff724d6c550229ad3bf1..78b34614d58c37fed71b0f91a6b0222f53dbf9f5 100644 (file)
@@ -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);
index 87aceb2ff0c67517958fae64aebfceab9e4c6a44..d25bc5f1563616a584cbb0d2cdeb4ab632fc33a2 100644 (file)
@@ -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,
index 9ae9feb739dfbdff1b78dbf21e3cf6b95900dfa6..71552abbc7653400302c7e702053a4e64a54f70d 100644 (file)
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -407,6 +407,23 @@ typedef struct DefElem
 } 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
  * ----------------------
index 4d4767a6d04bb5d6251b561f7fe06bd5971068e1..d2c91ed25fa9adcc5beab17e0868d35900fe6f90 100644 (file)
@@ -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 */
index 957311985a4b50e6e48e485c677539207b3143cc..9b0ff8514d8904576210343b24b3ec9a53fcf65f 100644 (file)
@@ -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 (file)
index 0000000..4d8d13e
--- /dev/null
@@ -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;
index 877a70f902b5f9b6423399ab8ee6de7b0dd65331..cd9d2d5260aca99ee1626ed5a088ea600f889119 100644 (file)
@@ -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
index 61a5d39b6492382c19ceec8e4cee4ccfc062c24b..c56b3561c2f3ab458129604d1c4513be58df60b3 100644 (file)
@@ -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 (file)
index 0000000..1417fe3
--- /dev/null
@@ -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;