pg_cast table, and standards-compliant CREATE/DROP CAST commands, plus
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.
This commit is contained in:
parent
a345ac8842
commit
97377048b4
|
@ -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">
|
||||
|
|
|
@ -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:
|
||||
-->
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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:
|
||||
-->
|
|
@ -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;
|
||||
©Table;
|
||||
&createAggregate;
|
||||
&createCast;
|
||||
&createConstraint;
|
||||
&createDatabase;
|
||||
&createDomain;
|
||||
|
@ -80,6 +81,7 @@ PostgreSQL Reference Manual
|
|||
&declare;
|
||||
&delete;
|
||||
&dropAggregate;
|
||||
&dropCast;
|
||||
&dropDatabase;
|
||||
&dropDomain;
|
||||
&dropFunction;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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] =
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
ReleaseSysCache(typeTuple);
|
||||
return expr;
|
||||
}
|
||||
/* It must also be an implicit cast. */
|
||||
castStruct = (Form_pg_cast) GETSTRUCT(castTuple);
|
||||
if (!castStruct->castimplicit)
|
||||
{
|
||||
ReleaseSysCache(procTuple);
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -36,29 +36,30 @@
|
|||
#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);
|
||||
|
|
|
@ -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 ****************
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 ****************
|
||||
|
||||
|
|
Loading…
Reference in New Issue