Ok. Updated patch attached.
authorBruce Momjian <bruce@momjian.us>
Wed, 6 Mar 2002 20:35:02 +0000 (20:35 +0000)
committerBruce Momjian <bruce@momjian.us>
Wed, 6 Mar 2002 20:35:02 +0000 (20:35 +0000)
- domain.patch -> source patch against pgsql in cvs
- drop_domain.sgml and create_domain.sgml -> New doc/src/sgml/ref docs

- dominfo.txt -> basic domain related queries I used for testing
[ ADDED TO /doc]

Enables domains of array elements -> CREATE DOMAIN dom int4[3][2];

Uses a typbasetype column to describe the origin of the domain.

Copies data to attnotnull rather than processing in execMain().

Some documentation differences from earlier.

If this is approved, I'll start working on pg_dump, and a \dD <domain>
option in psql, and regression tests.  I don't really feel like doing
those until the system table structure settles for pg_type.

CHECKS when added, will also be copied to to the table attributes.  FK
Constraints (if I ever figure out how) will be done similarly.  Both
will lbe handled by MergeDomainAttributes() which is called shortly
before MergeAttributes().

Rod Taylor

32 files changed:
doc/dominfo.txt [new file with mode: 0644]
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/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

diff --git a/doc/dominfo.txt b/doc/dominfo.txt
new file mode 100644 (file)
index 0000000..a439ff6
--- /dev/null
@@ -0,0 +1,87 @@
+
+
+-- Test Comment / Drop
+create domain domaindroptest int4;
+comment on domain domaindroptest is 'About to drop this..';
+
+select * from pg_type where typname = 'domaindroptest';
+
+drop domain domaindroptest restrict;
+
+select * from pg_type where typname = 'domaindroptest';
+
+-- 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;
+
+
+-- Array Test
+create domain domainint4arr int4[1];
+create domain domaintextarr text[2][3];
+
+create table arrtest
+           ( testint4arr domainint4arr
+           , testtextarr domaintextarr
+           );
+INSERT INTO arrtest values ('{2,2}', '{{"a","b"}{"c","d"}}');
+INSERT INTO arrtest values ('{{2,2}{2,2}}', '{{"a","b"}}');
+INSERT INTO arrtest values ('{2,2}', '{{"a","b"}{"c","d"}{"e"}}');
+INSERT INTO arrtest values ('{2,2}', '{{"a"}{"c"}}');
+INSERT INTO arrtest values (NULL, '{{"a","b"}{"c","d","e"}}');
+
+
+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;
+
+
+create domain ddef1 int4 DEFAULT 3;
+create domain ddef2 numeric(8,6) DEFAULT '1234.123456789';
+-- 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 table defaulttest
+            ( col1 ddef1
+            , col2 ddef2
+            , col3 ddef3
+            , col4 ddef4
+            , col5 ddef1 NOT NULL DEFAULT NULL
+            , col6 ddef2 DEFAULT '88.1'
+            , col7 ddef4 DEFAULT 8000
+            );
+insert into defaulttest default values;
+insert into defaulttest default values;
+insert into defaulttest default values;
+select * from defaulttest;
index ca56413481d8bb3c205c7a1f634ba16164e40acb..2b9b44bab5370fb85086708e215e473c23888b7e 100644 (file)
       </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
+       off of.  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.  Normally used only for domains.
+         </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 9b45e782f20d27b1996a3545183cadc613ab2a81..08a1f5eb649d63c0bdb09764ac34e589d69c739a 100644 (file)
@@ -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 be4b3eb0ccd60b4f72002aa03960af442f6ac12c..1fb75fe5ae5e21f34a0886539f34ea02632d7bf4 100644 (file)
@@ -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 'Domains are like abstracted fields';
 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..a4a3e83
--- /dev/null
@@ -0,0 +1,231 @@
+<!--
+$Header$
+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..f032c93
--- /dev/null
@@ -0,0 +1,167 @@
+<!--
+$Header$
+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 c4dc4e7393031df3ee3407c0ee0045f71942a5a6..f2f6750a92648361f334b999c5e529605bb6b495 100644 (file)
@@ -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 2f9dc6cb2693e9c0ae7817891b2fa68c8ef4b397..1fb4bd0f71ab641124dee79bd75e773d98c0fd75 100644 (file)
@@ -698,10 +698,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 domiains */
                           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 +1589,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 +1623,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 +1846,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 9367bb0d4513cc8c1484418e4d8175ab8f035534..6e8025c1f2089027cbe8e9c88248b5cef60d0cc5 100644 (file)
