diff --git a/doc/dominfo.txt b/doc/dominfo.txt new file mode 100644 index 0000000000000000000000000000000000000000..a439ff6c3c90e2029b6522e79b9cb32f54f728f0 --- /dev/null +++ b/doc/dominfo.txt @@ -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; diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index aab0a906d9b7a589c648e70e55dd4ab6b5e8adcb..357d17712b5b9ef9f64c7a7d0ccda1b0c3aae03d 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,6 +1,6 @@ <!-- Documentation of the system catalogs, directed toward PostgreSQL developers - $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.31 2002/03/01 22:45:03 petere Exp $ + $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.32 2002/03/06 20:34:43 momjian Exp $ --> <chapter id="catalogs"> @@ -2510,6 +2510,53 @@ </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> diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml index 94f1226c24f73997675812a41a2e4ab59afb9fe5..948e2cdac5ed13f110b147f88e44f8fbce1f652c 100644 --- a/doc/src/sgml/ref/allfiles.sgml +++ b/doc/src/sgml/ref/allfiles.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.33 2002/03/01 22:45:07 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.34 2002/03/06 20:34:44 momjian Exp $ PostgreSQL documentation Complete list of usable sgml source files in this directory. --> @@ -52,6 +52,7 @@ Complete list of usable sgml source files in this directory. <!entity createAggregate system "create_aggregate.sgml"> <!entity createConstraint system "create_constraint.sgml"> <!entity createDatabase system "create_database.sgml"> +<!entity createDomain system "create_domain.sgml"> <!entity createFunction system "create_function.sgml"> <!entity createGroup system "create_group.sgml"> <!entity createIndex system "create_index.sgml"> @@ -69,6 +70,7 @@ Complete list of usable sgml source files in this directory. <!entity delete system "delete.sgml"> <!entity dropAggregate system "drop_aggregate.sgml"> <!entity dropDatabase system "drop_database.sgml"> +<!entity dropDomain system "drop_domain.sgml"> <!entity dropFunction system "drop_function.sgml"> <!entity dropGroup system "drop_group.sgml"> <!entity dropIndex system "drop_index.sgml"> diff --git a/doc/src/sgml/ref/comment.sgml b/doc/src/sgml/ref/comment.sgml index 9a22b7589544beb96fac498e00b23218ca9728ad..2482a2d7e33fdde23ab5980bfcbe8bebed4c5a1f 100644 --- a/doc/src/sgml/ref/comment.sgml +++ b/doc/src/sgml/ref/comment.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/comment.sgml,v 1.12 2001/12/27 21:36:57 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/comment.sgml,v 1.13 2002/03/06 20:34:44 momjian Exp $ PostgreSQL documentation --> @@ -25,7 +25,7 @@ PostgreSQL documentation <synopsis> COMMENT ON [ - [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] <replaceable class="PARAMETER">object_name</replaceable> | + [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] <replaceable class="PARAMETER">object_name</replaceable> | COLUMN <replaceable class="PARAMETER">table_name</replaceable>.<replaceable class="PARAMETER">column_name</replaceable> | AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable>) | FUNCTION <replaceable class="PARAMETER">func_name</replaceable> (<replaceable class="PARAMETER">arg1</replaceable>, <replaceable class="PARAMETER">arg2</replaceable>, ...) | @@ -33,7 +33,7 @@ COMMENT ON TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable> ] IS <replaceable class="PARAMETER">'text'</replaceable> </synopsis> - + <refsect2 id="R2-SQL-COMMENT-1"> <refsect2info> <date>1999-10-25</date> @@ -64,7 +64,7 @@ COMMENT ON </variablelist> </para> </refsect2> - + <refsect2 id="R2-SQL-COMMENT-2"> <refsect2info> <date>1998-09-08</date> @@ -99,7 +99,7 @@ COMMENT </title> <para> <command>COMMENT</command> stores a comment about a database object. - Comments can be + Comments can be easily retrieved with <command>psql</command>'s <command>\dd</command>, <command>\d+</command>, or <command>\l+</command> commands. Other user interfaces to retrieve comments can be built atop @@ -141,6 +141,7 @@ COMMENT ON mytable IS 'This is my table.'; <programlisting> COMMENT ON DATABASE my_database IS 'Development Database'; +COMMENT ON DOMAIN my_domain IS '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 index 0000000000000000000000000000000000000000..f88069bfc20c5dbec5838c5c5bbeb0b5893ee8d5 --- /dev/null +++ b/doc/src/sgml/ref/create_domain.sgml @@ -0,0 +1,231 @@ +<!-- +$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_domain.sgml,v 1.1 2002/03/06 20:34:44 momjian Exp $ +PostgreSQL documentation +--> + +<refentry id="SQL-CREATEDOMAIN"> + <refmeta> + <refentrytitle id="sql-createdomian-title"> + CREATE DOMAIN + </refentrytitle> + <refmiscinfo>SQL - Language Statements</refmiscinfo> + </refmeta> + <refnamediv> + <refname> + CREATE DOMAIN + </refname> + <refpurpose> + define a new domain + </refpurpose> + </refnamediv> + <refsynopsisdiv> + <refsynopsisdivinfo> + <date>2002-02-24</date> + </refsynopsisdivinfo> + <synopsis> +CREATE DOMAIN <replaceable class="parameter">domainname</replaceable> <replaceable class="parameter">data_type</replaceable> [ DEFAULT <replaceable>default_expr</> ] [ <replaceable class="PARAMETER">column_constraint</replaceable> [, ... ] ] +[ CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> ] +{ NOT NULL | NULL <!-- | UNIQUE | PRIMARY KEY | + CHECK (<replaceable class="PARAMETER">expression</replaceable>) | + REFERENCES <replaceable class="PARAMETER">reftable</replaceable> [ ( <replaceable class="PARAMETER">refcolumn</replaceable> ) ] [ MATCH FULL | MATCH PARTIAL ] + [ ON DELETE <replaceable class="parameter">action</replaceable> ] [ ON UPDATE <replaceable class="parameter">action</replaceable> ] --> } +<!-- [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] --> + </synopsis> + + <refsect2 id="R2-SQL-CREATEDOMAIN-1"> + <refsect2info> + <date>2002-02-24</date> + </refsect2info> + <title> + Parameters + </title> + <para> + + <variablelist> + <varlistentry> + <term><replaceable class="parameter">domainname</replaceable></term> + <listitem> + <para> + The name of a domain to be created. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><replaceable class="PARAMETER">data_type</replaceable></term> + <listitem> + <para> + The data type of the domain. This may include array specifiers. + Refer to the <citetitle>User's Guide</citetitle> for further + information about data types and arrays. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>DEFAULT + <replaceable>default_expr</replaceable></literal></term> + <listitem> + <para> + The <literal>DEFAULT</> clause assigns a default data value for + the column whose column definition it appears within. The value + is any variable-free expression (subselects and cross-references + to other columns in the current table are not allowed). The + data type of the default expression must match the data type of the + domain. + </para> + + <para> + The default expression will be used in any insert operation that + does not specify a value for the domain. If there is no default + for a domain, then the default is NULL. + </para> + + <note> + <para> + The default of a column will be tested before that of the domain. + </para> + </note> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable></literal></term> + <listitem> + <para> + An optional name for a domain. If not specified, + the system generates a name. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>NOT NULL</></term> + <listitem> + <para> + The column is not allowed to contain NULL values. This is + equivalent to the column constraint <literal>CHECK (<replaceable + class="PARAMETER">column</replaceable> NOT NULL)</literal>. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>NULL</></term> + <listitem> + <para> + The column is allowed to contain NULL values. This is the default. + </para> + + <para> + This clause is only available for compatibility with + non-standard SQL databases. Its use is discouraged in new + applications. + </para> + </listitem> + </varlistentry> + + </variablelist> + </para> + </refsect2> + + <refsect2 id="R2-SQL-CREATEDOMAIN-2"> + <refsect2info> + <date>2002-02-24</date> + </refsect2info> + <title> + Outputs + </title> + <para> + + <variablelist> + <varlistentry> + <term><computeroutput> +CREATE DOMAIN + </computeroutput></term> + <listitem> + <para> + Message returned if the domain is successfully created. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </refsect2> + </refsynopsisdiv> + + <refsect1 id="R1-SQL-CREATEDOMAIN-1"> + <refsect1info> + <date>2002-02-24</date> + </refsect1info> + <title> + Description + </title> + + <para> + <command>CREATE DOMAIN</command> allows the user to register a new user data + domain with PostgreSQL for use in the current data base. The + user who defines a domain becomes its owner. + <replaceable class="parameter">domainname</replaceable> is + the name of the new type and must be unique within the + types and domains defined for this database. + </para> + + <para> + Domains are useful for abstracting common fields between tables into + a single location for maintenance. An email address column may be used + in several tables, all with the same properties. Define a domain and + use that rather than setting up each tables constraints individually. + </para> + </refsect1> + + <refsect1> + <title>Examples</title> + <para> + This example creates the <type>country_code</type> data type and then uses the + type in a table definition: +<programlisting> +CREATE DOMAIN country_code char(2) NOT NULL; +CREATE TABLE countrylist (id INT4, country country_code); +</programlisting> + </para> + </refsect1> + + <refsect1 id="SQL-CREATEDOMAIN-compatibility"> + <title>Compatibility</title> + + <para> + This <command>CREATE DOMAIN</command> command is a + <productname>PostgreSQL</productname> extension. CHECK and FOREIGN KEY + constraints are currently unsupported. + </para> + </refsect1> + + <refsect1 id="SQL-CREATEDOMAIN-see-also"> + <title>See Also</title> + + <simplelist type="inline"> + <member><xref linkend="sql-dropdomain"></member> + <member><citetitle>PostgreSQL Programmer's Guide</citetitle></member> + </simplelist> + </refsect1> + +</refentry> + + +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:nil +sgml-shorttag:t +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:1 +sgml-indent-data:t +sgml-parent-document:nil +sgml-default-dtd-file:"../reference.ced" +sgml-exposed-tags:nil +sgml-local-catalogs:"/usr/lib/sgml/catalog" +sgml-local-ecat-files:nil +End: +--> diff --git a/doc/src/sgml/ref/drop_domain.sgml b/doc/src/sgml/ref/drop_domain.sgml new file mode 100644 index 0000000000000000000000000000000000000000..d508d6aa15ed6be4d2eb63cfaecdec83a2845d7a --- /dev/null +++ b/doc/src/sgml/ref/drop_domain.sgml @@ -0,0 +1,167 @@ +<!-- +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_domain.sgml,v 1.1 2002/03/06 20:34:44 momjian Exp $ +PostgreSQL documentation +--> + +<refentry id="SQL-DROPDOMAIN"> + <refmeta> + <refentrytitle id="SQL-DROPDOMAIN-TITLE"> + DROP DOMAIN + </refentrytitle> + <refmiscinfo>SQL - Language Statements</refmiscinfo> + </refmeta> + <refnamediv> + <refname> + DROP DOMAIN + </refname> + <refpurpose> + remove a user-defined domain + </refpurpose> + </refnamediv> + <refsynopsisdiv> + <refsynopsisdivinfo> + <date>1999-07-20</date> + </refsynopsisdivinfo> + <synopsis> +DROP DOMAIN <replaceable class="PARAMETER">domainname</replaceable> [, ...] + </synopsis> + + <refsect2 id="R2-SQL-DROPDOMAIN-1"> + <refsect2info> + <date>2002-02-24</date> + </refsect2info> + <title> + Inputs + </title> + <para> + <variablelist> + <varlistentry> + <term><replaceable class="PARAMETER">domainname</replaceable></term> + <listitem> + <para> + The name of an existing domain. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </refsect2> + + <refsect2 id="R2-SQL-DROPDOMAIN-2"> + <refsect2info> + <date>2002-02-24</date> + </refsect2info> + <title> + Outputs + </title> + <para> + <variablelist> + <varlistentry> + <term><computeroutput> +DROP + </computeroutput></term> + <listitem> + <para> + The message returned if the command is successful. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><computeroutput> +ERROR: RemoveDomain: type '<replaceable class="parameter">domainname</replaceable>' does not exist + </computeroutput></term> + <listitem> + <para> + This message occurs if the specified domain (or type) is not found. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </refsect2> + </refsynopsisdiv> + + <refsect1 id="R1-SQL-DROPDOMAIN-1"> + <refsect1info> + <date>2002-02-24</date> + </refsect1info> + <title> + Description + </title> + <para> + <command>DROP DOMAIN</command> will remove a user domain from the + system catalogs. + </para> + <para> + Only the owner of a domain can remove it. + </para> + </refsect1> + + <refsect1 id="SQL-DROPDOMAIN-notes"> + <title>Notes</title> + + <itemizedlist> + <listitem> + <para> + It is the user's responsibility to remove any operators, + functions, aggregates, access methods, and tables that + use a deleted domain. + </para> + </listitem> + </itemizedlist> + </refsect1> + + <refsect1 id="SQL-DROPDOMAIN-examples"> + <title>Examples</title> + <para> + To remove the <type>box</type> domain: + +<programlisting> +DROP DOMAIN box RESTRICT; +</programlisting> + </para> + </refsect1> + + <refsect1 id="SQL-DROPDOMAIN-compatibility"> + <title>Compatibility</title> + + <para> + A <command>DROP DOMAIN</command> statement exists in SQL99. As with + most other <quote>drop</quote> commands, <command>DROP + DOMAIN</command> in SQL99 requires a <quote>drop behavior</quote> + clause to select between dropping all dependent objects or refusing + to drop if dependent objects exist: +<synopsis> +DROP DOMAIN <replaceable>name</replaceable> { CASCADE | RESTRICT } +</synopsis> + <productname>PostgreSQL</productname> enforces the existance of + RESTRICT or CASCADE but ignores their enforcement against the + system tables. + </para> + </refsect1> + + <refsect1 id="SQL-DROPDOMAIN-see-also"> + <title>See Also</title> + + <simplelist type="inline"> + <member><xref linkend="sql-createdomain"></member> + </simplelist> + </refsect1> +</refentry> + +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:nil +sgml-shorttag:t +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:1 +sgml-indent-data:t +sgml-parent-document:nil +sgml-default-dtd-file:"../reference.ced" +sgml-exposed-tags:nil +sgml-local-catalogs:"/usr/lib/sgml/catalog" +sgml-local-ecat-files:nil +End: +--> diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml index 27f218d33fb6d7e69e34b7e4f7b9618797a77baf..14fd89b0a4f6a795c423611d86c8c9779922ccc4 100644 --- a/doc/src/sgml/reference.sgml +++ b/doc/src/sgml/reference.sgml @@ -1,5 +1,5 @@ <!-- reference.sgml -$Header: /cvsroot/pgsql/doc/src/sgml/reference.sgml,v 1.21 2002/03/01 22:45:04 petere Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/reference.sgml,v 1.22 2002/03/06 20:34:43 momjian Exp $ PostgreSQL Reference Manual --> @@ -61,6 +61,7 @@ PostgreSQL Reference Manual &createAggregate; &createConstraint; &createDatabase; + &createDomain; &createFunction; &createGroup; &createIndex; @@ -78,6 +79,7 @@ PostgreSQL Reference Manual &delete; &dropAggregate; &dropDatabase; + &dropDomain; &dropFunction; &dropGroup; &dropIndex; @@ -115,7 +117,7 @@ PostgreSQL Reference Manual &unlisten; &update; &vacuum; - + </reference> <!-- diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 61fc2a451b93f472011f0cac127260ef8d8101e7..2b55700f3ada09577fd3ec44a536443d10b85315 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.184 2002/03/06 06:09:25 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.185 2002/03/06 20:34:45 momjian Exp $ * * * INTERFACE ROUTINES @@ -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) { diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index f14d06e0e273addeaf7da64d88a21d66c1ec1b3a..9991465a619412cb2cb7fe8d7ab66fe34363a639 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.65 2001/10/25 05:49:23 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.66 2002/03/06 20:34:46 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -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. diff --git a/src/backend/commands/creatinh.c b/src/backend/commands/creatinh.c index 27535429c39499b04cc479a05df8fd285cf66072..586cee63cce5bb3adb5778089801de59f063b1bd 100644 --- a/src/backend/commands/creatinh.c +++ b/src/backend/commands/creatinh.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.83 2002/03/06 06:09:31 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.84 2002/03/06 20:34:46 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -39,7 +39,7 @@ static bool change_varattnos_of_a_node(Node *node, const AttrNumber *newattno); static void StoreCatalogInheritance(Oid relationId, List *supers); static int findAttrByName(const char *attributeName, List *schema); static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass); - +static List *MergeDomainAttributes(List *schema); /* ---------------------------------------------------------------- * DefineRelation @@ -69,6 +69,13 @@ DefineRelation(CreateStmt *stmt, char relkind) */ StrNCpy(relname, stmt->relname, NAMEDATALEN); + /* + * 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. diff --git a/src/backend/commands/define.c b/src/backend/commands/define.c index 841fc73c30939c512722eb3e054b8a8933dc6e0f..cb71340eb2c61ccbf8b1125b100a949cf963ca7b 100644 --- a/src/backend/commands/define.c +++ b/src/backend/commands/define.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.67 2002/03/06 06:09:32 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.68 2002/03/06 20:34:47 momjian Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -40,6 +40,7 @@ #include "access/heapam.h" #include "catalog/catname.h" +#include "catalog/heap.h" #include "catalog/pg_aggregate.h" #include "catalog/pg_language.h" #include "catalog/pg_operator.h" @@ -475,6 +476,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); } diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c index a0456adeb930dc186971072f623d6c4f281dc2be..69e6e1b9000b48191151736256b974c3a8e25f5d 100644 --- a/src/backend/commands/remove.c +++ b/src/backend/commands/remove.c @@ -1,14 +1,14 @@ /*------------------------------------------------------------------------- * * remove.c - * POSTGRES remove (function | type | operator ) utilty code. + * POSTGRES remove (domain | function | type | operator ) utilty code. * * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.66 2002/03/06 06:09:35 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.67 2002/03/06 20:34:47 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -22,6 +22,7 @@ #include "commands/comment.h" #include "commands/defrem.h" #include "miscadmin.h" +#include "parser/parse.h" #include "parser/parse_agg.h" #include "parser/parse_expr.h" #include "parser/parse_func.h" @@ -275,6 +276,60 @@ RemoveType(char *typeName) /* type name to be removed */ heap_close(relation, RowExclusiveLock); } +/* + * RemoveDomain + * Removes the domain 'typeName' and all attributes and relations that + * use it. + */ +void +RemoveDomain(char *domainName, int behavior) /* domain name to be removed */ +{ + Relation relation; + HeapTuple tup; + TupleDesc description; + char typtype; + bool isnull; + + + /* Domains are stored as types. Check for permissions on the type */ + if (!pg_ownercheck(GetUserId(), domainName, TYPENAME)) + elog(ERROR, "RemoveDomain: type '%s': permission denied", + domainName); + + + relation = heap_openr(TypeRelationName, RowExclusiveLock); + description = RelationGetDescr(relation); + + tup = SearchSysCache(TYPENAME, + PointerGetDatum(domainName), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + elog(ERROR, "RemoveType: type '%s' does not exist", domainName); + + + /* Check that this is actually a domain */ + typtype = DatumGetChar(heap_getattr(tup, Anum_pg_type_typtype, description, &isnull)); + Assert(!isnull); + + if (typtype != 'd') { + elog(ERROR, "%s is not a domain", domainName); + } + + /* CASCADE unsupported */ + if (behavior == CASCADE) { + elog(ERROR, "DROP DOMAIN does not support the CASCADE keyword"); + } + + /* Delete any comments associated with this type */ + DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation)); + + simple_heap_delete(relation, &tup->t_self); + + ReleaseSysCache(tup); + + heap_close(relation, RowExclusiveLock); +} + /* * RemoveFunction * Deletes a function. diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index d3fe436ac77755e9578619e3c4dffd1c16fc7872..07acc5dde66308faf84d51a3eeb8b9b46bb74da8 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.165 2002/03/01 22:45:11 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.166 2002/03/06 20:34:47 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -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) { diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 661190dbaa86cec45861f8f2d4849b5c7ea21861..962471a5a97647d307205d9bd088d2bf7a531d42 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -20,7 +20,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.113 2002/03/06 06:09:49 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.114 2002/03/06 20:34:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -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; diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c index 4f637f48d1a0791fd982a4e84bc2440fbb6904fd..d8b376ba8cecba667664b9f4747ef0293ac4064f 100644 --- a/src/backend/optimizer/prep/preptlist.c +++ b/src/backend/optimizer/prep/preptlist.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.46 2001/11/05 17:46:26 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.47 2002/03/06 20:34:49 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -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; } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index a8aba404e76d91724905fe7919eab516df15256b..c1b46650917fe0c38c1d49b1a7bb8c38af70fadb 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.285 2002/03/06 06:09:53 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.286 2002/03/06 20:34:49 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -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"; } diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c index eaa0f7fa2b0424c051dc14c01397c0f74f05862f..02aff543d02679af0b9a263ee6fbb688bbd32321 100644 --- a/src/backend/parser/keywords.c +++ b/src/backend/parser/keywords.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.101 2002/03/05 05:33:15 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.102 2002/03/06 20:34:50 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -97,6 +97,7 @@ static ScanKeyword ScanKeywords[] = { {"desc", DESC}, {"distinct", DISTINCT}, {"do", DO}, + {"domain", DOMAIN_P}, {"double", DOUBLE}, {"drop", DROP}, {"each", EACH}, diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c index e81edb3efc530e2613667960f6963a0ded75a34e..8586d5e5cca5f98d8fb7353bc83b09d3ced1d914 100644 --- a/src/backend/parser/parse_coerce.c +++ b/src/backend/parser/parse_coerce.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.64 2001/10/25 05:49:39 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.65 2002/03/06 20:34:51 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -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 diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c index 339999c0c6356de510073b896e81697031b82357..b095fa44b874e9d1adc2222d1d3144f8d800f8fe 100644 --- a/src/backend/parser/parse_expr.c +++ b/src/backend/parser/parse_expr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.105 2001/11/12 20:05:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.106 2002/03/06 20:34:52 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1027,7 +1027,8 @@ parser_typecast_expression(ParseState *pstate, if (inputType != targetType) { expr = CoerceTargetExpr(pstate, expr, inputType, - targetType, typename->typmod); + getBaseType(targetType), + typename->typmod); if (expr == NULL) elog(ERROR, "Cannot cast type '%s' to '%s'", format_type_be(inputType), @@ -1039,7 +1040,7 @@ parser_typecast_expression(ParseState *pstate, * as well as a type coercion. */ expr = coerce_type_typmod(pstate, expr, - targetType, typename->typmod); + getBaseType(targetType), typename->typmod); return expr; } diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 528b93012c2bbf9285a08bbd87172b4614e63076..947bca0553684d71259b4129c4e2bcff7fe647e5 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.129 2002/03/05 05:33:19 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.130 2002/03/06 20:34:52 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -282,6 +282,11 @@ ProcessUtility(Node *parsetree, /* RemoveType does its own permissions checks */ RemoveType(relname); break; + + case DROP_DOMAIN_P: + /* RemoveDomain does its own permissions checks */ + RemoveDomain(relname, stmt->behavior); + break; } /* @@ -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 **** * diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c index 960d0b2bcf065176eca473edd66df70b5e293ea0..b825a5b14d2edee5475993a2e2d5dbd74a81396b 100644 --- a/src/backend/utils/adt/format_type.c +++ b/src/backend/utils/adt/format_type.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.24 2002/03/02 21:39:32 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.25 2002/03/06 20:34:53 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -126,6 +126,7 @@ format_type_internal(Oid type_oid, int32 typemod, bool is_array; char *name; char *buf; + char typtype; if (type_oid == InvalidOid && allow_invalid) return pstrdup("-"); @@ -144,6 +145,31 @@ format_type_internal(Oid type_oid, int32 typemod, array_base_type = ((Form_pg_type) GETSTRUCT(tuple))->typelem; typlen = ((Form_pg_type) GETSTRUCT(tuple))->typlen; + typtype = ((Form_pg_type) GETSTRUCT(tuple))->typtype; + + /* + * Domains look alot like arrays, so lets process them first, and return + * back to avoid the array and 'standard' formatting procedures that are + * use for base types. + */ + if (typtype == 'd') { + name = NameStr(((Form_pg_type) GETSTRUCT(tuple))->typname); + + /* + * Double-quote the name if it's not a standard identifier. + * Note this is *necessary* for ruleutils.c's use. + */ + if (strspn(name, "abcdefghijklmnopqrstuvwxyz0123456789_") != strlen(name) + || isdigit((unsigned char) name[0])) + buf = psnprintf(strlen(name) + 3, "\"%s\"", name); + else + buf = pstrdup(name); + + ReleaseSysCache(tuple); + + return buf; + } + if (array_base_type != InvalidOid && typlen < 0) { /* Switch our attention to the array element type */ diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 706397d28c6a25aa328a463e0eb6db9e4c96c5d2..3247c0aa8f6416d2b39b2b6312442e563eaaa49a 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.60 2002/03/01 04:09:26 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.61 2002/03/06 20:34:54 momjian Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -23,6 +23,7 @@ #include "catalog/pg_shadow.h" #include "catalog/pg_statistic.h" #include "catalog/pg_type.h" +#include "parser/parse_coerce.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/lsyscache.h" @@ -822,16 +823,17 @@ get_typstorage(Oid typid) * Returns FALSE if there is no default (effectively, default is NULL). * The result points to palloc'd storage for pass-by-reference types. */ -bool -get_typdefault(Oid typid, Datum *defaultValue) +Node * +get_typdefault(Oid typid, int32 atttypmod) { HeapTuple typeTuple; Form_pg_type type; - Oid typinput, - typelem; - Datum textDefaultVal; + Oid typinput; + Oid typbasetype; + char typtype; + Datum datum; bool isNull; - char *strDefaultVal; + Node *expr; typeTuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(typid), @@ -843,38 +845,41 @@ get_typdefault(Oid typid, Datum *defaultValue) type = (Form_pg_type) GETSTRUCT(typeTuple); typinput = type->typinput; - typelem = type->typelem; + typbasetype = type->typbasetype; + typtype = type->typtype; /* - * typdefault is potentially null, so don't try to access it as a + * typdefaultbin is potentially null, so don't try to access it as a * struct field. Must do it the hard way with SysCacheGetAttr. */ - textDefaultVal = SysCacheGetAttr(TYPEOID, - typeTuple, - Anum_pg_type_typdefault, - &isNull); + datum = SysCacheGetAttr(TYPEOID, + typeTuple, + Anum_pg_type_typdefaultbin, + &isNull); + ReleaseSysCache(typeTuple); if (isNull) - { - ReleaseSysCache(typeTuple); - *defaultValue = (Datum) 0; - return false; - } + return (Node *) NULL; - /* Convert text datum to C string */ - strDefaultVal = DatumGetCString(DirectFunctionCall1(textout, - textDefaultVal)); + /* Convert Datum to a Node */ + expr = stringToNode(DatumGetCString( + DirectFunctionCall1(textout, datum))); - /* Convert C string to a value of the given type */ - *defaultValue = OidFunctionCall3(typinput, - CStringGetDatum(strDefaultVal), - ObjectIdGetDatum(typelem), - Int32GetDatum(-1)); - pfree(strDefaultVal); - ReleaseSysCache(typeTuple); + /* + * Ensure we goto the basetype before the domain type. + * + * Prevents scenarios like the below from failing: + * CREATE DOMAIN dom text DEFAULT random(); + * + */ + if (typbasetype != InvalidOid) { + expr = coerce_type(NULL, expr, typid, + typbasetype, atttypmod); + } - return true; + + return expr; } /* diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 233689c22d72788ac5d5e51acce7bb1f43bad2a2..9997b25db1208cb7c32351f2812b499cae1c394b 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.154 2002/03/06 06:10:21 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.155 2002/03/06 20:34:54 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -512,8 +512,12 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, (char *) attp, ATTRIBUTE_TUPLE_SIZE); - /* Update constraint/default info */ - if (attp->attnotnull) + + + /* + * Update constraint/default info + */ + if (attp->attnotnull) constr->has_not_null = true; if (attp->atthasdef) diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index c68a5d4b50a9d00b8f1c8edcc4f00aa61c1f1aab..79c9e0b23a78f45b98f761693e57d44d4741a98b 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: heap.h,v 1.41 2001/11/05 17:46:31 momjian Exp $ + * $Id: heap.h,v 1.42 2002/03/06 20:34:55 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -15,6 +15,8 @@ #define HEAP_H #include "catalog/pg_attribute.h" +#include "nodes/parsenodes.h" +#include "parser/parse_node.h" #include "utils/rel.h" typedef struct RawColumnDefault @@ -45,6 +47,12 @@ extern void AddRelationRawConstraints(Relation rel, List *rawColDefaults, List *rawConstraints); +extern Node *cookDefault(ParseState *pstate + , Node *raw_default + , Oid atttypid + , int32 atttypmod + , char *attname); + extern int RemoveCheckConstraint(Relation rel, const char *constrName, bool inh); extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno, diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h index 43f806188e68593b77ff52d0b2481c170b49c2b3..e8d59f3ed2463a68faccc0083e4e074d2b75c3bb 100644 --- a/src/include/catalog/pg_attribute.h +++ b/src/include/catalog/pg_attribute.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_attribute.h,v 1.81 2002/03/01 22:45:16 petere Exp $ + * $Id: pg_attribute.h,v 1.82 2002/03/06 20:34:56 momjian Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -240,7 +240,13 @@ typedef FormData_pg_attribute *Form_pg_attribute; { 1247, {"typsend"}, 24, 0, 4, 14, 0, -1, -1, true, 'p', false, 'i', false, false }, \ { 1247, {"typalign"}, 18, 0, 1, 15, 0, -1, -1, true, 'p', false, 'c', false, false }, \ { 1247, {"typstorage"}, 18, 0, 1, 16, 0, -1, -1, true, 'p', false, 'c', false, false }, \ -{ 1247, {"typdefault"}, 25, 0, -1, 17, 0, -1, -1, false , 'x', false, 'i', false, false } +{ 1247, {"typnotnull"}, 16, 0, 1, 17, 0, -1, -1, true, 'p', false, 'c', false, false }, \ +{ 1247, {"typmod"}, 23, 0, 4, 18, 0, -1, -1, true, 'p', false, 'i', false, false }, \ +{ 1247, {"typbasetype"}, 26, 0, 4, 19, 0, -1, -1, true, 'p', false, 'i', false, false }, \ +{ 1247, {"typndims"}, 23, 0, 4, 20, 0, -1, -1, true, 'p', false, 'i', false, false }, \ +{ 1247, {"typdefaultbin"}, 25, 0, -1, 21, 0, -1, -1, false, 'x', false, 'i', false, false }, \ +{ 1247, {"typdefault"}, 25, 0, -1, 22, 0, -1, -1, false, 'x', false, 'i', false, false } + DATA(insert ( 1247 typname 19 DEFAULT_ATTSTATTARGET NAMEDATALEN 1 0 -1 -1 f p f i f f)); DATA(insert ( 1247 typowner 23 0 4 2 0 -1 -1 t p f i f f)); @@ -258,7 +264,12 @@ DATA(insert ( 1247 typreceive 24 0 4 13 0 -1 -1 t p f i f f)); DATA(insert ( 1247 typsend 24 0 4 14 0 -1 -1 t p f i f f)); DATA(insert ( 1247 typalign 18 0 1 15 0 -1 -1 t p f c f f)); DATA(insert ( 1247 typstorage 18 0 1 16 0 -1 -1 t p f c f f)); -DATA(insert ( 1247 typdefault 25 0 -1 17 0 -1 -1 f x f i f f)); +DATA(insert ( 1247 typnotnull 16 0 1 17 0 -1 -1 t p f c f f)); +DATA(insert ( 1247 typmod 23 0 4 18 0 -1 -1 t p f i f f)); +DATA(insert ( 1247 typbasetype 26 0 4 19 0 -1 -1 t p f i f f)); +DATA(insert ( 1247 typndims 23 0 4 20 0 -1 -1 t p f i f f)); +DATA(insert ( 1247 typdefaultbin 25 0 -1 21 0 -1 -1 f x f i f f)); +DATA(insert ( 1247 typdefault 25 0 -1 22 0 -1 -1 f x f i f f)); DATA(insert ( 1247 ctid 27 0 6 -1 0 -1 -1 f p f i f f)); DATA(insert ( 1247 oid 26 0 4 -2 0 -1 -1 t p f i f f)); DATA(insert ( 1247 xmin 28 0 4 -3 0 -1 -1 t p f i f f)); diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h index 2a4bc84a363834e7bb7dc63011f7e9b0281335ca..ffe7285c3cd37be558cecd0e2e0a89b601b44124 100644 --- a/src/include/catalog/pg_class.h +++ b/src/include/catalog/pg_class.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_class.h,v 1.59 2002/03/01 22:45:17 petere Exp $ + * $Id: pg_class.h,v 1.60 2002/03/06 20:34:56 momjian Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -132,7 +132,7 @@ typedef FormData_pg_class *Form_pg_class; * ---------------- */ -DATA(insert OID = 1247 ( pg_type 71 PGUID 0 1247 0 0 0 0 f f r 17 0 0 0 0 0 t f f f _null_ )); +DATA(insert OID = 1247 ( pg_type 71 PGUID 0 1247 0 0 0 0 f f r 22 0 0 0 0 0 t f f f _null_ )); DESCR(""); DATA(insert OID = 1249 ( pg_attribute 75 PGUID 0 1249 0 0 0 0 f f r 15 0 0 0 0 0 f f f f _null_ )); DESCR(""); diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h index 83b7d1bcc46cd953b12bf8427f6017cf28b1c15d..2fa15e3c38fc5922408d70be9a31c80094af3ce4 100644 --- a/src/include/catalog/pg_type.h +++ b/src/include/catalog/pg_type.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pg_type.h,v 1.114 2001/11/05 17:46:33 momjian Exp $ + * $Id: pg_type.h,v 1.115 2002/03/06 20:34:57 momjian Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -140,13 +140,50 @@ CATALOG(pg_type) BOOTSTRAP */ char typstorage; + /* + * This flag represents a "NOT NULL" constraint against this datatype. + * + * If true, the attnotnull column for a corresponding table column using + * this datatype will always enforce the NOT NULL constraint. + * + * Used primarily for domain types. + */ + bool typnotnull; + + /* + * typmod records type-specific data supplied at domain creation + * time (for example, the max length of a varchar field). It is + * passed to type-specific input and output functions as the third + * argument. The value will generally be -1 for types that do not need + * typmod. This value is copied to pg_attribute.atttypmod. + */ + int4 typmod; + + /* + * Domains use typbasetype to determine the base (or complex)type that + * the domain is based off. It must be non-zero if the type is a + * domain. + */ + Oid typbasetype; + + /* + * typndims is the declared number of dimensions, if an array typbasetype, + * otherwise zero. + */ + int4 typndims; + + /* + * typdefaultbin is the binary representation of typdefault + */ + text typdefaultbin; /* VARIABLE LENGTH FIELD */ + /* * typdefault is NULL if the type has no associated default value. If * it's not NULL, it contains the external representation of the - * type's default value --- this default is used whenever no - * per-column default is specified for a column of the datatype. + * type's default value */ text typdefault; /* VARIABLE LENGTH FIELD */ + } FormData_pg_type; /* ---------------- @@ -160,7 +197,7 @@ typedef FormData_pg_type *Form_pg_type; * compiler constants for pg_type * ---------------- */ -#define Natts_pg_type 17 +#define Natts_pg_type 22 #define Anum_pg_type_typname 1 #define Anum_pg_type_typowner 2 #define Anum_pg_type_typlen 3 @@ -177,7 +214,13 @@ typedef FormData_pg_type *Form_pg_type; #define Anum_pg_type_typsend 14 #define Anum_pg_type_typalign 15 #define Anum_pg_type_typstorage 16 -#define Anum_pg_type_typdefault 17 +#define Anum_pg_type_typnotnull 17 +#define Anum_pg_type_typmod 18 +#define Anum_pg_type_typbasetype 19 +#define Anum_pg_type_typndims 20 +#define Anum_pg_type_typdefaultbin 21 +#define Anum_pg_type_typdefault 22 + /* ---------------- * initial contents of pg_type @@ -192,82 +235,82 @@ typedef FormData_pg_type *Form_pg_type; */ /* OIDS 1 - 99 */ -DATA(insert OID = 16 ( bool PGUID 1 1 t b t \054 0 0 boolin boolout boolin boolout c p _null_ )); +DATA(insert OID = 16 ( bool PGUID 1 1 t b t \054 0 0 boolin boolout boolin boolout c p f -1 0 0 _null_ _null_ )); DESCR("boolean, 'true'/'false'"); #define BOOLOID 16 -DATA(insert OID = 17 ( bytea PGUID -1 -1 f b t \054 0 0 byteain byteaout byteain byteaout i x _null_ )); +DATA(insert OID = 17 ( bytea PGUID -1 -1 f b t \054 0 0 byteain byteaout byteain byteaout i x f -1 0 0 _null_ _null_ )); DESCR("variable-length string, binary values escaped"); #define BYTEAOID 17 -DATA(insert OID = 18 ( char PGUID 1 1 t b t \054 0 0 charin charout charin charout c p _null_ )); +DATA(insert OID = 18 ( char PGUID 1 1 t b t \054 0 0 charin charout charin charout c p f -1 0 0 _null_ _null_ )); DESCR("single character"); #define CHAROID 18 -DATA(insert OID = 19 ( name PGUID NAMEDATALEN NAMEDATALEN f b t \054 0 18 namein nameout namein nameout i p _null_ )); +DATA(insert OID = 19 ( name PGUID NAMEDATALEN NAMEDATALEN f b t \054 0 18 namein nameout namein nameout i p f -1 0 0 _null_ _null_ )); DESCR("31-character type for storing system identifiers"); #define NAMEOID 19 -DATA(insert OID = 20 ( int8 PGUID 8 20 f b t \054 0 0 int8in int8out int8in int8out d p _null_ )); +DATA(insert OID = 20 ( int8 PGUID 8 20 f b t \054 0 0 int8in int8out int8in int8out d p f -1 0 0 _null_ _null_ )); DESCR("~18 digit integer, 8-byte storage"); #define INT8OID 20 -DATA(insert OID = 21 ( int2 PGUID 2 5 t b t \054 0 0 int2in int2out int2in int2out s p _null_ )); +DATA(insert OID = 21 ( int2 PGUID 2 5 t b t \054 0 0 int2in int2out int2in int2out s p f -1 0 0 _null_ _null_ )); DESCR("-32 thousand to 32 thousand, 2-byte storage"); #define INT2OID 21 -DATA(insert OID = 22 ( int2vector PGUID INDEX_MAX_KEYS*2 -1 f b t \054 0 21 int2vectorin int2vectorout int2vectorin int2vectorout i p _null_ )); +DATA(insert OID = 22 ( int2vector PGUID INDEX_MAX_KEYS*2 -1 f b t \054 0 21 int2vectorin int2vectorout int2vectorin int2vectorout i p f -1 0 0 _null_ _null_ )); DESCR("array of INDEX_MAX_KEYS int2 integers, used in system tables"); #define INT2VECTOROID 22 -DATA(insert OID = 23 ( int4 PGUID 4 10 t b t \054 0 0 int4in int4out int4in int4out i p _null_ )); +DATA(insert OID = 23 ( int4 PGUID 4 10 t b t \054 0 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ )); DESCR("-2 billion to 2 billion integer, 4-byte storage"); #define INT4OID 23 -DATA(insert OID = 24 ( regproc PGUID 4 16 t b t \054 0 0 regprocin regprocout regprocin regprocout i p _null_ )); +DATA(insert OID = 24 ( regproc PGUID 4 16 t b t \054 0 0 regprocin regprocout regprocin regprocout i p f -1 0 0 _null_ _null_ )); DESCR("registered procedure"); #define REGPROCOID 24 -DATA(insert OID = 25 ( text PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x _null_ )); +DATA(insert OID = 25 ( text PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x f -1 0 0 _null_ _null_ )); DESCR("variable-length string, no limit specified"); #define TEXTOID 25 -DATA(insert OID = 26 ( oid PGUID 4 10 t b t \054 0 0 oidin oidout oidin oidout i p _null_ )); +DATA(insert OID = 26 ( oid PGUID 4 10 t b t \054 0 0 oidin oidout oidin oidout i p f -1 0 0 _null_ _null_ )); DESCR("object identifier(oid), maximum 4 billion"); #define OIDOID 26 -DATA(insert OID = 27 ( tid PGUID 6 19 f b t \054 0 0 tidin tidout tidin tidout i p _null_ )); +DATA(insert OID = 27 ( tid PGUID 6 19 f b t \054 0 0 tidin tidout tidin tidout i p f -1 0 0 _null_ _null_ )); DESCR("(Block, offset), physical location of tuple"); #define TIDOID 27 -DATA(insert OID = 28 ( xid PGUID 4 12 t b t \054 0 0 xidin xidout xidin xidout i p _null_ )); +DATA(insert OID = 28 ( xid PGUID 4 12 t b t \054 0 0 xidin xidout xidin xidout i p f -1 0 0 _null_ _null_ )); DESCR("transaction id"); #define XIDOID 28 -DATA(insert OID = 29 ( cid PGUID 4 10 t b t \054 0 0 cidin cidout cidin cidout i p _null_ )); +DATA(insert OID = 29 ( cid PGUID 4 10 t b t \054 0 0 cidin cidout cidin cidout i p f -1 0 0 _null_ _null_ )); DESCR("command identifier type, sequence in transaction id"); #define CIDOID 29 -DATA(insert OID = 30 ( oidvector PGUID INDEX_MAX_KEYS*4 -1 f b t \054 0 26 oidvectorin oidvectorout oidvectorin oidvectorout i p _null_ )); +DATA(insert OID = 30 ( oidvector PGUID INDEX_MAX_KEYS*4 -1 f b t \054 0 26 oidvectorin oidvectorout oidvectorin oidvectorout i p f -1 0 0 _null_ _null_ )); DESCR("array of INDEX_MAX_KEYS oids, used in system tables"); #define OIDVECTOROID 30 -DATA(insert OID = 32 ( SET PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p _null_ )); +DATA(insert OID = 32 ( SET PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p f -1 0 0 _null_ _null_ )); DESCR("set of tuples"); -DATA(insert OID = 71 ( pg_type PGUID 4 4 t c t \054 1247 0 int4in int4out int4in int4out i p _null_)); -DATA(insert OID = 75 ( pg_attribute PGUID 4 4 t c t \054 1249 0 int4in int4out int4in int4out i p _null_)); -DATA(insert OID = 81 ( pg_proc PGUID 4 4 t c t \054 1255 0 int4in int4out int4in int4out i p _null_)); -DATA(insert OID = 83 ( pg_class PGUID 4 4 t c t \054 1259 0 int4in int4out int4in int4out i p _null_)); -DATA(insert OID = 86 ( pg_shadow PGUID 4 4 t c t \054 1260 0 int4in int4out int4in int4out i p _null_)); -DATA(insert OID = 87 ( pg_group PGUID 4 4 t c t \054 1261 0 int4in int4out int4in int4out i p _null_)); -DATA(insert OID = 88 ( pg_database PGUID 4 4 t c t \054 1262 0 int4in int4out int4in int4out i p _null_)); +DATA(insert OID = 71 ( pg_type PGUID 4 4 t c t \054 1247 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 75 ( pg_attribute PGUID 4 4 t c t \054 1249 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 81 ( pg_proc PGUID 4 4 t c t \054 1255 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 83 ( pg_class PGUID 4 4 t c t \054 1259 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 86 ( pg_shadow PGUID 4 4 t c t \054 1260 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 87 ( pg_group PGUID 4 4 t c t \054 1261 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ )); +DATA(insert OID = 88 ( pg_database PGUID 4 4 t c t \054 1262 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ )); /* OIDS 100 - 199 */ /* OIDS 200 - 299 */ -DATA(insert OID = 210 ( smgr PGUID 2 12 t b t \054 0 0 smgrin smgrout smgrin smgrout s p _null_ )); +DATA(insert OID = 210 ( smgr PGUID 2 12 t b t \054 0 0 smgrin smgrout smgrin smgrout s p f -1 0 0 _null_ _null_ )); DESCR("storage manager"); /* OIDS 300 - 399 */ @@ -277,167 +320,167 @@ DESCR("storage manager"); /* OIDS 500 - 599 */ /* OIDS 600 - 699 */ -DATA(insert OID = 600 ( point PGUID 16 24 f b t \054 0 701 point_in point_out point_in point_out d p _null_ )); +DATA(insert OID = 600 ( point PGUID 16 24 f b t \054 0 701 point_in point_out point_in point_out d p f -1 0 0 _null_ _null_ )); DESCR("geometric point '(x, y)'"); #define POINTOID 600 -DATA(insert OID = 601 ( lseg PGUID 32 48 f b t \054 0 600 lseg_in lseg_out lseg_in lseg_out d p _null_ )); +DATA(insert OID = 601 ( lseg PGUID 32 48 f b t \054 0 600 lseg_in lseg_out lseg_in lseg_out d p f -1 0 0 _null_ _null_ )); DESCR("geometric line segment '(pt1,pt2)'"); #define LSEGOID 601 -DATA(insert OID = 602 ( path PGUID -1 -1 f b t \054 0 0 path_in path_out path_in path_out d x _null_ )); +DATA(insert OID = 602 ( path PGUID -1 -1 f b t \054 0 0 path_in path_out path_in path_out d x f -1 0 0 _null_ _null_ )); DESCR("geometric path '(pt1,...)'"); #define PATHOID 602 -DATA(insert OID = 603 ( box PGUID 32 100 f b t \073 0 600 box_in box_out box_in box_out d p _null_ )); +DATA(insert OID = 603 ( box PGUID 32 100 f b t \073 0 600 box_in box_out box_in box_out d p f -1 0 0 _null_ _null_ )); DESCR("geometric box '(lower left,upper right)'"); #define BOXOID 603 -DATA(insert OID = 604 ( polygon PGUID -1 -1 f b t \054 0 0 poly_in poly_out poly_in poly_out d x _null_ )); +DATA(insert OID = 604 ( polygon PGUID -1 -1 f b t \054 0 0 poly_in poly_out poly_in poly_out d x f -1 0 0 _null_ _null_ )); DESCR("geometric polygon '(pt1,...)'"); #define POLYGONOID 604 -DATA(insert OID = 628 ( line PGUID 32 48 f b t \054 0 701 line_in line_out line_in line_out d p _null_ )); +DATA(insert OID = 628 ( line PGUID 32 48 f b t \054 0 701 line_in line_out line_in line_out d p f -1 0 0 _null_ _null_ )); DESCR("geometric line '(pt1,pt2)'"); #define LINEOID 628 -DATA(insert OID = 629 ( _line PGUID -1 -1 f b t \054 0 628 array_in array_out array_in array_out d x _null_ )); +DATA(insert OID = 629 ( _line PGUID -1 -1 f b t \054 0 628 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); DESCR(""); /* OIDS 700 - 799 */ -DATA(insert OID = 700 ( float4 PGUID 4 12 f b t \054 0 0 float4in float4out float4in float4out i p _null_ )); +DATA(insert OID = 700 ( float4 PGUID 4 12 f b t \054 0 0 float4in float4out float4in float4out i p f -1 0 0 _null_ _null_ )); DESCR("single-precision floating point number, 4-byte storage"); #define FLOAT4OID 700 -DATA(insert OID = 701 ( float8 PGUID 8 24 f b t \054 0 0 float8in float8out float8in float8out d p _null_ )); +DATA(insert OID = 701 ( float8 PGUID 8 24 f b t \054 0 0 float8in float8out float8in float8out d p f -1 0 0 _null_ _null_ )); DESCR("double-precision floating point number, 8-byte storage"); #define FLOAT8OID 701 -DATA(insert OID = 702 ( abstime PGUID 4 20 t b t \054 0 0 nabstimein nabstimeout nabstimein nabstimeout i p _null_ )); +DATA(insert OID = 702 ( abstime PGUID 4 20 t b t \054 0 0 nabstimein nabstimeout nabstimein nabstimeout i p f -1 0 0 _null_ _null_ )); DESCR("absolute, limited-range date and time (Unix system time)"); #define ABSTIMEOID 702 -DATA(insert OID = 703 ( reltime PGUID 4 20 t b t \054 0 0 reltimein reltimeout reltimein reltimeout i p _null_ )); +DATA(insert OID = 703 ( reltime PGUID 4 20 t b t \054 0 0 reltimein reltimeout reltimein reltimeout i p f -1 0 0 _null_ _null_ )); DESCR("relative, limited-range time interval (Unix delta time)"); #define RELTIMEOID 703 -DATA(insert OID = 704 ( tinterval PGUID 12 47 f b t \054 0 0 tintervalin tintervalout tintervalin tintervalout i p _null_ )); +DATA(insert OID = 704 ( tinterval PGUID 12 47 f b t \054 0 0 tintervalin tintervalout tintervalin tintervalout i p f -1 0 0 _null_ _null_ )); DESCR("(abstime,abstime), time interval"); #define TINTERVALOID 704 -DATA(insert OID = 705 ( unknown PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p _null_ )); +DATA(insert OID = 705 ( unknown PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p f -1 0 0 _null_ _null_ )); DESCR(""); #define UNKNOWNOID 705 -DATA(insert OID = 718 ( circle PGUID 24 47 f b t \054 0 0 circle_in circle_out circle_in circle_out d p _null_ )); +DATA(insert OID = 718 ( circle PGUID 24 47 f b t \054 0 0 circle_in circle_out circle_in circle_out d p f -1 0 0 _null_ _null_ )); DESCR("geometric circle '(center,radius)'"); #define CIRCLEOID 718 -DATA(insert OID = 719 ( _circle PGUID -1 -1 f b t \054 0 718 array_in array_out array_in array_out d x _null_ )); -DATA(insert OID = 790 ( money PGUID 4 24 f b t \054 0 0 cash_in cash_out cash_in cash_out i p _null_ )); +DATA(insert OID = 719 ( _circle PGUID -1 -1 f b t \054 0 718 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 790 ( money PGUID 4 24 f b t \054 0 0 cash_in cash_out cash_in cash_out i p f -1 0 0 _null_ _null_ )); DESCR("$d,ddd.cc, money"); #define CASHOID 790 -DATA(insert OID = 791 ( _money PGUID -1 -1 f b t \054 0 790 array_in array_out array_in array_out i x _null_ )); +DATA(insert OID = 791 ( _money PGUID -1 -1 f b t \054 0 790 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); /* OIDS 800 - 899 */ -DATA(insert OID = 829 ( macaddr PGUID 6 -1 f b t \054 0 0 macaddr_in macaddr_out macaddr_in macaddr_out i p _null_ )); +DATA(insert OID = 829 ( macaddr PGUID 6 -1 f b t \054 0 0 macaddr_in macaddr_out macaddr_in macaddr_out i p f -1 0 0 _null_ _null_ )); DESCR("XX:XX:XX:XX:XX:XX, MAC address"); #define MACADDROID 829 -DATA(insert OID = 869 ( inet PGUID -1 -1 f b t \054 0 0 inet_in inet_out inet_in inet_out i p _null_ )); +DATA(insert OID = 869 ( inet PGUID -1 -1 f b t \054 0 0 inet_in inet_out inet_in inet_out i p f -1 0 0 _null_ _null_ )); DESCR("IP address/netmask, host address, netmask optional"); #define INETOID 869 -DATA(insert OID = 650 ( cidr PGUID -1 -1 f b t \054 0 0 cidr_in cidr_out cidr_in cidr_out i p _null_ )); +DATA(insert OID = 650 ( cidr PGUID -1 -1 f b t \054 0 0 cidr_in cidr_out cidr_in cidr_out i p f -1 0 0 _null_ _null_ )); DESCR("network IP address/netmask, network address"); #define CIDROID 650 /* OIDS 900 - 999 */ /* OIDS 1000 - 1099 */ -DATA(insert OID = 1000 ( _bool PGUID -1 -1 f b t \054 0 16 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1001 ( _bytea PGUID -1 -1 f b t \054 0 17 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1002 ( _char PGUID -1 -1 f b t \054 0 18 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1003 ( _name PGUID -1 -1 f b t \054 0 19 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1005 ( _int2 PGUID -1 -1 f b t \054 0 21 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1006 ( _int2vector PGUID -1 -1 f b t \054 0 22 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1007 ( _int4 PGUID -1 -1 f b t \054 0 23 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1008 ( _regproc PGUID -1 -1 f b t \054 0 24 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1009 ( _text PGUID -1 -1 f b t \054 0 25 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1028 ( _oid PGUID -1 -1 f b t \054 0 26 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1010 ( _tid PGUID -1 -1 f b t \054 0 27 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1011 ( _xid PGUID -1 -1 f b t \054 0 28 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1012 ( _cid PGUID -1 -1 f b t \054 0 29 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1013 ( _oidvector PGUID -1 -1 f b t \054 0 30 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1014 ( _bpchar PGUID -1 -1 f b t \054 0 1042 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1015 ( _varchar PGUID -1 -1 f b t \054 0 1043 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1016 ( _int8 PGUID -1 -1 f b t \054 0 20 array_in array_out array_in array_out d x _null_ )); -DATA(insert OID = 1017 ( _point PGUID -1 -1 f b t \054 0 600 array_in array_out array_in array_out d x _null_ )); -DATA(insert OID = 1018 ( _lseg PGUID -1 -1 f b t \054 0 601 array_in array_out array_in array_out d x _null_ )); -DATA(insert OID = 1019 ( _path PGUID -1 -1 f b t \054 0 602 array_in array_out array_in array_out d x _null_ )); -DATA(insert OID = 1020 ( _box PGUID -1 -1 f b t \073 0 603 array_in array_out array_in array_out d x _null_ )); -DATA(insert OID = 1021 ( _float4 PGUID -1 -1 f b t \054 0 700 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1022 ( _float8 PGUID -1 -1 f b t \054 0 701 array_in array_out array_in array_out d x _null_ )); -DATA(insert OID = 1023 ( _abstime PGUID -1 -1 f b t \054 0 702 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1024 ( _reltime PGUID -1 -1 f b t \054 0 703 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1025 ( _tinterval PGUID -1 -1 f b t \054 0 704 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1027 ( _polygon PGUID -1 -1 f b t \054 0 604 array_in array_out array_in array_out d x _null_ )); +DATA(insert OID = 1000 ( _bool PGUID -1 -1 f b t \054 0 16 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1001 ( _bytea PGUID -1 -1 f b t \054 0 17 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1002 ( _char PGUID -1 -1 f b t \054 0 18 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1003 ( _name PGUID -1 -1 f b t \054 0 19 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1005 ( _int2 PGUID -1 -1 f b t \054 0 21 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1006 ( _int2vector PGUID -1 -1 f b t \054 0 22 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1007 ( _int4 PGUID -1 -1 f b t \054 0 23 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1008 ( _regproc PGUID -1 -1 f b t \054 0 24 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1009 ( _text PGUID -1 -1 f b t \054 0 25 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1028 ( _oid PGUID -1 -1 f b t \054 0 26 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1010 ( _tid PGUID -1 -1 f b t \054 0 27 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1011 ( _xid PGUID -1 -1 f b t \054 0 28 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1012 ( _cid PGUID -1 -1 f b t \054 0 29 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1013 ( _oidvector PGUID -1 -1 f b t \054 0 30 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1014 ( _bpchar PGUID -1 -1 f b t \054 0 1042 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1015 ( _varchar PGUID -1 -1 f b t \054 0 1043 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1016 ( _int8 PGUID -1 -1 f b t \054 0 20 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1017 ( _point PGUID -1 -1 f b t \054 0 600 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1018 ( _lseg PGUID -1 -1 f b t \054 0 601 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1019 ( _path PGUID -1 -1 f b t \054 0 602 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1020 ( _box PGUID -1 -1 f b t \073 0 603 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1021 ( _float4 PGUID -1 -1 f b t \054 0 700 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1022 ( _float8 PGUID -1 -1 f b t \054 0 701 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1023 ( _abstime PGUID -1 -1 f b t \054 0 702 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1024 ( _reltime PGUID -1 -1 f b t \054 0 703 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1025 ( _tinterval PGUID -1 -1 f b t \054 0 704 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1027 ( _polygon PGUID -1 -1 f b t \054 0 604 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); /* * Note: the size of aclitem needs to match sizeof(AclItem) in acl.h. * Thanks to some padding, this will be 8 on all platforms. * We also have an Assert to make sure. */ #define ACLITEMSIZE 8 -DATA(insert OID = 1033 ( aclitem PGUID 8 -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i p _null_ )); +DATA(insert OID = 1033 ( aclitem PGUID 8 -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i p f -1 0 0 _null_ _null_ )); DESCR("access control list"); -DATA(insert OID = 1034 ( _aclitem PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1040 ( _macaddr PGUID -1 -1 f b t \054 0 829 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1041 ( _inet PGUID -1 -1 f b t \054 0 869 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 651 ( _cidr PGUID -1 -1 f b t \054 0 650 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1042 ( bpchar PGUID -1 -1 f b t \054 0 0 bpcharin bpcharout bpcharin bpcharout i x _null_ )); +DATA(insert OID = 1034 ( _aclitem PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1040 ( _macaddr PGUID -1 -1 f b t \054 0 829 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1041 ( _inet PGUID -1 -1 f b t \054 0 869 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 651 ( _cidr PGUID -1 -1 f b t \054 0 650 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1042 ( bpchar PGUID -1 -1 f b t \054 0 0 bpcharin bpcharout bpcharin bpcharout i x f -1 0 0 _null_ _null_ )); DESCR("char(length), blank-padded string, fixed storage length"); #define BPCHAROID 1042 -DATA(insert OID = 1043 ( varchar PGUID -1 -1 f b t \054 0 0 varcharin varcharout varcharin varcharout i x _null_ )); +DATA(insert OID = 1043 ( varchar PGUID -1 -1 f b t \054 0 0 varcharin varcharout varcharin varcharout i x f -1 0 0 _null_ _null_ )); DESCR("varchar(length), non-blank-padded string, variable storage length"); #define VARCHAROID 1043 -DATA(insert OID = 1082 ( date PGUID 4 10 t b t \054 0 0 date_in date_out date_in date_out i p _null_ )); +DATA(insert OID = 1082 ( date PGUID 4 10 t b t \054 0 0 date_in date_out date_in date_out i p f -1 0 0 _null_ _null_ )); DESCR("ANSI SQL date"); #define DATEOID 1082 -DATA(insert OID = 1083 ( time PGUID 8 16 f b t \054 0 0 time_in time_out time_in time_out d p _null_ )); +DATA(insert OID = 1083 ( time PGUID 8 16 f b t \054 0 0 time_in time_out time_in time_out d p f -1 0 0 _null_ _null_ )); DESCR("hh:mm:ss, ANSI SQL time"); #define TIMEOID 1083 /* OIDS 1100 - 1199 */ -DATA(insert OID = 1114 ( timestamp PGUID 8 47 f b t \054 0 0 timestamp_in timestamp_out timestamp_in timestamp_out d p _null_ )); +DATA(insert OID = 1114 ( timestamp PGUID 8 47 f b t \054 0 0 timestamp_in timestamp_out timestamp_in timestamp_out d p f -1 0 0 _null_ _null_ )); DESCR("date and time"); #define TIMESTAMPOID 1114 -DATA(insert OID = 1115 ( _timestamp PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x _null_ )); -DATA(insert OID = 1182 ( _date PGUID -1 -1 f b t \054 0 1082 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1183 ( _time PGUID -1 -1 f b t \054 0 1083 array_in array_out array_in array_out d x _null_ )); -DATA(insert OID = 1184 ( timestamptz PGUID 8 47 f b t \054 0 0 timestamptz_in timestamptz_out timestamptz_in timestamptz_out d p _null_ )); +DATA(insert OID = 1115 ( _timestamp PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1182 ( _date PGUID -1 -1 f b t \054 0 1082 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1183 ( _time PGUID -1 -1 f b t \054 0 1083 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1184 ( timestamptz PGUID 8 47 f b t \054 0 0 timestamptz_in timestamptz_out timestamptz_in timestamptz_out d p f -1 0 0 _null_ _null_ )); DESCR("date and time with time zone"); #define TIMESTAMPTZOID 1184 -DATA(insert OID = 1185 ( _timestamptz PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x _null_ )); -DATA(insert OID = 1186 ( interval PGUID 12 47 f b t \054 0 0 interval_in interval_out interval_in interval_out d p _null_ )); +DATA(insert OID = 1185 ( _timestamptz PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1186 ( interval PGUID 12 47 f b t \054 0 0 interval_in interval_out interval_in interval_out d p f -1 0 0 _null_ _null_ )); DESCR("@ <number> <units>, time interval"); #define INTERVALOID 1186 -DATA(insert OID = 1187 ( _interval PGUID -1 -1 f b t \054 0 1186 array_in array_out array_in array_out d x _null_ )); +DATA(insert OID = 1187 ( _interval PGUID -1 -1 f b t \054 0 1186 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); /* OIDS 1200 - 1299 */ -DATA(insert OID = 1231 ( _numeric PGUID -1 -1 f b t \054 0 1700 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1266 ( timetz PGUID 12 22 f b t \054 0 0 timetz_in timetz_out timetz_in timetz_out d p _null_ )); +DATA(insert OID = 1231 ( _numeric PGUID -1 -1 f b t \054 0 1700 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1266 ( timetz PGUID 12 22 f b t \054 0 0 timetz_in timetz_out timetz_in timetz_out d p f -1 0 0 _null_ _null_ )); DESCR("hh:mm:ss, ANSI SQL time"); #define TIMETZOID 1266 -DATA(insert OID = 1270 ( _timetz PGUID -1 -1 f b t \054 0 1266 array_in array_out array_in array_out d x _null_ )); +DATA(insert OID = 1270 ( _timetz PGUID -1 -1 f b t \054 0 1266 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ )); /* OIDS 1500 - 1599 */ -DATA(insert OID = 1560 ( bit PGUID -1 -1 f b t \054 0 0 bit_in bit_out bit_in bit_out i x _null_ )); +DATA(insert OID = 1560 ( bit PGUID -1 -1 f b t \054 0 0 bit_in bit_out bit_in bit_out i x f -1 0 0 _null_ _null_ )); DESCR("fixed-length bit string"); #define BITOID 1560 -DATA(insert OID = 1561 ( _bit PGUID -1 -1 f b t \054 0 1560 array_in array_out array_in array_out i x _null_ )); -DATA(insert OID = 1562 ( varbit PGUID -1 -1 f b t \054 0 0 varbit_in varbit_out varbit_in varbit_out i x _null_ )); +DATA(insert OID = 1561 ( _bit PGUID -1 -1 f b t \054 0 1560 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); +DATA(insert OID = 1562 ( varbit PGUID -1 -1 f b t \054 0 0 varbit_in varbit_out varbit_in varbit_out i x f -1 0 0 _null_ _null_ )); DESCR("variable-length bit string"); #define VARBITOID 1562 -DATA(insert OID = 1563 ( _varbit PGUID -1 -1 f b t \054 0 1562 array_in array_out array_in array_out i x _null_ )); +DATA(insert OID = 1563 ( _varbit PGUID -1 -1 f b t \054 0 1562 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ )); /* OIDS 1600 - 1699 */ /* OIDS 1700 - 1799 */ -DATA(insert OID = 1700 ( numeric PGUID -1 -1 f b t \054 0 0 numeric_in numeric_out numeric_in numeric_out i m _null_ )); +DATA(insert OID = 1700 ( numeric PGUID -1 -1 f b t \054 0 0 numeric_in numeric_out numeric_in numeric_out i m f -1 0 0 _null_ _null_ )); DESCR("numeric(precision, decimal), arbitrary precision number"); #define NUMERICOID 1700 /* OID 1790 */ -DATA(insert OID = 1790 ( refcursor PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x _null_ )); +DATA(insert OID = 1790 ( refcursor PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x f -1 0 0 _null_ _null_ )); DESCR("reference cursor (portal name)"); #define REFCURSOROID 1790 @@ -447,6 +490,7 @@ DESCR("reference cursor (portal name)"); */ extern Oid TypeGet(char *typeName, bool *defined); extern Oid TypeShellMake(char *typeName); + extern Oid TypeCreate(char *typeName, Oid assignedTypeOid, Oid relationOid, @@ -459,10 +503,17 @@ extern Oid TypeCreate(char *typeName, char *receiveProcedure, char *sendProcedure, char *elementTypeName, + char *baseTypeName, char *defaultTypeValue, + char *defaultTypeBin, bool passedByValue, char alignment, - char storage); + char storage, + int32 typeMod, + int32 typNDims, + bool typeNotNull); + + extern void TypeRename(const char *oldTypeName, const char *newTypeName); extern char *makeArrayTypeName(char *typeName); diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h index a69da106b4278e4cab210cd287888843769332cd..00ea79a03b81dfae8bcaf56d7ce450cdcc349c13 100644 --- a/src/include/commands/defrem.h +++ b/src/include/commands/defrem.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: defrem.h,v 1.28 2001/11/05 17:46:33 momjian Exp $ + * $Id: defrem.h,v 1.29 2002/03/06 20:34:59 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -39,10 +39,12 @@ extern void CreateFunction(ProcedureStmt *stmt); extern void DefineOperator(char *name, List *parameters); extern void DefineAggregate(char *name, List *parameters); extern void DefineType(char *name, List *parameters); +extern void DefineDomain(CreateDomainStmt *stmt); /* * prototypes in remove.c */ +extern void RemoveDomain(char *domainName, int behavior); extern void RemoveFunction(char *functionName, List *argTypes); extern void RemoveOperator(char *operatorName, char *typeName1, char *typeName2); diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index 96a89d9df56662f8999654ef6582154b72bad4b4..7c455a4c65c847b3c36d84ffa38a5ec1a60a64b9 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: nodes.h,v 1.98 2002/03/01 22:45:17 petere Exp $ + * $Id: nodes.h,v 1.99 2002/03/06 20:35:00 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -172,6 +172,7 @@ typedef enum NodeTag T_TransactionStmt, T_ViewStmt, T_LoadStmt, + T_CreateDomainStmt, T_CreatedbStmt, T_DropdbStmt, T_VacuumStmt, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index c6b1feb79b95790c1748f2aaaacdca021211c77a..330a3bd35986bd416e3a05b688f334c6dee6f7ba 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.156 2002/03/05 05:33:31 momjian Exp $ + * $Id: parsenodes.h,v 1.157 2002/03/06 20:35:00 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -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 ****************************************************************************/ diff --git a/src/include/parser/parse_coerce.h b/src/include/parser/parse_coerce.h index ce9fb7b558a3e960424dfa151bcdffd7f3f62f5f..c8f1891415b8e56cdd3d78aba847f9518c5fe907 100644 --- a/src/include/parser/parse_coerce.h +++ b/src/include/parser/parse_coerce.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parse_coerce.h,v 1.37 2001/11/05 17:46:34 momjian Exp $ + * $Id: parse_coerce.h,v 1.38 2002/03/06 20:35:01 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -81,5 +81,6 @@ extern Oid select_common_type(List *typeids, const char *context); extern Node *coerce_to_common_type(ParseState *pstate, Node *node, Oid targetTypeId, const char *context); +extern Oid getBaseType(Oid inType); #endif /* PARSE_COERCE_H */ diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index c76c8d53d88030dcd2216c73213bb01c3e932a1b..6454a56a9441d307af5b2356687e7b0bf77f9839 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: lsyscache.h,v 1.40 2002/03/01 04:09:28 tgl Exp $ + * $Id: lsyscache.h,v 1.41 2002/03/06 20:35:02 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -44,7 +44,7 @@ extern int16 get_typlen(Oid typid); extern bool get_typbyval(Oid typid); extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval); extern char get_typstorage(Oid typid); -extern bool get_typdefault(Oid typid, Datum *defaultValue); +extern Node *get_typdefault(Oid typid, int32 atttypmod); extern int32 get_typavgwidth(Oid typid, int32 typmod); extern int32 get_attavgwidth(Oid relid, AttrNumber attnum); extern bool get_attstatsslot(HeapTuple statstuple,