mirror of https://github.com/postgres/postgres
Extend syntax of CREATE FUNCTION to resemble SQL99.
This commit is contained in:
parent
97f7ceaaa6
commit
94bdc4855c
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.37 2002/04/23 02:07:15 tgl Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.38 2002/05/17 18:32:52 petere Exp $
|
||||
-->
|
||||
|
||||
<refentry id="SQL-CREATEFUNCTION">
|
||||
|
@ -17,13 +17,13 @@ $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.37 2002/04/23
|
|||
<synopsis>
|
||||
CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceable class="parameter">argtype</replaceable> [, ...] ] )
|
||||
RETURNS <replaceable class="parameter">rettype</replaceable>
|
||||
AS '<replaceable class="parameter">definition</replaceable>'
|
||||
LANGUAGE <replaceable class="parameter">langname</replaceable>
|
||||
[ WITH ( <replaceable class="parameter">attribute</replaceable> [, ...] ) ]
|
||||
CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceable class="parameter">argtype</replaceable> [, ...] ] )
|
||||
RETURNS <replaceable class="parameter">rettype</replaceable>
|
||||
AS '<replaceable class="parameter">obj_file</replaceable>', '<replaceable class="parameter">link_symbol</replaceable>'
|
||||
LANGUAGE <replaceable class="parameter">langname</replaceable>
|
||||
{ LANGUAGE <replaceable class="parameter">langname</replaceable>
|
||||
| IMMUTABLE | STABLE | VOLATILE
|
||||
| CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
|
||||
| IMPLICIT CAST
|
||||
| AS '<replaceable class="parameter">definition</replaceable>'
|
||||
| AS '<replaceable class="parameter">obj_file</replaceable>', '<replaceable class="parameter">link_symbol</replaceable>'
|
||||
} ...
|
||||
[ WITH ( <replaceable class="parameter">attribute</replaceable> [, ...] ) ]
|
||||
</synopsis>
|
||||
</refsynopsisdiv>
|
||||
|
@ -33,8 +33,13 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
|
|||
|
||||
<para>
|
||||
<command>CREATE FUNCTION</command> defines a new function.
|
||||
<command>CREATE OR REPLACE FUNCTION</command> will either create
|
||||
a new function, or replace an existing definition.
|
||||
<command>CREATE OR REPLACE FUNCTION</command> will either create a
|
||||
new function, or replace an existing definition.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The user that creates the function becomes the owner of the function.
|
||||
</para>
|
||||
|
||||
<variablelist>
|
||||
<title>Parameters</title>
|
||||
|
@ -81,7 +86,7 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
|
|||
|
||||
<listitem>
|
||||
<para>
|
||||
The return data type. The output type may be specified as a
|
||||
The return data type. The return type may be specified as a
|
||||
base type, complex type, <literal>setof</literal> type,
|
||||
<literal>opaque</literal>, or the same as the type of an
|
||||
existing column.
|
||||
|
@ -95,6 +100,105 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">langname</replaceable></term>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
The name of the language that the function is implemented in.
|
||||
May be <literal>SQL</literal>, <literal>C</literal>,
|
||||
<literal>internal</literal>, or the name of a user-defined
|
||||
procedural language. (See also <xref linkend="app-createlang"
|
||||
endterm="app-createlang-title">.) For backward compatibility,
|
||||
the name may be enclosed by single quotes.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>IMMUTABLE</term>
|
||||
<term>STABLE</term>
|
||||
<term>VOLATILE</term>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
These attributes inform the system whether it is safe to
|
||||
replace multiple evaluations of the function with a single
|
||||
evaluation, for run-time optimization. At most one choice
|
||||
should be specified. If none of these appear,
|
||||
<literal>VOLATILE</literal> is the default assumption.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<literal>IMMUTABLE</literal> indicates that the function always
|
||||
returns the same result when given the same argument values; that
|
||||
is, it does not do database lookups or otherwise use information not
|
||||
directly present in its parameter list. If this option is given,
|
||||
any call of the function with all-constant arguments can be
|
||||
immediately replaced with the function value.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<literal>STABLE</literal> indicates that within a single table scan
|
||||
the function will consistently
|
||||
return the same result for the same argument values, but that its
|
||||
result could change across SQL statements. This is the appropriate
|
||||
selection for functions whose results depend on database lookups,
|
||||
parameter variables (such as the current time zone), etc. Also note
|
||||
that the <literal>CURRENT_TIMESTAMP</> family of functions qualify
|
||||
as stable, since their values do not change within a transaction.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<literal>VOLATILE</literal> indicates that the function value can
|
||||
change even within a single table scan, so no optimizations can be
|
||||
made. Relatively few database functions are volatile in this sense;
|
||||
some examples are <literal>random()</>, <literal>currval()</>,
|
||||
<literal>timeofday()</>. Note that any function that has side-effects
|
||||
must be classified volatile, even if its result is quite predictable,
|
||||
to prevent calls from being optimized away; an example is
|
||||
<literal>setval()</>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>CALLED ON NULL INPUT</term>
|
||||
<term>RETURNS NULL ON NULL INPUT</term>
|
||||
<term>STRICT</term>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>CALLED ON NULL INPUT</literal> (the default) indicates
|
||||
that the function will be called normally when some of its
|
||||
arguments are null. It is then the function author's
|
||||
responsibility to check for NULLs if necessary and respond
|
||||
appropriately.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<literal>RETURNS NULL ON NULL INPUT</literal> or
|
||||
<literal>STRICT</literal> indicates that the function always
|
||||
returns NULL whenever any of its arguments are NULL. If this
|
||||
parameter is specified, the function is not executed when there
|
||||
are NULL arguments; instead a NULL result is assumed
|
||||
automatically.
|
||||
</para>
|
||||
</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><replaceable class="parameter">definition</replaceable></term>
|
||||
|
||||
|
@ -125,116 +229,56 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
|
|||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">langname</replaceable></term>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
May be <literal>SQL</literal>, <literal>C</literal>,
|
||||
<literal>internal</literal>, or <replaceable
|
||||
class="parameter">plname</replaceable>, where <replaceable
|
||||
class="parameter">plname</replaceable> is the name of a
|
||||
created procedural language. See
|
||||
<xref linkend="sql-createlanguage" endterm="sql-createlanguage-title">
|
||||
for details. For backward compatibility, the name may be
|
||||
enclosed by single quotes.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><replaceable class="parameter">attribute</replaceable></term>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
An optional piece of information about the function, used for
|
||||
optimization. See below for details.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
The historical way to specify optional pieces of information
|
||||
about the function. The following attributes may appear here:
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>isStrict</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Equivalent to <literal>STRICT</literal> or <literal>RETURNS NULL ON NULL INPUT</literal>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>isImmutable</term>
|
||||
<term>isCachable</term>
|
||||
<term>isStable</term>
|
||||
<term>isVolatile</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Equivalent to <literal>IMMUTABLE</literal>,
|
||||
<literal>STABLE</literal>, <literal>VOLATILE</literal>.
|
||||
<literal>isCachable</literal> is an obsolete equivalent of
|
||||
<literal>isImmutable</literal>; it's still accepted for
|
||||
backwards-compatibility reasons.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>implicitCoercion</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Same as <literal>IMPLICIT CAST</literal>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
Attribute names are not case-sensitive.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The user that creates the function becomes the owner of the function.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The following attributes may appear in the WITH clause:
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>isStrict</term>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>isStrict</option> indicates that the function always
|
||||
returns NULL whenever any of its arguments are NULL. If this
|
||||
attribute is specified, the function is not executed when there
|
||||
are NULL arguments; instead a NULL result is assumed automatically.
|
||||
When <option>isStrict</option> is not specified, the function will
|
||||
be called for NULL inputs. It is then the function author's
|
||||
responsibility to check for NULLs if necessary and respond
|
||||
appropriately.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>isImmutable</term>
|
||||
<term>isCachable</term>
|
||||
<term>isStable</term>
|
||||
<term>isVolatile</term>
|
||||
<listitem>
|
||||
<para>
|
||||
These attributes inform the system whether it is safe to replace
|
||||
multiple evaluations of the function with a single evaluation.
|
||||
At most one choice should be specified. (If none of these appear,
|
||||
<option>isVolatile</option> is the default assumption.)
|
||||
<option>isImmutable</option> indicates that the function always
|
||||
returns the same result when given the same argument values; that
|
||||
is, it does not do database lookups or otherwise use information not
|
||||
directly present in its parameter list. If this option is given,
|
||||
any call of the function with all-constant arguments can be
|
||||
immediately replaced with the function value.
|
||||
<option>isCachable</option> is an
|
||||
obsolete equivalent of <option>isImmutable</option>; it's still
|
||||
accepted for backwards-compatibility reasons.
|
||||
<option>isStable</option> indicates that within a single table scan
|
||||
the function will consistently
|
||||
return the same result for the same argument values, but that its
|
||||
result could change across SQL statements. This is the appropriate
|
||||
selection for functions whose results depend on database lookups,
|
||||
parameter variables (such as the current timezone), etc. Also note
|
||||
that the <literal>CURRENT_TIMESTAMP</> family of functions qualify
|
||||
as stable, since their values do not change within a transaction.
|
||||
<option>isVolatile</option> indicates that the function value can
|
||||
change even within a single table scan, so no optimizations can be
|
||||
made. Relatively few database functions are volatile in this sense;
|
||||
some examples are <literal>random()</>, <literal>currval()</>,
|
||||
<literal>timeofday()</>. Note that any function that has side-effects
|
||||
must be classified volatile, even if its result is quite predictable,
|
||||
to prevent calls from being optimized away; an example is
|
||||
<literal>setval()</>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>implicitCoercion</term>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>implicitCoercion</option> indicates that the function
|
||||
may be used for implicit type conversions.
|
||||
See <xref linkend="coercion-functions"
|
||||
endterm="coercion-functions-title"> for more detail.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
Attribute names are not case-sensitive.
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
|
||||
|
@ -328,21 +372,18 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
|
|||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="COERCION-FUNCTIONS">
|
||||
<refsect1info>
|
||||
<date>2002-04-11</date>
|
||||
</refsect1info>
|
||||
<title id="coercion-functions-title">
|
||||
Type Coercion Functions
|
||||
<refsect1 id="sql-createfunction-cast-function">
|
||||
<title id="sql-createfunction-cast-functions-title">
|
||||
Type Cast Functions
|
||||
</title>
|
||||
<para>
|
||||
A function that has one parameter and is named the same as its output
|
||||
datatype (including the schema name) is considered to be a <firstterm>type
|
||||
coercion function</>: it can be invoked to convert a value of its input
|
||||
datatype into a value
|
||||
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);
|
||||
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
|
||||
|
@ -350,31 +391,33 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
|
|||
</para>
|
||||
|
||||
<para>
|
||||
If a potential coercion function is marked <literal>implicitCoercion</>,
|
||||
then it can be invoked in any context where the conversion it defines
|
||||
is required. Coercion 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 foo.f1 is a column of type text, then
|
||||
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);
|
||||
INSERT INTO foo(f1) VALUES(42);
|
||||
</programlisting>
|
||||
will be allowed if <literal>text(int4)</> is marked
|
||||
<literal>implicitCoercion</>, otherwise not.
|
||||
<literal>IMPLICIT CAST</>, otherwise not.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It is wise to be conservative about marking coercion functions as
|
||||
implicit coercions. An overabundance of implicit coercion 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 coercions
|
||||
implicitly invokable only for information-preserving transformations
|
||||
between types in the same general type category. For example, int2
|
||||
to int4 coercion can reasonably be implicit, but be wary of marking
|
||||
int4 to text or float8 to int4 as implicit coercions.
|
||||
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>
|
||||
|
||||
|
@ -403,7 +446,7 @@ SELECT one() AS answer;
|
|||
user-created shared library named <filename>funcs.so</> (the extension
|
||||
may vary across platforms). The shared library file is sought in the
|
||||
server's dynamic library search path. This particular routine calculates
|
||||
a check digit and returns TRUE if the check digit in the function
|
||||
a check digit and returns true if the check digit in the function
|
||||
parameters is correct. It is intended for use in a CHECK
|
||||
constraint.
|
||||
|
||||
|
@ -422,7 +465,7 @@ CREATE TABLE product (
|
|||
</para>
|
||||
|
||||
<para>
|
||||
This example creates a function that does type conversion from the
|
||||
The next example creates a function that does type conversion from the
|
||||
user-defined type complex to the built-in type point. The
|
||||
function is implemented by a dynamically loaded object that was
|
||||
compiled from C source (we illustrate the now-deprecated alternative
|
||||
|
@ -436,7 +479,7 @@ CREATE TABLE product (
|
|||
<programlisting>
|
||||
CREATE FUNCTION point(complex) RETURNS point
|
||||
AS '/home/bernie/pgsql/lib/complex.so', 'complex_to_point'
|
||||
LANGUAGE C WITH (isStrict);
|
||||
LANGUAGE C STRICT;
|
||||
</programlisting>
|
||||
|
||||
The C declaration of the function could be:
|
||||
|
@ -466,7 +509,7 @@ Point * complex_to_point (Complex *z)
|
|||
<para>
|
||||
A <command>CREATE FUNCTION</command> command is defined in SQL99.
|
||||
The <application>PostgreSQL</application> version is similar but
|
||||
not compatible. The attributes are not portable, neither are the
|
||||
not fully compatible. The attributes are not portable, neither are the
|
||||
different available languages.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
@ -476,10 +519,11 @@ Point * complex_to_point (Complex *z)
|
|||
<title>See Also</title>
|
||||
|
||||
<para>
|
||||
<xref linkend="sql-dropfunction">,
|
||||
<xref linkend="sql-grant">,
|
||||
<xref linkend="sql-load">,
|
||||
<xref linkend="sql-revoke">,
|
||||
<xref linkend="sql-dropfunction" endterm="sql-dropfunction-title">,
|
||||
<xref linkend="sql-grant" endterm="sql-grant-title">,
|
||||
<xref linkend="sql-load" endterm="sql-load-title">,
|
||||
<xref linkend="sql-revoke" endterm="sql-revoke-title">,
|
||||
<xref linkend="app-createlang">,
|
||||
<citetitle>PostgreSQL Programmer's Guide</citetitle>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!--
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.135 2002/05/17 01:19:16 tgl Exp $
|
||||
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.136 2002/05/17 18:32:52 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[
|
||||
Syntax of CREATE FUNCTION has been extended to resemble SQL99
|
||||
Effects of SET within a transaction block now roll back if transaction aborts
|
||||
New SET LOCAL syntax sets a parameter for the life of the current transaction
|
||||
Datestyle, timezone, client_encoding can be set in postgresql.conf
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.3 2002/04/27 03:45:01 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.4 2002/05/17 18:32:52 petere Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* These routines take the parse tree and pick out the
|
||||
|
@ -159,6 +159,104 @@ compute_parameter_types(List *argTypes, Oid languageOid,
|
|||
return parameterCount;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Dissect the list of options assembled in gram.y into function
|
||||
* attributes.
|
||||
*/
|
||||
|
||||
static void
|
||||
compute_attributes_sql_style(const List *options,
|
||||
List **as,
|
||||
char **language,
|
||||
char *volatility_p,
|
||||
bool *strict_p,
|
||||
bool *security_definer,
|
||||
bool *implicit_cast)
|
||||
{
|
||||
const List *option;
|
||||
DefElem *as_item = NULL;
|
||||
DefElem *language_item = NULL;
|
||||
DefElem *volatility_item = NULL;
|
||||
DefElem *strict_item = NULL;
|
||||
DefElem *security_item = NULL;
|
||||
DefElem *implicit_item = NULL;
|
||||
|
||||
foreach(option, options)
|
||||
{
|
||||
DefElem *defel = (DefElem *) lfirst(option);
|
||||
|
||||
if (strcmp(defel->defname, "as")==0)
|
||||
{
|
||||
if (as_item)
|
||||
elog(ERROR, "conflicting or redundant options");
|
||||
as_item = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "language")==0)
|
||||
{
|
||||
if (language_item)
|
||||
elog(ERROR, "conflicting or redundant options");
|
||||
language_item = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "volatility")==0)
|
||||
{
|
||||
if (volatility_item)
|
||||
elog(ERROR, "conflicting or redundant options");
|
||||
volatility_item = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "strict")==0)
|
||||
{
|
||||
if (strict_item)
|
||||
elog(ERROR, "conflicting or redundant options");
|
||||
strict_item = defel;
|
||||
}
|
||||
else if (strcmp(defel->defname, "security")==0)
|
||||
{
|
||||
if (security_item)
|
||||
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");
|
||||
}
|
||||
|
||||
if (as_item)
|
||||
*as = (List *)as_item->arg;
|
||||
else
|
||||
elog(ERROR, "no function body specified");
|
||||
|
||||
if (language_item)
|
||||
*language = strVal(language_item->arg);
|
||||
else
|
||||
elog(ERROR, "no language specified");
|
||||
|
||||
if (volatility_item)
|
||||
{
|
||||
if (strcmp(strVal(volatility_item->arg), "immutable")==0)
|
||||
*volatility_p = PROVOLATILE_IMMUTABLE;
|
||||
else if (strcmp(strVal(volatility_item->arg), "stable")==0)
|
||||
*volatility_p = PROVOLATILE_STABLE;
|
||||
else if (strcmp(strVal(volatility_item->arg), "volatile")==0)
|
||||
*volatility_p = PROVOLATILE_VOLATILE;
|
||||
else
|
||||
elog(ERROR, "invalid volatility");
|
||||
}
|
||||
|
||||
if (strict_item)
|
||||
*strict_p = intVal(strict_item->arg);
|
||||
if (security_item)
|
||||
*security_definer = intVal(security_item->arg);
|
||||
if (implicit_item)
|
||||
*implicit_cast = intVal(implicit_item->arg);
|
||||
}
|
||||
|
||||
|
||||
/*-------------
|
||||
* Interpret the parameters *parameters and return their contents as
|
||||
* *byte_pct_p, etc.
|
||||
|
@ -183,23 +281,14 @@ compute_parameter_types(List *argTypes, Oid languageOid,
|
|||
*------------
|
||||
*/
|
||||
static void
|
||||
compute_full_attributes(List *parameters,
|
||||
int32 *byte_pct_p, int32 *perbyte_cpu_p,
|
||||
int32 *percall_cpu_p, int32 *outin_ratio_p,
|
||||
bool *isImplicit_p, bool *isStrict_p,
|
||||
char *volatility_p)
|
||||
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,
|
||||
char *volatility_p)
|
||||
{
|
||||
List *pl;
|
||||
|
||||
/* the defaults */
|
||||
*byte_pct_p = BYTE_PCT;
|
||||
*perbyte_cpu_p = PERBYTE_CPU;
|
||||
*percall_cpu_p = PERCALL_CPU;
|
||||
*outin_ratio_p = OUTIN_RATIO;
|
||||
*isImplicit_p = false;
|
||||
*isStrict_p = false;
|
||||
*volatility_p = PROVOLATILE_VOLATILE;
|
||||
|
||||
foreach(pl, parameters)
|
||||
{
|
||||
DefElem *param = (DefElem *) lfirst(pl);
|
||||
|
@ -290,12 +379,13 @@ interpret_AS_clause(Oid languageOid, const char *languageName, const List *as,
|
|||
* Execute a CREATE FUNCTION utility statement.
|
||||
*/
|
||||
void
|
||||
CreateFunction(ProcedureStmt *stmt)
|
||||
CreateFunction(CreateFunctionStmt *stmt)
|
||||
{
|
||||
char *probin_str;
|
||||
char *prosrc_str;
|
||||
Oid prorettype;
|
||||
bool returnsSet;
|
||||
char *language;
|
||||
char languageName[NAMEDATALEN];
|
||||
Oid languageOid;
|
||||
char *funcname;
|
||||
|
@ -308,10 +398,12 @@ CreateFunction(ProcedureStmt *stmt)
|
|||
percall_cpu,
|
||||
outin_ratio;
|
||||
bool isImplicit,
|
||||
isStrict;
|
||||
isStrict,
|
||||
security;
|
||||
char volatility;
|
||||
HeapTuple languageTuple;
|
||||
Form_pg_language languageStruct;
|
||||
List *as_clause;
|
||||
|
||||
/* Convert list of names to a name and namespace */
|
||||
namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
|
||||
|
@ -322,8 +414,21 @@ CreateFunction(ProcedureStmt *stmt)
|
|||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, get_namespace_name(namespaceId));
|
||||
|
||||
/* defaults attributes */
|
||||
byte_pct = BYTE_PCT;
|
||||
perbyte_cpu = PERBYTE_CPU;
|
||||
percall_cpu = PERCALL_CPU;
|
||||
outin_ratio = OUTIN_RATIO;
|
||||
isImplicit = false;
|
||||
isStrict = false;
|
||||
volatility = PROVOLATILE_VOLATILE;
|
||||
|
||||
/* override attributes from explicit list */
|
||||
compute_attributes_sql_style(stmt->options,
|
||||
&as_clause, &language, &volatility, &isStrict, &security, &isImplicit);
|
||||
|
||||
/* Convert language name to canonical case */
|
||||
case_translate_language_name(stmt->language, languageName);
|
||||
case_translate_language_name(language, languageName);
|
||||
|
||||
/* Look up the language and validate permissions */
|
||||
languageTuple = SearchSysCache(LANGNAME,
|
||||
|
@ -363,12 +468,12 @@ CreateFunction(ProcedureStmt *stmt)
|
|||
parameterCount = compute_parameter_types(stmt->argTypes, languageOid,
|
||||
parameterTypes);
|
||||
|
||||
compute_full_attributes(stmt->withClause,
|
||||
&byte_pct, &perbyte_cpu, &percall_cpu,
|
||||
&outin_ratio, &isImplicit, &isStrict,
|
||||
&volatility);
|
||||
compute_attributes_with_style(stmt->withClause,
|
||||
&byte_pct, &perbyte_cpu, &percall_cpu,
|
||||
&outin_ratio, &isImplicit, &isStrict,
|
||||
&volatility);
|
||||
|
||||
interpret_AS_clause(languageOid, languageName, stmt->as,
|
||||
interpret_AS_clause(languageOid, languageName, as_clause,
|
||||
&prosrc_str, &probin_str);
|
||||
|
||||
/*
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.186 2002/05/17 01:19:17 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.187 2002/05/17 18:32:52 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -2098,18 +2098,17 @@ _copyIndexStmt(IndexStmt *from)
|
|||
return newnode;
|
||||
}
|
||||
|
||||
static ProcedureStmt *
|
||||
_copyProcedureStmt(ProcedureStmt *from)
|
||||
static CreateFunctionStmt *
|
||||
_copyCreateFunctionStmt(CreateFunctionStmt *from)
|
||||
{
|
||||
ProcedureStmt *newnode = makeNode(ProcedureStmt);
|
||||
CreateFunctionStmt *newnode = makeNode(CreateFunctionStmt);
|
||||
|
||||
newnode->replace = from->replace;
|
||||
Node_Copy(from, newnode, funcname);
|
||||
Node_Copy(from, newnode, argTypes);
|
||||
Node_Copy(from, newnode, returnType);
|
||||
Node_Copy(from, newnode, options);
|
||||
Node_Copy(from, newnode, withClause);
|
||||
Node_Copy(from, newnode, as);
|
||||
newnode->language = pstrdup(from->language);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
@ -2865,8 +2864,8 @@ copyObject(void *from)
|
|||
case T_IndexStmt:
|
||||
retval = _copyIndexStmt(from);
|
||||
break;
|
||||
case T_ProcedureStmt:
|
||||
retval = _copyProcedureStmt(from);
|
||||
case T_CreateFunctionStmt:
|
||||
retval = _copyCreateFunctionStmt(from);
|
||||
break;
|
||||
case T_RemoveAggrStmt:
|
||||
retval = _copyRemoveAggrStmt(from);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.133 2002/05/17 01:19:17 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.134 2002/05/17 18:32:52 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -923,7 +923,7 @@ _equalIndexStmt(IndexStmt *a, IndexStmt *b)
|
|||
}
|
||||
|
||||
static bool
|
||||
_equalProcedureStmt(ProcedureStmt *a, ProcedureStmt *b)
|
||||
_equalCreateFunctionStmt(CreateFunctionStmt *a, CreateFunctionStmt *b)
|
||||
{
|
||||
if (a->replace != b->replace)
|
||||
return false;
|
||||
|
@ -933,12 +933,10 @@ _equalProcedureStmt(ProcedureStmt *a, ProcedureStmt *b)
|
|||
return false;
|
||||
if (!equal(a->returnType, b->returnType))
|
||||
return false;
|
||||
if (!equal(a->options, b->options))
|
||||
return false;
|
||||
if (!equal(a->withClause, b->withClause))
|
||||
return false;
|
||||
if (!equal(a->as, b->as))
|
||||
return false;
|
||||
if (!equalstr(a->language, b->language))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2020,8 +2018,8 @@ equal(void *a, void *b)
|
|||
case T_IndexStmt:
|
||||
retval = _equalIndexStmt(a, b);
|
||||
break;
|
||||
case T_ProcedureStmt:
|
||||
retval = _equalProcedureStmt(a, b);
|
||||
case T_CreateFunctionStmt:
|
||||
retval = _equalCreateFunctionStmt(a, b);
|
||||
break;
|
||||
case T_RemoveAggrStmt:
|
||||
retval = _equalRemoveAggrStmt(a, b);
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.316 2002/05/17 01:19:17 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.317 2002/05/17 18:32:52 petere Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
|
@ -141,7 +141,7 @@ static void doNegateFloat(Value *v);
|
|||
DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropAssertStmt, DropTrigStmt,
|
||||
DropRuleStmt, DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
|
||||
GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
|
||||
NotifyStmt, OptimizableStmt, ProcedureStmt, ReindexStmt,
|
||||
NotifyStmt, OptimizableStmt, CreateFunctionStmt, ReindexStmt,
|
||||
RemoveAggrStmt, RemoveFuncStmt, RemoveOperStmt,
|
||||
RenameStmt, RevokeStmt, RuleActionStmt, RuleActionStmtOrEmpty,
|
||||
RuleStmt, SelectStmt, TransactionStmt, TruncateStmt,
|
||||
|
@ -201,7 +201,7 @@ static void doNegateFloat(Value *v);
|
|||
|
||||
%type <list> stmtblock, stmtmulti,
|
||||
OptTableElementList, OptInherit, definition, opt_distinct,
|
||||
opt_with, func_args, func_args_list, func_as,
|
||||
opt_with, func_args, func_args_list, func_as, createfunc_opt_list
|
||||
oper_argtypes, RuleActionList, RuleActionMulti,
|
||||
opt_column_list, columnList, opt_name_list,
|
||||
sort_clause, sortby_list, index_params, index_list, name_list,
|
||||
|
@ -214,6 +214,7 @@ static void doNegateFloat(Value *v);
|
|||
|
||||
%type <range> into_clause, OptTempTableName
|
||||
|
||||
%type <defelt> createfunc_opt_item
|
||||
%type <typnam> func_arg, func_return, func_type, aggr_argtype
|
||||
|
||||
%type <boolean> opt_arg, TriggerForOpt, TriggerForType, OptTemp, OptWithOids
|
||||
|
@ -388,6 +389,9 @@ static void doNegateFloat(Value *v);
|
|||
TEMP, TEMPLATE, TOAST, TRUNCATE, TRUSTED,
|
||||
UNLISTEN, UNTIL, VACUUM, VALID, VERBOSE, VERSION
|
||||
|
||||
%token <keyword> CALLED, DEFINER, EXTERNAL, IMMUTABLE, IMPLICIT, INPUT,
|
||||
INVOKER, SECURITY, STABLE, STRICT, VOLATILE
|
||||
|
||||
/* The grammar thinks these are keywords, but they are not in the keywords.c
|
||||
* list and so can never be entered directly. The filter in parser.c
|
||||
* creates these tokens when required.
|
||||
|
@ -467,6 +471,7 @@ stmt : AlterDatabaseSetStmt
|
|||
| CreateStmt
|
||||
| CreateAsStmt
|
||||
| CreateDomainStmt
|
||||
| CreateFunctionStmt
|
||||
| CreateSchemaStmt
|
||||
| CreateGroupStmt
|
||||
| CreateSeqStmt
|
||||
|
@ -494,7 +499,6 @@ stmt : AlterDatabaseSetStmt
|
|||
| UnlistenStmt
|
||||
| LockStmt
|
||||
| NotifyStmt
|
||||
| ProcedureStmt
|
||||
| ReindexStmt
|
||||
| RemoveAggrStmt
|
||||
| RemoveOperStmt
|
||||
|
@ -2769,17 +2773,16 @@ RecipeStmt: EXECUTE RECIPE recipe_name
|
|||
*
|
||||
*****************************************************************************/
|
||||
|
||||
ProcedureStmt: CREATE opt_or_replace FUNCTION func_name func_args
|
||||
RETURNS func_return AS func_as LANGUAGE ColId_or_Sconst opt_with
|
||||
CreateFunctionStmt: CREATE opt_or_replace FUNCTION func_name func_args
|
||||
RETURNS func_return createfunc_opt_list opt_with
|
||||
{
|
||||
ProcedureStmt *n = makeNode(ProcedureStmt);
|
||||
CreateFunctionStmt *n = makeNode(CreateFunctionStmt);
|
||||
n->replace = $2;
|
||||
n->funcname = $4;
|
||||
n->argTypes = $5;
|
||||
n->returnType = $7;
|
||||
n->withClause = $12;
|
||||
n->as = $9;
|
||||
n->language = $11;
|
||||
n->options = $8;
|
||||
n->withClause = $9;
|
||||
$$ = (Node *)n;
|
||||
};
|
||||
|
||||
|
@ -2787,10 +2790,6 @@ opt_or_replace: OR REPLACE { $$ = TRUE; }
|
|||
| /*EMPTY*/ { $$ = FALSE; }
|
||||
;
|
||||
|
||||
opt_with: WITH definition { $$ = $2; }
|
||||
| /*EMPTY*/ { $$ = NIL; }
|
||||
;
|
||||
|
||||
func_args: '(' func_args_list ')' { $$ = $2; }
|
||||
| '(' ')' { $$ = NIL; }
|
||||
;
|
||||
|
@ -2831,12 +2830,6 @@ opt_arg: IN
|
|||
}
|
||||
;
|
||||
|
||||
func_as: Sconst
|
||||
{ $$ = makeList1(makeString($1)); }
|
||||
| Sconst ',' Sconst
|
||||
{ $$ = makeList2(makeString($1), makeString($3)); }
|
||||
;
|
||||
|
||||
func_return: func_type
|
||||
{
|
||||
/* We can catch over-specified arguments here if we want to,
|
||||
|
@ -2864,6 +2857,104 @@ func_type: Typename
|
|||
}
|
||||
;
|
||||
|
||||
|
||||
createfunc_opt_list: createfunc_opt_item
|
||||
{ $$ = makeList1($1); }
|
||||
| createfunc_opt_list createfunc_opt_item
|
||||
{ $$ = lappend($1, $2); }
|
||||
;
|
||||
|
||||
createfunc_opt_item: AS func_as
|
||||
{
|
||||
$$ = makeNode(DefElem);
|
||||
$$->defname = "as";
|
||||
$$->arg = (Node *)$2;
|
||||
}
|
||||
| LANGUAGE ColId_or_Sconst
|
||||
{
|
||||
$$ = makeNode(DefElem);
|
||||
$$->defname = "language";
|
||||
$$->arg = (Node *)makeString($2);
|
||||
}
|
||||
| IMMUTABLE
|
||||
{
|
||||
$$ = makeNode(DefElem);
|
||||
$$->defname = "volatility";
|
||||
$$->arg = (Node *)makeString("immutable");
|
||||
}
|
||||
| STABLE
|
||||
{
|
||||
$$ = makeNode(DefElem);
|
||||
$$->defname = "volatility";
|
||||
$$->arg = (Node *)makeString("stable");
|
||||
}
|
||||
| VOLATILE
|
||||
{
|
||||
$$ = makeNode(DefElem);
|
||||
$$->defname = "volatility";
|
||||
$$->arg = (Node *)makeString("volatile");
|
||||
}
|
||||
| CALLED ON NULL_P INPUT
|
||||
{
|
||||
$$ = makeNode(DefElem);
|
||||
$$->defname = "strict";
|
||||
$$->arg = (Node *)makeInteger(FALSE);
|
||||
}
|
||||
| RETURNS NULL_P ON NULL_P INPUT
|
||||
{
|
||||
$$ = makeNode(DefElem);
|
||||
$$->defname = "strict";
|
||||
$$->arg = (Node *)makeInteger(TRUE);
|
||||
}
|
||||
| STRICT
|
||||
{
|
||||
$$ = makeNode(DefElem);
|
||||
$$->defname = "strict";
|
||||
$$->arg = (Node *)makeInteger(TRUE);
|
||||
}
|
||||
| EXTERNAL SECURITY DEFINER
|
||||
{
|
||||
$$ = makeNode(DefElem);
|
||||
$$->defname = "security";
|
||||
$$->arg = (Node *)makeInteger(TRUE);
|
||||
}
|
||||
| EXTERNAL SECURITY INVOKER
|
||||
{
|
||||
$$ = makeNode(DefElem);
|
||||
$$->defname = "security";
|
||||
$$->arg = (Node *)makeInteger(FALSE);
|
||||
}
|
||||
| SECURITY DEFINER
|
||||
{
|
||||
$$ = makeNode(DefElem);
|
||||
$$->defname = "security";
|
||||
$$->arg = (Node *)makeInteger(TRUE);
|
||||
}
|
||||
| SECURITY INVOKER
|
||||
{
|
||||
$$ = makeNode(DefElem);
|
||||
$$->defname = "security";
|
||||
$$->arg = (Node *)makeInteger(FALSE);
|
||||
}
|
||||
| IMPLICIT CAST
|
||||
{
|
||||
$$ = makeNode(DefElem);
|
||||
$$->defname = "implicit";
|
||||
$$->arg = (Node *)makeInteger(TRUE);
|
||||
}
|
||||
;
|
||||
|
||||
func_as: Sconst
|
||||
{ $$ = makeList1(makeString($1)); }
|
||||
| Sconst ',' Sconst
|
||||
{ $$ = makeList2(makeString($1), makeString($3)); }
|
||||
;
|
||||
|
||||
opt_with: WITH definition { $$ = $2; }
|
||||
| /*EMPTY*/ { $$ = NIL; }
|
||||
;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* QUERY:
|
||||
|
@ -6137,6 +6228,7 @@ unreserved_keyword:
|
|||
| BEGIN_TRANS
|
||||
| BY
|
||||
| CACHE
|
||||
| CALLED
|
||||
| CASCADE
|
||||
| CHAIN
|
||||
| CHARACTERISTICS
|
||||
|
@ -6156,6 +6248,7 @@ unreserved_keyword:
|
|||
| DAY_P
|
||||
| DECLARE
|
||||
| DEFERRED
|
||||
| DEFINER
|
||||
| DELETE
|
||||
| DELIMITERS
|
||||
| DOMAIN_P
|
||||
|
@ -6168,6 +6261,7 @@ unreserved_keyword:
|
|||
| EXCLUSIVE
|
||||
| EXECUTE
|
||||
| EXPLAIN
|
||||
| EXTERNAL
|
||||
| FETCH
|
||||
| FORCE
|
||||
| FORWARD
|
||||
|
@ -6176,13 +6270,17 @@ unreserved_keyword:
|
|||
| HANDLER
|
||||
| HOUR_P
|
||||
| IMMEDIATE
|
||||
| IMMUTABLE
|
||||
| IMPLICIT
|
||||
| INCREMENT
|
||||
| INDEX
|
||||
| INHERITS
|
||||
| INOUT
|
||||
| INPUT
|
||||
| INSENSITIVE
|
||||
| INSERT
|
||||
| INSTEAD
|
||||
| INVOKER
|
||||
| ISOLATION
|
||||
| KEY
|
||||
| LANGUAGE
|
||||
|
@ -6238,18 +6336,21 @@ unreserved_keyword:
|
|||
| SCHEMA
|
||||
| SCROLL
|
||||
| SECOND_P
|
||||
| SECURITY
|
||||
| SESSION
|
||||
| SEQUENCE
|
||||
| SERIALIZABLE
|
||||
| SET
|
||||
| SHARE
|
||||
| SHOW
|
||||
| STABLE
|
||||
| START
|
||||
| STATEMENT
|
||||
| STATISTICS
|
||||
| STDIN
|
||||
| STDOUT
|
||||
| STORAGE
|
||||
| STRICT
|
||||
| SYSID
|
||||
| TEMP
|
||||
| TEMPLATE
|
||||
|
@ -6272,6 +6373,7 @@ unreserved_keyword:
|
|||
| VARYING
|
||||
| VERSION
|
||||
| VIEW
|
||||
| VOLATILE
|
||||
| WITH
|
||||
| WITHOUT
|
||||
| WORK
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.109 2002/05/03 00:32:16 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.110 2002/05/17 18:32:52 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -57,6 +57,7 @@ static const ScanKeyword ScanKeywords[] = {
|
|||
{"both", BOTH},
|
||||
{"by", BY},
|
||||
{"cache", CACHE},
|
||||
{"called", CALLED},
|
||||
{"cascade", CASCADE},
|
||||
{"case", CASE},
|
||||
{"cast", CAST},
|
||||
|
@ -95,6 +96,7 @@ static const ScanKeyword ScanKeywords[] = {
|
|||
{"default", DEFAULT},
|
||||
{"deferrable", DEFERRABLE},
|
||||
{"deferred", DEFERRED},
|
||||
{"definer", DEFINER},
|
||||
{"delete", DELETE},
|
||||
{"delimiters", DELIMITERS},
|
||||
{"desc", DESC},
|
||||
|
@ -114,6 +116,7 @@ static const ScanKeyword ScanKeywords[] = {
|
|||
{"execute", EXECUTE},
|
||||
{"exists", EXISTS},
|
||||
{"explain", EXPLAIN},
|
||||
{"external", EXTERNAL},
|
||||
{"extract", EXTRACT},
|
||||
{"false", FALSE_P},
|
||||
{"fetch", FETCH},
|
||||
|
@ -134,6 +137,8 @@ static const ScanKeyword ScanKeywords[] = {
|
|||
{"hour", HOUR_P},
|
||||
{"ilike", ILIKE},
|
||||
{"immediate", IMMEDIATE},
|
||||
{"immutable", IMMUTABLE},
|
||||
{"implicit", IMPLICIT},
|
||||
{"in", IN},
|
||||
{"increment", INCREMENT},
|
||||
{"index", INDEX},
|
||||
|
@ -141,6 +146,7 @@ static const ScanKeyword ScanKeywords[] = {
|
|||
{"initially", INITIALLY},
|
||||
{"inner", INNER_P},
|
||||
{"inout", INOUT},
|
||||
{"input", INPUT},
|
||||
{"insensitive", INSENSITIVE},
|
||||
{"insert", INSERT},
|
||||
{"instead", INSTEAD},
|
||||
|
@ -149,6 +155,7 @@ static const ScanKeyword ScanKeywords[] = {
|
|||
{"intersect", INTERSECT},
|
||||
{"interval", INTERVAL},
|
||||
{"into", INTO},
|
||||
{"invoker", INVOKER},
|
||||
{"is", IS},
|
||||
{"isnull", ISNULL},
|
||||
{"isolation", ISOLATION},
|
||||
|
@ -234,6 +241,7 @@ static const ScanKeyword ScanKeywords[] = {
|
|||
{"schema", SCHEMA},
|
||||
{"scroll", SCROLL},
|
||||
{"second", SECOND_P},
|
||||
{"security", SECURITY},
|
||||
{"select", SELECT},
|
||||
{"sequence", SEQUENCE},
|
||||
{"serializable", SERIALIZABLE},
|
||||
|
@ -245,12 +253,14 @@ static const ScanKeyword ScanKeywords[] = {
|
|||
{"show", SHOW},
|
||||
{"smallint", SMALLINT},
|
||||
{"some", SOME},
|
||||
{"stable", STABLE},
|
||||
{"start", START},
|
||||
{"statement", STATEMENT},
|
||||
{"statistics", STATISTICS},
|
||||
{"stdin", STDIN},
|
||||
{"stdout", STDOUT},
|
||||
{"storage", STORAGE},
|
||||
{"strict", STRICT},
|
||||
{"substring", SUBSTRING},
|
||||
{"sysid", SYSID},
|
||||
{"table", TABLE},
|
||||
|
@ -288,6 +298,7 @@ static const ScanKeyword ScanKeywords[] = {
|
|||
{"verbose", VERBOSE},
|
||||
{"version", VERSION},
|
||||
{"view", VIEW},
|
||||
{"volatile", VOLATILE},
|
||||
{"when", WHEN},
|
||||
{"where", WHERE},
|
||||
{"with", WITH},
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.265 2002/05/17 01:19:18 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.266 2002/05/17 18:32:52 petere Exp $
|
||||
*
|
||||
* NOTES
|
||||
* this is the "main" module of the postgres backend and
|
||||
|
@ -1688,7 +1688,7 @@ PostgresMain(int argc, char *argv[], const char *username)
|
|||
if (!IsUnderPostmaster)
|
||||
{
|
||||
puts("\nPOSTGRES backend interactive interface ");
|
||||
puts("$Revision: 1.265 $ $Date: 2002/05/17 01:19:18 $\n");
|
||||
puts("$Revision: 1.266 $ $Date: 2002/05/17 18:32:52 $\n");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2229,7 +2229,7 @@ CreateCommandTag(Node *parsetree)
|
|||
tag = "CREATE";
|
||||
break;
|
||||
|
||||
case T_ProcedureStmt: /* CREATE FUNCTION */
|
||||
case T_CreateFunctionStmt: /* CREATE FUNCTION */
|
||||
tag = "CREATE";
|
||||
break;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.154 2002/05/17 01:19:18 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.155 2002/05/17 18:32:52 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -574,8 +574,8 @@ ProcessUtility(Node *parsetree,
|
|||
}
|
||||
break;
|
||||
|
||||
case T_ProcedureStmt: /* CREATE FUNCTION */
|
||||
CreateFunction((ProcedureStmt *) parsetree);
|
||||
case T_CreateFunctionStmt: /* CREATE FUNCTION */
|
||||
CreateFunction((CreateFunctionStmt *) parsetree);
|
||||
break;
|
||||
|
||||
case T_IndexStmt: /* CREATE INDEX */
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.260 2002/05/13 17:45:30 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.261 2002/05/17 18:32:52 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -3152,18 +3152,14 @@ dumpProcLangs(Archive *fout, FuncInfo *finfo, int numFuncs)
|
|||
|
||||
(*deps)[depIdx++] = strdup(lanplcallfoid);
|
||||
|
||||
appendPQExpBuffer(delqry, "DROP PROCEDURAL LANGUAGE ");
|
||||
formatStringLiteral(delqry, lanname, CONV_ALL);
|
||||
appendPQExpBuffer(delqry, ";\n");
|
||||
appendPQExpBuffer(delqry, "DROP PROCEDURAL LANGUAGE %s;\n", fmtId(lanname, force_quotes));
|
||||
|
||||
appendPQExpBuffer(defqry, "CREATE %sPROCEDURAL LANGUAGE ",
|
||||
appendPQExpBuffer(defqry, "CREATE %sPROCEDURAL LANGUAGE %s",
|
||||
(PQgetvalue(res, i, i_lanpltrusted)[0] == 't') ?
|
||||
"TRUSTED " : "");
|
||||
formatStringLiteral(defqry, lanname, CONV_ALL);
|
||||
appendPQExpBuffer(defqry, " HANDLER %s LANCOMPILER ",
|
||||
"TRUSTED " : "",
|
||||
fmtId(lanname, force_quotes));
|
||||
appendPQExpBuffer(defqry, " HANDLER %s;\n",
|
||||
fmtId(finfo[fidx].proname, force_quotes));
|
||||
formatStringLiteral(defqry, lancompiler, CONV_ALL);
|
||||
appendPQExpBuffer(defqry, ";\n");
|
||||
|
||||
(*deps)[depIdx++] = NULL; /* End of List */
|
||||
|
||||
|
@ -3221,9 +3217,6 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
|
|||
char *proimplicit;
|
||||
char *proisstrict;
|
||||
char *lanname;
|
||||
char *listSep;
|
||||
char *listSepComma = ",";
|
||||
char *listSepNone = "";
|
||||
char *rettypename;
|
||||
|
||||
if (finfo->dumped)
|
||||
|
@ -3337,52 +3330,33 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
|
|||
rettypename = getFormattedTypeName(finfo->prorettype, zeroAsOpaque);
|
||||
|
||||
appendPQExpBuffer(q, "CREATE FUNCTION %s ", fn->data);
|
||||
appendPQExpBuffer(q, "RETURNS %s%s %s LANGUAGE ",
|
||||
appendPQExpBuffer(q, "RETURNS %s%s %s LANGUAGE %s",
|
||||
(proretset[0] == 't') ? "SETOF " : "",
|
||||
rettypename,
|
||||
asPart->data);
|
||||
formatStringLiteral(q, lanname, CONV_ALL);
|
||||
asPart->data,
|
||||
fmtId(lanname, force_quotes));
|
||||
|
||||
free(rettypename);
|
||||
|
||||
if (provolatile[0] != PROVOLATILE_VOLATILE ||
|
||||
proimplicit[0] == 't' ||
|
||||
proisstrict[0] == 't') /* OR in new attrs here */
|
||||
if (provolatile[0] != PROVOLATILE_VOLATILE)
|
||||
{
|
||||
appendPQExpBuffer(q, " WITH (");
|
||||
listSep = listSepNone;
|
||||
|
||||
if (provolatile[0] == PROVOLATILE_IMMUTABLE)
|
||||
{
|
||||
appendPQExpBuffer(q, "%s isImmutable", listSep);
|
||||
listSep = listSepComma;
|
||||
}
|
||||
appendPQExpBuffer(q, " IMMUTABLE");
|
||||
else if (provolatile[0] == PROVOLATILE_STABLE)
|
||||
{
|
||||
appendPQExpBuffer(q, "%s isStable", listSep);
|
||||
listSep = listSepComma;
|
||||
}
|
||||
appendPQExpBuffer(q, " STABLE");
|
||||
else if (provolatile[0] != PROVOLATILE_VOLATILE)
|
||||
{
|
||||
write_msg(NULL, "Unexpected provolatile value for function %s\n",
|
||||
finfo->proname);
|
||||
exit_nicely();
|
||||
}
|
||||
}
|
||||
|
||||
if (proimplicit[0] == 't')
|
||||
{
|
||||
appendPQExpBuffer(q, "%s implicitCoercion", listSep);
|
||||
listSep = listSepComma;
|
||||
}
|
||||
if (proimplicit[0] == 't')
|
||||
appendPQExpBuffer(q, " IMPLICIT CAST");
|
||||
|
||||
if (proisstrict[0] == 't')
|
||||
{
|
||||
appendPQExpBuffer(q, "%s isStrict", listSep);
|
||||
listSep = listSepComma;
|
||||
}
|
||||
|
||||
appendPQExpBuffer(q, " )");
|
||||
}
|
||||
if (proisstrict[0] == 't')
|
||||
appendPQExpBuffer(q, " STRICT");
|
||||
|
||||
appendPQExpBuffer(q, ";\n");
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: defrem.h,v 1.36 2002/04/16 23:08:12 tgl Exp $
|
||||
* $Id: defrem.h,v 1.37 2002/05/17 18:32:52 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -38,7 +38,7 @@ extern void ReindexDatabase(const char *databaseName, bool force, bool all);
|
|||
* DefineFoo and RemoveFoo are now both in foocmds.c
|
||||
*/
|
||||
|
||||
extern void CreateFunction(ProcedureStmt *stmt);
|
||||
extern void CreateFunction(CreateFunctionStmt *stmt);
|
||||
extern void RemoveFunction(List *functionName, List *argTypes);
|
||||
|
||||
extern void DefineOperator(List *names, List *parameters);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: nodes.h,v 1.107 2002/05/12 23:43:04 tgl Exp $
|
||||
* $Id: nodes.h,v 1.108 2002/05/17 18:32:52 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -160,7 +160,7 @@ typedef enum NodeTag
|
|||
T_CommentStmt,
|
||||
T_FetchStmt,
|
||||
T_IndexStmt,
|
||||
T_ProcedureStmt,
|
||||
T_CreateFunctionStmt,
|
||||
T_RemoveAggrStmt,
|
||||
T_RemoveFuncStmt,
|
||||
T_RemoveOperStmt,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: parsenodes.h,v 1.177 2002/05/17 01:19:19 tgl Exp $
|
||||
* $Id: parsenodes.h,v 1.178 2002/05/17 18:32:52 petere Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -1200,17 +1200,16 @@ typedef struct IndexStmt
|
|||
* Create Function Statement
|
||||
* ----------------------
|
||||
*/
|
||||
typedef struct ProcedureStmt
|
||||
typedef struct CreateFunctionStmt
|
||||
{
|
||||
NodeTag type;
|
||||
bool replace; /* T => replace if already exists */
|
||||
List *funcname; /* qualified name of function to create */
|
||||
List *argTypes; /* list of argument types (TypeName nodes) */
|
||||
TypeName *returnType; /* the return type */
|
||||
List *options; /* a list of DefElem */
|
||||
List *withClause; /* a list of DefElem */
|
||||
List *as; /* definition of function body */
|
||||
char *language; /* C, SQL, etc */
|
||||
} ProcedureStmt;
|
||||
} CreateFunctionStmt;
|
||||
|
||||
/* ----------------------
|
||||
* Drop Aggregate Statement
|
||||
|
|
Loading…
Reference in New Issue