Commit 337b22cb authored by Tom Lane's avatar Tom Lane

Code review for DOMAIN patch.

parent 251282d4
<!-- <!--
Documentation of the system catalogs, directed toward PostgreSQL developers Documentation of the system catalogs, directed toward PostgreSQL developers
$Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.34 2002/03/19 02:18:10 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.35 2002/03/20 19:43:24 tgl Exp $
--> -->
<chapter id="catalogs"> <chapter id="catalogs">
...@@ -2274,7 +2274,8 @@ ...@@ -2274,7 +2274,8 @@
This catalog stores information about datatypes. Scalar types This catalog stores information about datatypes. Scalar types
(<quote>base types</>) are created with <command>CREATE TYPE</command>. (<quote>base types</>) are created with <command>CREATE TYPE</command>.
A complex type is also created for each table in the database, to A complex type is also created for each table in the database, to
represent the row structure of the table. represent the row structure of the table. It is also possible to create
derived types with <command>CREATE DOMAIN</command>.
</para> </para>
<table> <table>
...@@ -2345,11 +2346,10 @@ ...@@ -2345,11 +2346,10 @@
<entry></entry> <entry></entry>
<entry> <entry>
<structfield>typtype</structfield> is <literal>b</literal> for <structfield>typtype</structfield> is <literal>b</literal> for
a base type and <literal>c</literal> for a complex type (i.e., a base type, <literal>c</literal> for a complex type (i.e.,
a table's row type). If <structfield>typtype</structfield> is a table's row type), or <literal>d</literal> for a derived type (i.e.,
<literal>c</literal>, <structfield>typrelid</structfield> is a domain). See also <structfield>typrelid</structfield>
the OID of the type's entry in and <structfield>typbasetype</structfield>.
<structname>pg_class</structname>.
</entry> </entry>
</row> </row>
...@@ -2382,6 +2382,7 @@ ...@@ -2382,6 +2382,7 @@
the <structfield>pg_class</structfield> entry that defines the the <structfield>pg_class</structfield> entry that defines the
corresponding table. A table could theoretically be used as a corresponding table. A table could theoretically be used as a
composite data type, but this is not fully functional. composite data type, but this is not fully functional.
Zero for non-complex types.
</entry> </entry>
</row> </row>
...@@ -2511,38 +2512,53 @@ ...@@ -2511,38 +2512,53 @@
</row> </row>
<row> <row>
<entry>typbasetype</entry> <entry>typnotnull</entry>
<entry><type>oid</type></entry> <entry><type>bool</type></entry>
<entry></entry> <entry></entry>
<entry><para> <entry><para>
<structfield>typbasetype</structfield> is the type that this one is based <structfield>typnotnull</structfield> represents a NOT NULL
on. Normally references the domains parent type, and is 0 otherwise. constraint on a type. Presently used for domains only.
</para></entry> </para></entry>
</row> </row>
<row> <row>
<entry>typnotnull</entry> <entry>typbasetype</entry>
<entry><type>boolean</type></entry> <entry><type>oid</type></entry>
<entry></entry> <entry>pg_type.oid</entry>
<entry><para> <entry><para>
<structfield>typnotnull</structfield> represents a NOT NULL If this is a derived type (see <structfield>typtype</structfield>),
constraint on a type. Used for domains only. then <structfield>typbasetype</structfield> identifies
</para></entry> the type that this one is based on. Zero if not a derived type.
</row> </para></entry>
</row>
<row> <row>
<entry>typmod</entry> <entry>typtypmod</entry>
<entry><type>integer</type></entry> <entry><type>int4</type></entry>
<entry></entry> <entry></entry>
<entry><para> <entry><para>
<structfield>typmod</structfield> records type-specific data <structfield>typtypmod</structfield> records type-specific data
supplied at table creation time (for example, the maximum supplied at table creation time (for example, the maximum
length of a <type>varchar</type> column). It is passed to length of a <type>varchar</type> column). It is passed to
type-specific input and output functions as the third type-specific input and output functions as the third
argument. The value will generally be -1 for types that do not argument. The value will generally be -1 for types that do not
need typmod. This data is copied to need typmod. This value is copied to
<structfield>pg_attribute.atttypmod</structfield> on creation <structfield>pg_attribute.atttypmod</structfield> when
of a table using a domain as it's field type. creating a column of a domain type.
</para></entry>
</row>
<row>
<entry>typndims</entry>
<entry><type>int4</type></entry>
<entry></entry>
<entry><para>
<structfield>typndims</structfield> is the number of array dimensions
for a domain that is an array. (The array element type is
typbasetype.) Zero for non-domains and non-array domains.
This value is copied to
<structfield>pg_attribute.attndims</structfield> when
creating a column of a domain type.
</para></entry> </para></entry>
</row> </row>
...@@ -2551,9 +2567,9 @@ ...@@ -2551,9 +2567,9 @@
<entry><type>text</type></entry> <entry><type>text</type></entry>
<entry></entry> <entry></entry>
<entry><para> <entry><para>
<structfield>typdefaultbin</structfield> is NULL for types without a If <structfield>typdefaultbin</> is not NULL, it is the nodeToString
default value. If it's not NULL, it contains the internal string representation of a default expression for the type. Currently this is
representation of the default expression node. only used for domains.
</para></entry> </para></entry>
</row> </row>
...@@ -2562,9 +2578,14 @@ ...@@ -2562,9 +2578,14 @@
<entry><type>text</type></entry> <entry><type>text</type></entry>
<entry></entry> <entry></entry>
<entry><para> <entry><para>
<structfield>typdefault</structfield> is NULL for types without a <structfield>typdefault</> is NULL if the type has no associated
default value. If it's not NULL, it contains the external string default value. If <structfield>typdefaultbin</> is not NULL,
representation of the type's default value. <structfield>typdefault</> must contain a human-readable version of the
default expression represented by <structfield>typdefaultbin</>. If
<structfield>typdefaultbin</> is NULL and <structfield>typdefault</> is
not, then <structfield>typdefault</> is the external representation of
the type's default value, which may be fed to the type's input
converter to produce a constant.
</para></entry> </para></entry>
</row> </row>
</tbody> </tbody>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_domain.sgml,v 1.3 2002/03/19 02:18:13 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_domain.sgml,v 1.4 2002/03/20 19:43:28 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -23,13 +23,14 @@ PostgreSQL documentation ...@@ -23,13 +23,14 @@ PostgreSQL documentation
<date>2002-02-24</date> <date>2002-02-24</date>
</refsynopsisdivinfo> </refsynopsisdivinfo>
<synopsis> <synopsis>
CREATE DOMAIN <replaceable class="parameter">domainname</replaceable> <replaceable class="parameter">data_type</replaceable> [ DEFAULT <replaceable>default_expr</> ] [ <replaceable class="PARAMETER">column_constraint</replaceable> [, ... ] ] CREATE DOMAIN <replaceable class="parameter">domainname</replaceable> [AS] <replaceable class="parameter">data_type</replaceable>
[ DEFAULT <replaceable>default_expr</> ]
[ <replaceable class="PARAMETER">constraint</replaceable> [, ... ] ]
where <replaceable class="PARAMETER">constraint</replaceable> is:
[ CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> ] [ CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> ]
{ NOT NULL | NULL <!-- | UNIQUE | PRIMARY KEY | { NOT NULL | NULL }
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> </synopsis>
<refsect2 id="R2-SQL-CREATEDOMAIN-1"> <refsect2 id="R2-SQL-CREATEDOMAIN-1">
...@@ -67,23 +68,26 @@ CREATE DOMAIN <replaceable class="parameter">domainname</replaceable> <replaceab ...@@ -67,23 +68,26 @@ CREATE DOMAIN <replaceable class="parameter">domainname</replaceable> <replaceab
<replaceable>default_expr</replaceable></literal></term> <replaceable>default_expr</replaceable></literal></term>
<listitem> <listitem>
<para> <para>
The <literal>DEFAULT</> clause assigns a default data value for The <literal>DEFAULT</> clause specifies a default value for
the column whose column definition it appears within. The value columns of the domain data type. The value
is any variable-free expression (subselects and cross-references is any variable-free expression (but subselects are not allowed).
to other columns in the current table are not allowed). The The
data type of the default expression must match the data type of the data type of the default expression must match the data type of the
domain. domain.
</para> </para>
<para> <para>
The default expression will be used in any insert operation that The default expression will be used in any insert operation that
does not specify a value for the domain. If there is no default does not specify a value for the column. If there is no default
for a domain, then the default is NULL. for a domain, then the default is NULL.
</para> </para>
<note> <note>
<para> <para>
The default of a column will be tested before that of the domain. If a default value is specified for a particular column, it
overrides any default associated with the domain. In turn,
the domain default overrides any default value associated with
the underlying data type.
</para> </para>
</note> </note>
</listitem> </listitem>
...@@ -93,7 +97,7 @@ CREATE DOMAIN <replaceable class="parameter">domainname</replaceable> <replaceab ...@@ -93,7 +97,7 @@ CREATE DOMAIN <replaceable class="parameter">domainname</replaceable> <replaceab
<term><literal>CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable></literal></term> <term><literal>CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable></literal></term>
<listitem> <listitem>
<para> <para>
An optional name for a domain. If not specified, An optional name for a constraint. If not specified,
the system generates a name. the system generates a name.
</para> </para>
</listitem> </listitem>
...@@ -103,7 +107,7 @@ CREATE DOMAIN <replaceable class="parameter">domainname</replaceable> <replaceab ...@@ -103,7 +107,7 @@ CREATE DOMAIN <replaceable class="parameter">domainname</replaceable> <replaceab
<term><literal>NOT NULL</></term> <term><literal>NOT NULL</></term>
<listitem> <listitem>
<para> <para>
The column is not allowed to contain NULL values. This is Values of this domain are not allowed to be NULL. This is
equivalent to the column constraint <literal>CHECK (<replaceable equivalent to the column constraint <literal>CHECK (<replaceable
class="PARAMETER">column</replaceable> NOT NULL)</literal>. class="PARAMETER">column</replaceable> NOT NULL)</literal>.
</para> </para>
...@@ -114,7 +118,7 @@ CREATE DOMAIN <replaceable class="parameter">domainname</replaceable> <replaceab ...@@ -114,7 +118,7 @@ CREATE DOMAIN <replaceable class="parameter">domainname</replaceable> <replaceab
<term><literal>NULL</></term> <term><literal>NULL</></term>
<listitem> <listitem>
<para> <para>
The column is allowed to contain NULL values. This is the default. Values of this domain are allowed to be NULL. This is the default.
</para> </para>
<para> <para>
...@@ -175,7 +179,7 @@ CREATE DOMAIN ...@@ -175,7 +179,7 @@ CREATE DOMAIN
Domains are useful for abstracting common fields between tables into Domains are useful for abstracting common fields between tables into
a single location for maintenance. An email address column may be used a single location for maintenance. An email address column may be used
in several tables, all with the same properties. Define a domain and in several tables, all with the same properties. Define a domain and
use that rather than setting up each tables constraints individually. use that rather than setting up each table's constraints individually.
</para> </para>
</refsect1> </refsect1>
...@@ -195,9 +199,9 @@ CREATE TABLE countrylist (id INT4, country country_code); ...@@ -195,9 +199,9 @@ CREATE TABLE countrylist (id INT4, country country_code);
<title>Compatibility</title> <title>Compatibility</title>
<para> <para>
This <command>CREATE DOMAIN</command> command is a SQL99 defines CREATE DOMAIN, but says that the only allowed constraint
<productname>PostgreSQL</productname> extension. CHECK and FOREIGN KEY type is CHECK constraints. CHECK constraints for domains are not yet
constraints are currently unsupported. supported by <productname>PostgreSQL</productname>.
</para> </para>
</refsect1> </refsect1>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_domain.sgml,v 1.3 2002/03/19 02:18:13 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_domain.sgml,v 1.4 2002/03/20 19:43:28 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -23,7 +23,7 @@ PostgreSQL documentation ...@@ -23,7 +23,7 @@ PostgreSQL documentation
<date>1999-07-20</date> <date>1999-07-20</date>
</refsynopsisdivinfo> </refsynopsisdivinfo>
<synopsis> <synopsis>
DROP DOMAIN <replaceable class="PARAMETER">domainname</replaceable> [, ...] DROP DOMAIN <replaceable class="PARAMETER">domainname</replaceable> [, ...] [ CASCADE | RESTRICT ]
</synopsis> </synopsis>
<refsect2 id="R2-SQL-DROPDOMAIN-1"> <refsect2 id="R2-SQL-DROPDOMAIN-1">
...@@ -43,6 +43,25 @@ DROP DOMAIN <replaceable class="PARAMETER">domainname</replaceable> [, ...] ...@@ -43,6 +43,25 @@ DROP DOMAIN <replaceable class="PARAMETER">domainname</replaceable> [, ...]
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><literal>CASCADE</></term>
<listitem>
<para>
Automatically drop objects that depend on the domain. This
behavior is not currently supported.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>RESTRICT</></term>
<listitem>
<para>
Do not drop dependent objects. This is the default.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</para> </para>
</refsect2> </refsect2>
...@@ -117,7 +136,7 @@ ERROR: RemoveDomain: type '<replaceable class="parameter">domainname</replaceab ...@@ -117,7 +136,7 @@ ERROR: RemoveDomain: type '<replaceable class="parameter">domainname</replaceab
To remove the <type>box</type> domain: To remove the <type>box</type> domain:
<programlisting> <programlisting>
DROP DOMAIN box RESTRICT; DROP DOMAIN box;
</programlisting> </programlisting>
</para> </para>
</refsect1> </refsect1>
...@@ -134,9 +153,8 @@ DROP DOMAIN box RESTRICT; ...@@ -134,9 +153,8 @@ DROP DOMAIN box RESTRICT;
<synopsis> <synopsis>
DROP DOMAIN <replaceable>name</replaceable> { CASCADE | RESTRICT } DROP DOMAIN <replaceable>name</replaceable> { CASCADE | RESTRICT }
</synopsis> </synopsis>
<productname>PostgreSQL</productname> enforces the existance of <productname>PostgreSQL</productname> accepts only the RESTRICT
RESTRICT or CASCADE but ignores their enforcement against the option, and currently does not check for existence of dependent objects.
system tables.
</para> </para>
</refsect1> </refsect1>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.64 2002/03/19 02:32:19 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.65 2002/03/20 19:43:30 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -419,21 +419,10 @@ testdb=> ...@@ -419,21 +419,10 @@ testdb=>
<term><literal>\dD</literal> [ <replaceable class="parameter">pattern</replaceable> ]</term> <term><literal>\dD</literal> [ <replaceable class="parameter">pattern</replaceable> ]</term>
<listitem> <listitem>
<para> <para>
Lists all database domains. Lists all available domains (derived types).
</para> If <replaceable class="parameter">pattern</replaceable>
(a regular expression) is specified, only matching domains are shown.
<para>
Descriptions for objects can be generated with the <command>COMMENT ON</command>
<acronym>SQL</acronym> command.
</para>
<note>
<para>
<productname>PostgreSQL</productname> stores the object descriptions in the
pg_description system table.
</para> </para>
</note>
</listitem> </listitem>
</varlistentry> </varlistentry>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.188 2002/03/19 02:58:19 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.189 2002/03/20 19:43:34 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -705,7 +705,7 @@ AddNewRelationType(char *typeName, Oid new_rel_oid, Oid new_type_oid) ...@@ -705,7 +705,7 @@ AddNewRelationType(char *typeName, Oid new_rel_oid, Oid new_type_oid)
true, /* passed by value */ true, /* passed by value */
'i', /* default alignment - same as for OID */ 'i', /* default alignment - same as for OID */
'p', /* Not TOASTable */ 'p', /* Not TOASTable */
-1, /* Type mod length */ -1, /* typmod */
0, /* array dimensions for typBaseType */ 0, /* array dimensions for typBaseType */
false); /* Type NOT NULL */ false); /* Type NOT NULL */
} }
...@@ -1589,10 +1589,7 @@ AddRelationRawConstraints(Relation rel, ...@@ -1589,10 +1589,7 @@ AddRelationRawConstraints(Relation rel,
RangeTblEntry *rte; RangeTblEntry *rte;
int numchecks; int numchecks;
List *listptr; List *listptr;
Node *expr;
/* Probably shouldn't be null by default */
Node *expr = NULL;
/* /*
* Get info about existing constraints. * Get info about existing constraints.
...@@ -1624,17 +1621,11 @@ AddRelationRawConstraints(Relation rel, ...@@ -1624,17 +1621,11 @@ AddRelationRawConstraints(Relation rel,
foreach(listptr, rawColDefaults) foreach(listptr, rawColDefaults)
{ {
RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr); RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr);
Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1]; Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
expr = cookDefault(pstate, colDef->raw_default expr = cookDefault(pstate, colDef->raw_default,
, atp->atttypid, atp->atttypmod atp->atttypid, atp->atttypmod,
, NameStr(atp->attname)); NameStr(atp->attname));
/*
* OK, store it.
*/
StoreAttrDefault(rel, colDef->attnum, nodeToString(expr)); StoreAttrDefault(rel, colDef->attnum, nodeToString(expr));
} }
...@@ -1646,7 +1637,6 @@ AddRelationRawConstraints(Relation rel, ...@@ -1646,7 +1637,6 @@ AddRelationRawConstraints(Relation rel,
{ {
Constraint *cdef = (Constraint *) lfirst(listptr); Constraint *cdef = (Constraint *) lfirst(listptr);
char *ccname; char *ccname;
Node *expr;
if (cdef->contype != CONSTR_CHECK || cdef->raw_expr == NULL) if (cdef->contype != CONSTR_CHECK || cdef->raw_expr == NULL)
continue; continue;
...@@ -1851,17 +1841,21 @@ SetRelationNumChecks(Relation rel, int numchecks) ...@@ -1851,17 +1841,21 @@ SetRelationNumChecks(Relation rel, int numchecks)
* Take a raw default and convert it to a cooked format ready for * Take a raw default and convert it to a cooked format ready for
* storage. * storage.
* *
* Parse state, attypid, attypmod and attname are required for * Parse state should be set up to recognize any vars that might appear
* CoerceTargetExpr() and more importantly transformExpr(). * in the expression. (Even though we plan to reject vars, it's more
* user-friendly to give the correct error message than "unknown var".)
*
* If atttypid is not InvalidOid, check that the expression is coercible
* to the specified type. atttypmod is needed in this case, and attname
* is used in the error message if any.
*/ */
Node * Node *
cookDefault(ParseState *pstate, cookDefault(ParseState *pstate,
Node *raw_default, Node *raw_default,
Oid atttypid, Oid atttypid,
int32 atttypmod, int32 atttypmod,
char *attname) { char *attname)
{
Oid type_id;
Node *expr; Node *expr;
Assert(raw_default != NULL); Assert(raw_default != NULL);
...@@ -1896,22 +1890,20 @@ cookDefault(ParseState *pstate, ...@@ -1896,22 +1890,20 @@ cookDefault(ParseState *pstate,
* will actually do the coercion, to ensure we don't accept an * will actually do the coercion, to ensure we don't accept an
* unusable default expression. * unusable default expression.
*/ */
type_id = exprType(expr); if (OidIsValid(atttypid))
if (type_id != InvalidOid && atttypid != InvalidOid) { {
if (type_id != atttypid) { Oid type_id = exprType(expr);
/* Try coercing to the base type of the domain if available */ if (type_id != atttypid)
{
if (CoerceTargetExpr(pstate, expr, type_id, if (CoerceTargetExpr(pstate, expr, type_id,
getBaseType(atttypid), atttypid, atttypmod) == NULL)
atttypmod) == NULL) {
elog(ERROR, "Column \"%s\" is of type %s" elog(ERROR, "Column \"%s\" is of type %s"
" but default expression is of type %s" " but default expression is of type %s"
"\n\tYou will need to rewrite or cast the expression", "\n\tYou will need to rewrite or cast the expression",
attname, attname,
format_type_be(atttypid), format_type_be(atttypid),
format_type_be(type_id)); format_type_be(type_id));
}
} }
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.40 2001/10/25 05:49:23 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.41 2002/03/20 19:43:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -135,14 +135,13 @@ AggregateCreate(char *aggName, ...@@ -135,14 +135,13 @@ AggregateCreate(char *aggName,
/* /*
* If the transfn is strict and the initval is NULL, make sure input * If the transfn is strict and the initval is NULL, make sure input
* type and transtype are the same (or at least binary- compatible), * type and transtype are the same (or at least binary-compatible),
* so that it's OK to use the first input value as the initial * so that it's OK to use the first input value as the initial
* transValue. * transValue.
*/ */
if (proc->proisstrict && agginitval == NULL) if (proc->proisstrict && agginitval == NULL)
{ {
if (basetype != transtype && if (!IsBinaryCompatible(basetype, transtype))
!IS_BINARY_COMPATIBLE(basetype, transtype))
elog(ERROR, "must not omit initval when transfn is strict and transtype is not compatible with input type"); elog(ERROR, "must not omit initval when transfn is strict and transtype is not compatible with input type");
} }
ReleaseSysCache(tup); ReleaseSysCache(tup);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.65 2002/03/06 06:09:26 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.66 2002/03/20 19:43:36 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -423,7 +423,7 @@ checkretval(Oid rettype, List *queryTreeList) ...@@ -423,7 +423,7 @@ checkretval(Oid rettype, List *queryTreeList)
format_type_be(rettype)); format_type_be(rettype));
restype = ((TargetEntry *) lfirst(tlist))->resdom->restype; restype = ((TargetEntry *) lfirst(tlist))->resdom->restype;
if (restype != rettype && !IS_BINARY_COMPATIBLE(restype, rettype)) if (!IsBinaryCompatible(restype, rettype))
elog(ERROR, "return type mismatch in function: declared to return %s, returns %s", elog(ERROR, "return type mismatch in function: declared to return %s, returns %s",
format_type_be(rettype), format_type_be(restype)); format_type_be(rettype), format_type_be(restype));
...@@ -440,7 +440,7 @@ checkretval(Oid rettype, List *queryTreeList) ...@@ -440,7 +440,7 @@ checkretval(Oid rettype, List *queryTreeList)
if (tlistlen == 1) if (tlistlen == 1)
{ {
restype = ((TargetEntry *) lfirst(tlist))->resdom->restype; restype = ((TargetEntry *) lfirst(tlist))->resdom->restype;
if (restype == rettype || IS_BINARY_COMPATIBLE(restype, rettype)) if (IsBinaryCompatible(restype, rettype))
return; return;
} }
...@@ -470,7 +470,7 @@ checkretval(Oid rettype, List *queryTreeList) ...@@ -470,7 +470,7 @@ checkretval(Oid rettype, List *queryTreeList)
continue; continue;
tletype = exprType(tle->expr); tletype = exprType(tle->expr);
atttype = reln->rd_att->attrs[i]->atttypid; atttype = reln->rd_att->attrs[i]->atttypid;
if (tletype != atttype && !IS_BINARY_COMPATIBLE(tletype, atttype)) if (!IsBinaryCompatible(tletype, atttype))
elog(ERROR, "function declared to return %s returns %s instead of %s at column %d", elog(ERROR, "function declared to return %s returns %s instead of %s at column %d",
format_type_be(rettype), format_type_be(rettype),
format_type_be(tletype), format_type_be(tletype),
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.68 2002/03/19 02:18:14 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.69 2002/03/20 19:43:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -179,13 +179,11 @@ TypeShellMakeWithOpenRelation(Relation pg_type_desc, char *typeName) ...@@ -179,13 +179,11 @@ TypeShellMakeWithOpenRelation(Relation pg_type_desc, char *typeName)
values[i++] = CharGetDatum('i'); /* 15 */ values[i++] = CharGetDatum('i'); /* 15 */
values[i++] = CharGetDatum('p'); /* 16 */ values[i++] = CharGetDatum('p'); /* 16 */
values[i++] = BoolGetDatum(false); /* 17 */ values[i++] = BoolGetDatum(false); /* 17 */
values[i++] = Int32GetDatum(-1); /* 18 */ values[i++] = ObjectIdGetDatum(InvalidOid); /* 18 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 19 */ values[i++] = Int32GetDatum(-1); /* 19 */
values[i++] = Int32GetDatum(0); /* 20 */ values[i++] = Int32GetDatum(0); /* 20 */
values[i++] = DirectFunctionCall1(textin, nulls[i++] = 'n'; /* 21 */
CStringGetDatum(typeName)); /* 21 */ nulls[i++] = 'n'; /* 22 */
values[i++] = DirectFunctionCall1(textin,
CStringGetDatum(typeName)); /* 22 */
/* /*
* create a new type tuple with FormHeapTuple * create a new type tuple with FormHeapTuple
...@@ -288,7 +286,7 @@ TypeCreate(char *typeName, ...@@ -288,7 +286,7 @@ TypeCreate(char *typeName,
char storage, char storage,
int32 typeMod, int32 typeMod,
int32 typNDims, /* Array dimensions for baseTypeName */ int32 typNDims, /* Array dimensions for baseTypeName */
bool typeNotNull) /* binary default representation (cooked) */ bool typeNotNull)
{ {
int i, int i,
j; j;
...@@ -452,21 +450,10 @@ TypeCreate(char *typeName, ...@@ -452,21 +450,10 @@ TypeCreate(char *typeName,
*/ */
values[i++] = CharGetDatum(storage); /* 16 */ values[i++] = CharGetDatum(storage); /* 16 */
/* /* set typnotnull, typbasetype, typtypmod, typndims */
* set the typenotnull value values[i++] = BoolGetDatum(typeNotNull); /* 17 */
*/ values[i++] = ObjectIdGetDatum(baseObjectId); /* 18 */
values[i++] = BoolGetDatum(typeNotNull); /* 17 */ values[i++] = Int32GetDatum(typeMod); /* 19 */
/*
* 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 */ values[i++] = Int32GetDatum(typNDims); /* 20 */
/* /*
...@@ -475,17 +462,17 @@ TypeCreate(char *typeName, ...@@ -475,17 +462,17 @@ TypeCreate(char *typeName,
*/ */
if (defaultTypeBin) if (defaultTypeBin)
values[i] = DirectFunctionCall1(textin, values[i] = DirectFunctionCall1(textin,
CStringGetDatum(defaultTypeBin)); CStringGetDatum(defaultTypeBin));
else else
nulls[i] = 'n'; nulls[i] = 'n';
i++; /* 21 */ i++; /* 21 */
/* /*
* initialize the default value for this type. * initialize the default value for this type.
*/ */
if (defaultTypeValue) if (defaultTypeValue)
values[i] = DirectFunctionCall1(textin, values[i] = DirectFunctionCall1(textin,
CStringGetDatum(defaultTypeValue)); CStringGetDatum(defaultTypeValue));
else else
nulls[i] = 'n'; nulls[i] = 'n';
i++; /* 22 */ i++; /* 22 */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.87 2002/03/19 02:58:19 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.88 2002/03/20 19:43:42 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -42,6 +42,7 @@ static int findAttrByName(const char *attributeName, List *schema); ...@@ -42,6 +42,7 @@ static int findAttrByName(const char *attributeName, List *schema);
static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass); static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
static List *MergeDomainAttributes(List *schema); static List *MergeDomainAttributes(List *schema);
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* DefineRelation * DefineRelation
* Creates a new relation. * Creates a new relation.
...@@ -71,9 +72,9 @@ DefineRelation(CreateStmt *stmt, char relkind) ...@@ -71,9 +72,9 @@ DefineRelation(CreateStmt *stmt, char relkind)
StrNCpy(relname, stmt->relname, NAMEDATALEN); StrNCpy(relname, stmt->relname, NAMEDATALEN);
/* /*
* Inherit domain attributes into the known columns before table inheritance * Merge domain attributes into the known columns before processing table
* applies it's changes otherwise we risk adding double constraints * inheritance. Otherwise we risk adding double constraints to a
* to a domain thats inherited. * domain-type column that's inherited.
*/ */
schema = MergeDomainAttributes(schema); schema = MergeDomainAttributes(schema);
...@@ -273,11 +274,8 @@ TruncateRelation(const char *relname) ...@@ -273,11 +274,8 @@ TruncateRelation(const char *relname)
/* /*
* MergeDomainAttributes * MergeDomainAttributes
* Returns a new table schema with the constraints, types, and other * Returns a new table schema with the constraints, types, and other
* attributes of the domain resolved for fields using the domain as * attributes of domains resolved for fields using a domain as
* their type. * their type.
*
* Defaults are pulled out by the table attribute as required, similar to
* how all types defaults are processed.
*/ */
static List * static List *
MergeDomainAttributes(List *schema) MergeDomainAttributes(List *schema)
...@@ -295,34 +293,25 @@ MergeDomainAttributes(List *schema) ...@@ -295,34 +293,25 @@ MergeDomainAttributes(List *schema)
HeapTuple tuple; HeapTuple tuple;
Form_pg_type typeTup; Form_pg_type typeTup;
tuple = SearchSysCache(TYPENAME, tuple = SearchSysCache(TYPENAME,
CStringGetDatum(coldef->typename->name), CStringGetDatum(coldef->typename->name),
0,0,0); 0,0,0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
elog(ERROR, "MergeDomainAttributes: Type %s does not exist", elog(ERROR, "MergeDomainAttributes: Type %s does not exist",
coldef->typename->name); coldef->typename->name);
typeTup = (Form_pg_type) GETSTRUCT(tuple); 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 */ if (typeTup->typtype == 'd')
coldef->is_not_null |= typeTup->typnotnull; {
/* Force the column to have the correct typmod. */
coldef->typename->typmod = typeTup->typtypmod;
/* XXX more to do here? */
}
/* Enforce the element type in the event the domain is an array /* Enforce type NOT NULL || column definition NOT NULL -> NOT NULL */
* /* Currently only used for domains, but could be valid for all */
* BUG: How do we fill out arrayBounds and attrname from typelem and typNDimms? coldef->is_not_null |= typeTup->typnotnull;
*/
}
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
} }
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.63 2002/03/06 06:09:33 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.64 2002/03/20 19:43:47 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -314,8 +314,7 @@ FuncIndexArgs(IndexInfo *indexInfo, ...@@ -314,8 +314,7 @@ FuncIndexArgs(IndexInfo *indexInfo,
for (i = 0; i < nargs; i++) for (i = 0; i < nargs; i++)
{ {
if (argTypes[i] != true_typeids[i] && if (!IsBinaryCompatible(argTypes[i], true_typeids[i]))
!IS_BINARY_COMPATIBLE(argTypes[i], true_typeids[i]))
func_error("DefineIndex", funcIndex->name, nargs, argTypes, func_error("DefineIndex", funcIndex->name, nargs, argTypes,
"Index function must be binary-compatible with table datatype"); "Index function must be binary-compatible with table datatype");
} }
...@@ -418,8 +417,7 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType, ...@@ -418,8 +417,7 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
opInputType = ((Form_pg_opclass) GETSTRUCT(tuple))->opcintype; opInputType = ((Form_pg_opclass) GETSTRUCT(tuple))->opcintype;
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
if (attrType != opInputType && if (!IsBinaryCompatible(attrType, opInputType))
!IS_BINARY_COMPATIBLE(attrType, opInputType))
elog(ERROR, "operator class \"%s\" does not accept data type %s", elog(ERROR, "operator class \"%s\" does not accept data type %s",
attribute->class, format_type_be(attrType)); attribute->class, format_type_be(attrType));
...@@ -470,7 +468,7 @@ GetDefaultOpClass(Oid attrType, Oid accessMethodId) ...@@ -470,7 +468,7 @@ GetDefaultOpClass(Oid attrType, Oid accessMethodId)
nexact++; nexact++;
exactOid = tuple->t_data->t_oid; exactOid = tuple->t_data->t_oid;
} }
else if (IS_BINARY_COMPATIBLE(opclass->opcintype, attrType)) else if (IsBinaryCompatible(opclass->opcintype, attrType))
{ {
ncompatible++; ncompatible++;
compatibleOid = tuple->t_data->t_oid; compatibleOid = tuple->t_data->t_oid;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.69 2002/03/19 02:18:16 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.70 2002/03/20 19:43:49 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -282,23 +282,18 @@ RemoveType(char *typeName) /* type name to be removed */ ...@@ -282,23 +282,18 @@ RemoveType(char *typeName) /* type name to be removed */
* use it. * use it.
*/ */
void void
RemoveDomain(char *domainName, int behavior) /* domain name to be removed */ RemoveDomain(char *domainName, int behavior)
{ {
Relation relation; Relation relation;
HeapTuple tup; HeapTuple tup;
TupleDesc description;
char typtype; char typtype;
bool isnull;
/* Domains are stored as types. Check for permissions on the type */ /* Domains are stored as types. Check for permissions on the type */
if (!pg_ownercheck(GetUserId(), domainName, TYPENAME)) if (!pg_ownercheck(GetUserId(), domainName, TYPENAME))
elog(ERROR, "RemoveDomain: type '%s': permission denied", elog(ERROR, "RemoveDomain: type '%s': permission denied",
domainName); domainName);
relation = heap_openr(TypeRelationName, RowExclusiveLock); relation = heap_openr(TypeRelationName, RowExclusiveLock);
description = RelationGetDescr(relation);
tup = SearchSysCache(TYPENAME, tup = SearchSysCache(TYPENAME,
PointerGetDatum(domainName), PointerGetDatum(domainName),
...@@ -306,14 +301,11 @@ RemoveDomain(char *domainName, int behavior) /* domain name to be removed */ ...@@ -306,14 +301,11 @@ RemoveDomain(char *domainName, int behavior) /* domain name to be removed */
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
elog(ERROR, "RemoveType: type '%s' does not exist", domainName); elog(ERROR, "RemoveType: type '%s' does not exist", domainName);
/* Check that this is actually a domain */ /* Check that this is actually a domain */
typtype = DatumGetChar(heap_getattr(tup, Anum_pg_type_typtype, description, &isnull)); typtype = ((Form_pg_type) GETSTRUCT(tup))->typtype;
Assert(!isnull);
if (typtype != 'd') { if (typtype != 'd')
elog(ERROR, "%s is not a domain", domainName); elog(ERROR, "%s is not a domain", domainName);
}
/* CASCADE unsupported */ /* CASCADE unsupported */
if (behavior == CASCADE) { if (behavior == CASCADE) {
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.79 2002/03/02 21:39:25 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.80 2002/03/20 19:43:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -896,8 +896,7 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) ...@@ -896,8 +896,7 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
*/ */
Oid inputType = exprType(aggref->target); Oid inputType = exprType(aggref->target);
if (inputType != aggform->aggtranstype && if (!IsBinaryCompatible(inputType, aggform->aggtranstype))
!IS_BINARY_COMPATIBLE(inputType, aggform->aggtranstype))
elog(ERROR, "Aggregate %s needs to have compatible input type and transition type", elog(ERROR, "Aggregate %s needs to have compatible input type and transition type",
aggname); aggname);
} }
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.170 2002/03/19 02:18:16 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.171 2002/03/20 19:43:58 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2026,6 +2026,7 @@ _copyDropStmt(DropStmt *from) ...@@ -2026,6 +2026,7 @@ _copyDropStmt(DropStmt *from)
Node_Copy(from, newnode, names); Node_Copy(from, newnode, names);
newnode->removeType = from->removeType; newnode->removeType = from->removeType;
newnode->behavior = from->behavior;
return newnode; return newnode;
} }
...@@ -2238,7 +2239,6 @@ _copyCreateDomainStmt(CreateDomainStmt *from) ...@@ -2238,7 +2239,6 @@ _copyCreateDomainStmt(CreateDomainStmt *from)
if (from->domainname) if (from->domainname)
newnode->domainname = pstrdup(from->domainname); newnode->domainname = pstrdup(from->domainname);
Node_Copy(from, newnode, typename); Node_Copy(from, newnode, typename);
Node_Copy(from, newnode, constraints); Node_Copy(from, newnode, constraints);
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.118 2002/03/19 02:18:16 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.119 2002/03/20 19:44:01 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -878,6 +878,8 @@ _equalDropStmt(DropStmt *a, DropStmt *b) ...@@ -878,6 +878,8 @@ _equalDropStmt(DropStmt *a, DropStmt *b)
return false; return false;
if (a->removeType != b->removeType) if (a->removeType != b->removeType)
return false; return false;
if (a->behavior != b->behavior)
return false;
return true; return true;
} }
......
...@@ -8,16 +8,7 @@ ...@@ -8,16 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.26 2001/03/22 03:59:32 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/makefuncs.c,v 1.27 2002/03/20 19:44:04 tgl Exp $
*
* NOTES
* Creator functions in POSTGRES 4.2 are generated automatically. Most of
* them are rarely used. Now we don't generate them any more. If you want
* one, you have to write it yourself.
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
* Andrew Yu Oct 20, 1994 file creation
*/ */
#include "postgres.h" #include "postgres.h"
...@@ -184,3 +175,19 @@ makeAttr(char *relname, char *attname) ...@@ -184,3 +175,19 @@ makeAttr(char *relname, char *attname)
return a; return a;
} }
/*
* makeRelabelType -
* creates a RelabelType node
*/
RelabelType *
makeRelabelType(Node *arg, Oid rtype, int32 rtypmod)
{
RelabelType *r = makeNode(RelabelType);
r->arg = arg;
r->resulttype = rtype;
r->resulttypmod = rtypmod;
return r;
}
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.113 2002/03/02 21:39:26 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.114 2002/03/20 19:44:09 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -900,9 +900,9 @@ indexable_operator(Expr *clause, Oid opclass, bool indexkey_on_left) ...@@ -900,9 +900,9 @@ indexable_operator(Expr *clause, Oid opclass, bool indexkey_on_left)
*/ */
if (ltype == indexkeytype && rtype == indexkeytype) if (ltype == indexkeytype && rtype == indexkeytype)
return InvalidOid; /* no chance for a different operator */ return InvalidOid; /* no chance for a different operator */
if (ltype != indexkeytype && !IS_BINARY_COMPATIBLE(ltype, indexkeytype)) if (!IsBinaryCompatible(ltype, indexkeytype))
return InvalidOid; return InvalidOid;
if (rtype != indexkeytype && !IS_BINARY_COMPATIBLE(rtype, indexkeytype)) if (!IsBinaryCompatible(rtype, indexkeytype))
return InvalidOid; return InvalidOid;
/* /*
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.49 2002/03/19 02:18:17 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.50 2002/03/20 19:44:15 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -355,9 +355,9 @@ build_column_default(Relation rel, int attrno) ...@@ -355,9 +355,9 @@ build_column_default(Relation rel, int attrno)
Form_pg_attribute att_tup = rd_att->attrs[attrno - 1]; Form_pg_attribute att_tup = rd_att->attrs[attrno - 1];
Oid atttype = att_tup->atttypid; Oid atttype = att_tup->atttypid;
int32 atttypmod = att_tup->atttypmod; int32 atttypmod = att_tup->atttypmod;
int16 typlen; int16 typlen = att_tup->attlen;
bool typbyval; bool typbyval = att_tup->attbyval;
Node *expr; Node *expr = NULL;
/* /*
* Scan to see if relation has a default for this column. * Scan to see if relation has a default for this column.
...@@ -371,110 +371,86 @@ build_column_default(Relation rel, int attrno) ...@@ -371,110 +371,86 @@ build_column_default(Relation rel, int attrno)
{ {
if (attrno == defval[ndef].adnum) if (attrno == defval[ndef].adnum)
{ {
Oid type_id;
/* /*
* Found it, convert string representation to node tree. * Found it, convert string representation to node tree.
*/ */
expr = stringToNode(defval[ndef].adbin); expr = stringToNode(defval[ndef].adbin);
break;
/*
* Make sure the value is coerced to the target column
* type (might not be right type yet if it's not a
* constant!) This should match the parser's processing of
* non-defaulted expressions --- see
* updateTargetListEntry().
*/
type_id = exprType(expr);
if (type_id != atttype)
{
expr = CoerceTargetExpr(NULL, expr, type_id,
getBaseType(atttype), atttypmod);
/*
* This really shouldn't fail; should have checked the
* default's type when it was created ...
*/
if (expr == 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(att_tup->attname),
format_type_be(atttype),
format_type_be(type_id));
}
/*
* If the column is a fixed-length type, it may need a
* length coercion as well as a type coercion.
*/
expr = coerce_type_typmod(NULL, expr,
atttype, atttypmod);
return expr;
} }
} }
} }
/* if (expr == NULL)
* No per-column default, so look for a default for the type itself.
* If there isn't one, we generate a NULL constant of the correct
* type.
*/
if (att_tup->attisset)
{ {
/* /*
* Set attributes are represented as OIDs no matter what the set * No per-column default, so look for a default for the type itself.
* element type is, and the element type's default is irrelevant
* too.
*/ */
typlen = sizeof(Oid); if (att_tup->attisset)
typbyval = true; {
/*
* Set attributes are represented as OIDs no matter what the set
* element type is, and the element type's default is irrelevant
* too.
*/
typlen = sizeof(Oid);
typbyval = true;
}
else
{
expr = get_typdefault(atttype);
}
}
if (expr == NULL)
{
/*
* No default anywhere, so generate a NULL constant.
*/
expr = (Node *) makeConst(atttype, expr = (Node *) makeConst(atttype,
typlen, typlen,
(Datum) 0, (Datum) 0,
true, true, /* isnull */
typbyval, typbyval,
false, /* not a set */ false, /* not a set */
false); false);
} }
else else
{ {
#ifdef _DROP_COLUMN_HACK__ Oid exprtype;
if (COLUMN_IS_DROPPED(att_tup))
/*
* Make sure the value is coerced to the target column
* type (might not be right type yet if it's not a
* constant!) This should match the parser's processing of
* non-defaulted expressions --- see
* updateTargetListEntry().
*/
exprtype = exprType(expr);
if (exprtype != atttype)
{ {
expr = CoerceTargetExpr(NULL, expr, exprtype,
atttype, atttypmod);
expr = (Node *) makeConst(atttype, /*
typlen, * This really shouldn't fail; should have checked the
(Datum) 0, * default's type when it was created ...
true, */
typbyval, if (expr == NULL)
false, /* not a set */ elog(ERROR, "Column \"%s\" is of type %s"
false); " but default expression is of type %s"
} "\n\tYou will need to rewrite or cast the expression",
else NameStr(att_tup->attname),
#endif /* _DROP_COLUMN_HACK__ */ format_type_be(atttype),
expr = get_typdefault(atttype, atttypmod); format_type_be(exprtype));
if (expr == NULL) {
expr = (Node *) makeConst(atttype,
typlen,
(Datum) 0,
true,
typbyval,
false, /* not a set */
false);
} }
get_typlenbyval(atttype, &typlen, &typbyval);
}
/* /*
* If the column is a fixed-length type, it may need a length coercion * If the column is a fixed-length type, it may need a
* as well as a type coercion, as well as direction to the final type. * length coercion as well as a type coercion.
*/ */
expr = coerce_type_typmod(NULL, expr, expr = coerce_type_typmod(NULL, expr, atttype, atttypmod);
atttype, atttypmod); }
return expr; return expr;
} }
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.293 2002/03/19 12:52:20 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.294 2002/03/20 19:44:21 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -135,8 +135,7 @@ static void doNegateFloat(Value *v); ...@@ -135,8 +135,7 @@ static void doNegateFloat(Value *v);
ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt, ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt,
CopyStmt, CreateAsStmt, CreateDomainStmt, CreateGroupStmt, CreatePLangStmt, CopyStmt, CreateAsStmt, CreateDomainStmt, CreateGroupStmt, CreatePLangStmt,
CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt, CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
CreateUserStmt, CreatedbStmt, CursorStmt, CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt,
DefineStmt, DeleteStmt,
DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt, DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt, DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt, GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
...@@ -151,7 +150,7 @@ static void doNegateFloat(Value *v); ...@@ -151,7 +150,7 @@ static void doNegateFloat(Value *v);
simple_select simple_select
%type <node> alter_column_default %type <node> alter_column_default
%type <ival> drop_behavior %type <ival> drop_behavior, opt_drop_behavior
%type <list> createdb_opt_list, createdb_opt_item %type <list> createdb_opt_list, createdb_opt_item
%type <boolean> opt_equal %type <boolean> opt_equal
...@@ -1181,6 +1180,10 @@ drop_behavior: CASCADE { $$ = CASCADE; } ...@@ -1181,6 +1180,10 @@ drop_behavior: CASCADE { $$ = CASCADE; }
| RESTRICT { $$ = RESTRICT; } | RESTRICT { $$ = RESTRICT; }
; ;
opt_drop_behavior: CASCADE { $$ = CASCADE; }
| RESTRICT { $$ = RESTRICT; }
| /* EMPTY */ { $$ = RESTRICT; /* default */ }
;
/***************************************************************************** /*****************************************************************************
...@@ -2030,22 +2033,13 @@ def_list: def_elem { $$ = makeList1($1); } ...@@ -2030,22 +2033,13 @@ def_list: def_elem { $$ = makeList1($1); }
| def_list ',' def_elem { $$ = lappend($1, $3); } | def_list ',' def_elem { $$ = lappend($1, $3); }
; ;
def_elem: DEFAULT '=' b_expr def_elem: ColLabel '=' def_arg
{
$$ = makeNode(DefElem);
$$->defname = "default";
if (exprIsNullConstant($3))
$$->arg = (Node *)NULL;
else
$$->arg = $3;
}
| ColId '=' def_arg
{ {
$$ = makeNode(DefElem); $$ = makeNode(DefElem);
$$->defname = $1; $$->defname = $1;
$$->arg = (Node *)$3; $$->arg = (Node *)$3;
} }
| ColId | ColLabel
{ {
$$ = makeNode(DefElem); $$ = makeNode(DefElem);
$$->defname = $1; $$->defname = $1;
...@@ -2069,19 +2063,11 @@ def_arg: func_return { $$ = (Node *)$1; } ...@@ -2069,19 +2063,11 @@ def_arg: func_return { $$ = (Node *)$1; }
* *
*****************************************************************************/ *****************************************************************************/
DropStmt: DROP drop_type name_list DropStmt: DROP drop_type name_list opt_drop_behavior
{ {
DropStmt *n = makeNode(DropStmt); DropStmt *n = makeNode(DropStmt);
n->removeType = $2; n->removeType = $2;
n->names = $3; 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; n->behavior = $4;
$$ = (Node *)n; $$ = (Node *)n;
} }
...@@ -2092,7 +2078,8 @@ drop_type: TABLE { $$ = DROP_TABLE; } ...@@ -2092,7 +2078,8 @@ drop_type: TABLE { $$ = DROP_TABLE; }
| VIEW { $$ = DROP_VIEW; } | VIEW { $$ = DROP_VIEW; }
| INDEX { $$ = DROP_INDEX; } | INDEX { $$ = DROP_INDEX; }
| RULE { $$ = DROP_RULE; } | RULE { $$ = DROP_RULE; }
| TYPE_P { $$ = DROP_TYPE_P; } | TYPE_P { $$ = DROP_TYPE; }
| DOMAIN_P { $$ = DROP_DOMAIN; }
; ;
/***************************************************************************** /*****************************************************************************
...@@ -3194,12 +3181,19 @@ createdb_opt_item: LOCATION opt_equal Sconst ...@@ -3194,12 +3181,19 @@ createdb_opt_item: LOCATION opt_equal Sconst
} }
; ;
/*
* Though the equals sign doesn't match other WITH options, pg_dump uses
* equals for backward compability, and it doesn't seem worth remove it.
*/
opt_equal: '=' { $$ = TRUE; }
| /*EMPTY*/ { $$ = FALSE; }
;
/***************************************************************************** /*****************************************************************************
* *
* DROP DATABASE * DROP DATABASE
* *
*
*****************************************************************************/ *****************************************************************************/
DropdbStmt: DROP DATABASE database_name DropdbStmt: DROP DATABASE database_name
...@@ -3210,20 +3204,11 @@ DropdbStmt: DROP DATABASE database_name ...@@ -3210,20 +3204,11 @@ DropdbStmt: DROP DATABASE database_name
} }
; ;
/*
* Though the equals sign doesn't match other WITH options, pg_dump uses
* equals for backward compability, and it doesn't seem worth remove it.
*/
opt_equal: '=' { $$ = TRUE; }
| /*EMPTY*/ { $$ = FALSE; }
;
/***************************************************************************** /*****************************************************************************
* *
* ALTER DATABASE * ALTER DATABASE
* *
*
*****************************************************************************/ *****************************************************************************/
AlterDatabaseSetStmt: ALTER DATABASE database_name VariableSetStmt AlterDatabaseSetStmt: ALTER DATABASE database_name VariableSetStmt
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.109 2002/03/19 02:18:20 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.110 2002/03/20 19:44:25 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1027,8 +1027,7 @@ parser_typecast_expression(ParseState *pstate, ...@@ -1027,8 +1027,7 @@ parser_typecast_expression(ParseState *pstate,
if (inputType != targetType) if (inputType != targetType)
{ {
expr = CoerceTargetExpr(pstate, expr, inputType, expr = CoerceTargetExpr(pstate, expr, inputType,
getBaseType(targetType), targetType, typename->typmod);
typename->typmod);
if (expr == NULL) if (expr == NULL)
elog(ERROR, "Cannot cast type '%s' to '%s'", elog(ERROR, "Cannot cast type '%s' to '%s'",
format_type_be(inputType), format_type_be(inputType),
...@@ -1040,7 +1039,7 @@ parser_typecast_expression(ParseState *pstate, ...@@ -1040,7 +1039,7 @@ parser_typecast_expression(ParseState *pstate,
* as well as a type coercion. * as well as a type coercion.
*/ */
expr = coerce_type_typmod(pstate, expr, expr = coerce_type_typmod(pstate, expr,
getBaseType(targetType), typename->typmod); targetType, typename->typmod);
return expr; return expr;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.117 2002/03/12 00:51:55 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.118 2002/03/20 19:44:29 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -575,8 +575,7 @@ agg_select_candidate(Oid typeid, CandidateList candidates) ...@@ -575,8 +575,7 @@ agg_select_candidate(Oid typeid, CandidateList candidates)
{ {
current_typeid = current_candidate->args[0]; current_typeid = current_candidate->args[0];
if (current_typeid == typeid if (IsBinaryCompatible(current_typeid, typeid))
|| IS_BINARY_COMPATIBLE(current_typeid, typeid))
{ {
last_candidate = current_candidate; last_candidate = current_candidate;
ncandidates++; ncandidates++;
...@@ -815,9 +814,7 @@ func_select_candidate(int nargs, ...@@ -815,9 +814,7 @@ func_select_candidate(int nargs,
{ {
if (input_typeids[i] != UNKNOWNOID) if (input_typeids[i] != UNKNOWNOID)
{ {
if (current_typeids[i] == input_typeids[i] || if (IsBinaryCompatible(current_typeids[i], input_typeids[i]))
IS_BINARY_COMPATIBLE(current_typeids[i],
input_typeids[i]))
nmatch++; nmatch++;
} }
} }
...@@ -1115,8 +1112,7 @@ func_get_detail(char *funcname, ...@@ -1115,8 +1112,7 @@ func_get_detail(char *funcname,
Node *arg1 = lfirst(fargs); Node *arg1 = lfirst(fargs);
if ((sourceType == UNKNOWNOID && IsA(arg1, Const)) || if ((sourceType == UNKNOWNOID && IsA(arg1, Const)) ||
sourceType == targetType || IsBinaryCompatible(sourceType, targetType))
IS_BINARY_COMPATIBLE(sourceType, targetType))
{ {
/* Yup, it's a type coercion */ /* Yup, it's a type coercion */
*funcid = InvalidOid; *funcid = InvalidOid;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.52 2002/02/19 20:11:15 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_oper.c,v 1.53 2002/03/20 19:44:31 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -354,9 +354,7 @@ oper_select_candidate(int nargs, ...@@ -354,9 +354,7 @@ oper_select_candidate(int nargs,
{ {
if (input_typeids[i] != UNKNOWNOID) if (input_typeids[i] != UNKNOWNOID)
{ {
if (current_typeids[i] == input_typeids[i] || if (IsBinaryCompatible(current_typeids[i], input_typeids[i]))
IS_BINARY_COMPATIBLE(current_typeids[i],
input_typeids[i]))
nmatch++; nmatch++;
} }
} }
...@@ -736,10 +734,8 @@ compatible_oper(char *op, Oid arg1, Oid arg2, bool noError) ...@@ -736,10 +734,8 @@ compatible_oper(char *op, Oid arg1, Oid arg2, bool noError)
/* but is it good enough? */ /* but is it good enough? */
opform = (Form_pg_operator) GETSTRUCT(optup); opform = (Form_pg_operator) GETSTRUCT(optup);
if ((opform->oprleft == arg1 || if (IsBinaryCompatible(opform->oprleft, arg1) &&
IS_BINARY_COMPATIBLE(opform->oprleft, arg1)) && IsBinaryCompatible(opform->oprright, arg2))
(opform->oprright == arg2 ||
IS_BINARY_COMPATIBLE(opform->oprright, arg2)))
return optup; return optup;
/* nope... */ /* nope... */
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.134 2002/03/19 02:58:19 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.135 2002/03/20 19:44:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -276,12 +276,12 @@ ProcessUtility(Node *parsetree, ...@@ -276,12 +276,12 @@ ProcessUtility(Node *parsetree,
} }
break; break;
case DROP_TYPE_P: case DROP_TYPE:
/* RemoveType does its own permissions checks */ /* RemoveType does its own permissions checks */
RemoveType(relname); RemoveType(relname);
break; break;
case DROP_DOMAIN_P: case DROP_DOMAIN:
/* RemoveDomain does its own permissions checks */ /* RemoveDomain does its own permissions checks */
RemoveDomain(relname, stmt->behavior); RemoveDomain(relname, stmt->behavior);
break; break;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.27 2002/03/19 02:18:21 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.28 2002/03/20 19:44:40 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -123,10 +123,10 @@ format_type_internal(Oid type_oid, int32 typemod, ...@@ -123,10 +123,10 @@ format_type_internal(Oid type_oid, int32 typemod,
HeapTuple tuple; HeapTuple tuple;
Oid array_base_type; Oid array_base_type;
int16 typlen; int16 typlen;
char typtype;
bool is_array; bool is_array;
char *name; char *name;
char *buf; char *buf;
char typtype;
if (type_oid == InvalidOid && allow_invalid) if (type_oid == InvalidOid && allow_invalid)
return pstrdup("-"); return pstrdup("-");
...@@ -143,34 +143,16 @@ format_type_internal(Oid type_oid, int32 typemod, ...@@ -143,34 +143,16 @@ format_type_internal(Oid type_oid, int32 typemod,
type_oid); type_oid);
} }
/*
* Check if it's an array (and not a domain --- we don't want to show
* the substructure of a domain type). Fixed-length array types such
* as "name" shouldn't get deconstructed either.
*/
array_base_type = ((Form_pg_type) GETSTRUCT(tuple))->typelem; array_base_type = ((Form_pg_type) GETSTRUCT(tuple))->typelem;
typlen = ((Form_pg_type) GETSTRUCT(tuple))->typlen; typlen = ((Form_pg_type) GETSTRUCT(tuple))->typlen;
typtype = ((Form_pg_type) GETSTRUCT(tuple))->typtype; typtype = ((Form_pg_type) GETSTRUCT(tuple))->typtype;
/* if (array_base_type != InvalidOid && typlen < 0 && typtype != 'd')
* 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 */ /* Switch our attention to the array element type */
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.63 2002/03/19 02:18:21 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.64 2002/03/20 19:44:42 tgl Exp $
* *
* NOTES * NOTES
* Eventually, the index information should go through here, too. * Eventually, the index information should go through here, too.
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include "catalog/pg_shadow.h" #include "catalog/pg_shadow.h"
#include "catalog/pg_statistic.h" #include "catalog/pg_statistic.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "parser/parse_coerce.h" #include "nodes/makefuncs.h"
#include "utils/array.h" #include "utils/array.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
...@@ -818,19 +818,19 @@ get_typstorage(Oid typid) ...@@ -818,19 +818,19 @@ get_typstorage(Oid typid)
/* /*
* get_typdefault * get_typdefault
*
* Given a type OID, return the type's default value, if any. * Given a type OID, return the type's default value, if any.
* Returns FALSE if there is no default (effectively, default is NULL). *
* The result points to palloc'd storage for pass-by-reference types. * The result is a palloc'd expression node tree, or NULL if there
* is no defined default for the datatype.
*
* NB: caller should be prepared to coerce result to correct datatype;
* the returned expression tree might produce something of the wrong type.
*/ */
Node * Node *
get_typdefault(Oid typid, int32 atttypmod) get_typdefault(Oid typid)
{ {
HeapTuple typeTuple; HeapTuple typeTuple;
Form_pg_type type; Form_pg_type type;
Oid typinput;
Oid typbasetype;
char typtype;
Datum datum; Datum datum;
bool isNull; bool isNull;
Node *expr; Node *expr;
...@@ -838,48 +838,102 @@ get_typdefault(Oid typid, int32 atttypmod) ...@@ -838,48 +838,102 @@ get_typdefault(Oid typid, int32 atttypmod)
typeTuple = SearchSysCache(TYPEOID, typeTuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typid), ObjectIdGetDatum(typid),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(typeTuple)) if (!HeapTupleIsValid(typeTuple))
elog(ERROR, "get_typdefault: failed to lookup type %u", typid); elog(ERROR, "get_typdefault: failed to lookup type %u", typid);
type = (Form_pg_type) GETSTRUCT(typeTuple); type = (Form_pg_type) GETSTRUCT(typeTuple);
typinput = type->typinput;
typbasetype = type->typbasetype;
typtype = type->typtype;
/* /*
* typdefaultbin is potentially null, so don't try to access it as a * typdefault and typdefaultbin are potentially null, so don't try to
* struct field. Must do it the hard way with SysCacheGetAttr. * access 'em as struct fields. Must do it the hard way with
* SysCacheGetAttr.
*/ */
datum = SysCacheGetAttr(TYPEOID, datum = SysCacheGetAttr(TYPEOID,
typeTuple, typeTuple,
Anum_pg_type_typdefaultbin, Anum_pg_type_typdefaultbin,
&isNull); &isNull);
ReleaseSysCache(typeTuple); if (!isNull)
if (isNull) {
return (Node *) NULL; /* We have an expression default */
expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout,
datum)));
}
else
{
/* Perhaps we have a plain literal default */
datum = SysCacheGetAttr(TYPEOID,
typeTuple,
Anum_pg_type_typdefault,
&isNull);
/* Convert Datum to a Node */ if (!isNull)
expr = stringToNode(DatumGetCString( {
DirectFunctionCall1(textout, datum))); char *strDefaultVal;
/* Convert text datum to C string */
strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
datum));
/* Convert C string to a value of the given type */
datum = OidFunctionCall3(type->typinput,
CStringGetDatum(strDefaultVal),
ObjectIdGetDatum(type->typelem),
Int32GetDatum(-1));
/* Build a Const node containing the value */
expr = (Node *) makeConst(typid,
type->typlen,
datum,
false,
type->typbyval,
false, /* not a set */
false);
pfree(strDefaultVal);
}
else
{
/* No default */
expr = NULL;
}
}
ReleaseSysCache(typeTuple);
return expr;
}
/*
* getBaseType
* If the given type is a domain, return its base type;
* otherwise return the type's own OID.
*/
Oid
getBaseType(Oid typid)
{
/* /*
* Ensure we goto the basetype before the domain type. * We loop to find the bottom base type in a stack of domains.
*
* Prevents scenarios like the below from failing:
* CREATE DOMAIN dom text DEFAULT random();
*
*/ */
if (typbasetype != InvalidOid) { for (;;)
expr = coerce_type(NULL, expr, typid, {
typbasetype, atttypmod); HeapTuple tup;
} Form_pg_type typTup;
tup = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typid),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "getBaseType: failed to lookup type %u", typid);
typTup = (Form_pg_type) GETSTRUCT(tup);
if (typTup->typtype != 'd')
{
/* Not a domain, so done */
ReleaseSysCache(tup);
break;
}
typid = typTup->typbasetype;
ReleaseSysCache(tup);
}
return expr; return typid;
} }
/* /*
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright 2000 by PostgreSQL Global Development Group * Copyright 2000 by PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.46 2002/03/19 02:32:21 momjian Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.47 2002/03/20 19:44:45 tgl Exp $
*/ */
#include "postgres_fe.h" #include "postgres_fe.h"
#include "describe.h" #include "describe.h"
...@@ -1053,7 +1053,7 @@ listDomains(const char *name) ...@@ -1053,7 +1053,7 @@ listDomains(const char *name)
snprintf(buf, sizeof(buf), snprintf(buf, sizeof(buf),
"SELECT t.typname as \"%s\",\n" "SELECT t.typname as \"%s\",\n"
" format_type( t.typbasetype, t.typmod) as \"%s\",\n" " format_type( t.typbasetype, t.typtypmod) as \"%s\",\n"
" CASE WHEN t.typnotnull AND t.typdefault IS NOT NULL THEN 'not null default '||t.typdefault\n" " CASE WHEN t.typnotnull AND t.typdefault IS NOT NULL THEN 'not null default '||t.typdefault\n"
" WHEN t.typnotnull AND t.typdefault IS NULL THEN 'not null'\n" " WHEN t.typnotnull AND t.typdefault IS NULL THEN 'not null'\n"
" WHEN NOT t.typnotnull AND t.typdefault IS NOT NULL THEN 'default '||t.typdefault\n" " WHEN NOT t.typnotnull AND t.typdefault IS NOT NULL THEN 'default '||t.typdefault\n"
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: catversion.h,v 1.106 2002/03/12 00:51:59 tgl Exp $ * $Id: catversion.h,v 1.107 2002/03/20 19:44:48 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200203111 #define CATALOG_VERSION_NO 200203191
#endif #endif
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: heap.h,v 1.45 2002/03/19 02:58:19 momjian Exp $ * $Id: heap.h,v 1.46 2002/03/20 19:44:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -47,11 +47,11 @@ extern void AddRelationRawConstraints(Relation rel, ...@@ -47,11 +47,11 @@ extern void AddRelationRawConstraints(Relation rel,
List *rawColDefaults, List *rawColDefaults,
List *rawConstraints); List *rawConstraints);
extern Node *cookDefault(ParseState *pstate extern Node *cookDefault(ParseState *pstate,
, Node *raw_default Node *raw_default,
, Oid atttypid Oid atttypid,
, int32 atttypmod int32 atttypmod,
, char *attname); char *attname);
extern int RemoveCheckConstraint(Relation rel, const char *constrName, bool inh); extern int RemoveCheckConstraint(Relation rel, const char *constrName, bool inh);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_attribute.h,v 1.84 2002/03/19 02:18:22 momjian Exp $ * $Id: pg_attribute.h,v 1.85 2002/03/20 19:44:55 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -241,8 +241,8 @@ typedef FormData_pg_attribute *Form_pg_attribute; ...@@ -241,8 +241,8 @@ typedef FormData_pg_attribute *Form_pg_attribute;
{ 1247, {"typalign"}, 18, 0, 1, 15, 0, -1, -1, true, 'p', false, 'c', 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, {"typstorage"}, 18, 0, 1, 16, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1247, {"typnotnull"}, 16, 0, 1, 17, 0, -1, -1, true, 'p', false, 'c', 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, 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, {"typtypmod"}, 23, 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, {"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, {"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 } { 1247, {"typdefault"}, 25, 0, -1, 22, 0, -1, -1, false, 'x', false, 'i', false, false }
...@@ -265,8 +265,8 @@ DATA(insert ( 1247 typsend 24 0 4 14 0 -1 -1 t p f i f f)); ...@@ -265,8 +265,8 @@ 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 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 typstorage 18 0 1 16 0 -1 -1 t p f c f f));
DATA(insert ( 1247 typnotnull 16 0 1 17 0 -1 -1 t p f c 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 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 typtypmod 23 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 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 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 typdefault 25 0 -1 22 0 -1 -1 f x f i f f));
......
This diff is collapsed.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: makefuncs.h,v 1.30 2001/11/05 17:46:34 momjian Exp $ * $Id: makefuncs.h,v 1.31 2002/03/20 19:45:01 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -46,4 +46,6 @@ extern Const *makeNullConst(Oid consttype); ...@@ -46,4 +46,6 @@ extern Const *makeNullConst(Oid consttype);
extern Attr *makeAttr(char *relname, char *attname); extern Attr *makeAttr(char *relname, char *attname);
extern RelabelType *makeRelabelType(Node *arg, Oid rtype, int32 rtypmod);
#endif /* MAKEFUNC_H */ #endif /* MAKEFUNC_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: parsenodes.h,v 1.161 2002/03/19 02:18:24 momjian Exp $ * $Id: parsenodes.h,v 1.162 2002/03/20 19:45:02 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -407,23 +407,6 @@ typedef struct DefElem ...@@ -407,23 +407,6 @@ typedef struct DefElem
} 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 * Nodes for a Query tree
****************************************************************************/ ****************************************************************************/
...@@ -1056,11 +1039,23 @@ typedef struct VersionStmt ...@@ -1056,11 +1039,23 @@ typedef struct VersionStmt
typedef struct DefineStmt typedef struct DefineStmt
{ {
NodeTag type; NodeTag type;
int defType; /* OPERATOR|P_TYPE|AGGREGATE */ int defType; /* OPERATOR|TYPE_P|AGGREGATE */
char *defname; char *defname;
List *definition; /* a list of DefElem */ List *definition; /* a list of DefElem */
} DefineStmt; } DefineStmt;
/* ----------------------
* Create Domain Statement
* ----------------------
*/
typedef struct CreateDomainStmt
{
NodeTag type;
char *domainname; /* name of domain to create */
TypeName *typename; /* the base type */
List *constraints; /* constraints (list of Constraint nodes) */
} CreateDomainStmt;
/* ---------------------- /* ----------------------
* Drop Table|Sequence|View|Index|Rule|Type Statement * Drop Table|Sequence|View|Index|Rule|Type Statement
* ---------------------- * ----------------------
...@@ -1071,8 +1066,8 @@ typedef struct DefineStmt ...@@ -1071,8 +1066,8 @@ typedef struct DefineStmt
#define DROP_VIEW 3 #define DROP_VIEW 3
#define DROP_INDEX 4 #define DROP_INDEX 4
#define DROP_RULE 5 #define DROP_RULE 5
#define DROP_TYPE_P 6 #define DROP_TYPE 6
#define DROP_DOMAIN_P 7 #define DROP_DOMAIN 7
typedef struct DropStmt typedef struct DropStmt
{ {
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: parse_coerce.h,v 1.40 2002/03/19 02:18:24 momjian Exp $ * $Id: parse_coerce.h,v 1.41 2002/03/20 19:45:07 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -34,38 +34,7 @@ typedef enum CATEGORY ...@@ -34,38 +34,7 @@ typedef enum CATEGORY
} CATEGORY; } CATEGORY;
/* IS_BINARY_COMPATIBLE() extern bool IsBinaryCompatible(Oid type1, Oid type2);
* Check for types with the same underlying binary representation.
* This allows us to cheat and directly exchange values without
* going through the trouble of calling a conversion function.
*
* Remove equivalencing of FLOAT8 and TIMESTAMP. They really are not
* close enough in behavior, with the TIMESTAMP reserved values
* and special formatting. - thomas 1999-01-24
*/
#define IS_BINARY_COMPATIBLE(a,b) \
(((a) == BPCHAROID && (b) == TEXTOID) \
|| ((a) == BPCHAROID && (b) == VARCHAROID) \
|| ((a) == VARCHAROID && (b) == TEXTOID) \
|| ((a) == VARCHAROID && (b) == BPCHAROID) \
|| ((a) == TEXTOID && (b) == BPCHAROID) \
|| ((a) == TEXTOID && (b) == VARCHAROID) \
|| ((a) == OIDOID && (b) == INT4OID) \
|| ((a) == OIDOID && (b) == REGPROCOID) \
|| ((a) == INT4OID && (b) == OIDOID) \
|| ((a) == INT4OID && (b) == REGPROCOID) \
|| ((a) == REGPROCOID && (b) == OIDOID) \
|| ((a) == REGPROCOID && (b) == INT4OID) \
|| ((a) == ABSTIMEOID && (b) == INT4OID) \
|| ((a) == INT4OID && (b) == ABSTIMEOID) \
|| ((a) == RELTIMEOID && (b) == INT4OID) \
|| ((a) == INT4OID && (b) == RELTIMEOID) \
|| ((a) == INETOID && (b) == CIDROID) \
|| ((a) == CIDROID && (b) == INETOID) \
|| ((a) == BITOID && (b) == VARBITOID) \
|| ((a) == VARBITOID && (b) == BITOID))
extern bool IsPreferredType(CATEGORY category, Oid type); extern bool IsPreferredType(CATEGORY category, Oid type);
extern CATEGORY TypeCategory(Oid type); extern CATEGORY TypeCategory(Oid type);
...@@ -81,6 +50,5 @@ extern Oid select_common_type(List *typeids, const char *context); ...@@ -81,6 +50,5 @@ extern Oid select_common_type(List *typeids, const char *context);
extern Node *coerce_to_common_type(ParseState *pstate, Node *node, extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
Oid targetTypeId, Oid targetTypeId,
const char *context); const char *context);
extern Oid getBaseType(Oid inType);
#endif /* PARSE_COERCE_H */ #endif /* PARSE_COERCE_H */
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: lsyscache.h,v 1.43 2002/03/19 02:18:24 momjian Exp $ * $Id: lsyscache.h,v 1.44 2002/03/20 19:45:09 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -44,7 +44,8 @@ extern int16 get_typlen(Oid typid); ...@@ -44,7 +44,8 @@ extern int16 get_typlen(Oid typid);
extern bool get_typbyval(Oid typid); extern bool get_typbyval(Oid typid);
extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval); extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval);
extern char get_typstorage(Oid typid); extern char get_typstorage(Oid typid);
extern Node *get_typdefault(Oid typid, int32 atttypmod); extern Node *get_typdefault(Oid typid);
extern Oid getBaseType(Oid typid);
extern int32 get_typavgwidth(Oid typid, int32 typmod); extern int32 get_typavgwidth(Oid typid, int32 typmod);
extern int32 get_attavgwidth(Oid relid, AttrNumber attnum); extern int32 get_attavgwidth(Oid relid, AttrNumber attnum);
extern bool get_attstatsslot(HeapTuple statstuple, extern bool get_attstatsslot(HeapTuple statstuple,
......
...@@ -3,9 +3,9 @@ create domain domaindroptest int4; ...@@ -3,9 +3,9 @@ create domain domaindroptest int4;
comment on domain domaindroptest is 'About to drop this..'; comment on domain domaindroptest is 'About to drop this..';
create domain basetypetest domaindroptest; create domain basetypetest domaindroptest;
ERROR: DefineDomain: domaindroptest is not a basetype ERROR: DefineDomain: domaindroptest is not a basetype
drop domain domaindroptest cascade;
ERROR: DROP DOMAIN does not support the CASCADE keyword
drop domain domaindroptest; drop domain domaindroptest;
ERROR: parser: parse error at or near ";"
drop domain domaindroptest restrict;
-- TEST Domains. -- TEST Domains.
create domain domainvarchar varchar(5); create domain domainvarchar varchar(5);
create domain domainnumeric numeric(8,2); create domain domainnumeric numeric(8,2);
...@@ -29,11 +29,21 @@ select * from basictest; ...@@ -29,11 +29,21 @@ select * from basictest;
88 | haha | short | 123.12 88 | haha | short | 123.12
(2 rows) (2 rows)
-- check that domains inherit operations from base types
-- XXX shouldn't have to quote the constant here
select testtext || testvarchar as concat, testnumeric + '42' as sum
from basictest;
concat | sum
-----------+--------
hahashort | 165.12
hahashort | 165.12
(2 rows)
drop table basictest; drop table basictest;
drop domain domainvarchar restrict; drop domain domainvarchar restrict;
drop domain domainnumeric restrict; drop domain domainnumeric restrict;
drop domain domainint4 restrict; drop domain domainint4 restrict;
drop domain domaintext restrict; drop domain domaintext;
-- Array Test -- Array Test
create domain domainint4arr int4[1]; create domain domainint4arr int4[1];
create domain domaintextarr text[2][3]; create domain domaintextarr text[2][3];
...@@ -46,6 +56,26 @@ INSERT INTO domarrtest values ('{{2,2}{2,2}}', '{{"a","b"}}'); ...@@ -46,6 +56,26 @@ INSERT INTO domarrtest values ('{{2,2}{2,2}}', '{{"a","b"}}');
INSERT INTO domarrtest values ('{2,2}', '{{"a","b"}{"c","d"}{"e"}}'); INSERT INTO domarrtest values ('{2,2}', '{{"a","b"}{"c","d"}{"e"}}');
INSERT INTO domarrtest values ('{2,2}', '{{"a"}{"c"}}'); INSERT INTO domarrtest values ('{2,2}', '{{"a"}{"c"}}');
INSERT INTO domarrtest values (NULL, '{{"a","b"}{"c","d","e"}}'); INSERT INTO domarrtest values (NULL, '{{"a","b"}{"c","d","e"}}');
select * from domarrtest;
testint4arr | testtextarr
---------------+---------------------
{2,2} | {{a,c},{"",d}}
{{2,2},{0,2}} | {{a,b}}
{2,2} | {{a},{c},{e}}
{2,2} | {{c},{""}}
| {{a,c,""},{"",d,e}}
(5 rows)
select testint4arr[1], testtextarr[2:2] from domarrtest;
testint4arr | testtextarr
-------------+-------------
2 | {{"",d}}
|
2 | {{c}}
2 | {{""}}
| {{"",d,e}}
(5 rows)
drop table domarrtest; drop table domarrtest;
drop domain domainint4arr restrict; drop domain domainint4arr restrict;
drop domain domaintextarr restrict; drop domain domaintextarr restrict;
......
...@@ -6,8 +6,8 @@ comment on domain domaindroptest is 'About to drop this..'; ...@@ -6,8 +6,8 @@ comment on domain domaindroptest is 'About to drop this..';
create domain basetypetest domaindroptest; create domain basetypetest domaindroptest;
drop domain domaindroptest cascade;
drop domain domaindroptest; drop domain domaindroptest;
drop domain domaindroptest restrict;
-- TEST Domains. -- TEST Domains.
...@@ -31,11 +31,16 @@ INSERT INTO basictest values ('88', 'haha', 'short text', '123.12'); -- Bad varc ...@@ -31,11 +31,16 @@ INSERT INTO basictest values ('88', 'haha', 'short text', '123.12'); -- Bad varc
INSERT INTO basictest values ('88', 'haha', 'short', '123.1212'); -- Truncate numeric INSERT INTO basictest values ('88', 'haha', 'short', '123.1212'); -- Truncate numeric
select * from basictest; select * from basictest;
-- check that domains inherit operations from base types
-- XXX shouldn't have to quote the constant here
select testtext || testvarchar as concat, testnumeric + '42' as sum
from basictest;
drop table basictest; drop table basictest;
drop domain domainvarchar restrict; drop domain domainvarchar restrict;
drop domain domainnumeric restrict; drop domain domainnumeric restrict;
drop domain domainint4 restrict; drop domain domainint4 restrict;
drop domain domaintext restrict; drop domain domaintext;
-- Array Test -- Array Test
...@@ -51,6 +56,8 @@ INSERT INTO domarrtest values ('{{2,2}{2,2}}', '{{"a","b"}}'); ...@@ -51,6 +56,8 @@ INSERT INTO domarrtest values ('{{2,2}{2,2}}', '{{"a","b"}}');
INSERT INTO domarrtest values ('{2,2}', '{{"a","b"}{"c","d"}{"e"}}'); INSERT INTO domarrtest values ('{2,2}', '{{"a","b"}{"c","d"}{"e"}}');
INSERT INTO domarrtest values ('{2,2}', '{{"a"}{"c"}}'); INSERT INTO domarrtest values ('{2,2}', '{{"a"}{"c"}}');
INSERT INTO domarrtest values (NULL, '{{"a","b"}{"c","d","e"}}'); INSERT INTO domarrtest values (NULL, '{{"a","b"}{"c","d","e"}}');
select * from domarrtest;
select testint4arr[1], testtextarr[2:2] from domarrtest;
drop table domarrtest; drop table domarrtest;
drop domain domainint4arr restrict; drop domain domainint4arr restrict;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment