]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
pg_cast table, and standards-compliant CREATE/DROP CAST commands, plus
authorPeter Eisentraut <peter_e@gmx.net>
Thu, 18 Jul 2002 23:11:32 +0000 (23:11 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
Thu, 18 Jul 2002 23:11:32 +0000 (23:11 +0000)
extension to create binary compatible casts.  Includes dependency tracking
as well.

pg_proc.proimplicit is now defunct, but will be removed in a separate
commit.

pg_dump provides a migration path from the previous scheme to declare
casts.  Dumping binary compatible casts is currently impossible, though.

36 files changed:
doc/src/sgml/ref/allfiles.sgml
doc/src/sgml/ref/create_cast.sgml [new file with mode: 0644]
doc/src/sgml/ref/create_function.sgml
doc/src/sgml/ref/drop_cast.sgml [new file with mode: 0644]
doc/src/sgml/reference.sgml
doc/src/sgml/release.sgml
src/backend/catalog/Makefile
src/backend/catalog/dependency.c
src/backend/catalog/indexing.c
src/backend/catalog/pg_aggregate.c
src/backend/catalog/pg_proc.c
src/backend/commands/functioncmds.c
src/backend/parser/gram.y
src/backend/parser/keywords.c
src/backend/parser/parse_coerce.c
src/backend/tcop/postgres.c
src/backend/tcop/utility.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/adt/sets.c
src/backend/utils/cache/syscache.c
src/bin/initdb/initdb.sh
src/bin/pg_dump/common.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dump.h
src/include/catalog/catname.h
src/include/catalog/catversion.h
src/include/catalog/indexing.h
src/include/catalog/pg_cast.h [new file with mode: 0644]
src/include/catalog/pg_proc.h
src/include/commands/defrem.h
src/include/nodes/nodes.h
src/include/nodes/parsenodes.h
src/include/utils/syscache.h
src/test/regress/expected/opr_sanity.out
src/test/regress/expected/sanity_check.out
src/test/regress/sql/opr_sanity.sql

index c9ece5af561b559127569f474f1db22de4416842..55b4fc5c9f096c2703c7b941a33f3007a13ee775 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.40 2002/07/18 16:47:22 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.41 2002/07/18 23:11:27 petere Exp $
 PostgreSQL documentation
 Complete list of usable sgml source files in this directory.
 -->
@@ -51,6 +51,7 @@ Complete list of usable sgml source files in this directory.
 <!entity commit             system "commit.sgml">
 <!entity copyTable          system "copy.sgml">
 <!entity createAggregate    system "create_aggregate.sgml">
+<!entity createCast         system "create_cast.sgml">
 <!entity createConstraint   system "create_constraint.sgml">
 <!entity createDatabase     system "create_database.sgml">
 <!entity createDomain       system "create_domain.sgml">
@@ -71,6 +72,7 @@ Complete list of usable sgml source files in this directory.
 <!entity declare            system "declare.sgml">
 <!entity delete             system "delete.sgml">
 <!entity dropAggregate      system "drop_aggregate.sgml">
+<!entity dropCast           system "drop_cast.sgml">
 <!entity dropDatabase       system "drop_database.sgml">
 <!entity dropDomain         system "drop_domain.sgml">
 <!entity dropFunction       system "drop_function.sgml">
diff --git a/doc/src/sgml/ref/create_cast.sgml b/doc/src/sgml/ref/create_cast.sgml
new file mode 100644 (file)
index 0000000..8125994
--- /dev/null
@@ -0,0 +1,232 @@
+<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_cast.sgml,v 1.1 2002/07/18 23:11:27 petere Exp $ -->
+
+<refentry id="SQL-CREATECAST">
+ <refmeta>
+  <refentrytitle id="SQL-CREATECAST-TITLE">CREATE CAST</refentrytitle>
+  <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+  <refname>CREATE CAST</refname>
+  <refpurpose>define a user-defined cast</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+CREATE CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</replaceable>)
+    WITH FUNCTION <replaceable>funcname</replaceable> (<replaceable>argtype</replaceable>)
+    [AS ASSIGNMENT]
+
+CREATE CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</replaceable>)
+    WITHOUT FUNCTION
+    [AS ASSIGNMENT]
+</synopsis>
+ </refsynopsisdiv>
+  
+ <refsect1 id="sql-createcast-description">
+  <title>Description</title>
+
+  <para>
+   <command>CREATE CAST</command> defines a new cast.  A cast
+   specifies which function can be invoked when a conversion between
+   two data types is requested.  For example,
+<programlisting>
+SELECT CAST(42 AS text);
+</programlisting>
+   converts the integer constant 42 to type <type>text</type> by
+   invoking a previously specified function, in this case
+   <literal>text(int4)</>. (If no suitable cast has been defined, the
+   conversion fails.)
+  </para>
+
+  <para>
+   Two types may be <firstterm>binary compatible</firstterm>, which
+   means that they can be converted into one another <quote>for
+   free</quote> without invoking any function.  This requires that
+   corresponding values use the same internal representation.  For
+   instance, the types <type>text</type> and <type>varchar</type> are
+   binary compatible.
+  </para>
+
+  <para>
+   A cast can marked <literal>AS ASSIGNMENT</>, which means that it
+   can be invoked implicitly in any context where the conversion it
+   defines is required.  Cast functions not so marked can be invoked
+   only by explicit <literal>CAST</>,
+   <replaceable>x</><literal>::</><replaceable>typename</>, or
+   <replaceable>typename</>(<replaceable>x</>) constructs.  For
+   example, supposing that <literal>foo.f1</literal> is a column of
+   type <type>text</type>, then
+<programlisting>
+INSERT INTO foo(f1) VALUES(42);
+</programlisting>
+   will be allowed if the cast from type <type>integer</type> to type
+   <type>text</type> is marked <literal>AS ASSIGNMENT</>, otherwise
+   not. (We generally use the term <firstterm>implicit
+   cast</firstterm> to describe this kind of cast.)
+  </para>
+
+  <para>
+   It is wise to be conservative about marking casts as implicit.  An
+   overabundance of implicit casting paths can cause
+   <productname>PostgreSQL</productname> to choose surprising
+   interpretations of commands, or to be unable to resolve commands at
+   all because there are multiple possible interpretations.  A good
+   rule of thumb is to make cast implicitly invokable only for
+   information-preserving transformations between types in the same
+   general type category.  For example, <type>int2</type> to
+   <type>int4</type> casts can reasonably be implicit, but be wary of
+   marking <type>int4</type> to <type>text</type> or
+   <type>float8</type> to <type>int4</type> as implicit casts.
+  </para>
+
+  <para>
+   To be able to create a cast, you must own the underlying function.
+   To be able to create a binary compatible cast, you must own both
+   the source and the target data type.
+  </para>
+
+   <variablelist>
+    <title>Parameters</title>
+
+    <varlistentry>
+     <term><replaceable>sourcetype</replaceable></term>
+
+     <listitem>
+      <para>
+       The name of the source data type of the cast.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><replaceable>targettype</replaceable></term>
+
+     <listitem>
+      <para>
+       The name of the target data type of the cast.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><replaceable>funcname</replaceable>(<replaceable>argtype</replaceable>)</term>
+
+     <listitem>
+      <para>
+       The function used to perform the cast.  The function name may
+       be schema-qualified.  If it is not, the function will be looked
+       up in the path.  The argument type must be identical to the
+       source type, the result data type must match the target type of
+       the cast.  Cast functions must be marked immutable.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><literal>WITHOUT FUNCTION</literal></term>
+
+     <listitem>
+      <para>
+       Indicates that the source type and the target type are binary
+       compatible, so no function is required to perform the cast.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><literal>AS ASSIGNMENT</literal></term>
+
+     <listitem>
+      <para>
+       Indicates that the cast may be invoked implicitly.
+      </para>
+     </listitem>
+    </varlistentry>
+   </variablelist>
+
+ </refsect1>
+
+ <refsect1 id="sql-createcast-notes">
+  <title>Notes</title>
+
+  <para>
+   Use <command>DROP CAST</command> to remove user-defined casts.
+  </para>
+
+  <para>
+   The privileges required to create a cast may be changed in a future
+   release.
+  </para>
+
+  <para>
+   Remember that if you want to be able to convert types both ways you
+   need to declare casts both ways explicitly.
+  </para>
+
+  <para>
+   Prior to PostgreSQL 7.3, every function that had the same name as a
+   data type, returned that data type, and took one argument of a
+   different type was automatically a cast function.  This system has
+   been abandoned in face of the introduction of schemas and to be
+   able to store binary compatible casts.  The built-in cast functions
+   still follow this naming scheme, but they have to be declared as
+   casts explicitly now.
+  </para>
+ </refsect1>
+
+
+ <refsect1 id="sql-createcast-examples">
+  <title>Examples</title>
+
+  <para>
+   To create a cast from type <type>text</type> to type
+   <type>int</type> using the function <literal>int4(text)</literal>:
+<programlisting>
+CREATE CAST (text AS int4) WITH FUNCTION int4(text);
+</programlisting>
+   (This cast is already predefined in the system.)
+  </para>
+ </refsect1>
+
+ <refsect1 id="sql-createcast-compat">
+  <title>Compatibility</title>
+
+  <para>
+   The <command>CREATE CAST</command> command conforms to SQL99,
+   except that SQL99 does not make provisions for binary compatible
+   types.
+  </para>
+ </refsect1>
+
+
+ <refsect1 id="sql-createcast-seealso">
+  <title>See Also</title>
+
+  <para>
+   <xref linkend="sql-createfunction" endterm="sql-createfunction-title">,
+   <xref linkend="sql-createtype" endterm="sql-createtype-title">,
+   <xref linkend="sql-dropcast" endterm="sql-dropcast-title">,
+   <citetitle>PostgreSQL Programmer's Guide</citetitle>
+  </para>
+ </refsect1>
+
+</refentry>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode:sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:"../reference.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:("/usr/lib/sgml/catalog")
+sgml-local-ecat-files:nil
+End:
+-->
index b2d2314a7332383232be2854f116507664c666a9..e2170dcc45d252a5a55dd9fc36cbc1b8d1bc417d 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.39 2002/05/18 13:47:59 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.40 2002/07/18 23:11:27 petere Exp $
 -->
 
 <refentry id="SQL-CREATEFUNCTION">