@@ -178,8 +178,13 @@ TypeShellMakeWithOpenRelation(Relation pg_type_desc, char *typeName)
        values[i++] = ObjectIdGetDatum(InvalidOid); /* 14 */
        values[i++] = CharGetDatum('i');        /* 15 */
        values[i++] = CharGetDatum('p');        /* 16 */
+               values[i++] = BoolGetDatum(false);      /* 17 */
+                       values[i++] = Int32GetDatum(-1);        /* 18 */
        values[i++] = DirectFunctionCall1(textin,
-                                                                         CStringGetDatum(typeName));           /* 17 */
+                                                                         CStringGetDatum(typeName));           /* 19 */
+       values[i++] = DirectFunctionCall1(textin,
+                                                                         CStringGetDatum(typeName));           /* 20 */
+
 
        /*
         * create a new type tuple with FormHeapTuple
@@ -264,7 +269,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 +279,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 +295,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 +328,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 +410,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 +433,7 @@ TypeCreate(char *typeName,
                                                                                 PointerGetDatum(argList),
                                                                                 0);
                        }
+
                        if (!OidIsValid(procOid))
                                func_error("TypeCreate", procname, 1, argList, NULL);
                }
@@ -428,6 +451,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 +487,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 58a09d21e6ab86af22944938955c3558b1951839..15c6f1c3cca322e7e8f732e1c8fc11b1743d4b04 100644 (file)
@@ -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);
 
+       /*
+        * Merge domain attributes into the known columns before 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,88 @@ TruncateRelation(char *name)
        heap_truncate(name);
 }
 
+
+/*
+ * MergeDomainAttributes
+ *      Returns a new schema with the constraints, types, and other
+ *      attributes of the domain resolved.
+ *
+ * Defaults are processed at execution time by taking the default of
+ * the type (domain) if it is null.  This does not need to be merged
+ * here.
+ */
+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);
+
+//typedef struct TypeName
+//{
+       //NodeTag               type;
+       //char     *name;                       /* name of the type */
+       //bool          timezone;               /* timezone specified? */
+       //bool          setof;                  /* is a set? */
+       //int32         typmod;                 /* type modifier */
+       //List     *arrayBounds;        /* array bounds */
+       //char     *attrname;           /* field name when using %TYPE */
+//} TypeName;
+
+// ColumnDef
+//             NodeTag         type;
+//             char       *colname;            /* name of column */
+//             TypeName   *typename;           /* type of column */
+//             bool            is_not_null;    /* NOT NULL constraint specified? */
+//             Node       *raw_default;        /* default value (untransformed parse
+//                                                              * tree) */
+//             char       *cooked_default; /* nodeToString representation */
+//             List       *constraints;        /* other constraints on column */
+
+       }
+
+       return schema;
+}
+
 /*----------
  * MergeAttributes
  *             Returns new schema given initial schema and superclasses.
index 3fedb6328be2421545f7052d0d9a4ea14fb06d1d..982d68afd29f6dc22a1cb59b9fea2e324e969dfe 100644 (file)
@@ -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,322 @@ 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 =                       DatumGetBool(heap_getattr(typeTup, Anum_pg_type_typbyval, pg_type_dsc, &isnull));
+       Assert(!isnull);
+
+       /* Required Alignment */
+       alignment =             DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typalign, pg_type_dsc, &isnull));
+       Assert(!isnull);
+
+       /* Storage Length */
+       internalLength =        DatumGetInt16(heap_getattr(typeTup, Anum_pg_type_typlen, pg_type_dsc, &isnull));
+       Assert(!isnull);
+
+       /* External Length (unused) */
+       externalLength =        DatumGetInt16(heap_getattr(typeTup, Anum_pg_type_typprtlen, pg_type_dsc, &isnull));
+       Assert(!isnull);
+
+       /* Array element Delimiter */
+       delimiter =             DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typdelim, pg_type_dsc, &isnull));
+       Assert(!isnull);
+
+       /* 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 =                       DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typstorage, pg_type_dsc, &isnull));
+       Assert(!isnull);
+
+       /* Inherited default value */
+       datum =                         heap_getattr(typeTup, Anum_pg_type_typdefault, pg_type_dsc, &isnull);
+       if (!isnull) {
+               defaultValue =  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 +807,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 +850,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 +910,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 +951,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 +982,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 da2feff94c86e149de218c0f20b97e8bf182831f..f583399610808023f89fdfcb8e78fb2b0f70691f 100644 (file)
@@ -1,7 +1,7 @@
 /*-------------------------------------------------------------------------
  *
  * 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
@@ -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 538cd0ef449d577d796de5ea50fe3b1c57e55489..77a2b88559a305c5645be8848a01c8695c499f68 100644 (file)
@@ -2227,6 +2227,19 @@ _copyLoadStmt(LoadStmt *from)
        return newnode;
 }
 
+static CreateDomainStmt *
+_copyCreateDomainStmt(CreateDomainStmt *from)
+{
+       CreateDomainStmt *newnode = makeNode(CreateDomainStmt);
+
+       if (from->domainname)
+               newnode->domainname = pstrdup(from->domainname);
+       if (from->typename)
+               newnode->typename = from->typename;
+
+       return newnode;
+}
+
 static CreatedbStmt *
 _copyCreatedbStmt(CreatedbStmt *from)
 {
index 17b8edf0b1a0e51505c70d92364eed94ef2b012c..c794a64a48d14bb0d3689c2b42330b165e1b3b34 100644 (file)
@@ -1095,6 +1095,17 @@ _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;
+
+       return true;
+}
+
 static bool
 _equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
 {
@@ -2011,6 +2022,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 f7e3673946eb2a312adccbb4f2b6778f4926c64c..236a02e29b346f66df94b63b1df92875afde53a5 100644 (file)
@@ -355,7 +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;
@@ -392,7 +391,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 +429,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 c45d37c2821592bb4d69063aedae1c1e50c64e03..f1af1c23b0fb0b9fab9afdd29dbfd3b5d14c7233 100644 (file)
@@ -135,7 +135,8 @@ static void doNegateFloat(Value *v);
                ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt,
                CopyStmt, CreateAsStmt, CreateGroupStmt, CreatePLangStmt,
                CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
-               CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt,
+               CreateUserStmt, CreateDomainStmt, CreatedbStmt, CursorStmt,
+               DefineStmt, DeleteStmt,
                DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
                DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
                GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
@@ -289,6 +290,8 @@ static void doNegateFloat(Value *v);
 %type <list>   constraints_set_namelist
 %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 +346,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 +449,7 @@ stmt : AlterDatabaseSetStmt
                | CopyStmt
                | CreateStmt
                | CreateAsStmt
+               | CreateDomainStmt
                | CreateSchemaStmt
                | CreateGroupStmt
                | CreateSeqStmt
@@ -776,7 +780,10 @@ DropSchemaStmt:  DROP SCHEMA UserId
                                        n->dbname = $3;
                                        $$ = (Node *)n;
                                }
+               ;
+
 
 
 /*****************************************************************************
  *
@@ -1461,7 +1468,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
@@ -2043,7 +2053,16 @@ 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;
+                               }
+               | ColLabel '=' def_arg
                                {
                                        $$ = makeNode(DefElem);
                                        $$->defname = $1;
@@ -2078,6 +2097,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;
                                }
                ;
@@ -2110,7 +2138,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
@@ -2196,6 +2224,7 @@ comment_type:     DATABASE { $$ = DATABASE; }
                | RULE { $$ = RULE; }
                | SEQUENCE { $$ = SEQUENCE; }
                | TABLE { $$ = TABLE; }
+               | DOMAIN_P { $$ = TYPE_P; }
                | TYPE_P { $$ = TYPE_P; }
                | VIEW { $$ = VIEW; }
                ;               
@@ -3222,6 +3251,30 @@ AlterDatabaseSetStmt: ALTER DATABASE database_name VariableSetStmt
                                }
                ;
 
+/*****************************************************************************
+ *
+ * Manipulate a domain
+ *
+ *
+ *****************************************************************************/
+
+CreateDomainStmt:  CREATE DOMAIN_P name opt_as Typename ColQualList opt_collate
+                               {
+                                       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; }
+       ;
 
 /*****************************************************************************
  *
@@ -5879,6 +5932,7 @@ unreserved_keyword:
                | DEFERRED                                              { $$ = "deferred"; }
                | DELETE                                                { $$ = "delete"; }
                | DELIMITERS                                    { $$ = "delimiters"; }
+               | DOMAIN_P                                              { $$ = "domain"; }
                | DOUBLE                                                { $$ = "double"; }
                | DROP                                                  { $$ = "drop"; }
                | EACH                                                  { $$ = "each"; }
index 950ef58d02f536c2a67edd67f520cdafa7254fa4..c86ff6820feaecb7467e732a17b8d5c1d6685552 100644 (file)
@@ -97,6 +97,7 @@ static ScanKeyword ScanKeywords[] = {
        {"desc", DESC},
        {"distinct", DISTINCT},
        {"do", DO},
+       {"domain", DOMAIN_P},
        {"double", DOUBLE},
        {"drop", DROP},
        {"each", EACH},
index 56e285c6722e0d630925d871e2a14ed1272f7ac5..6d0c71770681045d08632aa662bb1696937c7ff1 100644 (file)
@@ -38,6 +38,7 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
 {
        Node       *result;
 
+
        if (targetTypeId == inputTypeId ||
                targetTypeId == InvalidOid ||
                node == NULL)
@@ -605,3 +606,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;
+}
\ No newline at end of file
index 65af0481a262d10681d2fd8b37395249ad61131a..a22b6d1d4ad402ebf738e1d3797c96be7673a8d3 100644 (file)
@@ -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 5384d0ffdbaa54631337f0c172da6e2a1bf6ef7c..ddceb4c1bfdc50fe4accf1c6b132ee3505dfb66c 100644 (file)
@@ -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;
                                        }
 
                                        /*
@@ -742,6 +747,16 @@ ProcessUtility(Node *parsetree,
                        DropProceduralLanguage((DropPLangStmt *) parsetree);
                        break;
 
+                       /*
+                        * ******************************** DOMAIN statements ****
+                        *
+                        */
+               case T_CreateDomainStmt:
+                       set_ps_display(commandTag = "CREATE DOMAIN");
+
+                       DefineDomain((CreateDomainStmt *) parsetree);
+                       break;
+
                        /*
                         * ******************************** USER statements ****
                         *
index 4fda9021bbb9b706c7b93a8ded4f4d23bdad36b2..9722eacbd3313598bff70a6e6def2b26de96673b 100644 (file)
@@ -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 5baf293962bc90b2bc6a2d65ebaca5f5d4e5d744..b23250b9a0cbb48f8b79ff48d835a01ef8020627 100644 (file)
@@ -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 f1f030b314ef153182bd8a83be2f0259233cebca..ae90fd97190d3fe5161f2dfd1506c1bc009b8a13 100644 (file)
@@ -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 45b12028c3001e150ffb6638e411b37b5fa5ecc8..1d0d19b56f3cf1408d90c2d8e9a9aa1c4b766faf 100644 (file)
@@ -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 8b677276e443af20abb3d624b2d2ab0506b91827..885d2db0d57921637cff258557870d74dd1893f5 100644 (file)
@@ -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 923256df902fa453b255138fcce23f0014240e47..8e4e4397352755121f0f692c3e5f92dc7b1ee921 100644 (file)
@@ -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 259ae675590d876b0e82831b2228fdb557fd94ea..50793c814ac5a960d24bfc80c081e913675cac98 100644 (file)
@@ -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 23fcfa6740f69f89f09db0a80660f6955af55e02..3d4abcab1989161c5de075bb3464593dd70d6590 100644 (file)
@@ -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 6fefdc0bd31bd923fe024f9cacd7224ce1ead774..020328f85971eae012eb94dad34a8856d2c3a63e 100644 (file)
@@ -172,6 +172,7 @@ typedef enum NodeTag
        T_TransactionStmt,
        T_ViewStmt,
        T_LoadStmt,
+       T_CreateDomainStmt,
        T_CreatedbStmt,
        T_DropdbStmt,
        T_VacuumStmt,
index c8811dc17da5a33eb7e424b5b5ee54a135b8d4a2..d8d0eded28ae41867df99d5a5551d7ac93d2d4d9 100644 (file)
@@ -468,12 +468,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;
 
 /* ----------------------
@@ -682,6 +684,7 @@ typedef struct LoadStmt
        char       *filename;           /* file to load */
 } LoadStmt;
 
+
 /* ----------------------
  *             Createdb Statement
  * ----------------------
@@ -1280,6 +1283,22 @@ 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
  ****************************************************************************/
index 28bb69ab334a0bd12f0dd6a8524b3107a6ba4c3b..4fbda424ac3ad9251bf2347e548e933d50dc5dc5 100644 (file)
@@ -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 880f208dc47020daafab2cc68691859d28126718..ef74eb3c41fa78eb167f512d6a944df50aeb7856 100644 (file)
@@ -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,