@@ -20,7 +20,6 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
   { LANGUAGE <replaceable class="parameter">langname</replaceable>
     | IMMUTABLE | STABLE | VOLATILE
     | CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
-    | IMPLICIT CAST
     | [EXTERNAL] SECURITY INVOKER | [EXTERNAL] SECURITY DEFINER
     | AS '<replaceable class="parameter">definition</replaceable>'
     | AS '<replaceable class="parameter">obj_file</replaceable>', '<replaceable class="parameter">link_symbol</replaceable>'
@@ -188,18 +187,6 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
      </listitem>
     </varlistentry>
 
-    <varlistentry>
-     <term><literal>IMPLICIT CAST</literal</term>
-
-     <listitem>
-      <para>
-       Indicates that the function may be used for implicit type
-       conversions.  See <xref linkend="sql-createfunction-cast-functions"
-       endterm="sql-createfunction-cast-functions-title"> for more detail.
-      </para>
-     </listitem>
-    </varlistentry>
-
    <varlistentry>
     <term><optional>EXTERNAL</optional> SECURITY INVOKER</term>
     <term><optional>EXTERNAL</optional> SECURITY DEFINER</term>
@@ -285,14 +272,6 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
         </listitem>
        </varlistentry>
 
-       <varlistentry>
-        <term>implicitCoercion</term>
-        <listitem>
-         <para>
-          Same as <literal>IMPLICIT CAST</literal>
-         </para>
-        </listitem>
-       </varlistentry>
       </variablelist>
 
       Attribute names are not case-sensitive.
@@ -394,55 +373,6 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
   </para>
  </refsect1>
 
- <refsect1 id="sql-createfunction-cast-functions">
-  <title id="sql-createfunction-cast-functions-title">
-   Type Cast Functions
-  </title>
-  <para>
-   A function that has one argument and is named the same as its return
-   data type (including the schema name) is considered to be a <firstterm>type
-   casting function</>: it can be invoked to convert a value of its input
-   data type into a value 
-   of its output datatype.  For example,
-<programlisting>
-SELECT CAST(42 AS text);
-</programlisting>
-   converts the integer constant 42 to text by invoking a function
-   <literal>text(int4)</>, if such a function exists and returns type
-   text.  (If no suitable conversion function can be found, the cast fails.)
-  </para>
-
-  <para>
-   If a potential cast function is marked <literal>IMPLICIT CAST</>,
-   then it can be invoked implicitly in any context where the
-   conversion it defines is required.  Cast functions not so marked
-   can be invoked only by explicit <literal>CAST</>,
-   <replaceable>x</><literal>::</><replaceable>typename</>, or
-   <replaceable>typename</>(<replaceable>x</>) constructs.  For
-   example, supposing that <literal>foo.f1</literal> is a column of
-   type <type>text</type>, then
-<programlisting>
-INSERT INTO foo(f1) VALUES(42);
-</programlisting>
-   will be allowed if <literal>text(int4)</> is marked
-   <literal>IMPLICIT CAST</>, otherwise not.
-  </para>
-
-  <para>
-   It is wise to be conservative about marking cast functions as
-   implicit casts.  An overabundance of implicit casting paths can
-   cause <productname>PostgreSQL</productname> to choose surprising
-   interpretations of commands, or to be unable to resolve commands at
-   all because there are multiple possible interpretations.  A good
-   rule of thumb is to make cast implicitly invokable only for
-   information-preserving transformations between types in the same
-   general type category.  For example, <type>int2</type> to
-   <type>int4</type> casts can reasonably be implicit, but be wary of
-   marking <type>int4</type> to <type>text</type> or
-   <type>float8</type> to <type>int4</type> as implicit casts.
-  </para>
- </refsect1>
-  
  <refsect1 id="sql-createfunction-examples">
   <title>Examples</title>
 
diff --git a/doc/src/sgml/ref/drop_cast.sgml b/doc/src/sgml/ref/drop_cast.sgml
new file mode 100644 (file)
index 0000000..3715211
--- /dev/null
@@ -0,0 +1,133 @@
+<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_cast.sgml,v 1.1 2002/07/18 23:11:27 petere Exp $ -->
+
+<refentry id="SQL-DROPCAST">
+ <refmeta>
+  <refentrytitle id="SQL-DROPCAST-TITLE">DROP CAST</refentrytitle>
+  <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+  <refname>DROP CAST</refname>
+  <refpurpose>remove a user-defined cast</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+DROP CAST (<replaceable>sourcetype</replaceable> AS <replaceable>targettype</replaceable>)
+    [ CASCADE | RESTRICT ]
+</synopsis>
+ </refsynopsisdiv>
+  
+ <refsect1 id="sql-dropcast-description">
+  <title>Description</title>
+
+  <para>
+   <command>DROP CAST</command> removes a previously defined cast.
+  </para>
+
+  <para>
+   To be able to drop a cast, you must own the underlying function.
+   To be able to drop a binary compatible cast, you must own both the
+   source and the target data type.  These are the same privileges
+   that are required to create a cast.
+  </para>
+
+   <variablelist>
+    <title>Parameters</title>
+
+    <varlistentry>
+     <term><replaceable>sourcetype</replaceable></term>
+
+     <listitem>
+      <para>
+       The name of the source data type of the cast.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><replaceable>targettype</replaceable></term>
+
+     <listitem>
+      <para>
+       The name of the target data type of the cast.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><literal>CASCADE</literal></term>
+     <term><literal>RESTRICT</literal></term>
+
+     <listitem>
+      <para>
+       These key words do not have any effect, since there are no
+       dependencies on casts.
+      </para>
+     </listitem>
+    </varlistentry>
+   </variablelist>
+
+ </refsect1>
+
+ <refsect1 id="sql-dropcast-notes">
+  <title>Notes</title>
+
+  <para>
+   Use <command>CREATE CAST</command> to create user-defined casts.
+  </para>
+
+  <para>
+   The privileges required to drop a cast may be changed in a future
+   release.
+  </para>
+ </refsect1>
+
+
+ <refsect1 id="sql-dropcast-examples">
+  <title>Examples</title>
+
+  <para>
+   To drop the cast from type <type>text</type> to type <type>int</type>:
+<programlisting>
+DROP CAST (text AS int4);
+</programlisting>
+  </para>
+ </refsect1>
+
+ <refsect1 id="sql-dropcast-compat">
+  <title>Compatibility</title>
+
+  <para>
+   The <command>DROP CAST</command> command conforms to SQL99.
+  </para>
+ </refsect1>
+
+
+ <refsect1 id="sql-dropcast-seealso">
+  <title>See Also</title>
+
+  <para>
+   <xref linkend="sql-createcast" endterm="sql-createcast-title">
+  </para>
+ </refsect1>
+
+</refentry>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode:sgml
+sgml-omittag:nil
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+sgml-parent-document:nil
+sgml-default-dtd-file:"../reference.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:("/usr/lib/sgml/catalog")
+sgml-local-ecat-files:nil
+End:
+-->
index 8249039826ced554fb9356f5812e61a6bdb700a4..39fec262dd06223f2c047f960af3921fcad287ca 100644 (file)
@@ -1,5 +1,5 @@
 <!-- reference.sgml
-$Header: /cvsroot/pgsql/doc/src/sgml/reference.sgml,v 1.29 2002/07/18 16:47:22 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/reference.sgml,v 1.30 2002/07/18 23:11:27 petere Exp $
 
 PostgreSQL Reference Manual
 -->
@@ -60,6 +60,7 @@ PostgreSQL Reference Manual
    &commit;
    &copyTable;
    &createAggregate;
+   &createCast;
    &createConstraint;
    &createDatabase;
    &createDomain;
@@ -80,6 +81,7 @@ PostgreSQL Reference Manual
    &declare;
    &delete;
    &dropAggregate;
+   &dropCast;
    &dropDatabase;
    &dropDomain;
    &dropFunction;
index f215c84b93e0c0c73808f36020b071b6302ba95f..4f7911ff4e1dc543487b836663d10ae9556d9f9e 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.141 2002/07/16 22:12:18 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.142 2002/07/18 23:11:27 petere Exp $
 -->
 
 <appendix id="release">
@@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without
 worries about funny characters.
 -->
 <literallayout><![CDATA[
+CREATE CAST/DROP CAST
 Sequences created by SERIAL column definitions now auto-drop with the column
 Most forms of DROP now support RESTRICT and CASCADE options
 Recursive SQL functions can be defined
index 22e033524eeffe232e104533bac37837056026c1..37681565ecff6e93ccf315d71937b3c0bf51354d 100644 (file)
@@ -2,7 +2,7 @@
 #
 # Makefile for backend/catalog
 #
-# $Header: /cvsroot/pgsql/src/backend/catalog/Makefile,v 1.41 2002/07/12 18:43:13 tgl Exp $
+# $Header: /cvsroot/pgsql/src/backend/catalog/Makefile,v 1.42 2002/07/18 23:11:27 petere Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -30,7 +30,7 @@ POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
        pg_attrdef.h pg_constraint.h pg_inherits.h pg_index.h \
        pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
        pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \
-       pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h \
+       pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h pg_cast.h \
        pg_namespace.h pg_conversion.h pg_database.h pg_shadow.h pg_group.h \
        pg_depend.h indexing.h \
     )
index d2dc8b3795ade3c2f83f5db66e8a19a7982a248c..638843c3e0795f8c94d7861131bf6f64a7c9eff1 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.4 2002/07/18 16:47:22 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.5 2002/07/18 23:11:27 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -47,6 +47,7 @@
 /* This enum covers all system catalogs whose OIDs can appear in classid. */
 typedef enum ObjectClasses
 {
+       OCLASS_CAST,                            /* pg_cast */
        OCLASS_CLASS,                           /* pg_class */
        OCLASS_PROC,                            /* pg_proc */
        OCLASS_TYPE,                            /* pg_type */
@@ -604,6 +605,10 @@ doDeletion(const ObjectAddress *object)
                        RemoveSchemaById(object->objectId);
                        break;
 
+               case OCLASS_CAST:
+                       DropCastById(object->objectId);
+                       break;
+
                default:
                        elog(ERROR, "doDeletion: Unsupported object class %u",
                                 object->classId);
@@ -979,6 +984,7 @@ term_object_addresses(ObjectAddresses *addrs)
 static void
 init_object_classes(void)
 {
+       object_classes[OCLASS_CAST] = get_system_catalog_relid(CastRelationName);
        object_classes[OCLASS_CLASS] = RelOid_pg_class;
        object_classes[OCLASS_PROC] = RelOid_pg_proc;
        object_classes[OCLASS_TYPE] = RelOid_pg_type;
@@ -1023,6 +1029,11 @@ getObjectClass(const ObjectAddress *object)
        if (!object_classes_initialized)
                init_object_classes();
 
+       if (object->classId == object_classes[OCLASS_CAST])
+       {
+               Assert(object->objectSubId == 0);
+               return OCLASS_CAST;
+       }
        if (object->classId == object_classes[OCLASS_CONSTRAINT])
        {
                Assert(object->objectSubId == 0);
@@ -1078,6 +1089,10 @@ getObjectDescription(const ObjectAddress *object)
 
        switch (getObjectClass(object))
        {
+               case OCLASS_CAST:
+                       appendStringInfo(&buffer, "cast");
+                       break;
+
                case OCLASS_CLASS:
                        getRelationDescription(&buffer, object->objectId);
                        if (object->objectSubId != 0)
index 9f16b4d4cc18ea3cd89a2ddb94509c6a0776436d..80e3a15cf57a75295f2ffabe4d41f232b98cd8d2 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.97 2002/07/15 16:33:31 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.98 2002/07/18 23:11:27 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -43,6 +43,8 @@ char     *Name_pg_attr_indices[Num_pg_attr_indices] =
 {AttributeRelidNameIndex, AttributeRelidNumIndex};
 char      *Name_pg_attrdef_indices[Num_pg_attrdef_indices] =
 {AttrDefaultIndex, AttrDefaultOidIndex};
+char      *Name_pg_cast_indices[Num_pg_cast_indices] =
+{CastSourceTargetIndex};
 char      *Name_pg_class_indices[Num_pg_class_indices] =
 {ClassNameNspIndex, ClassOidIndex};
 char      *Name_pg_constraint_indices[Num_pg_constraint_indices] =
index 28d7e83f575e8026e191ec2304fd3ebf678ffb5c..189db5d77da89204653d6fa3a9ec9759e5034e74 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.50 2002/07/16 22:12:18 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.51 2002/07/18 23:11:27 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -144,7 +144,6 @@ AggregateCreate(const char *aggName,
                                                          "-",                  /* probin */
                                                          true,                 /* isAgg */
                                                          false,                /* security invoker (currently not definable for agg) */
-                                                         false,                /* isImplicit */
                                                          false,                /* isStrict (not needed for agg) */
                                                          PROVOLATILE_IMMUTABLE,        /* volatility (not needed for agg) */
                                                          BYTE_PCT,             /* default cost values */
index f8693fa7fece1ca54a79e970f70b1e6b61ea2b21..29cfbb9b46e4312148314b4b4fcfea2e69848ce0 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.78 2002/07/18 16:47:23 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.79 2002/07/18 23:11:27 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -55,7 +55,6 @@ ProcedureCreate(const char *procedureName,
                                const char *probin,
                                bool isAgg,
                                bool security_definer,
-                               bool isImplicit,
                                bool isStrict,
                                char volatility,
                                int32 byte_pct,
@@ -163,7 +162,7 @@ ProcedureCreate(const char *procedureName,
        values[i++] = ObjectIdGetDatum(languageObjectId); /* prolang */
        values[i++] = BoolGetDatum(isAgg);                      /* proisagg */
        values[i++] = BoolGetDatum(security_definer); /* prosecdef */
-       values[i++] = BoolGetDatum(isImplicit);         /* proimplicit */
+       values[i++] = BoolGetDatum(false);                      /* proimplicit */
        values[i++] = BoolGetDatum(isStrict);           /* proisstrict */
        values[i++] = BoolGetDatum(returnsSet);         /* proretset */
        values[i++] = CharGetDatum(volatility);         /* provolatile */
index 9a33810b07351dac3d2c2281b3d41efb78bf2955..2ed9581b665d7c0c2fbf22f6ffe84b986e40d7bb 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.8 2002/07/12 18:43:16 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.9 2002/07/18 23:11:27 petere Exp $
  *
  * DESCRIPTION
  *       These routines take the parse tree and pick out the
@@ -34,7 +34,9 @@
 #include "access/heapam.h"
 #include "catalog/catname.h"
 #include "catalog/dependency.h"
+#include "catalog/indexing.h"
 #include "catalog/namespace.h"
+#include "catalog/pg_cast.h"
 #include "catalog/pg_language.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
@@ -44,6 +46,7 @@
 #include "parser/parse_func.h"
 #include "parser/parse_type.h"
 #include "utils/acl.h"
+#include "utils/fmgroids.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
 
@@ -171,8 +174,7 @@ compute_attributes_sql_style(const List *options,
                                                         char **language,
                                                         char *volatility_p,
                                                         bool *strict_p,
-                                                        bool *security_definer,
-                                                        bool *implicit_cast)
+                                                        bool *security_definer)
 {
        const List *option;
        DefElem *as_item = NULL;
@@ -180,7 +182,6 @@ compute_attributes_sql_style(const List *options,
        DefElem *volatility_item = NULL;
        DefElem *strict_item = NULL;
        DefElem *security_item = NULL;
-       DefElem *implicit_item = NULL;
 
        foreach(option, options)
        {
@@ -216,12 +217,6 @@ compute_attributes_sql_style(const List *options,
                                elog(ERROR, "conflicting or redundant options");
                        security_item = defel;
                }
-               else if (strcmp(defel->defname, "implicit")==0)
-               {
-                       if (implicit_item)
-                               elog(ERROR, "conflicting or redundant options");
-                       implicit_item = defel;
-               }
                else
                        elog(ERROR, "invalid CREATE FUNCTION option");
        }
@@ -252,8 +247,6 @@ compute_attributes_sql_style(const List *options,
                *strict_p = intVal(strict_item->arg);
        if (security_item)
                *security_definer = intVal(security_item->arg);
-       if (implicit_item)
-               *implicit_cast = intVal(implicit_item->arg);
 }
 
 
@@ -264,10 +257,7 @@ compute_attributes_sql_style(const List *options,
  *     These parameters supply optional information about a function.
  *     All have defaults if not specified.
  *
- *     Note: currently, only three of these parameters actually do anything:
- *
- *      * isImplicit means the function may be used as an implicit type
- *        coercion.
+ *     Note: currently, only two of these parameters actually do anything:
  *
  *      * isStrict means the function should not be called when any NULL
  *        inputs are present; instead a NULL result value should be assumed.
@@ -284,7 +274,7 @@ static void
 compute_attributes_with_style(List *parameters,
                                                          int32 *byte_pct_p, int32 *perbyte_cpu_p,
                                                          int32 *percall_cpu_p, int32 *outin_ratio_p,
-                                                         bool *isImplicit_p, bool *isStrict_p,
+                                                         bool *isStrict_p,
                                                          char *volatility_p)
 {
        List       *pl;
@@ -293,9 +283,7 @@ compute_attributes_with_style(List *parameters,
        {
                DefElem    *param = (DefElem *) lfirst(pl);
 
-               if (strcasecmp(param->defname, "implicitcoercion") == 0)
-                       *isImplicit_p = true;
-               else if (strcasecmp(param->defname, "isstrict") == 0)
+               if (strcasecmp(param->defname, "isstrict") == 0)
                        *isStrict_p = true;
                else if (strcasecmp(param->defname, "isimmutable") == 0)
                        *volatility_p = PROVOLATILE_IMMUTABLE;
@@ -398,8 +386,7 @@ CreateFunction(CreateFunctionStmt *stmt)
                                perbyte_cpu,
                                percall_cpu,
                                outin_ratio;
-       bool            isImplicit,
-                               isStrict,
+       bool            isStrict,
                                security;
        char            volatility;
        HeapTuple       languageTuple;
@@ -420,14 +407,13 @@ CreateFunction(CreateFunctionStmt *stmt)
        perbyte_cpu = PERBYTE_CPU;
        percall_cpu = PERCALL_CPU;
        outin_ratio = OUTIN_RATIO;
-       isImplicit = false;
        isStrict = false;
        security = false;
        volatility = PROVOLATILE_VOLATILE;
 
        /* override attributes from explicit list */
        compute_attributes_sql_style(stmt->options,
-                                                                &as_clause, &language, &volatility, &isStrict, &security, &isImplicit);
+                                                                &as_clause, &language, &volatility, &isStrict, &security);
 
        /* Convert language name to canonical case */
        case_translate_language_name(language, languageName);
@@ -474,8 +460,7 @@ CreateFunction(CreateFunctionStmt *stmt)
 
        compute_attributes_with_style(stmt->withClause,
                                                                  &byte_pct, &perbyte_cpu, &percall_cpu,
-                                                                 &outin_ratio, &isImplicit, &isStrict,
-                                                                 &volatility);
+                                                                 &outin_ratio, &isStrict, &volatility);
 
        interpret_AS_clause(languageOid, languageName, as_clause,
                                                &prosrc_str, &probin_str);
@@ -517,7 +502,6 @@ CreateFunction(CreateFunctionStmt *stmt)
                                        probin_str, /* converted to text later */
                                        false,          /* not an aggregate */
                                        security,
-                                       isImplicit,
                                        isStrict,
                                        volatility,
                                        byte_pct,
@@ -639,3 +623,217 @@ RemoveFunctionById(Oid funcOid)
                heap_close(relation, RowExclusiveLock);
        }
 }
+
+
+
+/*
+ * CREATE CAST
+ */
+void
+CreateCast(CreateCastStmt *stmt)
+{
+       Oid                     sourcetypeid;
+       Oid                     targettypeid;
+       Oid                     funcid;
+       HeapTuple       tuple;
+       Relation        relation;
+       Form_pg_proc procstruct;
+
+       Datum           values[Natts_pg_proc];
+       char            nulls[Natts_pg_proc];
+       int                     i;
+
+       ObjectAddress myself,
+               referenced;
+
+       sourcetypeid = LookupTypeName(stmt->sourcetype);
+       if (!OidIsValid(sourcetypeid))
+               elog(ERROR, "source data type %s does not exist",
+                        TypeNameToString(stmt->sourcetype));
+
+       targettypeid = LookupTypeName(stmt->targettype);
+       if (!OidIsValid(targettypeid))
+               elog(ERROR, "target data type %s does not exist",
+                        TypeNameToString(stmt->targettype));
+
+       if (sourcetypeid == targettypeid)
+               elog(ERROR, "source data type and target data type are the same");
+
+       relation = heap_openr(CastRelationName, RowExclusiveLock);
+
+       tuple = SearchSysCache(CASTSOURCETARGET,
+                                                  ObjectIdGetDatum(sourcetypeid),
+                                                  ObjectIdGetDatum(targettypeid),
+                                                  0, 0);
+       if (HeapTupleIsValid(tuple))
+               elog(ERROR, "cast from data type %s to data type %s already exists",
+                        TypeNameToString(stmt->sourcetype),
+                        TypeNameToString(stmt->targettype));
+
+       if (stmt->func != NULL)
+       {
+               funcid = LookupFuncNameTypeNames(stmt->func->funcname, stmt->func->funcargs, false, "CreateCast");
+
+               if(!pg_proc_ownercheck(funcid, GetUserId()))
+                       elog(ERROR, "permission denied");
+
+               tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(funcid), 0, 0, 0);
+               if (!HeapTupleIsValid(tuple))
+                       elog(ERROR, "cache lookup of function %u failed", funcid);
+
+               procstruct = (Form_pg_proc) GETSTRUCT(tuple);
+               if (procstruct->pronargs != 1)
+                       elog(ERROR, "cast function must take 1 argument");
+               if (procstruct->proargtypes[0] != sourcetypeid)
+                       elog(ERROR, "argument of cast function must match source data type");
+               if (procstruct->prorettype != targettypeid)
+                       elog(ERROR, "return data type of cast function must match target data type");
+               if (procstruct->provolatile != PROVOLATILE_IMMUTABLE)
+                       elog(ERROR, "cast function must be immutable");
+               if (procstruct->proisagg)
+                       elog(ERROR, "cast function must not be an aggregate function");
+               if (procstruct->proretset)
+                       elog(ERROR, "cast function must be not return a set");
+
+               ReleaseSysCache(tuple);
+       }
+       else
+       {
+               /* indicates binary compatibility */
+               if (!pg_type_ownercheck(sourcetypeid, GetUserId())
+                       || !pg_type_ownercheck(targettypeid, GetUserId()))
+                       elog(ERROR, "permission denied");
+               funcid = 0;
+       }
+
+       /* ready to go */
+       values[Anum_pg_cast_castsource-1] = ObjectIdGetDatum(sourcetypeid);
+       values[Anum_pg_cast_casttarget-1] = ObjectIdGetDatum(targettypeid);
+       values[Anum_pg_cast_castfunc-1] = ObjectIdGetDatum(funcid);
+       values[Anum_pg_cast_castimplicit-1] = BoolGetDatum(stmt->implicit);
+
+       for (i = 0; i < Natts_pg_cast; ++i)
+               nulls[i] = ' ';
+
+       tuple = heap_formtuple(RelationGetDescr(relation), values, nulls);
+       simple_heap_insert(relation, tuple);
+
+       if (RelationGetForm(relation)->relhasindex)
+       {
+               Relation        idescs[Num_pg_cast_indices];
+
+               CatalogOpenIndices(Num_pg_cast_indices, Name_pg_cast_indices, idescs);
+               CatalogIndexInsert(idescs, Num_pg_cast_indices, relation, tuple);
+               CatalogCloseIndices(Num_pg_cast_indices, idescs);
+       }
+
+       myself.classId = get_system_catalog_relid(CastRelationName);
+       myself.objectId = tuple->t_data->t_oid;
+       myself.objectSubId = 0;
+
+       /* dependency on source type */
+       referenced.classId = RelOid_pg_type;
+       referenced.objectId = sourcetypeid;
+       referenced.objectSubId = 0;
+       recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+       /* dependency on target type */
+       referenced.classId = RelOid_pg_type;
+       referenced.objectId = targettypeid;
+       referenced.objectSubId = 0;
+       recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+       /* dependency on function */
+       if (OidIsValid(funcid))
+       {
+               referenced.classId = RelOid_pg_proc;
+               referenced.objectId = funcid;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       }
+
+       heap_freetuple(tuple);
+       heap_close(relation, RowExclusiveLock);
+}
+
+
+
+/*
+ * DROP CAST
+ */
+void
+DropCast(DropCastStmt *stmt)
+{
+       Oid                     sourcetypeid;
+       Oid                     targettypeid;
+       HeapTuple       tuple;
+       Form_pg_cast caststruct;
+       ObjectAddress object;
+
+       sourcetypeid = LookupTypeName(stmt->sourcetype);
+       if (!OidIsValid(sourcetypeid))
+               elog(ERROR, "source data type %s does not exist",
+                        TypeNameToString(stmt->sourcetype));
+
+       targettypeid = LookupTypeName(stmt->targettype);
+       if (!OidIsValid(targettypeid))
+               elog(ERROR, "target data type %s does not exist",
+                        TypeNameToString(stmt->targettype));
+
+       tuple = SearchSysCache(CASTSOURCETARGET,
+                                                ObjectIdGetDatum(sourcetypeid),
+                                                ObjectIdGetDatum(targettypeid),
+                                                0, 0);
+       if (!HeapTupleIsValid(tuple))
+               elog(ERROR, "cast from type %s to type %s does not exist",
+                        TypeNameToString(stmt->sourcetype),
+                        TypeNameToString(stmt->targettype));
+
+       /* Permission check */
+       caststruct = (Form_pg_cast) GETSTRUCT(tuple);
+       if (caststruct->castfunc != InvalidOid)
+       {
+               if(!pg_proc_ownercheck(caststruct->castfunc, GetUserId()))
+                       elog(ERROR, "permission denied");
+       }
+       else
+       {
+               if (!pg_type_ownercheck(sourcetypeid, GetUserId())
+                       || !pg_type_ownercheck(targettypeid, GetUserId()))
+                       elog(ERROR, "permission denied");
+       }
+
+       ReleaseSysCache(tuple);
+
+       /*
+        * Do the deletion
+        */
+       object.classId = get_system_catalog_relid(CastRelationName);
+       object.objectId = tuple->t_data->t_oid;
+       object.objectSubId = 0;
+
+       performDeletion(&object, stmt->behavior);
+}
+
+
+void
+DropCastById(Oid castOid)
+{
+       Relation        relation;
+       ScanKeyData scankey;
+       HeapScanDesc scan;
+       HeapTuple       tuple;
+
+       relation = heap_openr(CastRelationName, RowExclusiveLock);
+       ScanKeyEntryInitialize(&scankey, 0x0,
+                                                  ObjectIdAttributeNumber, F_OIDEQ,
+                                                  ObjectIdGetDatum(castOid));
+       scan = heap_beginscan(relation, SnapshotNow, 1, &scankey);
+       tuple = heap_getnext(scan, ForwardScanDirection);
+       if (HeapTupleIsValid(tuple))
+               simple_heap_delete(relation, &tuple->t_self);
+       else
+               elog(ERROR, "could not find tuple for cast %u", castOid);
+       heap_endscan(scan);
+       heap_close(relation, RowExclusiveLock);
+}
index bece9e0f1848cd00a0e69c49b295d5c3fcc4d890..4bc561f96ab54edb17ae1b67cce52f7f85373e5e 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.346 2002/07/18 17:14:19 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.347 2002/07/18 23:11:27 petere Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -135,13 +135,13 @@ static void doNegateFloat(Value *v);
                AlterDatabaseSetStmt, AlterGroupStmt,
                AlterTableStmt, AlterUserStmt, AlterUserSetStmt,
                AnalyzeStmt, ClosePortalStmt, ClusterStmt, CommentStmt,
-               ConstraintsSetStmt, CopyStmt, CreateAsStmt,
+               ConstraintsSetStmt, CopyStmt, CreateAsStmt, CreateCastStmt,
                CreateDomainStmt, CreateGroupStmt, CreatePLangStmt,
                CreateSchemaStmt, CreateSeqStmt, CreateStmt,
                CreateAssertStmt, CreateTrigStmt, CreateUserStmt,
                CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt,
                DropGroupStmt, DropPLangStmt, DropStmt,
-               DropAssertStmt, DropTrigStmt, DropRuleStmt,
+               DropAssertStmt, DropTrigStmt, DropRuleStmt, DropCastStmt,
                DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
                GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt,
                LockStmt, NotifyStmt, OptimizableStmt,
@@ -165,7 +165,7 @@ static void doNegateFloat(Value *v);
 %type <defelt> createdb_opt_item, copy_opt_item
 
 %type <ival>   opt_lock, lock_type
-%type <boolean>        opt_force, opt_or_replace
+%type <boolean>        opt_force, opt_or_replace, opt_assignment
 
 %type <list>   user_list
 
@@ -346,7 +346,7 @@ static void doNegateFloat(Value *v);
 
        HANDLER, HAVING, HOUR_P,
 
-       ILIKE, IMMEDIATE, IMMUTABLE, IMPLICIT, IN_P, INCREMENT,
+       ILIKE, IMMEDIATE, IMMUTABLE, IN_P, INCREMENT,
        INDEX, INHERITS, INITIALLY, INNER_P, INOUT, INPUT,
        INSENSITIVE, INSERT, INSTEAD, INT, INTEGER, INTERSECT,
        INTERVAL, INTO, INVOKER, IS, ISNULL, ISOLATION,
@@ -475,6 +475,7 @@ stmt :
                        | CopyStmt
                        | CreateStmt
                        | CreateAsStmt
+                       | CreateCastStmt
                        | CreateDomainStmt
                        | CreateFunctionStmt
                        | CreateSchemaStmt
@@ -489,6 +490,7 @@ stmt :
                        | DropStmt
                        | TruncateStmt
                        | CommentStmt
+                       | DropCastStmt
                        | DropGroupStmt
                        | DropPLangStmt
                        | DropAssertStmt
@@ -2886,15 +2888,6 @@ RecipeStmt:  EXECUTE RECIPE recipe_name
  *                                             as <filename or code in language as appropriate>
  *                                             language <lang> [with parameters]
  *
- * CAST() form allowing all options from the CREATE FUNCTION form:
- *                             create [or replace] cast (<type> as <type>)
- *                                             as <filename or code in language as appropriate>
- *                                             language <lang> [with parameters]
- *
- * SQL99 CAST() form (requires a function to be previously defined):
- *                             create [or replace] cast (<type> as <type>)
- *                                             with function fname (<type>) [as assignment]
- *
  *****************************************************************************/
 
 CreateFunctionStmt:
@@ -2910,63 +2903,6 @@ CreateFunctionStmt:
                                        n->withClause = $9;
                                        $$ = (Node *)n;
                                }
-               /* CREATE CAST SQL99 standard form */
-               | CREATE opt_or_replace CAST '(' func_type AS func_type ')'
-                       WITH FUNCTION func_name func_args opt_assignment opt_definition
-                               {
-                                       CreateFunctionStmt *n;
-                                       char buf[256];
-                                       n = makeNode(CreateFunctionStmt);
-                                       n->replace = $2;
-                                       n->funcname = $7->names;
-                                       n->argTypes = makeList1($5);
-                                       n->returnType = $7;
-                                       /* expand this into a string of SQL language */
-                                       strcpy(buf, "select ");
-                                       strcat(buf, ((Value *)lfirst($11))->val.str);
-                                       strcat(buf, "($1)");
-                                       n->options = lappend($14, makeDefElem("as", (Node *)makeList1(makeString(pstrdup(buf)))));
-                                       /* make sure that this will allow implicit casting */
-                                       n->options = lappend(n->options,
-                                                                                makeDefElem("implicit", (Node *)makeInteger(TRUE)));
-                                       /* and mention that this is SQL language */
-                                       n->options = lappend(n->options,
-                                                                                makeDefElem("language", (Node *)makeString(pstrdup("sql"))));
-                                       $$ = (Node *)n;
-                               }
-               /* CREATE CAST SQL99 minimally variant form */
-               | CREATE opt_or_replace CAST '(' func_type AS func_type ')'
-                       WITH FUNCTION func_name func_args AS Sconst opt_definition
-                               {
-                                       CreateFunctionStmt *n;
-                                       n = makeNode(CreateFunctionStmt);
-                                       n->replace = $2;
-                                       n->funcname = $7->names;
-                                       n->argTypes = makeList1($5);
-                                       n->returnType = $7;
-                                       n->options = lappend($15, makeDefElem("as", (Node *)lcons(makeList1(makeString($14)), $11)));
-                                       /* make sure that this will allow implicit casting */
-                                       n->options = lappend(n->options,
-                                                                                makeDefElem("implicit", (Node *)makeInteger(TRUE)));
-                                       n->options = lappend(n->options,
-                                                                                makeDefElem("language", (Node *)makeString(pstrdup("c"))));
-                                       $$ = (Node *)n;
-                               }
-               /* CREATE CAST with mostly CREATE FUNCTION clauses */
-               | CREATE opt_or_replace CAST '(' func_type AS func_type ')'
-                       createfunc_opt_list opt_definition
-                               {
-                                       CreateFunctionStmt *n;
-                                       n = makeNode(CreateFunctionStmt);
-                                       n->replace = $2;
-                                       n->funcname = $7->names;
-                                       n->argTypes = makeList1($5);
-                                       n->returnType = $7;
-                                       /* make sure that this will allow implicit casting */
-                                       n->options = lappend($9, makeDefElem("implicit", (Node *)makeInteger(TRUE)));
-                                       n->withClause = $10;
-                                       $$ = (Node *)n;
-                               }
                ;
 
 opt_or_replace:
@@ -3090,10 +3026,6 @@ createfunc_opt_item:
                                {
                                        $$ = makeDefElem("security", (Node *)makeInteger(FALSE));
                                }
-                       | IMPLICIT CAST
-                               {
-                                       $$ = makeDefElem("implicit", (Node *)makeInteger(TRUE));
-                               }
                ;
 
 func_as:       Sconst                                          { $$ = makeList1(makeString($1)); }
@@ -3108,10 +3040,6 @@ opt_definition:
                        | /*EMPTY*/                                                             { $$ = NIL; }
                ;
 
-opt_assignment:  AS ASSIGNMENT                                 {}
-               | /*EMPTY*/                                                             {}
-               ;
-
 
 /*****************************************************************************
  *
@@ -3132,14 +3060,6 @@ RemoveFuncStmt:
                                        n->behavior = $5;
                                        $$ = (Node *)n;
                                }
-               | DROP CAST '(' func_type AS func_type ')' opt_drop_behavior
-                               {
-                                       RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
-                                       n->funcname = $6->names;
-                                       n->args = makeList1($4);
-                                       n->behavior = $8;
-                                       $$ = (Node *)n;
-                               }
                ;
 
 RemoveAggrStmt:
@@ -3190,6 +3110,49 @@ any_operator:
                ;
 
 
+/*****************************************************************************
+ *
+ *             CREATE CAST / DROP CAST
+ *
+ *****************************************************************************/
+
+CreateCastStmt: CREATE CAST '(' ConstTypename AS ConstTypename ')'
+                                       WITH FUNCTION function_with_argtypes opt_assignment
+                               {
+                                       CreateCastStmt *n = makeNode(CreateCastStmt);
+                                       n->sourcetype = $4;
+                                       n->targettype = $6;
+                                       n->func = (FuncWithArgs *) $10;
+                                       n->implicit = $11;
+                                       $$ = (Node *)n;
+                               }
+                       | CREATE CAST '(' ConstTypename AS ConstTypename ')'
+                                       WITHOUT FUNCTION opt_assignment
+                               {
+                                       CreateCastStmt *n = makeNode(CreateCastStmt);
+                                       n->sourcetype = $4;
+                                       n->targettype = $6;
+                                       n->func = NULL;
+                                       n->implicit = $10;
+                                       $$ = (Node *)n;
+                               }
+
+opt_assignment:  AS ASSIGNMENT                                 { $$ = TRUE; }
+               | /*EMPTY*/                                                             { $$ = FALSE; }
+               ;
+
+
+DropCastStmt: DROP CAST '(' ConstTypename AS ConstTypename ')' opt_drop_behavior
+                               {
+                                       DropCastStmt *n = makeNode(DropCastStmt);
+                                       n->sourcetype = $4;
+                                       n->targettype = $6;
+                                       n->behavior = $8;
+                                       $$ = (Node *)n;
+                               }
+
+
+
 /*****************************************************************************
  *
  *             QUERY:
@@ -6701,7 +6664,6 @@ unreserved_keyword:
                        | HOUR_P
                        | IMMEDIATE
                        | IMMUTABLE
-                       | IMPLICIT
                        | INCREMENT
                        | INDEX
                        | INHERITS
index f007092f668ba1339c3e15557f7ef67232976482..02c9fcdda93e2594c73dd92060880443b64d7752 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.121 2002/07/18 17:14:19 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.122 2002/07/18 23:11:28 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -142,7 +142,6 @@ static const ScanKeyword ScanKeywords[] = {
        {"ilike", ILIKE},
        {"immediate", IMMEDIATE},
        {"immutable", IMMUTABLE},
-       {"implicit", IMPLICIT},
        {"in", IN_P},
        {"increment", INCREMENT},
        {"index", INDEX},
index fda9100d67d67dfda8528ea684d88c5e6082c350..15896a37d78be2e85c838b56b8948fe1a0b3b2c2 100644 (file)
@@ -8,12 +8,13 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.77 2002/07/09 13:52:14 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.78 2002/07/18 23:11:28 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
+#include "catalog/pg_cast.h"
 #include "catalog/pg_proc.h"
 #include "nodes/makefuncs.h"
 #include "optimizer/clauses.h"
@@ -31,8 +32,9 @@ Oid                   PromoteTypeToNext(Oid inType);
 
 static Oid     PreferredType(CATEGORY category, Oid type);
 static Node *build_func_call(Oid funcid, Oid rettype, List *args);
-static Oid     find_coercion_function(Oid targetTypeId, Oid inputTypeId,
-                                                                  Oid secondArgType, bool isExplicit);
+static Oid     find_coercion_function(Oid targetTypeId, Oid sourceTypeId,
+                                                                  bool isExplicit);
+static Oid     find_typmod_coercion_function(Oid typeId);
 static Node    *TypeConstraints(Node *arg, Oid typeId);
 
 /* coerce_type()
@@ -142,7 +144,6 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
 
                funcId = find_coercion_function(baseTypeId,
                                                                                getBaseType(inputTypeId),
-                                                                               InvalidOid,
                                                                                isExplicit);
                if (!OidIsValid(funcId))
                        elog(ERROR, "coerce_type: no conversion function from '%s' to '%s'",
@@ -258,7 +259,6 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids,
                 */
                funcId = find_coercion_function(getBaseType(targetTypeId),
                                                                                getBaseType(inputTypeId),
-                                                                               InvalidOid,
                                                                                isExplicit);
                if (!OidIsValid(funcId))
                        return false;
@@ -312,8 +312,7 @@ coerce_type_typmod(ParseState *pstate, Node *node,
        if (atttypmod < 0 || atttypmod == exprTypmod(node))
                return node;
 
-       /* Note this is always implicit coercion */
-       funcId = find_coercion_function(baseTypeId, baseTypeId, INT4OID, false);
+       funcId = find_typmod_coercion_function(baseTypeId);
        if (OidIsValid(funcId))
        {
                Const      *cons;
@@ -621,21 +620,25 @@ TypeCategory(Oid inType)
 static bool
 DirectlyBinaryCompatible(Oid type1, Oid type2)
 {
+       HeapTuple       tuple;
+       bool            result;
+
        if (type1 == type2)
                return true;
-       if (TypeIsTextGroup(type1) && TypeIsTextGroup(type2))
-               return true;
-       if (TypeIsInt4GroupA(type1) && TypeIsInt4GroupA(type2))
-               return true;
-       if (TypeIsInt4GroupB(type1) && TypeIsInt4GroupB(type2))
-               return true;
-       if (TypeIsInt4GroupC(type1) && TypeIsInt4GroupC(type2))
-               return true;
-       if (TypeIsInetGroup(type1) && TypeIsInetGroup(type2))
-               return true;
-       if (TypeIsBitGroup(type1) && TypeIsBitGroup(type2))
-               return true;
-       return false;
+
+       tuple = SearchSysCache(CASTSOURCETARGET, type1, type2, 0, 0);
+       if (HeapTupleIsValid(tuple))
+       {
+               Form_pg_cast caststruct;
+
+               caststruct = (Form_pg_cast) GETSTRUCT(tuple);
+               result = caststruct->castfunc == InvalidOid && caststruct->castimplicit;
+               ReleaseSysCache(tuple);
+       }
+       else
+               result = false;
+
+       return result;
 }
 
 
@@ -750,34 +753,51 @@ PreferredType(CATEGORY category, Oid type)
  * If a function is found, return its pg_proc OID; else return InvalidOid.
  */
 static Oid
-find_coercion_function(Oid targetTypeId, Oid inputTypeId, Oid secondArgType,
-                                          bool isExplicit)
+find_coercion_function(Oid targetTypeId, Oid sourceTypeId, bool isExplicit)
+{
+       Oid                     funcid = InvalidOid;
+       HeapTuple       tuple;
+
+       tuple = SearchSysCache(CASTSOURCETARGET,
+                                                  ObjectIdGetDatum(sourceTypeId),
+                                                  ObjectIdGetDatum(targetTypeId),
+                                                  0, 0);
+
+       if (HeapTupleIsValid(tuple))
+       {
+               Form_pg_cast cform = (Form_pg_cast) GETSTRUCT(tuple);
+
+               if (isExplicit || cform->castimplicit)
+                       funcid = cform->castfunc;
+
+               ReleaseSysCache(tuple);
+       }
+
+       return funcid;
+}
+
+
+static Oid
+find_typmod_coercion_function(Oid typeId)
 {
        Oid                     funcid = InvalidOid;
        Type            targetType;
        char       *typname;
        Oid                     typnamespace;
        Oid                     oid_array[FUNC_MAX_ARGS];
-       int                     nargs;
        HeapTuple       ftup;
 
-       targetType = typeidType(targetTypeId);
+       targetType = typeidType(typeId);
        typname = NameStr(((Form_pg_type) GETSTRUCT(targetType))->typname);
        typnamespace = ((Form_pg_type) GETSTRUCT(targetType))->typnamespace;
 
        MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
-       oid_array[0] = inputTypeId;
-       if (OidIsValid(secondArgType))
-       {
-               oid_array[1] = secondArgType;
-               nargs = 2;
-       }
-       else
-               nargs = 1;
+       oid_array[0] = typeId;
+       oid_array[1] = INT4OID;
 
        ftup = SearchSysCache(PROCNAMENSP,
                                                  CStringGetDatum(typname),
-                                                 Int16GetDatum(nargs),
+                                                 Int16GetDatum(2),
                                                  PointerGetDatum(oid_array),
                                                  ObjectIdGetDatum(typnamespace));
        if (HeapTupleIsValid(ftup))
@@ -785,15 +805,11 @@ find_coercion_function(Oid targetTypeId, Oid inputTypeId, Oid secondArgType,
                Form_pg_proc pform = (Form_pg_proc) GETSTRUCT(ftup);
 
                /* Make sure the function's result type is as expected */
-               if (pform->prorettype == targetTypeId && !pform->proretset &&
+               if (pform->prorettype == typeId && !pform->proretset &&
                        !pform->proisagg)
                {
-                       /* If needed, make sure it can be invoked implicitly */
-                       if (isExplicit || pform->proimplicit)
-                       {
-                               /* Okay to use it */
-                               funcid = ftup->t_data->t_oid;
-                       }
+                       /* Okay to use it */
+                       funcid = ftup->t_data->t_oid;
                }
                ReleaseSysCache(ftup);
        }
index 862faf34cae8b9b735592f6ecdc954e4b455e6ec..d9137368335d3b5cd7abb6fd233db48789019a75 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.271 2002/07/18 16:47:25 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.272 2002/07/18 23:11:28 petere Exp $
  *
  * NOTES
  *       this is the "main" module of the postgres backend and
@@ -1693,7 +1693,7 @@ PostgresMain(int argc, char *argv[], const char *username)
        if (!IsUnderPostmaster)
        {
                puts("\nPOSTGRES backend interactive interface ");
-               puts("$Revision: 1.271 $ $Date: 2002/07/18 16:47:25 $\n");
+               puts("$Revision: 1.272 $ $Date: 2002/07/18 23:11:28 $\n");
        }
 
        /*
@@ -2444,6 +2444,14 @@ CreateCommandTag(Node *parsetree)
                        tag = "CREATE CONVERSION";
                        break;
 
+               case T_CreateCastStmt:
+                       tag = "CREATE CAST";
+                       break;
+
+               case T_DropCastStmt:
+                       tag = "DROP CAST";
+                       break;
+
                default:
                        elog(LOG, "CreateCommandTag: unknown parse node type %d",
                                 nodeTag(parsetree));
index 8ba7466ee286b663b4ead170fe06e8ca231df270..54eeab77cd1c404b542751a9555a9869249d6781 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.163 2002/07/18 16:47:25 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.164 2002/07/18 23:11:28 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -829,6 +829,14 @@ ProcessUtility(Node *parsetree,
                        }
                        break;
 
+               case T_CreateCastStmt:
+                       CreateCast((CreateCastStmt *) parsetree);
+                       break;
+
+               case T_DropCastStmt:
+                       DropCast((DropCastStmt *) parsetree);
+                       break;
+
                default:
                        elog(ERROR, "ProcessUtility: command #%d unsupported",
                                 nodeTag(parsetree));
index 2772b668738409a9ffb35b2a69e8822f62ffacef..5999ad96285c2b0e5235e8f577015ef01048e7d9 100644 (file)
@@ -3,7 +3,7 @@
  *                             back to source text
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.111 2002/07/18 17:14:20 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.112 2002/07/18 23:11:28 petere Exp $
  *
  *       This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -43,6 +43,7 @@
 #include "catalog/heap.h"
 #include "catalog/index.h"
 #include "catalog/namespace.h"
+#include "catalog/pg_cast.h"
 #include "catalog/pg_index.h"
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_operator.h"
@@ -2048,9 +2049,9 @@ get_agg_expr(Aggref *aggref, deparse_context *context)
  *             Strip any type coercions at the top of the given expression tree,
  *             as long as they are coercions to the given datatype.
  *
- * A RelabelType node is always a type coercion.  A function call is also
- * considered a type coercion if it has one argument and the function name
- * is the same as the (internal) name of its result type.
+ * A RelabelType node is always a type coercion.  A function call is
+ * also considered a type coercion if it has one argument and there is
+ * a cast declared that uses it.
  *
  * XXX It'd be better if the parsetree retained some explicit indication
  * of the coercion, so we didn't need these heuristics.
@@ -2069,9 +2070,9 @@ strip_type_coercion(Node *expr, Oid resultType)
        {
                Func       *func;
                HeapTuple       procTuple;
-               HeapTuple       typeTuple;
+               HeapTuple       castTuple;
                Form_pg_proc procStruct;
-               Form_pg_type typeStruct;
+               Form_pg_cast castStruct;
 
                func = (Func *) (((Expr *) expr)->oper);
                Assert(IsA(func, Func));
@@ -2085,33 +2086,33 @@ strip_type_coercion(Node *expr, Oid resultType)
                        elog(ERROR, "cache lookup for proc %u failed", func->funcid);
                procStruct = (Form_pg_proc) GETSTRUCT(procTuple);
                /* Double-check func has one arg and correct result type */
-               /* Also, it must be an implicit coercion function */
                if (procStruct->pronargs != 1 ||
-                       procStruct->prorettype != resultType ||
-                       !procStruct->proimplicit)
+                       procStruct->prorettype != resultType)
                {
                        ReleaseSysCache(procTuple);
                        return expr;
                }
-               /* See if function has same name/namespace as its result type */
-               typeTuple = SearchSysCache(TYPEOID,
-                                                               ObjectIdGetDatum(procStruct->prorettype),
-                                                                  0, 0, 0);
-               if (!HeapTupleIsValid(typeTuple))
-                       elog(ERROR, "cache lookup for type %u failed",
-                                procStruct->prorettype);
-               typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
-               if (strcmp(NameStr(procStruct->proname),
-                                  NameStr(typeStruct->typname)) != 0 ||
-                       procStruct->pronamespace != typeStruct->typnamespace)
+               /* See if function has is actually declared as a cast */
+               castTuple = SearchSysCache(CASTSOURCETARGET,
+                                                                  ObjectIdGetDatum(procStruct->proargtypes[0]),
+                                                                  ObjectIdGetDatum(procStruct->prorettype),
+                                                                  0, 0);
+               if (!HeapTupleIsValid(castTuple))
+               {
+                       ReleaseSysCache(procTuple);
+                       return expr;
+               }
+               /* It must also be an implicit cast. */
+               castStruct = (Form_pg_cast) GETSTRUCT(castTuple);
+               if (!castStruct->castimplicit)
                {
                        ReleaseSysCache(procTuple);
-                       ReleaseSysCache(typeTuple);
+                       ReleaseSysCache(castTuple);
                        return expr;
                }
                /* Okay, it is indeed a type-coercion function */
                ReleaseSysCache(procTuple);
-               ReleaseSysCache(typeTuple);
+               ReleaseSysCache(castTuple);
                return strip_type_coercion(lfirst(((Expr *) expr)->args), resultType);
        }
 
index 52763d29e43f8de0e3cd98a1b3ba95bf7384b805..d03fd88e4df0c8fd26c26975f960491cc77a5fe9 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.46 2002/06/20 20:29:38 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.47 2002/07/18 23:11:29 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -63,7 +63,6 @@ SetDefine(char *querystr, Oid elemType)
                                                         fileName,      /* probin */
                                                         false,         /* not aggregate */
                                                         false,         /* security invoker */
-                                                        false,         /* not implicit coercion */
                                                         false,         /* isStrict (irrelevant, no args) */
                                                         PROVOLATILE_VOLATILE,  /* assume unsafe */
                                                         100,           /* byte_pct */
index a724a0874eec35050497b54161ed2d5cb62cd7b1..5f0be16b75a8f20f50d8ee6887d36fe7f0489b2c 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.81 2002/07/11 07:39:27 ishii Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.82 2002/07/18 23:11:29 petere Exp $
  *
  * NOTES
  *       These routines allow the parser/planner/executor to perform
@@ -28,6 +28,7 @@
 #include "catalog/pg_aggregate.h"
 #include "catalog/pg_amop.h"
 #include "catalog/pg_amproc.h"
+#include "catalog/pg_cast.h"
 #include "catalog/pg_conversion.h"
 #include "catalog/pg_group.h"
 #include "catalog/pg_index.h"
@@ -174,6 +175,17 @@ static const struct cachedesc cacheinfo[] = {
                        0,
                        0
        }},
+       {
+               CastRelationName,                       /* CASTSOURCETARGET */
+               CastSourceTargetIndex,
+               0,
+               2,
+               {
+                       Anum_pg_cast_castsource,
+                       Anum_pg_cast_casttarget,
+                       0,
+                       0
+       }},
        {OperatorClassRelationName, /* CLAAMNAMENSP */
                OpclassAmNameNspIndex,
                0,
index 9902a24fc4f498b5206b44c403a26ab363b4c81b..f582da72c39ec938e26892e964d2ef0f3cc4d9d1 100644 (file)
@@ -27,7 +27,7 @@
 # Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
 # Portions Copyright (c) 1994, Regents of the University of California
 #
-# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.160 2002/07/18 16:47:25 tgl Exp $
+# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.161 2002/07/18 23:11:29 petere Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -708,6 +708,7 @@ $ECHO_N "initializing pg_depend... "$ECHO_C
 -- First delete any already-made entries; PINs override all else, and must
 -- be the only entries for their objects.
 DELETE FROM pg_depend;
+INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_cast;
 INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_class;
 INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_proc;
 INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_type;
index 827459b4db4ea98cdfd5bf5aafa2ac155d8a2c68..123ef3df056dcbb41c19330567dced91436383a8 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.65 2002/06/20 20:29:41 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.66 2002/07/18 23:11:29 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -170,6 +170,13 @@ dumpSchema(Archive *fout,
                dumpOprs(fout, oprinfo, numOperators);
        }
 
+       if (!dataOnly)
+       {
+               if (g_verbose)
+                       write_msg(NULL, "dumping out user-defined casts\n");
+               dumpCasts(fout, finfo, numFuncs, tinfo, numTypes);
+       }
+
        *numTablesPtr = numTables;
        return tblinfo;
 }
@@ -386,6 +393,23 @@ findFuncByOid(FuncInfo *finfo, int numFuncs, const char *oid)
        return -1;
 }
 
+/*
+ * Finds the index (in tinfo) of the type with the given OID.  Returns
+ * -1 if not found.
+ */
+int
+findTypeByOid(TypeInfo *tinfo, int numTypes, const char *oid)
+{
+       int                     i;
+
+       for (i = 0; i < numTypes; i++)
+       {
+               if (strcmp(tinfo[i].oid, oid) == 0)
+                       return i;
+       }
+       return -1;
+}
+
 /*
  * findOprByOid
  *       given the oid of an operator, return the name of the operator
index 1aefb9801aafa5b1e1928b2bdb553c130bc22549..a173839b4d4ca20d2b85350c6c90af4edf1f5ca9 100644 (file)
@@ -22,7 +22,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.273 2002/07/18 04:50:51 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.274 2002/07/18 23:11:29 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3398,7 +3398,6 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
        char       *prosrc;
        char       *probin;
        char       *provolatile;
-       char       *proimplicit;
        char       *proisstrict;
        char       *prosecdef;
        char       *lanname;
@@ -3417,7 +3416,7 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
        {
                appendPQExpBuffer(query,
                                                  "SELECT proretset, prosrc, probin, "
-                                                 "provolatile, proimplicit, proisstrict, prosecdef, "
+                                                 "provolatile, proisstrict, prosecdef, "
                                                  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
                                                  "FROM pg_catalog.pg_proc "
                                                  "WHERE oid = '%s'::pg_catalog.oid",
@@ -3428,7 +3427,6 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
                appendPQExpBuffer(query,
                                                  "SELECT proretset, prosrc, probin, "
                                                  "case when proiscachable then 'i' else 'v' end as provolatile, "
-                                                 "'f'::boolean as proimplicit, "
                                                  "proisstrict, "
                                                  "'f'::boolean as prosecdef, "
                                                  "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
@@ -3441,7 +3439,6 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
                appendPQExpBuffer(query,
                                                  "SELECT proretset, prosrc, probin, "
                                                  "case when proiscachable then 'i' else 'v' end as provolatile, "
-                                                 "'f'::boolean as proimplicit, "
                                                  "'f'::boolean as proisstrict, "
                                                  "'f'::boolean as prosecdef, "
                                                  "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
@@ -3472,7 +3469,6 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
        prosrc = PQgetvalue(res, 0, PQfnumber(res, "prosrc"));
        probin = PQgetvalue(res, 0, PQfnumber(res, "probin"));
        provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile"));
-       proimplicit = PQgetvalue(res, 0, PQfnumber(res, "proimplicit"));
        proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict"));
        prosecdef = PQgetvalue(res, 0, PQfnumber(res, "prosecdef"));
        lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname"));
@@ -3533,9 +3529,6 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
                }
        }
 
-       if (proimplicit[0] == 't')
-               appendPQExpBuffer(q, " IMPLICIT CAST");
-
        if (proisstrict[0] == 't')
                appendPQExpBuffer(q, " STRICT");
 
@@ -3569,6 +3562,108 @@ done:
        free(funcsig_tag);
 }
 
+
+/*
+ * Dump all casts
+ */
+void
+dumpCasts(Archive *fout,
+                 FuncInfo *finfo, int numFuncs,
+                 TypeInfo *tinfo, int numTypes)
+{
+       PGresult   *res;
+       PQExpBuffer query = createPQExpBuffer();
+       PQExpBuffer defqry = createPQExpBuffer();
+       PQExpBuffer delqry = createPQExpBuffer();
+       int                     ntups;
+       int                     i;
+
+       /* Make sure we are in proper schema */
+       selectSourceSchema("pg_catalog");
+
+       if (fout->remoteVersion >= 70300)
+               appendPQExpBuffer(query, "SELECT oid, castsource, casttarget, castfunc, castimplicit FROM pg_cast ORDER BY 1,2,3;");
+       else
+               appendPQExpBuffer(query, "SELECT p.oid, t1.oid, t2.oid, p.oid, true FROM pg_type t1, pg_type t2, pg_proc p WHERE p.pronargs = 1 AND p.proargtypes[0] = t1.oid AND p.prorettype = t2.oid AND p.proname = t2.typname ORDER BY 1,2,3;");
+
+       res = PQexec(g_conn, query->data);
+       if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
+       {
+               write_msg(NULL, "query to obtain list of casts failed: %s",
+                                 PQerrorMessage(g_conn));
+               exit_nicely();
+       }
+       ntups = PQntuples(res);
+
+       for (i = 0; i < ntups; i++)
+       {
+               char * castoid = PQgetvalue(res, i, 0);
+               char * castsource = PQgetvalue(res, i, 1);
+               char * casttarget = PQgetvalue(res, i, 2);
+               char * castfunc = PQgetvalue(res, i, 3);
+               char * castimplicit = PQgetvalue(res, i, 4);
+               int fidx = -1;
+               const char *((*deps)[]);
+
+               if (strcmp(castfunc, "0") != 0)
+                       fidx = findFuncByOid(finfo, numFuncs, castfunc);
+
+               /*
+                * We treat the cast as being in the namespace of the
+                * underlying function.  This doesn't handle binary compatible
+                * casts.  Where should those go?
+                */
+               if (fidx < 0 || !finfo[fidx].pronamespace->dump)
+                       continue;
+
+               /* Make a dependency to ensure function is dumped first */
+               if (fidx >= 0)
+               {
+                       deps = malloc(sizeof(char *) * 2);
+
+                       (*deps)[0] = strdup(castfunc);
+                       (*deps)[1] = NULL;      /* End of List */
+               }
+               else
+                       deps = NULL;
+
+               resetPQExpBuffer(defqry);
+               resetPQExpBuffer(delqry);
+
+               appendPQExpBuffer(delqry, "DROP CAST (%s AS %s);\n",
+                                                 getFormattedTypeName(castsource, zeroAsNone),
+                                                 getFormattedTypeName(casttarget, zeroAsNone));
+
+               appendPQExpBuffer(defqry, "CREATE CAST (%s AS %s) ",
+                                                 getFormattedTypeName(castsource, zeroAsNone),
+                                                 getFormattedTypeName(casttarget, zeroAsNone));
+
+               if (strcmp(castfunc, "0")==0)
+                       appendPQExpBuffer(defqry, "WITHOUT FUNCTION");
+               else
+                       appendPQExpBuffer(defqry, "WITH FUNCTION %s",
+                                                         format_function_signature(&finfo[fidx], true));
+
+               if (strcmp(castimplicit, "t")==0)
+                       appendPQExpBuffer(defqry, " AS ASSIGNMENT");
+               appendPQExpBuffer(defqry, ";\n");
+
+               ArchiveEntry(fout, castoid,
+                                        format_function_signature(&finfo[fidx], false),
+                                        finfo[fidx].pronamespace->nspname, "",
+                                        "CAST", deps,
+                                        defqry->data, delqry->data,
+                                        NULL, NULL, NULL);
+       }
+
+       PQclear(res);
+
+       destroyPQExpBuffer(query);
+       destroyPQExpBuffer(defqry);
+       destroyPQExpBuffer(delqry);
+}
+
+
 /*
  * dumpOprs
  *       writes out to fout the queries to recreate all the user-defined operators
index 17491b027e57d0cdacc114585b9b356e80c85055..732fdfb74e411aa2ee6d611e955481827032ddf5 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_dump.h,v 1.90 2002/07/06 20:12:30 momjian Exp $
+ * $Id: pg_dump.h,v 1.91 2002/07/18 23:11:29 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -177,6 +177,7 @@ typedef enum _OidOptions
 extern int     findTableByOid(TableInfo *tbinfo, int numTables, const char *oid);
 extern char *findOprByOid(OprInfo *oprinfo, int numOprs, const char *oid);
 extern int     findFuncByOid(FuncInfo *finfo, int numFuncs, const char *oid);
+extern int     findTypeByOid(TypeInfo *tinfo, int numTypes, const char *oid);
 
 extern void check_conn_and_db(void);
 extern void exit_nicely(void);
@@ -202,6 +203,8 @@ extern void dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs,
                  TypeInfo *tinfo, int numTypes);
 extern void dumpProcLangs(Archive *fout, FuncInfo finfo[], int numFuncs);
 extern void dumpFuncs(Archive *fout, FuncInfo finfo[], int numFuncs);
+extern void dumpCasts(Archive *fout, FuncInfo *finfo, int numFuncs,
+                                         TypeInfo *tinfo, int numTypes);
 extern void dumpAggs(Archive *fout, AggInfo agginfo[], int numAggregates);
 extern void dumpOprs(Archive *fout, OprInfo *oprinfo, int numOperators);
 extern void dumpTables(Archive *fout, TableInfo tblinfo[], int numTables,
index 0e452a9ca3e7c3f27fac9ac3e96b5487fd74158d..dc1fedae9e1db6b349b7df3260114af2ecfec0f6 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catname.h,v 1.28 2002/07/12 18:43:19 tgl Exp $
+ * $Id: catname.h,v 1.29 2002/07/18 23:11:30 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,6 +20,7 @@
 #define  AccessMethodOperatorRelationName "pg_amop"
 #define  AccessMethodProcedureRelationName "pg_amproc"
 #define  AttributeRelationName "pg_attribute"
+#define  CastRelationName "pg_cast"
 #define  ConstraintRelationName "pg_constraint"
 #define  ConversionRelationName "pg_conversion"
 #define  DatabaseRelationName "pg_database"
index 5fd581b254870a82320ff205d5b0944d2e526674..077da864a418d4577e6b032e9c65db57a1b80d05 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.140 2002/07/15 16:33:31 tgl Exp $
+ * $Id: catversion.h,v 1.141 2002/07/18 23:11:30 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200207141
+#define CATALOG_VERSION_NO     200207191
 
 #endif
index 91e35934470387e668f8cf8d4d409db5dee0f367..777a4031dd79b14f52682588642b1eb6684c379d 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: indexing.h,v 1.70 2002/07/15 16:33:31 tgl Exp $
+ * $Id: indexing.h,v 1.71 2002/07/18 23:11:30 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,6 +26,7 @@
 #define Num_pg_amproc_indices          1
 #define Num_pg_attr_indices                    2
 #define Num_pg_attrdef_indices         2
+#define Num_pg_cast_indices                    1
 #define Num_pg_class_indices           2
 #define Num_pg_constraint_indices      3
 #define Num_pg_conversion_indices      3
@@ -60,6 +61,7 @@
 #define AttrDefaultOidIndex                    "pg_attrdef_oid_index"
 #define AttributeRelidNameIndex                "pg_attribute_relid_attnam_index"
 #define AttributeRelidNumIndex         "pg_attribute_relid_attnum_index"
+#define CastSourceTargetIndex          "pg_cast_source_target_index"
 #define ClassNameNspIndex                      "pg_class_relname_nsp_index"
 #define ClassOidIndex                          "pg_class_oid_index"
 #define ConstraintNameNspIndex         "pg_constraint_conname_nsp_index"
@@ -108,6 +110,7 @@ extern char *Name_pg_amop_indices[];
 extern char *Name_pg_amproc_indices[];
 extern char *Name_pg_attr_indices[];
 extern char *Name_pg_attrdef_indices[];
+extern char *Name_pg_cast_indices[];
 extern char *Name_pg_class_indices[];
 extern char *Name_pg_constraint_indices[];
 extern char *Name_pg_conversion_indices[];
@@ -166,6 +169,7 @@ DECLARE_UNIQUE_INDEX(pg_attrdef_adrelid_adnum_index on pg_attrdef using btree(ad
 DECLARE_UNIQUE_INDEX(pg_attrdef_oid_index on pg_attrdef using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index on pg_attribute using btree(attrelid oid_ops, attname name_ops));
 DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnum_index on pg_attribute using btree(attrelid oid_ops, attnum int2_ops));
+DECLARE_UNIQUE_INDEX(pg_cast_source_target_index on pg_cast using btree(castsource oid_ops, casttarget oid_ops));
 DECLARE_UNIQUE_INDEX(pg_class_oid_index on pg_class using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index on pg_class using btree(relname name_ops, relnamespace oid_ops));
 /* This following index is not used for a cache and is not unique */
diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h
new file mode 100644 (file)
index 0000000..4e042a3
--- /dev/null
@@ -0,0 +1,225 @@
+/*-------------------------------------------------------------------------
+ *
+ * $Header: /cvsroot/pgsql/src/include/catalog/pg_cast.h,v 1.1 2002/07/18 23:11:30 petere Exp $
+ *
+ * Copyright (c) 2002, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CAST_H
+#define PG_CAST_H
+
+CATALOG(pg_cast)
+{
+       Oid                     castsource;
+       Oid                     casttarget;
+       Oid                     castfunc;               /* 0 = binary compatible */
+       bool            castimplicit;
+} FormData_pg_cast;
+
+typedef FormData_pg_cast *Form_pg_cast;
+
+#define Natts_pg_cast                          4
+#define Anum_pg_cast_castsource                1
+#define Anum_pg_cast_casttarget                2
+#define Anum_pg_cast_castfunc          3
+#define Anum_pg_cast_castimplicit      4
+
+/* ----------------
+ *             initial contents of pg_cast
+ * ----------------
+ */
+
+/*
+ * binary compatible casts
+ */
+DATA(insert (   25 1042    0 t ));
+DATA(insert (   25 1043    0 t ));
+DATA(insert ( 1042   25    0 t ));
+DATA(insert ( 1042 1043    0 t ));
+DATA(insert ( 1043   25    0 t ));
+DATA(insert ( 1043 1042    0 t ));
+
+DATA(insert (   23   24    0 t ));
+DATA(insert (   23   26    0 t ));
+DATA(insert (   23 2202    0 t ));
+DATA(insert (   23 2203    0 t ));
+DATA(insert (   23 2204    0 t ));
+DATA(insert (   23 2205    0 t ));
+DATA(insert (   23 2206    0 t ));
+DATA(insert (   24   23    0 t ));
+DATA(insert (   24   26    0 t ));
+DATA(insert (   24 2202    0 t ));
+DATA(insert (   24 2203    0 t ));
+DATA(insert (   24 2204    0 t ));
+DATA(insert (   24 2205    0 t ));
+DATA(insert (   24 2206    0 t ));
+DATA(insert (   26   23    0 t ));
+DATA(insert (   26   24    0 t ));
+DATA(insert (   26 2202    0 t ));
+DATA(insert (   26 2203    0 t ));
+DATA(insert (   26 2204    0 t ));
+DATA(insert (   26 2205    0 t ));
+DATA(insert (   26 2206    0 t ));
+DATA(insert ( 2202   23    0 t ));
+DATA(insert ( 2202   24    0 t ));
+DATA(insert ( 2202   26    0 t ));
+DATA(insert ( 2202 2203    0 t ));
+DATA(insert ( 2202 2204    0 t ));
+DATA(insert ( 2202 2205    0 t ));
+DATA(insert ( 2202 2206    0 t ));
+DATA(insert ( 2203   23    0 t ));
+DATA(insert ( 2203   24    0 t ));
+DATA(insert ( 2203   26    0 t ));
+DATA(insert ( 2203 2202    0 t ));
+DATA(insert ( 2203 2204    0 t ));
+DATA(insert ( 2203 2205    0 t ));
+DATA(insert ( 2203 2206    0 t ));
+DATA(insert ( 2204   23    0 t ));
+DATA(insert ( 2204   24    0 t ));
+DATA(insert ( 2204   26    0 t ));
+DATA(insert ( 2204 2202    0 t ));
+DATA(insert ( 2204 2203    0 t ));
+DATA(insert ( 2204 2205    0 t ));
+DATA(insert ( 2204 2206    0 t ));
+DATA(insert ( 2205   23    0 t ));
+DATA(insert ( 2205   24    0 t ));
+DATA(insert ( 2205   26    0 t ));
+DATA(insert ( 2205 2202    0 t ));
+DATA(insert ( 2205 2203    0 t ));
+DATA(insert ( 2205 2204    0 t ));
+DATA(insert ( 2205 2206    0 t ));
+DATA(insert ( 2206   23    0 t ));
+DATA(insert ( 2206   24    0 t ));
+DATA(insert ( 2206   26    0 t ));
+DATA(insert ( 2206 2202    0 t ));
+DATA(insert ( 2206 2203    0 t ));
+DATA(insert ( 2206 2204    0 t ));
+DATA(insert ( 2206 2205    0 t ));
+
+DATA(insert (   23  702    0 t ));
+DATA(insert (  702   23    0 t ));
+
+DATA(insert (   23  703    0 t ));
+DATA(insert (  703   23    0 t ));
+
+DATA(insert (  650  869    0 t ));
+DATA(insert (  869  650    0 t ));
+
+DATA(insert ( 1560 1562    0 t ));
+DATA(insert ( 1562 1560    0 t ));
+
+/*
+ * regular casts through a function
+ *
+ * This list can be obtained from the following query as long as the
+ * naming convention of the cast functions remains the same:
+ *
+ * select p.proargtypes[0] as source, p.prorettype as target, p.oid as func, p.proimplicit as implicit from pg_proc p, pg_type t where p.pronargs=1 and p.proname = t.typname and p.prorettype = t.oid order by 1, 2;
+ */
+DATA(insert (   18   25  946 t ));
+DATA(insert (   18 1042  860 t ));
+DATA(insert (   19   25  406 t ));
+DATA(insert (   19 1042  408 t ));
+DATA(insert (   19 1043 1401 t ));
+DATA(insert (   20   21  714 t ));
+DATA(insert (   20   23  480 t ));
+DATA(insert (   20   25 1288 t ));
+DATA(insert (   20  701  482 t ));
+DATA(insert (   20 1043 1623 f ));
+DATA(insert (   20 1700 1781 t ));
+DATA(insert (   21   20  754 t ));
+DATA(insert (   21   23  313 t ));
+DATA(insert (   21   25  113 t ));
+DATA(insert (   21  700  236 t ));
+DATA(insert (   21  701  235 t ));
+DATA(insert (   21 1700 1782 t ));
+DATA(insert (   23   20  481 t ));
+DATA(insert (   23   21  314 t ));
+DATA(insert (   23   25  112 t ));
+DATA(insert (   23  700  318 t ));
+DATA(insert (   23  701  316 t ));
+/*xDATA(insert (   23  703 1200 f ));*/
+DATA(insert (   23 1043 1619 f ));
+DATA(insert (   23 1700 1740 t ));
+DATA(insert (   25   18  944 t ));
+DATA(insert (   25   19  407 t ));
+DATA(insert (   25   20 1289 f ));
+DATA(insert (   25   21  818 f ));
+DATA(insert (   25   23  819 f ));
+DATA(insert (   25   26  817 f ));
+DATA(insert (   25  650 1714 f ));
+DATA(insert (   25  700  839 f ));
+DATA(insert (   25  701  838 f ));
+DATA(insert (   25  829  767 f ));
+DATA(insert (   25  869 1713 f ));
+DATA(insert (   25 1082  748 f ));
+DATA(insert (   25 1083  837 f ));
+DATA(insert (   25 1114 2022 f ));
+DATA(insert (   25 1184 1191 f ));
+DATA(insert (   25 1186 1263 f ));
+DATA(insert (   25 1266  938 f ));
+DATA(insert (   26   25  114 f ));
+DATA(insert (  601  600 1532 f ));
+DATA(insert (  602  600 1533 f ));
+DATA(insert (  602  604 1449 f ));
+DATA(insert (  603  600 1534 f ));
+DATA(insert (  603  601 1541 f ));
+DATA(insert (  603  604 1448 f ));
+DATA(insert (  603  718 1479 f ));
+DATA(insert (  604  600 1540 f ));
+DATA(insert (  604  602 1447 f ));
+DATA(insert (  604  603 1446 f ));
+DATA(insert (  604  718 1474 f ));
+DATA(insert (  700   21  238 f ));
+DATA(insert (  700   23  319 f ));
+DATA(insert (  700   25  841 t ));
+DATA(insert (  700  701  311 t ));
+DATA(insert (  700 1700 1742 t ));
+DATA(insert (  701   20  483 f ));
+DATA(insert (  701   21  237 f ));
+DATA(insert (  701   23  317 f ));
+DATA(insert (  701   25  840 t ));
+DATA(insert (  701  700  312 t ));
+DATA(insert (  701 1700 1743 t ));
+DATA(insert (  702 1082 1179 f ));
+DATA(insert (  702 1083 1364 f ));
+DATA(insert (  702 1114 2023 t ));
+DATA(insert (  702 1184 1173 t ));
+DATA(insert (  703 1186 1177 t ));
+DATA(insert (  718  600 1416 f ));
+DATA(insert (  718  603 1480 f ));
+DATA(insert (  718  604 1544 f ));
+DATA(insert (  829   25  752 f ));
+DATA(insert (  869   25  730 f ));
+DATA(insert ( 1042   19  409 t ));
+DATA(insert ( 1043   19 1400 t ));
+DATA(insert ( 1082   25  749 t ));
+DATA(insert ( 1082 1114 2024 t ));
+DATA(insert ( 1082 1184 1174 t ));
+DATA(insert ( 1083   25  948 t ));
+DATA(insert ( 1083 1186 1370 t ));
+DATA(insert ( 1083 1266 2047 t ));
+DATA(insert ( 1114   25 2034 t ));
+DATA(insert ( 1114  702 2030 f ));
+DATA(insert ( 1114 1082 2029 f ));
+DATA(insert ( 1114 1083 1316 f ));
+DATA(insert ( 1114 1184 2028 t ));
+DATA(insert ( 1184   25 1192 t ));
+DATA(insert ( 1184  702 1180 f ));
+DATA(insert ( 1184 1082 1178 f ));
+DATA(insert ( 1184 1083 2019 f ));
+DATA(insert ( 1184 1114 2027 t ));
+DATA(insert ( 1184 1266 1388 f ));
+DATA(insert ( 1186   25 1193 t ));
+DATA(insert ( 1186  703 1194 f ));
+DATA(insert ( 1186 1083 1419 f ));
+DATA(insert ( 1266   25  939 t ));
+DATA(insert ( 1266 1083 2046 t ));
+DATA(insert ( 1700   20 1779 f ));
+DATA(insert ( 1700   21 1783 f ));
+DATA(insert ( 1700   23 1744 f ));
+DATA(insert ( 1700  700 1745 f ));
+DATA(insert ( 1700  701 1746 f ));
+
+#endif   /* PG_CAST_H */
index 0bb719a55ab72decaeb87ff862e79125551f3cd8..c84ac13a9591d7e9c11f4933d767eb28bf264c2b 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_proc.h,v 1.243 2002/06/20 20:29:44 momjian Exp $
+ * $Id: pg_proc.h,v 1.244 2002/07/18 23:11:30 petere Exp $
  *
  * NOTES
  *       The script catalog/genbki.sh reads this file and generates .bki
@@ -45,7 +45,7 @@ CATALOG(pg_proc) BOOTSTRAP
        Oid                     prolang;                /* OID of pg_language entry */
        bool            proisagg;               /* is it an aggregate? */
        bool            prosecdef;              /* security definer */
-       bool            proimplicit;    /* can be invoked as implicit coercion? */
+       bool            proimplicit;    /* unused */
        bool            proisstrict;    /* strict with respect to NULLs? */
        bool            proretset;              /* returns a set? */
        char            provolatile;    /* see PROVOLATILE_ categories below */
@@ -3007,7 +3007,6 @@ extern Oid ProcedureCreate(const char *procedureName,
                                const char *probin,
                                bool isAgg,
                                bool security_definer,
-                               bool isImplicit,
                                bool isStrict,
                                char volatility,
                                int32 byte_pct,
index 169ec3f3dff1dc132428a0600ac5ceaa750c32c1..707ba1d1b819f6dd9707e4a9288e10695558b81e 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: defrem.h,v 1.41 2002/07/12 18:43:19 tgl Exp $
+ * $Id: defrem.h,v 1.42 2002/07/18 23:11:32 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -42,6 +42,9 @@ extern void ReindexDatabase(const char *databaseName, bool force, bool all);
 extern void CreateFunction(CreateFunctionStmt *stmt);
 extern void RemoveFunction(RemoveFuncStmt *stmt);
 extern void RemoveFunctionById(Oid funcOid);
+extern void CreateCast(CreateCastStmt *stmt);
+extern void DropCast(DropCastStmt *stmt);
+extern void DropCastById(Oid castOid);
 
 extern void DefineOperator(List *names, List *parameters);
 extern void RemoveOperator(RemoveOperStmt *stmt);
index 308bf95877d462c25020b23b0e75ae290d2f0e4d..3583315a274a24f3a527877ef41c8a3d048adbaf 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: nodes.h,v 1.112 2002/07/18 17:14:20 momjian Exp $
+ * $Id: nodes.h,v 1.113 2002/07/18 23:11:32 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -199,6 +199,8 @@ typedef enum NodeTag
        T_AlterDatabaseSetStmt,
        T_AlterUserSetStmt,
        T_CreateConversionStmt,
+       T_CreateCastStmt,
+       T_DropCastStmt,
 
        T_A_Expr = 700,
        T_ColumnRef,
index b2e42ab71648b88ae48cfb215a06df54a5175253..e4c6b625d11f0ce5d3f6d130e4e939c732e27296 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: parsenodes.h,v 1.192 2002/07/18 17:14:20 momjian Exp $
+ * $Id: parsenodes.h,v 1.193 2002/07/18 23:11:32 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1555,4 +1555,30 @@ typedef struct CreateConversionStmt
        bool            def;                            /* is this a default conversion? */
 } CreateConversionStmt;
 
+/* ----------------------
+ *     CREATE CAST Statement
+ * ----------------------
+ */
+typedef struct CreateCastStmt
+{
+       NodeTag         type;
+       TypeName   *sourcetype;
+       TypeName   *targettype;
+       FuncWithArgs *func;
+       bool            implicit;
+} CreateCastStmt;
+
+/* ----------------------
+ *     DROP CAST Statement
+ * ----------------------
+ */
+typedef struct DropCastStmt
+{
+       NodeTag         type;
+       TypeName   *sourcetype;
+       TypeName   *targettype;
+       DropBehavior behavior;
+} DropCastStmt;
+
+
 #endif   /* PARSENODES_H */
index f40471d7948754c01e645dce11330dbe905eb172..5d964bb5668815c1c977af3272085c4741574b66 100644 (file)
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: syscache.h,v 1.49 2002/07/11 07:39:28 ishii Exp $
+ * $Id: syscache.h,v 1.50 2002/07/18 23:11:32 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
 #define AMPROCNUM              5
 #define ATTNAME                        6
 #define ATTNUM                 7
-#define CLAAMNAMENSP   8
-#define CLAOID                 9
-#define CONNAMESP              10
-#define GRONAME                        11
-#define GROSYSID               12
-#define INDEXRELID             13
-#define INHRELID               14
-#define LANGNAME               15
-#define LANGOID                        16
-#define NAMESPACENAME  17
-#define NAMESPACEOID   18
-#define OPERNAMENSP            19
-#define OPEROID                        20
-#define PROCNAMENSP            21
-#define PROCOID                        22
-#define RELNAMENSP             23
-#define RELOID                 24
-#define RULERELNAME            25
-#define SHADOWNAME             26
-#define SHADOWSYSID            27
-#define STATRELATT             28
-#define TYPENAMENSP            29
-#define TYPEOID                        30
+#define CASTSOURCETARGET 8
+#define CLAAMNAMENSP   9
+#define CLAOID                 10
+#define CONNAMESP              11
+#define GRONAME                        12
+#define GROSYSID               13
+#define INDEXRELID             14
+#define INHRELID               15
+#define LANGNAME               16
+#define LANGOID                        17
+#define NAMESPACENAME  18
+#define NAMESPACEOID   19
+#define OPERNAMENSP            20
+#define OPEROID                        21
+#define PROCNAMENSP            22
+#define PROCOID                        23
+#define RELNAMENSP             24
+#define RELOID                 25
+#define RULERELNAME            26
+#define SHADOWNAME             27
+#define SHADOWSYSID            28
+#define STATRELATT             29
+#define TYPENAMENSP            30
+#define TYPEOID                        31
 
 extern void InitCatalogCache(void);
 extern void InitCatalogCachePhase2(void);
index 98ac26c0c20788ebf8892ff2d950312e130c796d..cb1193b0407eb9365024747b864e7cac47d58c60 100644 (file)
@@ -1,7 +1,7 @@
 --
 -- OPR_SANITY
 -- Sanity checks for common errors in making operator/procedure system tables:
--- pg_operator, pg_proc, pg_aggregate, pg_am, pg_amop, pg_amproc, pg_opclass.
+-- pg_operator, pg_proc, pg_cast, pg_aggregate, pg_am, pg_amop, pg_amproc, pg_opclass.
 --
 -- None of the SELECTs here should ever find any matching entries,
 -- so the expected output is easy to maintain ;-).
@@ -180,20 +180,49 @@ WHERE p1.oid != p2.oid AND
 -------------+-------------
 (0 rows)
 
--- If a proc is marked as an implicit cast, then it should be something that
--- the system might actually use as a cast function: name same as the name
--- of its output type, and either one arg that's a different type, or two
--- args where the first is the same as the output type and the second is int4.
-SELECT p1.oid, p1.proname
-FROM pg_proc as p1
-WHERE p1.proimplicit AND
-    (NOT EXISTS (SELECT 1 FROM pg_type t WHERE t.oid = p1.prorettype AND
-                 t.typname = p1.proname) OR
-     NOT ((p1.pronargs = 1 AND p1.proargtypes[0] != prorettype) OR
-          (p1.pronargs = 2 AND p1.proargtypes[0] = prorettype AND
-           p1.proargtypes[1] = 'int4'::regtype)));
- oid | proname 
------+---------
+-- **************** pg_cast ****************
+-- Look for casts from and to the same type.  This is not harmful, but
+-- useless.
+SELECT *
+FROM pg_cast c
+WHERE c.castsource = c.casttarget;
+ castsource | casttarget | castfunc | castimplicit 
+------------+------------+----------+--------------
+(0 rows)
+
+-- Look for cast functions with incorrect number or type of argument
+-- or return value.
+SELECT c.*
+FROM pg_cast c, pg_proc p
+WHERE c.castfunc = p.oid AND
+    (p.pronargs <> 1 OR
+     p.proargtypes[0] <> c.castsource OR
+     p.prorettype <> c.casttarget);
+ castsource | casttarget | castfunc | castimplicit 
+------------+------------+----------+--------------
+(0 rows)
+
+-- Look for binary compatible casts that are not implicit.  This is
+-- legal, but probably not intended.
+SELECT *
+FROM pg_cast c
+WHERE c.castfunc = 0 AND NOT c.castimplicit;
+ castsource | casttarget | castfunc | castimplicit 
+------------+------------+----------+--------------
+(0 rows)
+
+-- Look for binary compatible casts that do not have the reverse
+-- direction registered as well, or where the reverse direction is not
+-- also binary compatible.  This is legal, but probably not intended.
+SELECT *
+FROM pg_cast c
+WHERE c.castfunc = 0 AND
+    NOT EXISTS (SELECT * FROM pg_cast k
+                WHERE k.castfunc = 0 AND
+                    k.castsource = c.casttarget AND
+                    k.casttarget = c.castsource);
+ castsource | casttarget | castfunc | castimplicit 
+------------+------------+----------+--------------
 (0 rows)
 
 -- **************** pg_operator ****************
index 2e0cf3a03300daa482a2aba217aa99510c74f103..25e7b091c22e0b8a9313927f7177915ffe253668 100644 (file)
@@ -37,6 +37,7 @@ SELECT relname, relhasindex
  pg_amproc           | t
  pg_attrdef          | t
  pg_attribute        | t
+ pg_cast             | t
  pg_class            | t
  pg_constraint       | t
  pg_conversion       | t
@@ -62,5 +63,5 @@ SELECT relname, relhasindex
  shighway            | t
  tenk1               | t
  tenk2               | t
-(52 rows)
+(53 rows)
 
index 270c275b87a4907225fa9149501eb1f04ab442a6..9d08dbd5bb37f2a780b47c6034e6243a38e91966 100644 (file)
@@ -1,7 +1,7 @@
 --
 -- OPR_SANITY
 -- Sanity checks for common errors in making operator/procedure system tables:
--- pg_operator, pg_proc, pg_aggregate, pg_am, pg_amop, pg_amproc, pg_opclass.
+-- pg_operator, pg_proc, pg_cast, pg_aggregate, pg_am, pg_amop, pg_amproc, pg_opclass.
 --
 -- None of the SELECTs here should ever find any matching entries,
 -- so the expected output is easy to maintain ;-).
@@ -141,19 +141,43 @@ WHERE p1.oid != p2.oid AND
     NOT p1.proisagg AND NOT p2.proisagg AND
     (p1.proargtypes[7] < p2.proargtypes[7]);
 
--- If a proc is marked as an implicit cast, then it should be something that
--- the system might actually use as a cast function: name same as the name
--- of its output type, and either one arg that's a different type, or two
--- args where the first is the same as the output type and the second is int4.
+-- **************** pg_cast ****************
 
-SELECT p1.oid, p1.proname
-FROM pg_proc as p1
-WHERE p1.proimplicit AND
-    (NOT EXISTS (SELECT 1 FROM pg_type t WHERE t.oid = p1.prorettype AND
-                 t.typname = p1.proname) OR
-     NOT ((p1.pronargs = 1 AND p1.proargtypes[0] != prorettype) OR
-          (p1.pronargs = 2 AND p1.proargtypes[0] = prorettype AND
-           p1.proargtypes[1] = 'int4'::regtype)));
+-- Look for casts from and to the same type.  This is not harmful, but
+-- useless.
+
+SELECT *
+FROM pg_cast c
+WHERE c.castsource = c.casttarget;
+
+-- Look for cast functions with incorrect number or type of argument
+-- or return value.
+
+SELECT c.*
+FROM pg_cast c, pg_proc p
+WHERE c.castfunc = p.oid AND
+    (p.pronargs <> 1 OR
+     p.proargtypes[0] <> c.castsource OR
+     p.prorettype <> c.casttarget);
+
+-- Look for binary compatible casts that are not implicit.  This is
+-- legal, but probably not intended.
+
+SELECT *
+FROM pg_cast c
+WHERE c.castfunc = 0 AND NOT c.castimplicit;
+
+-- Look for binary compatible casts that do not have the reverse
+-- direction registered as well, or where the reverse direction is not
+-- also binary compatible.  This is legal, but probably not intended.
+
+SELECT *
+FROM pg_cast c
+WHERE c.castfunc = 0 AND
+    NOT EXISTS (SELECT * FROM pg_cast k
+                WHERE k.castfunc = 0 AND
+                    k.castsource = c.casttarget AND
+                    k.casttarget = c.castsource);
 
 -- **************** pg_operator ****************