Commit 4bdb4be6 authored by Tom Lane's avatar Tom Lane

Divide functions into three volatility classes (immutable, stable, and

volatile), rather than the old cachable/noncachable distinction.  This
allows indexscan optimizations in many places where we formerly didn't.
Also, add a pronamespace column to pg_proc (it doesn't do anything yet,
however).
parent 0e11aea2
<!-- <!--
Documentation of the system catalogs, directed toward PostgreSQL developers Documentation of the system catalogs, directed toward PostgreSQL developers
$Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.39 2002/03/29 19:05:57 tgl Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.40 2002/04/05 00:31:22 tgl Exp $
--> -->
<chapter id="catalogs"> <chapter id="catalogs">
...@@ -1653,6 +1653,15 @@ ...@@ -1653,6 +1653,15 @@
<entry>Name of the function</entry> <entry>Name of the function</entry>
</row> </row>
<row>
<entry>pronamespace</entry>
<entry><type>oid</type></entry>
<entry>pg_namespace.oid</entry>
<entry>
The OID of the namespace that contains this function
</entry>
</row>
<row> <row>
<entry>proowner</entry> <entry>proowner</entry>
<entry><type>int4</type></entry> <entry><type>int4</type></entry>
...@@ -1681,13 +1690,6 @@ ...@@ -1681,13 +1690,6 @@
<entry>not functional</entry> <entry>not functional</entry>
</row> </row>
<row>
<entry>proiscachable</entry>
<entry><type>bool</type></entry>
<entry></entry>
<entry>Function returns same result for same input values</entry>
</row>
<row> <row>
<entry>proisstrict</entry> <entry>proisstrict</entry>
<entry><type>bool</type></entry> <entry><type>bool</type></entry>
...@@ -1700,6 +1702,25 @@ ...@@ -1700,6 +1702,25 @@
</entry> </entry>
</row> </row>
<row>
<entry>provolatile</entry>
<entry><type>char</type></entry>
<entry></entry>
<entry>
<structfield>provolatile</structfield> tells whether the function's
result depends only on its input arguments, or is affected by outside
factors.
It is <literal>i</literal> for <quote>immutable</> functions,
which always deliver the same result for the same inputs.
It is <literal>s</literal> for <quote>stable</> functions,
whose results (for fixed inputs) do not change within a scan.
It is <literal>v</literal> for <quote>volatile</> functions,
whose results may change at any time. (Use <literal>v</literal> also
for functions with side-effects, so that calls to them cannot get
optimized away.)
</entry>
</row>
<row> <row>
<entry>pronargs</entry> <entry>pronargs</entry>
<entry><type>int2</type></entry> <entry><type>int2</type></entry>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.34 2002/03/22 19:20:37 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.35 2002/04/05 00:31:24 tgl Exp $
--> -->
<refentry id="SQL-CREATEFUNCTION"> <refentry id="SQL-CREATEFUNCTION">
...@@ -160,35 +160,63 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable> ...@@ -160,35 +160,63 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term>iscachable</term> <term>isStrict</term>
<listitem> <listitem>
<para> <para>
<option>Iscachable</option> indicates that the function always <option>isStrict</option> indicates that the function always
returns the same result when given the same argument values (i.e., returns NULL whenever any of its arguments are NULL. If this
it does not do database lookups or otherwise use information not attribute is specified, the function is not executed when there
directly present in its parameter list). The optimizer uses are NULL arguments; instead a NULL result is assumed automatically.
<option>iscachable</option> to know whether it is safe to When <option>isStrict</option> is not specified, the function will
pre-evaluate a call of the function. be called for NULL inputs. It is then the function author's
responsibility to check for NULLs if necessary and respond
appropriately.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term>isstrict</term> <term>isImmutable</term>
<term>isCachable</term>
<term>isStable</term>
<term>isVolatile</term>
<listitem> <listitem>
<para> <para>
<option>isstrict</option> indicates that the function always These attributes inform the system whether it is safe to replace
returns NULL whenever any of its arguments are NULL. If this multiple evaluations of the function with a single evaluation.
attribute is specified, the function is not executed when there At most one choice should be specified. (If none of these appear,
are NULL arguments; instead a NULL result is assumed automatically. <option>isVolatile</option> is the default assumption.)
When <option>isstrict</option> is not specified, the function will <option>isImmutable</option> indicates that the function always
be called for NULL inputs. It is then the function author's returns the same result when given the same argument values; that
responsibility to check for NULLs if necessary and respond is, it does not do database lookups or otherwise use information not
appropriately. 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> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
Attribute names are not case-sensitive.
</para> </para>
</refsect1> </refsect1>
...@@ -342,7 +370,7 @@ CREATE TABLE product ( ...@@ -342,7 +370,7 @@ CREATE TABLE product (
<programlisting> <programlisting>
CREATE FUNCTION point(complex) RETURNS point CREATE FUNCTION point(complex) RETURNS point
AS '/home/bernie/pgsql/lib/complex.so', 'complex_to_point' AS '/home/bernie/pgsql/lib/complex.so', 'complex_to_point'
LANGUAGE C; LANGUAGE C WITH (isStrict);
</programlisting> </programlisting>
The C declaration of the function could be: The C declaration of the function could be:
...@@ -359,6 +387,9 @@ Point * complex_to_point (Complex *z) ...@@ -359,6 +387,9 @@ Point * complex_to_point (Complex *z)
return p; return p;
} }
</programlisting> </programlisting>
Note that the function is marked <quote>strict</>; this allows us
to skip checking for NULL input in the function body.
</para> </para>
</refsect1> </refsect1>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.130 2002/04/03 05:39:28 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.131 2002/04/05 00:31:23 tgl Exp $
--> -->
<appendix id="release"> <appendix id="release">
...@@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without ...@@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without
worries about funny characters. worries about funny characters.
--> -->
<literallayout><![CDATA[ <literallayout><![CDATA[
Define a third class of function volatility to allow indexscans in more cases
Locale support is now built by default; choice of locale is set by initdb and/or at run-time Locale support is now built by default; choice of locale is set by initdb and/or at run-time
ALTER TABLE ALTER COLUMN SET/DROP NOT NULL ALTER TABLE ALTER COLUMN SET/DROP NOT NULL
EXPLAIN output comes out as a query result, not a NOTICE message EXPLAIN output comes out as a query result, not a NOTICE message
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.86 2002/03/29 19:06:00 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.87 2002/04/05 00:31:24 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -64,7 +64,7 @@ char *Name_pg_opclass_indices[Num_pg_opclass_indices] = ...@@ -64,7 +64,7 @@ char *Name_pg_opclass_indices[Num_pg_opclass_indices] =
char *Name_pg_operator_indices[Num_pg_operator_indices] = char *Name_pg_operator_indices[Num_pg_operator_indices] =
{OperatorOidIndex, OperatorNameIndex}; {OperatorOidIndex, OperatorNameIndex};
char *Name_pg_proc_indices[Num_pg_proc_indices] = char *Name_pg_proc_indices[Num_pg_proc_indices] =
{ProcedureOidIndex, ProcedureNameIndex}; {ProcedureOidIndex, ProcedureNameNspIndex};
char *Name_pg_relcheck_indices[Num_pg_relcheck_indices] = char *Name_pg_relcheck_indices[Num_pg_relcheck_indices] =
{RelCheckIndex}; {RelCheckIndex};
char *Name_pg_rewrite_indices[Num_pg_rewrite_indices] = char *Name_pg_rewrite_indices[Num_pg_rewrite_indices] =
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.67 2002/03/29 19:06:02 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.68 2002/04/05 00:31:25 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -40,17 +40,17 @@ static void checkretval(Oid rettype, List *queryTreeList); ...@@ -40,17 +40,17 @@ static void checkretval(Oid rettype, List *queryTreeList);
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
Oid Oid
ProcedureCreate(char *procedureName, ProcedureCreate(const char *procedureName,
Oid procNamespace, Oid procNamespace,
bool replace, bool replace,
bool returnsSet, bool returnsSet,
Oid returnType, Oid returnType,
Oid languageObjectId, Oid languageObjectId,
char *prosrc, const char *prosrc,
char *probin, const char *probin,
bool trusted, bool trusted,
bool canCache,
bool isStrict, bool isStrict,
char volatility,
int32 byte_pct, int32 byte_pct,
int32 perbyte_cpu, int32 perbyte_cpu,
int32 percall_cpu, int32 percall_cpu,
...@@ -167,7 +167,7 @@ ProcedureCreate(char *procedureName, ...@@ -167,7 +167,7 @@ ProcedureCreate(char *procedureName,
*/ */
if (parameterCount == 1 && OidIsValid(typev[0]) && if (parameterCount == 1 && OidIsValid(typev[0]) &&
(relid = typeidTypeRelid(typev[0])) != 0 && (relid = typeidTypeRelid(typev[0])) != 0 &&
get_attnum(relid, procedureName) != InvalidAttrNumber) get_attnum(relid, (char *) procedureName) != InvalidAttrNumber)
elog(ERROR, "method %s already an attribute of type %s", elog(ERROR, "method %s already an attribute of type %s",
procedureName, typeidTypeName(typev[0])); procedureName, typeidTypeName(typev[0]));
...@@ -180,7 +180,9 @@ ProcedureCreate(char *procedureName, ...@@ -180,7 +180,9 @@ ProcedureCreate(char *procedureName,
if (languageObjectId == SQLlanguageId) if (languageObjectId == SQLlanguageId)
{ {
querytree_list = pg_parse_and_rewrite(prosrc, typev, parameterCount); querytree_list = pg_parse_and_rewrite((char *) prosrc,
typev,
parameterCount);
/* typecheck return value */ /* typecheck return value */
checkretval(returnType, querytree_list); checkretval(returnType, querytree_list);
} }
...@@ -196,12 +198,11 @@ ProcedureCreate(char *procedureName, ...@@ -196,12 +198,11 @@ ProcedureCreate(char *procedureName,
* of backwards compatibility, accept an empty 'prosrc' value as * of backwards compatibility, accept an empty 'prosrc' value as
* meaning the supplied SQL function name. * meaning the supplied SQL function name.
*/ */
if (languageObjectId == INTERNALlanguageId) if (languageObjectId == INTERNALlanguageId)
{ {
if (strlen(prosrc) == 0) if (strlen(prosrc) == 0)
prosrc = procedureName; prosrc = procedureName;
if (fmgr_internal_function(prosrc) == InvalidOid) if (fmgr_internal_function((char *) prosrc) == InvalidOid)
elog(ERROR, elog(ERROR,
"there is no built-in function named \"%s\"", "there is no built-in function named \"%s\"",
prosrc); prosrc);
...@@ -216,7 +217,6 @@ ProcedureCreate(char *procedureName, ...@@ -216,7 +217,6 @@ ProcedureCreate(char *procedureName,
* called, but it seems friendlier to verify the library's validity at * called, but it seems friendlier to verify the library's validity at
* CREATE FUNCTION time. * CREATE FUNCTION time.
*/ */
if (languageObjectId == ClanguageId) if (languageObjectId == ClanguageId)
{ {
void *libraryhandle; void *libraryhandle;
...@@ -224,9 +224,11 @@ ProcedureCreate(char *procedureName, ...@@ -224,9 +224,11 @@ ProcedureCreate(char *procedureName,
/* If link symbol is specified as "-", substitute procedure name */ /* If link symbol is specified as "-", substitute procedure name */
if (strcmp(prosrc, "-") == 0) if (strcmp(prosrc, "-") == 0)
prosrc = procedureName; prosrc = procedureName;
(void) load_external_function(probin, prosrc, true, (void) load_external_function((char *) probin,
(char *) prosrc,
true,
&libraryhandle); &libraryhandle);
(void) fetch_finfo_record(libraryhandle, prosrc); (void) fetch_finfo_record(libraryhandle, (char *) prosrc);
} }
/* /*
...@@ -242,18 +244,18 @@ ProcedureCreate(char *procedureName, ...@@ -242,18 +244,18 @@ ProcedureCreate(char *procedureName,
i = 0; i = 0;
namestrcpy(&procname, procedureName); namestrcpy(&procname, procedureName);
values[i++] = NameGetDatum(&procname); values[i++] = NameGetDatum(&procname); /* proname */
values[i++] = Int32GetDatum(GetUserId()); values[i++] = ObjectIdGetDatum(procNamespace); /* pronamespace */
values[i++] = ObjectIdGetDatum(languageObjectId); values[i++] = Int32GetDatum(GetUserId()); /* proowner */
/* XXX isinherited is always false for now */ values[i++] = ObjectIdGetDatum(languageObjectId); /* prolang */
values[i++] = BoolGetDatum(false); values[i++] = BoolGetDatum(false); /* proisinh (unused) */
values[i++] = BoolGetDatum(trusted); values[i++] = BoolGetDatum(trusted); /* proistrusted */
values[i++] = BoolGetDatum(canCache); values[i++] = BoolGetDatum(isStrict); /* proisstrict */
values[i++] = BoolGetDatum(isStrict); values[i++] = CharGetDatum(volatility); /* provolatile */
values[i++] = UInt16GetDatum(parameterCount); values[i++] = UInt16GetDatum(parameterCount); /* pronargs */
values[i++] = BoolGetDatum(returnsSet); values[i++] = BoolGetDatum(returnsSet); /* proretset */
values[i++] = ObjectIdGetDatum(returnType); values[i++] = ObjectIdGetDatum(returnType); /* prorettype */
values[i++] = PointerGetDatum(typev); values[i++] = PointerGetDatum(typev); /* proargtypes */
values[i++] = Int32GetDatum(byte_pct); /* probyte_pct */ values[i++] = Int32GetDatum(byte_pct); /* probyte_pct */
values[i++] = Int32GetDatum(perbyte_cpu); /* properbyte_cpu */ values[i++] = Int32GetDatum(perbyte_cpu); /* properbyte_cpu */
values[i++] = Int32GetDatum(percall_cpu); /* propercall_cpu */ values[i++] = Int32GetDatum(percall_cpu); /* propercall_cpu */
...@@ -262,6 +264,8 @@ ProcedureCreate(char *procedureName, ...@@ -262,6 +264,8 @@ ProcedureCreate(char *procedureName,
CStringGetDatum(prosrc)); CStringGetDatum(prosrc));
values[i++] = DirectFunctionCall1(textin, /* probin */ values[i++] = DirectFunctionCall1(textin, /* probin */
CStringGetDatum(probin)); CStringGetDatum(probin));
/* proacl will be handled below */
rel = heap_openr(ProcedureRelationName, RowExclusiveLock); rel = heap_openr(ProcedureRelationName, RowExclusiveLock);
tupDesc = rel->rd_att; tupDesc = rel->rd_att;
...@@ -294,7 +298,7 @@ ProcedureCreate(char *procedureName, ...@@ -294,7 +298,7 @@ ProcedureCreate(char *procedureName,
elog(ERROR, "ProcedureCreate: cannot change return type of existing function." elog(ERROR, "ProcedureCreate: cannot change return type of existing function."
"\n\tUse DROP FUNCTION first."); "\n\tUse DROP FUNCTION first.");
/* do not change existing permissions */ /* do not change existing permissions, either */
replaces[Anum_pg_proc_proacl-1] = ' '; replaces[Anum_pg_proc_proacl-1] = ' ';
/* Okay, do it... */ /* Okay, do it... */
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.72 2002/03/29 19:06:06 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.73 2002/04/05 00:31:25 tgl Exp $
* *
* DESCRIPTION * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
...@@ -145,7 +145,7 @@ static void ...@@ -145,7 +145,7 @@ static void
compute_full_attributes(List *parameters, compute_full_attributes(List *parameters,
int32 *byte_pct_p, int32 *perbyte_cpu_p, int32 *byte_pct_p, int32 *perbyte_cpu_p,
int32 *percall_cpu_p, int32 *outin_ratio_p, int32 *percall_cpu_p, int32 *outin_ratio_p,
bool *canCache_p, bool *isStrict_p) bool *isStrict_p, char *volatility_p)
{ {
/*------------- /*-------------
* Interpret the parameters *parameters and return their contents as * Interpret the parameters *parameters and return their contents as
...@@ -156,18 +156,15 @@ compute_full_attributes(List *parameters, ...@@ -156,18 +156,15 @@ compute_full_attributes(List *parameters,
* *
* Note: currently, only two of these parameters actually do anything: * Note: currently, only two of these parameters actually do anything:
* *
* * canCache means the optimizer's constant-folder is allowed to
* pre-evaluate the function when all its inputs are constants.
*
* * isStrict means the function should not be called when any NULL * * isStrict means the function should not be called when any NULL
* inputs are present; instead a NULL result value should be assumed. * inputs are present; instead a NULL result value should be assumed.
* *
* * volatility tells the optimizer whether the function's result can
* be assumed to be repeatable over multiple evaluations.
*
* The other four parameters are not used anywhere. They used to be * The other four parameters are not used anywhere. They used to be
* used in the "expensive functions" optimizer, but that's been dead code * used in the "expensive functions" optimizer, but that's been dead code
* for a long time. * for a long time.
*
* Since canCache and isStrict are useful for any function, we now allow
* attributes to be supplied for all functions regardless of language.
*------------ *------------
*/ */
List *pl; List *pl;
...@@ -177,17 +174,26 @@ compute_full_attributes(List *parameters, ...@@ -177,17 +174,26 @@ compute_full_attributes(List *parameters,
*perbyte_cpu_p = PERBYTE_CPU; *perbyte_cpu_p = PERBYTE_CPU;
*percall_cpu_p = PERCALL_CPU; *percall_cpu_p = PERCALL_CPU;
*outin_ratio_p = OUTIN_RATIO; *outin_ratio_p = OUTIN_RATIO;
*canCache_p = false;
*isStrict_p = false; *isStrict_p = false;
*volatility_p = PROVOLATILE_VOLATILE;
foreach(pl, parameters) foreach(pl, parameters)
{ {
DefElem *param = (DefElem *) lfirst(pl); DefElem *param = (DefElem *) lfirst(pl);
if (strcasecmp(param->defname, "iscachable") == 0) if (strcasecmp(param->defname, "isstrict") == 0)
*canCache_p = true;
else if (strcasecmp(param->defname, "isstrict") == 0)
*isStrict_p = true; *isStrict_p = true;
else if (strcasecmp(param->defname, "isimmutable") == 0)
*volatility_p = PROVOLATILE_IMMUTABLE;
else if (strcasecmp(param->defname, "isstable") == 0)
*volatility_p = PROVOLATILE_STABLE;
else if (strcasecmp(param->defname, "isvolatile") == 0)
*volatility_p = PROVOLATILE_VOLATILE;
else if (strcasecmp(param->defname, "iscachable") == 0)
{
/* obsolete spelling of isImmutable */
*volatility_p = PROVOLATILE_IMMUTABLE;
}
else if (strcasecmp(param->defname, "trusted") == 0) else if (strcasecmp(param->defname, "trusted") == 0)
{ {
/* /*
...@@ -273,8 +279,8 @@ CreateFunction(ProcedureStmt *stmt) ...@@ -273,8 +279,8 @@ CreateFunction(ProcedureStmt *stmt)
perbyte_cpu, perbyte_cpu,
percall_cpu, percall_cpu,
outin_ratio; outin_ratio;
bool canCache, bool isStrict;
isStrict; char volatility;
HeapTuple languageTuple; HeapTuple languageTuple;
Form_pg_language languageStruct; Form_pg_language languageStruct;
...@@ -311,7 +317,7 @@ CreateFunction(ProcedureStmt *stmt) ...@@ -311,7 +317,7 @@ CreateFunction(ProcedureStmt *stmt)
compute_full_attributes(stmt->withClause, compute_full_attributes(stmt->withClause,
&byte_pct, &perbyte_cpu, &percall_cpu, &byte_pct, &perbyte_cpu, &percall_cpu,
&outin_ratio, &canCache, &isStrict); &outin_ratio, &isStrict, &volatility);
interpret_AS_clause(languageOid, languageName, stmt->as, interpret_AS_clause(languageOid, languageName, stmt->as,
&prosrc_str, &probin_str); &prosrc_str, &probin_str);
...@@ -329,8 +335,8 @@ CreateFunction(ProcedureStmt *stmt) ...@@ -329,8 +335,8 @@ CreateFunction(ProcedureStmt *stmt)
prosrc_str, /* converted to text later */ prosrc_str, /* converted to text later */
probin_str, /* converted to text later */ probin_str, /* converted to text later */
true, /* (obsolete "trusted") */ true, /* (obsolete "trusted") */
canCache,
isStrict, isStrict,
volatility,
byte_pct, byte_pct,
perbyte_cpu, perbyte_cpu,
percall_cpu, percall_cpu,
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.66 2002/03/31 06:26:30 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.67 2002/04/05 00:31:26 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "catalog/index.h" #include "catalog/index.h"
#include "catalog/namespace.h" #include "catalog/namespace.h"
#include "catalog/pg_opclass.h" #include "catalog/pg_opclass.h"
#include "catalog/pg_proc.h"
#include "commands/defrem.h" #include "commands/defrem.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "optimizer/clauses.h" #include "optimizer/clauses.h"
...@@ -233,11 +234,11 @@ CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid) ...@@ -233,11 +234,11 @@ CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid)
elog(ERROR, "Cannot use aggregate in index predicate"); elog(ERROR, "Cannot use aggregate in index predicate");
/* /*
* A predicate using noncachable functions is probably wrong, for the * A predicate using mutable functions is probably wrong, for the
* same reasons that we don't allow a functional index to use one. * same reasons that we don't allow a functional index to use one.
*/ */
if (contain_noncachable_functions((Node *) predList)) if (contain_mutable_functions((Node *) predList))
elog(ERROR, "Cannot use non-cachable function in index predicate"); elog(ERROR, "Functions in index predicate must be marked isImmutable");
} }
...@@ -320,13 +321,13 @@ FuncIndexArgs(IndexInfo *indexInfo, ...@@ -320,13 +321,13 @@ FuncIndexArgs(IndexInfo *indexInfo,
} }
/* /*
* Require that the function be marked cachable. Using a noncachable * Require that the function be marked immutable. Using a mutable
* function for a functional index is highly questionable, since if * function for a functional index is highly questionable, since if
* you aren't going to get the same result for the same data every * you aren't going to get the same result for the same data every
* time, it's not clear what the index entries mean at all. * time, it's not clear what the index entries mean at all.
*/ */
if (!func_iscachable(funcid)) if (func_volatile(funcid) != PROVOLATILE_IMMUTABLE)
elog(ERROR, "DefineIndex: index function must be marked iscachable"); elog(ERROR, "DefineIndex: index function must be marked isImmutable");
/* Process opclass, using func return type as default type */ /* Process opclass, using func return type as default type */
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.114 2002/03/20 19:44:09 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.115 2002/04/05 00:31:26 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -783,7 +783,7 @@ match_clause_to_indexkey(RelOptInfo *rel, ...@@ -783,7 +783,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
* Check for an indexqual that could be handled by a nestloop * Check for an indexqual that could be handled by a nestloop
* join. We need the index key to be compared against an * join. We need the index key to be compared against an
* expression that uses none of the indexed relation's vars and * expression that uses none of the indexed relation's vars and
* contains no non-cachable functions. * contains no volatile functions.
*/ */
if (match_index_to_operand(indexkey, leftop, rel, index)) if (match_index_to_operand(indexkey, leftop, rel, index))
{ {
...@@ -792,7 +792,7 @@ match_clause_to_indexkey(RelOptInfo *rel, ...@@ -792,7 +792,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
isIndexable = isIndexable =
!intMember(lfirsti(rel->relids), othervarnos) && !intMember(lfirsti(rel->relids), othervarnos) &&
!contain_noncachable_functions((Node *) rightop) && !contain_volatile_functions((Node *) rightop) &&
is_indexable_operator(clause, opclass, true); is_indexable_operator(clause, opclass, true);
freeList(othervarnos); freeList(othervarnos);
return isIndexable; return isIndexable;
...@@ -804,7 +804,7 @@ match_clause_to_indexkey(RelOptInfo *rel, ...@@ -804,7 +804,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
isIndexable = isIndexable =
!intMember(lfirsti(rel->relids), othervarnos) && !intMember(lfirsti(rel->relids), othervarnos) &&
!contain_noncachable_functions((Node *) leftop) && !contain_volatile_functions((Node *) leftop) &&
is_indexable_operator(clause, opclass, false); is_indexable_operator(clause, opclass, false);
freeList(othervarnos); freeList(othervarnos);
return isIndexable; return isIndexable;
...@@ -1142,7 +1142,7 @@ static const StrategyNumber ...@@ -1142,7 +1142,7 @@ static const StrategyNumber
* implies another. A simple and general way is to see if they are * implies another. A simple and general way is to see if they are
* equal(); this works for any kind of expression. (Actually, there * equal(); this works for any kind of expression. (Actually, there
* is an implied assumption that the functions in the expression are * is an implied assumption that the functions in the expression are
* cachable, ie dependent only on their input arguments --- but this * immutable, ie dependent only on their input arguments --- but this
* was checked for the predicate by CheckPredicate().) * was checked for the predicate by CheckPredicate().)
* *
* Our other way works only for (binary boolean) operators that are * Our other way works only for (binary boolean) operators that are
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.95 2002/03/21 16:00:44 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.96 2002/04/05 00:31:27 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -52,7 +52,8 @@ static bool contain_subplans_walker(Node *node, void *context); ...@@ -52,7 +52,8 @@ static bool contain_subplans_walker(Node *node, void *context);
static bool pull_subplans_walker(Node *node, List **listptr); static bool pull_subplans_walker(Node *node, List **listptr);
static bool check_subplans_for_ungrouped_vars_walker(Node *node, static bool check_subplans_for_ungrouped_vars_walker(Node *node,
check_subplans_for_ungrouped_vars_context * context); check_subplans_for_ungrouped_vars_context * context);
static bool contain_noncachable_functions_walker(Node *node, void *context); static bool contain_mutable_functions_walker(Node *node, void *context);
static bool contain_volatile_functions_walker(Node *node, void *context);
static Node *eval_const_expressions_mutator(Node *node, void *context); static Node *eval_const_expressions_mutator(Node *node, void *context);
static Expr *simplify_op_or_func(Expr *expr, List *args); static Expr *simplify_op_or_func(Expr *expr, List *args);
...@@ -698,29 +699,29 @@ check_subplans_for_ungrouped_vars_walker(Node *node, ...@@ -698,29 +699,29 @@ check_subplans_for_ungrouped_vars_walker(Node *node,
/***************************************************************************** /*****************************************************************************
* Check clauses for noncachable functions * Check clauses for mutable functions
*****************************************************************************/ *****************************************************************************/
/* /*
* contain_noncachable_functions * contain_mutable_functions
* Recursively search for noncachable functions within a clause. * Recursively search for mutable functions within a clause.
* *
* Returns true if any noncachable function (or operator implemented by a * Returns true if any mutable function (or operator implemented by a
* noncachable function) is found. This test is needed so that we don't * mutable function) is found. This test is needed so that we don't
* mistakenly think that something like "WHERE random() < 0.5" can be treated * mistakenly think that something like "WHERE random() < 0.5" can be treated
* as a constant qualification. * as a constant qualification.
* *
* XXX we do not examine sublinks/subplans to see if they contain uses of * XXX we do not examine sublinks/subplans to see if they contain uses of
* noncachable functions. It's not real clear if that is correct or not... * mutable functions. It's not real clear if that is correct or not...
*/ */
bool bool
contain_noncachable_functions(Node *clause) contain_mutable_functions(Node *clause)
{ {
return contain_noncachable_functions_walker(clause, NULL); return contain_mutable_functions_walker(clause, NULL);
} }
static bool static bool
contain_noncachable_functions_walker(Node *node, void *context) contain_mutable_functions_walker(Node *node, void *context)
{ {
if (node == NULL) if (node == NULL)
return false; return false;
...@@ -731,18 +732,67 @@ contain_noncachable_functions_walker(Node *node, void *context) ...@@ -731,18 +732,67 @@ contain_noncachable_functions_walker(Node *node, void *context)
switch (expr->opType) switch (expr->opType)
{ {
case OP_EXPR: case OP_EXPR:
if (!op_iscachable(((Oper *) expr->oper)->opno)) if (op_volatile(((Oper *) expr->oper)->opno) != PROVOLATILE_IMMUTABLE)
return true; return true;
break; break;
case FUNC_EXPR: case FUNC_EXPR:
if (!func_iscachable(((Func *) expr->oper)->funcid)) if (func_volatile(((Func *) expr->oper)->funcid) != PROVOLATILE_IMMUTABLE)
return true; return true;
break; break;
default: default:
break; break;
} }
} }
return expression_tree_walker(node, contain_noncachable_functions_walker, return expression_tree_walker(node, contain_mutable_functions_walker,
context);
}
/*****************************************************************************
* Check clauses for volatile functions
*****************************************************************************/
/*
* contain_volatile_functions
* Recursively search for volatile functions within a clause.
*
* Returns true if any volatile function (or operator implemented by a
* volatile function) is found. This test prevents invalid conversions
* of volatile expressions into indexscan quals.
*
* XXX we do not examine sublinks/subplans to see if they contain uses of
* volatile functions. It's not real clear if that is correct or not...
*/
bool
contain_volatile_functions(Node *clause)
{
return contain_volatile_functions_walker(clause, NULL);
}
static bool
contain_volatile_functions_walker(Node *node, void *context)
{
if (node == NULL)
return false;
if (IsA(node, Expr))
{
Expr *expr = (Expr *) node;
switch (expr->opType)
{
case OP_EXPR:
if (op_volatile(((Oper *) expr->oper)->opno) == PROVOLATILE_VOLATILE)
return true;
break;
case FUNC_EXPR:
if (func_volatile(((Func *) expr->oper)->funcid) == PROVOLATILE_VOLATILE)
return true;
break;
default:
break;
}
}
return expression_tree_walker(node, contain_volatile_functions_walker,
context); context);
} }
...@@ -754,23 +804,25 @@ contain_noncachable_functions_walker(Node *node, void *context) ...@@ -754,23 +804,25 @@ contain_noncachable_functions_walker(Node *node, void *context)
/* /*
* is_pseudo_constant_clause * is_pseudo_constant_clause
* Detect whether a clause is "constant", ie, it contains no variables * Detect whether a clause is "constant", ie, it contains no variables
* of the current query level and no uses of noncachable functions. * of the current query level and no uses of volatile functions.
* Such a clause is not necessarily a true constant: it can still contain * Such a clause is not necessarily a true constant: it can still contain
* Params and outer-level Vars. However, its value will be constant over * Params and outer-level Vars, not to mention functions whose results
* any one scan of the current query, so it can be used as an indexscan * may vary from one statement to the next. However, the clause's value
* key or (if a top-level qual) can be pushed up to become a gating qual. * will be constant over any one scan of the current query, so it can be
* used as an indexscan key or (if a top-level qual) can be pushed up to
* become a gating qual.
*/ */
bool bool
is_pseudo_constant_clause(Node *clause) is_pseudo_constant_clause(Node *clause)
{ {
/* /*
* We could implement this check in one recursive scan. But since the * We could implement this check in one recursive scan. But since the
* check for noncachable functions is both moderately expensive and * check for volatile functions is both moderately expensive and
* unlikely to fail, it seems better to look for Vars first and only * unlikely to fail, it seems better to look for Vars first and only
* check for noncachable functions if we find no Vars. * check for volatile functions if we find no Vars.
*/ */
if (!contain_var_clause(clause) && if (!contain_var_clause(clause) &&
!contain_noncachable_functions(clause)) !contain_volatile_functions(clause))
return true; return true;
return false; return false;
} }
...@@ -1019,7 +1071,7 @@ CommuteClause(Expr *clause) ...@@ -1019,7 +1071,7 @@ CommuteClause(Expr *clause)
* *
* We do understand that certain functions may deliver non-constant * We do understand that certain functions may deliver non-constant
* results even with constant inputs, "nextval()" being the classic * results even with constant inputs, "nextval()" being the classic
* example. Functions that are not marked "proiscachable" in pg_proc * example. Functions that are not marked "immutable" in pg_proc
* will not be pre-evaluated here, although we will reduce their * will not be pre-evaluated here, although we will reduce their
* arguments as far as possible. Functions that are the arguments * arguments as far as possible. Functions that are the arguments
* of Iter nodes are also not evaluated. * of Iter nodes are also not evaluated.
...@@ -1412,7 +1464,7 @@ simplify_op_or_func(Expr *expr, List *args) ...@@ -1412,7 +1464,7 @@ simplify_op_or_func(Expr *expr, List *args)
Oid result_typeid; Oid result_typeid;
HeapTuple func_tuple; HeapTuple func_tuple;
Form_pg_proc funcform; Form_pg_proc funcform;
bool proiscachable; char provolatile;
bool proisstrict; bool proisstrict;
bool proretset; bool proretset;
int16 resultTypLen; int16 resultTypLen;
...@@ -1447,7 +1499,7 @@ simplify_op_or_func(Expr *expr, List *args) ...@@ -1447,7 +1499,7 @@ simplify_op_or_func(Expr *expr, List *args)
/* /*
* Get the function procedure's OID and look to see whether it is * Get the function procedure's OID and look to see whether it is
* marked proiscachable. * marked immutable.
* *
* XXX would it be better to take the result type from the pg_proc tuple, * XXX would it be better to take the result type from the pg_proc tuple,
* rather than the Oper or Func node? * rather than the Oper or Func node?
...@@ -1469,7 +1521,7 @@ simplify_op_or_func(Expr *expr, List *args) ...@@ -1469,7 +1521,7 @@ simplify_op_or_func(Expr *expr, List *args)
} }
/* /*
* we could use func_iscachable() here, but we need several fields out * we could use func_volatile() here, but we need several fields out
* of the func tuple, so might as well just look it up once. * of the func tuple, so might as well just look it up once.
*/ */
func_tuple = SearchSysCache(PROCOID, func_tuple = SearchSysCache(PROCOID,
...@@ -1478,12 +1530,12 @@ simplify_op_or_func(Expr *expr, List *args) ...@@ -1478,12 +1530,12 @@ simplify_op_or_func(Expr *expr, List *args)
if (!HeapTupleIsValid(func_tuple)) if (!HeapTupleIsValid(func_tuple))
elog(ERROR, "Function OID %u does not exist", funcid); elog(ERROR, "Function OID %u does not exist", funcid);
funcform = (Form_pg_proc) GETSTRUCT(func_tuple); funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
proiscachable = funcform->proiscachable; provolatile = funcform->provolatile;
proisstrict = funcform->proisstrict; proisstrict = funcform->proisstrict;
proretset = funcform->proretset; proretset = funcform->proretset;
ReleaseSysCache(func_tuple); ReleaseSysCache(func_tuple);
if (!proiscachable) if (provolatile != PROVOLATILE_IMMUTABLE)
return NULL; return NULL;
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.122 2002/03/29 22:10:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.123 2002/04/05 00:31:27 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -525,7 +525,7 @@ func_get_candidates(char *funcname, int nargs) ...@@ -525,7 +525,7 @@ func_get_candidates(char *funcname, int nargs)
(RegProcedure) F_INT2EQ, (RegProcedure) F_INT2EQ,
Int16GetDatum(nargs)); Int16GetDatum(nargs));
funcscan = systable_beginscan(heapRelation, ProcedureNameIndex, true, funcscan = systable_beginscan(heapRelation, ProcedureNameNspIndex, true,
SnapshotNow, 2, skey); SnapshotNow, 2, skey);
while (HeapTupleIsValid(tuple = systable_getnext(funcscan))) while (HeapTupleIsValid(tuple = systable_getnext(funcscan)))
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
# #
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh,v 1.21 2002/02/18 23:11:20 petere Exp $ # $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh,v 1.22 2002/04/05 00:31:28 tgl Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -99,7 +99,7 @@ sed -e 's/^.*OID[^=]*=[^0-9]*//' \ ...@@ -99,7 +99,7 @@ sed -e 's/^.*OID[^=]*=[^0-9]*//' \
-e 's/[ ]*).*$//' | \ -e 's/[ ]*).*$//' | \
$AWK ' $AWK '
/^#/ { print; next; } /^#/ { print; next; }
$4 == "12" { print; next; }' > $CPPTMPFILE $5 == "12" { print; next; }' > $CPPTMPFILE
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
cleanup cleanup
...@@ -232,7 +232,7 @@ $AWK 'BEGIN { ...@@ -232,7 +232,7 @@ $AWK 'BEGIN {
Bool["f"] = "false" Bool["f"] = "false"
} }
{ printf (" { %d, \"%s\", %d, %s, %s, %s },\n"), \ { printf (" { %d, \"%s\", %d, %s, %s, %s },\n"), \
$1, $(NF-2), $9, Bool[$8], Bool[$10], $(NF-2) $1, $(NF-2), $10, Bool[$8], Bool[$11], $(NF-2)
}' $RAWFILE >> "$$-$TABLEFILE" }' $RAWFILE >> "$$-$TABLEFILE"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.64 2001/10/25 05:49:45 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.65 2002/04/05 00:31:29 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -42,13 +42,13 @@ regprocin(PG_FUNCTION_ARGS) ...@@ -42,13 +42,13 @@ regprocin(PG_FUNCTION_ARGS)
char *pro_name_or_oid = PG_GETARG_CSTRING(0); char *pro_name_or_oid = PG_GETARG_CSTRING(0);
RegProcedure result = InvalidOid; RegProcedure result = InvalidOid;
int matches = 0; int matches = 0;
ScanKeyData skey[1];
if (pro_name_or_oid[0] == '-' && pro_name_or_oid[1] == '\0') if (pro_name_or_oid[0] == '-' && pro_name_or_oid[1] == '\0')
PG_RETURN_OID(InvalidOid); PG_RETURN_OID(InvalidOid);
if (pro_name_or_oid[0] >= '0' && if (pro_name_or_oid[0] >= '0' &&
pro_name_or_oid[0] <= '9') pro_name_or_oid[0] <= '9' &&
strspn(pro_name_or_oid, "0123456789") == strlen(pro_name_or_oid))
{ {
Oid searchOid; Oid searchOid;
...@@ -61,67 +61,33 @@ regprocin(PG_FUNCTION_ARGS) ...@@ -61,67 +61,33 @@ regprocin(PG_FUNCTION_ARGS)
elog(ERROR, "No procedure with oid %s", pro_name_or_oid); elog(ERROR, "No procedure with oid %s", pro_name_or_oid);
matches = 1; matches = 1;
} }
else if (!IsIgnoringSystemIndexes()) else
{ {
Relation hdesc; Relation hdesc;
Relation idesc; ScanKeyData skey[1];
IndexScanDesc sd; SysScanDesc funcscan;
RetrieveIndexResult indexRes; HeapTuple tuple;
HeapTupleData tuple;
Buffer buffer;
ScanKeyEntryInitialize(&skey[0], 0x0, ScanKeyEntryInitialize(&skey[0], 0x0,
(AttrNumber) 1, (AttrNumber) Anum_pg_proc_proname,
(RegProcedure) F_NAMEEQ, (RegProcedure) F_NAMEEQ,
CStringGetDatum(pro_name_or_oid)); CStringGetDatum(pro_name_or_oid));
hdesc = heap_openr(ProcedureRelationName, AccessShareLock); hdesc = heap_openr(ProcedureRelationName, AccessShareLock);
idesc = index_openr(ProcedureNameIndex);
sd = index_beginscan(idesc, false, 1, skey);
while ((indexRes = index_getnext(sd, ForwardScanDirection)))
{
tuple.t_datamcxt = NULL;
tuple.t_data = NULL;
tuple.t_self = indexRes->heap_iptr;
heap_fetch(hdesc, SnapshotNow, &tuple, &buffer, sd);
pfree(indexRes);
if (tuple.t_data != NULL)
{
result = (RegProcedure) tuple.t_data->t_oid;
ReleaseBuffer(buffer);
if (++matches > 1)
break;
}
}
index_endscan(sd); funcscan = systable_beginscan(hdesc, ProcedureNameNspIndex, true,
index_close(idesc); SnapshotNow, 1, skey);
heap_close(hdesc, AccessShareLock);
}
else
{
Relation proc;
HeapScanDesc procscan;
HeapTuple proctup;
ScanKeyEntryInitialize(&skey[0], 0x0, while (HeapTupleIsValid(tuple = systable_getnext(funcscan)))
(AttrNumber) Anum_pg_proc_proname,
(RegProcedure) F_NAMEEQ,
CStringGetDatum(pro_name_or_oid));
proc = heap_openr(ProcedureRelationName, AccessShareLock);
procscan = heap_beginscan(proc, 0, SnapshotNow, 1, skey);
while (HeapTupleIsValid(proctup = heap_getnext(procscan, 0)))
{ {
result = proctup->t_data->t_oid; result = (RegProcedure) tuple->t_data->t_oid;
if (++matches > 1) if (++matches > 1)
break; break;
} }
heap_endscan(procscan); systable_endscan(funcscan);
heap_close(proc, AccessShareLock);
heap_close(hdesc, AccessShareLock);
} }
if (matches > 1) if (matches > 1)
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.41 2002/03/29 19:06:14 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.42 2002/04/05 00:31:29 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -61,8 +61,8 @@ SetDefine(char *querystr, Oid elemType) ...@@ -61,8 +61,8 @@ SetDefine(char *querystr, Oid elemType)
querystr, /* sourceCode */ querystr, /* sourceCode */
fileName, /* fileName */ fileName, /* fileName */
true, /* trusted */ true, /* trusted */
false, /* canCache (assume unsafe) */
false, /* isStrict (irrelevant, no args) */ false, /* isStrict (irrelevant, no args) */
PROVOLATILE_VOLATILE, /* assume unsafe */
100, /* byte_pct */ 100, /* byte_pct */
0, /* perbyte_cpu */ 0, /* perbyte_cpu */
0, /* percall_cpu */ 0, /* percall_cpu */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.68 2002/04/02 01:03:07 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.69 2002/04/05 00:31:30 tgl Exp $
* *
* NOTES * NOTES
* Eventually, the index information should go through here, too. * Eventually, the index information should go through here, too.
...@@ -470,19 +470,19 @@ op_hashjoinable(Oid opno, Oid ltype, Oid rtype) ...@@ -470,19 +470,19 @@ op_hashjoinable(Oid opno, Oid ltype, Oid rtype)
} }
/* /*
* op_iscachable * op_volatile
* *
* Get the proiscachable flag for the operator's underlying function. * Get the provolatile flag for the operator's underlying function.
*/ */
bool char
op_iscachable(Oid opno) op_volatile(Oid opno)
{ {
RegProcedure funcid = get_opcode(opno); RegProcedure funcid = get_opcode(opno);
if (funcid == (RegProcedure) InvalidOid) if (funcid == (RegProcedure) InvalidOid)
elog(ERROR, "Operator OID %u does not exist", opno); elog(ERROR, "Operator OID %u does not exist", opno);
return func_iscachable((Oid) funcid); return func_volatile((Oid) funcid);
} }
/* /*
...@@ -613,14 +613,14 @@ get_func_rettype(Oid funcid) ...@@ -613,14 +613,14 @@ get_func_rettype(Oid funcid)
} }
/* /*
* func_iscachable * func_volatile
* Given procedure id, return the function's proiscachable flag. * Given procedure id, return the function's provolatile flag.
*/ */
bool char
func_iscachable(Oid funcid) func_volatile(Oid funcid)
{ {
HeapTuple tp; HeapTuple tp;
bool result; char result;
tp = SearchSysCache(PROCOID, tp = SearchSysCache(PROCOID,
ObjectIdGetDatum(funcid), ObjectIdGetDatum(funcid),
...@@ -628,7 +628,7 @@ func_iscachable(Oid funcid) ...@@ -628,7 +628,7 @@ func_iscachable(Oid funcid)
if (!HeapTupleIsValid(tp)) if (!HeapTupleIsValid(tp))
elog(ERROR, "Function OID %u does not exist", funcid); elog(ERROR, "Function OID %u does not exist", funcid);
result = ((Form_pg_proc) GETSTRUCT(tp))->proiscachable; result = ((Form_pg_proc) GETSTRUCT(tp))->provolatile;
ReleaseSysCache(tp); ReleaseSysCache(tp);
return result; return result;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.72 2002/03/31 06:26:32 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.73 2002/04/05 00:31:31 tgl Exp $
* *
* NOTES * NOTES
* These routines allow the parser/planner/executor to perform * These routines allow the parser/planner/executor to perform
...@@ -304,7 +304,7 @@ static const struct cachedesc cacheinfo[] = { ...@@ -304,7 +304,7 @@ static const struct cachedesc cacheinfo[] = {
0 0
}}, }},
{ProcedureRelationName, /* PROCNAME */ {ProcedureRelationName, /* PROCNAME */
ProcedureNameIndex, ProcedureNameNspIndex, /* XXX very temporary */
0, 0,
3, 3,
{ {
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.244 2002/03/21 05:47:14 momjian Exp $ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.245 2002/04/05 00:31:31 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
#include "access/attnum.h" #include "access/attnum.h"
#include "access/htup.h" #include "access/htup.h"
#include "catalog/pg_class.h" #include "catalog/pg_class.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_trigger.h" #include "catalog/pg_trigger.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
...@@ -1953,7 +1954,7 @@ getFuncs(int *numFuncs) ...@@ -1953,7 +1954,7 @@ getFuncs(int *numFuncs)
int i_proretset; int i_proretset;
int i_prosrc; int i_prosrc;
int i_probin; int i_probin;
int i_iscachable; int i_provolatile;
int i_isstrict; int i_isstrict;
int i_usename; int i_usename;
...@@ -1965,7 +1966,20 @@ getFuncs(int *numFuncs) ...@@ -1965,7 +1966,20 @@ getFuncs(int *numFuncs)
"SELECT pg_proc.oid, proname, prolang, pronargs, prorettype, " "SELECT pg_proc.oid, proname, prolang, pronargs, prorettype, "
"proretset, proargtypes, prosrc, probin, " "proretset, proargtypes, prosrc, probin, "
"(select usename from pg_user where proowner = usesysid) as usename, " "(select usename from pg_user where proowner = usesysid) as usename, "
"proiscachable, 'f'::boolean as proisstrict " "case when proiscachable then 'i' else 'v' end as provolatile, "
"'f'::boolean as proisstrict "
"from pg_proc "
"where pg_proc.oid > '%u'::oid",
g_last_builtin_oid);
}
else if (g_fout->remoteVersion < 70300)
{
appendPQExpBuffer(query,
"SELECT pg_proc.oid, proname, prolang, pronargs, prorettype, "
"proretset, proargtypes, prosrc, probin, "
"(select usename from pg_user where proowner = usesysid) as usename, "
"case when proiscachable then 'i' else 'v' end as provolatile, "
"proisstrict "
"from pg_proc " "from pg_proc "
"where pg_proc.oid > '%u'::oid", "where pg_proc.oid > '%u'::oid",
g_last_builtin_oid); g_last_builtin_oid);
...@@ -1976,7 +1990,7 @@ getFuncs(int *numFuncs) ...@@ -1976,7 +1990,7 @@ getFuncs(int *numFuncs)
"SELECT pg_proc.oid, proname, prolang, pronargs, prorettype, " "SELECT pg_proc.oid, proname, prolang, pronargs, prorettype, "
"proretset, proargtypes, prosrc, probin, " "proretset, proargtypes, prosrc, probin, "
"(select usename from pg_user where proowner = usesysid) as usename, " "(select usename from pg_user where proowner = usesysid) as usename, "
"proiscachable, proisstrict " "provolatile, proisstrict "
"from pg_proc " "from pg_proc "
"where pg_proc.oid > '%u'::oid", "where pg_proc.oid > '%u'::oid",
g_last_builtin_oid); g_last_builtin_oid);
...@@ -2008,7 +2022,7 @@ getFuncs(int *numFuncs) ...@@ -2008,7 +2022,7 @@ getFuncs(int *numFuncs)
i_proretset = PQfnumber(res, "proretset"); i_proretset = PQfnumber(res, "proretset");
i_prosrc = PQfnumber(res, "prosrc"); i_prosrc = PQfnumber(res, "prosrc");
i_probin = PQfnumber(res, "probin"); i_probin = PQfnumber(res, "probin");
i_iscachable = PQfnumber(res, "proiscachable"); i_provolatile = PQfnumber(res, "provolatile");
i_isstrict = PQfnumber(res, "proisstrict"); i_isstrict = PQfnumber(res, "proisstrict");
i_usename = PQfnumber(res, "usename"); i_usename = PQfnumber(res, "usename");
...@@ -2025,7 +2039,7 @@ getFuncs(int *numFuncs) ...@@ -2025,7 +2039,7 @@ getFuncs(int *numFuncs)
finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs)); finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang)); finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
finfo[i].usename = strdup(PQgetvalue(res, i, i_usename)); finfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
finfo[i].iscachable = (strcmp(PQgetvalue(res, i, i_iscachable), "t") == 0); finfo[i].provolatile = (PQgetvalue(res, i, i_provolatile))[0];
finfo[i].isstrict = (strcmp(PQgetvalue(res, i, i_isstrict), "t") == 0); finfo[i].isstrict = (strcmp(PQgetvalue(res, i, i_isstrict), "t") == 0);
if (strlen(finfo[i].usename) == 0) if (strlen(finfo[i].usename) == 0)
...@@ -3559,20 +3573,32 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo, int i, ...@@ -3559,20 +3573,32 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo, int i,
asPart->data); asPart->data);
formatStringLiteral(q, func_lang, CONV_ALL); formatStringLiteral(q, func_lang, CONV_ALL);
if (finfo[i].iscachable || finfo[i].isstrict) /* OR in new attrs here */ if (finfo[i].provolatile != PROVOLATILE_VOLATILE ||
finfo[i].isstrict) /* OR in new attrs here */
{ {
appendPQExpBuffer(q, " WITH ("); appendPQExpBuffer(q, " WITH (");
listSep = listSepNone; listSep = listSepNone;
if (finfo[i].iscachable) if (finfo[i].provolatile == PROVOLATILE_IMMUTABLE)
{
appendPQExpBuffer(q, "%s isImmutable", listSep);
listSep = listSepComma;
}
else if (finfo[i].provolatile == PROVOLATILE_STABLE)
{ {
appendPQExpBuffer(q, "%s iscachable", listSep); appendPQExpBuffer(q, "%s isStable", listSep);
listSep = listSepComma; listSep = listSepComma;
} }
else if (finfo[i].provolatile != PROVOLATILE_VOLATILE)
{
write_msg(NULL, "Unexpected provolatile value for function %s\n",
finfo[i].proname);
exit_nicely();
}
if (finfo[i].isstrict) if (finfo[i].isstrict)
{ {
appendPQExpBuffer(q, "%s isstrict", listSep); appendPQExpBuffer(q, "%s isStrict", listSep);
listSep = listSepComma; listSep = listSepComma;
} }
appendPQExpBuffer(q, " )"); appendPQExpBuffer(q, " )");
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_dump.h,v 1.78 2002/02/11 00:18:20 tgl Exp $ * $Id: pg_dump.h,v 1.79 2002/04/05 00:31:32 tgl Exp $
* *
* Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2 * Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
* *
...@@ -71,8 +71,8 @@ typedef struct _funcInfo ...@@ -71,8 +71,8 @@ typedef struct _funcInfo
char *prosrc; char *prosrc;
char *probin; char *probin;
char *usename; char *usename;
int iscachable; /* Attr */ char provolatile; /* Attr */
int isstrict; /* Attr */ bool isstrict; /* Attr */
int dumped; /* 1 if already dumped */ int dumped; /* 1 if already dumped */
} FuncInfo; } FuncInfo;
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: catversion.h,v 1.112 2002/03/29 19:06:17 tgl Exp $ * $Id: catversion.h,v 1.113 2002/04/05 00:31:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200203261 #define CATALOG_VERSION_NO 200204031
#endif #endif
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: indexing.h,v 1.60 2002/03/29 19:06:17 tgl Exp $ * $Id: indexing.h,v 1.61 2002/04/05 00:31:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
#define OpclassOidIndex "pg_opclass_oid_index" #define OpclassOidIndex "pg_opclass_oid_index"
#define OperatorNameIndex "pg_operator_oprname_l_r_k_index" #define OperatorNameIndex "pg_operator_oprname_l_r_k_index"
#define OperatorOidIndex "pg_operator_oid_index" #define OperatorOidIndex "pg_operator_oid_index"
#define ProcedureNameIndex "pg_proc_proname_narg_type_index" #define ProcedureNameNspIndex "pg_proc_proname_args_nsp_index"
#define ProcedureOidIndex "pg_proc_oid_index" #define ProcedureOidIndex "pg_proc_oid_index"
#define RelCheckIndex "pg_relcheck_rcrelid_index" #define RelCheckIndex "pg_relcheck_rcrelid_index"
#define RewriteOidIndex "pg_rewrite_oid_index" #define RewriteOidIndex "pg_rewrite_oid_index"
...@@ -176,7 +176,7 @@ DECLARE_UNIQUE_INDEX(pg_opclass_oid_index on pg_opclass using btree(oid oid_ops) ...@@ -176,7 +176,7 @@ DECLARE_UNIQUE_INDEX(pg_opclass_oid_index on pg_opclass using btree(oid oid_ops)
DECLARE_UNIQUE_INDEX(pg_operator_oid_index on pg_operator using btree(oid oid_ops)); DECLARE_UNIQUE_INDEX(pg_operator_oid_index on pg_operator using btree(oid oid_ops));
DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_k_index on pg_operator using btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprkind char_ops)); DECLARE_UNIQUE_INDEX(pg_operator_oprname_l_r_k_index on pg_operator using btree(oprname name_ops, oprleft oid_ops, oprright oid_ops, oprkind char_ops));
DECLARE_UNIQUE_INDEX(pg_proc_oid_index on pg_proc using btree(oid oid_ops)); DECLARE_UNIQUE_INDEX(pg_proc_oid_index on pg_proc using btree(oid oid_ops));
DECLARE_UNIQUE_INDEX(pg_proc_proname_narg_type_index on pg_proc using btree(proname name_ops, pronargs int2_ops, proargtypes oidvector_ops)); DECLARE_UNIQUE_INDEX(pg_proc_proname_args_nsp_index on pg_proc using btree(proname name_ops, pronargs int2_ops, proargtypes oidvector_ops, pronamespace oid_ops));
/* This following index is not used for a cache and is not unique */ /* This following index is not used for a cache and is not unique */
DECLARE_INDEX(pg_relcheck_rcrelid_index on pg_relcheck using btree(rcrelid oid_ops)); DECLARE_INDEX(pg_relcheck_rcrelid_index on pg_relcheck using btree(rcrelid oid_ops));
DECLARE_UNIQUE_INDEX(pg_rewrite_oid_index on pg_rewrite using btree(oid oid_ops)); DECLARE_UNIQUE_INDEX(pg_rewrite_oid_index on pg_rewrite using btree(oid oid_ops));
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_attribute.h,v 1.88 2002/04/02 08:51:49 inoue Exp $ * $Id: pg_attribute.h,v 1.89 2002/04/05 00:31:33 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -295,42 +295,44 @@ DATA(insert ( 1262 tableoid 26 0 4 -7 0 -1 -1 t p f i f f)); ...@@ -295,42 +295,44 @@ DATA(insert ( 1262 tableoid 26 0 4 -7 0 -1 -1 t p f i f f));
*/ */
#define Schema_pg_proc \ #define Schema_pg_proc \
{ 1255, {"proname"}, 19, DEFAULT_ATTSTATTARGET, NAMEDATALEN, 1, 0, -1, -1, false, 'p', false, 'i', false, false }, \ { 1255, {"proname"}, 19, DEFAULT_ATTSTATTARGET, NAMEDATALEN, 1, 0, -1, -1, false, 'p', false, 'i', false, false }, \
{ 1255, {"proowner"}, 23, 0, 4, 2, 0, -1, -1, true, 'p', false, 'i', false, false }, \ { 1255, {"pronamespace"}, 26, 0, 4, 2, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"prolang"}, 26, 0, 4, 3, 0, -1, -1, true, 'p', false, 'i', false, false }, \ { 1255, {"proowner"}, 23, 0, 4, 3, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"proisinh"}, 16, 0, 1, 4, 0, -1, -1, true, 'p', false, 'c', false, false }, \ { 1255, {"prolang"}, 26, 0, 4, 4, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"proistrusted"}, 16, 0, 1, 5, 0, -1, -1, true, 'p', false, 'c', false, false }, \ { 1255, {"proisinh"}, 16, 0, 1, 5, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1255, {"proiscachable"}, 16, 0, 1, 6, 0, -1, -1, true, 'p', false, 'c', false, false }, \ { 1255, {"proistrusted"}, 16, 0, 1, 6, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1255, {"proisstrict"}, 16, 0, 1, 7, 0, -1, -1, true, 'p', false, 'c', false, false }, \ { 1255, {"proisstrict"}, 16, 0, 1, 7, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1255, {"pronargs"}, 21, 0, 2, 8, 0, -1, -1, true, 'p', false, 's', false, false }, \ { 1255, {"provolatile"}, 18, 0, 1, 8, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1255, {"proretset"}, 16, 0, 1, 9, 0, -1, -1, true, 'p', false, 'c', false, false }, \ { 1255, {"pronargs"}, 21, 0, 2, 9, 0, -1, -1, true, 'p', false, 's', false, false }, \
{ 1255, {"prorettype"}, 26, 0, 4, 10, 0, -1, -1, true, 'p', false, 'i', false, false }, \ { 1255, {"proretset"}, 16, 0, 1, 10, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1255, {"proargtypes"}, 30, 0, INDEX_MAX_KEYS*4, 11, 0, -1, -1, false, 'p', false, 'i', false, false }, \ { 1255, {"prorettype"}, 26, 0, 4, 11, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"probyte_pct"}, 23, 0, 4, 12, 0, -1, -1, true, 'p', false, 'i', false, false }, \ { 1255, {"proargtypes"}, 30, 0, INDEX_MAX_KEYS*4, 12, 0, -1, -1, false, 'p', false, 'i', false, false }, \
{ 1255, {"properbyte_cpu"}, 23, 0, 4, 13, 0, -1, -1, true, 'p', false, 'i', false, false }, \ { 1255, {"probyte_pct"}, 23, 0, 4, 13, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"propercall_cpu"}, 23, 0, 4, 14, 0, -1, -1, true, 'p', false, 'i', false, false }, \ { 1255, {"properbyte_cpu"}, 23, 0, 4, 14, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"prooutin_ratio"}, 23, 0, 4, 15, 0, -1, -1, true, 'p', false, 'i', false, false }, \ { 1255, {"propercall_cpu"}, 23, 0, 4, 15, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"prosrc"}, 25, 0, -1, 16, 0, -1, -1, false, 'x', false, 'i', false, false }, \ { 1255, {"prooutin_ratio"}, 23, 0, 4, 16, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1255, {"probin"}, 17, 0, -1, 17, 0, -1, -1, false, 'x', false, 'i', false, false }, \ { 1255, {"prosrc"}, 25, 0, -1, 17, 0, -1, -1, false, 'x', false, 'i', false, false }, \
{ 1255, {"proacl"}, 1034, 0, -1, 18, 0, -1, -1, false, 'x', false, 'i', false, false } { 1255, {"probin"}, 17, 0, -1, 18, 0, -1, -1, false, 'x', false, 'i', false, false }, \
{ 1255, {"proacl"}, 1034, 0, -1, 19, 0, -1, -1, false, 'x', false, 'i', false, false }
DATA(insert ( 1255 proname 19 DEFAULT_ATTSTATTARGET NAMEDATALEN 1 0 -1 -1 f p f i f f)); DATA(insert ( 1255 proname 19 DEFAULT_ATTSTATTARGET NAMEDATALEN 1 0 -1 -1 f p f i f f));
DATA(insert ( 1255 proowner 23 0 4 2 0 -1 -1 t p f i f f)); DATA(insert ( 1255 pronamespace 26 0 4 2 0 -1 -1 t p f i f f));
DATA(insert ( 1255 prolang 26 0 4 3 0 -1 -1 t p f i f f)); DATA(insert ( 1255 proowner 23 0 4 3 0 -1 -1 t p f i f f));
DATA(insert ( 1255 proisinh 16 0 1 4 0 -1 -1 t p f c f f)); DATA(insert ( 1255 prolang 26 0 4 4 0 -1 -1 t p f i f f));
DATA(insert ( 1255 proistrusted 16 0 1 5 0 -1 -1 t p f c f f)); DATA(insert ( 1255 proisinh 16 0 1 5 0 -1 -1 t p f c f f));
DATA(insert ( 1255 proiscachable 16 0 1 6 0 -1 -1 t p f c f f)); DATA(insert ( 1255 proistrusted 16 0 1 6 0 -1 -1 t p f c f f));
DATA(insert ( 1255 proisstrict 16 0 1 7 0 -1 -1 t p f c f f)); DATA(insert ( 1255 proisstrict 16 0 1 7 0 -1 -1 t p f c f f));
DATA(insert ( 1255 pronargs 21 0 2 8 0 -1 -1 t p f s f f)); DATA(insert ( 1255 provolatile 18 0 1 8 0 -1 -1 t p f c f f));
DATA(insert ( 1255 proretset 16 0 1 9 0 -1 -1 t p f c f f)); DATA(insert ( 1255 pronargs 21 0 2 9 0 -1 -1 t p f s f f));
DATA(insert ( 1255 prorettype 26 0 4 10 0 -1 -1 t p f i f f)); DATA(insert ( 1255 proretset 16 0 1 10 0 -1 -1 t p f c f f));
DATA(insert ( 1255 proargtypes 30 0 INDEX_MAX_KEYS*4 11 0 -1 -1 f p f i f f)); DATA(insert ( 1255 prorettype 26 0 4 11 0 -1 -1 t p f i f f));
DATA(insert ( 1255 probyte_pct 23 0 4 12 0 -1 -1 t p f i f f)); DATA(insert ( 1255 proargtypes 30 0 INDEX_MAX_KEYS*4 12 0 -1 -1 f p f i f f));
DATA(insert ( 1255 properbyte_cpu 23 0 4 13 0 -1 -1 t p f i f f)); DATA(insert ( 1255 probyte_pct 23 0 4 13 0 -1 -1 t p f i f f));
DATA(insert ( 1255 propercall_cpu 23 0 4 14 0 -1 -1 t p f i f f)); DATA(insert ( 1255 properbyte_cpu 23 0 4 14 0 -1 -1 t p f i f f));
DATA(insert ( 1255 prooutin_ratio 23 0 4 15 0 -1 -1 t p f i f f)); DATA(insert ( 1255 propercall_cpu 23 0 4 15 0 -1 -1 t p f i f f));
DATA(insert ( 1255 prosrc 25 0 -1 16 0 -1 -1 f x f i f f)); DATA(insert ( 1255 prooutin_ratio 23 0 4 16 0 -1 -1 t p f i f f));
DATA(insert ( 1255 probin 17 0 -1 17 0 -1 -1 f x f i f f)); DATA(insert ( 1255 prosrc 25 0 -1 17 0 -1 -1 f x f i f f));
DATA(insert ( 1255 proacl 1034 0 -1 18 0 -1 -1 f x f i f f)); DATA(insert ( 1255 probin 17 0 -1 18 0 -1 -1 f x f i f f));
DATA(insert ( 1255 proacl 1034 0 -1 19 0 -1 -1 f x f i f f));
DATA(insert ( 1255 ctid 27 0 6 -1 0 -1 -1 f p f i f f)); DATA(insert ( 1255 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
DATA(insert ( 1255 oid 26 0 4 -2 0 -1 -1 t p f i f f)); DATA(insert ( 1255 oid 26 0 4 -2 0 -1 -1 t p f i f f));
DATA(insert ( 1255 xmin 28 0 4 -3 0 -1 -1 t p f i f f)); DATA(insert ( 1255 xmin 28 0 4 -3 0 -1 -1 t p f i f f));
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_class.h,v 1.64 2002/03/29 19:06:18 tgl Exp $ * $Id: pg_class.h,v 1.65 2002/04/05 00:31:33 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -138,7 +138,7 @@ DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 0 f f r 23 0 0 0 ...@@ -138,7 +138,7 @@ DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 0 f f r 23 0 0 0
DESCR(""); DESCR("");
DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 f f r 15 0 0 0 0 0 f f f f _null_ )); DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 f f r 15 0 0 0 0 0 f f f f _null_ ));
DESCR(""); DESCR("");
DATA(insert OID = 1255 ( pg_proc PGNSP 81 PGUID 0 1255 0 0 0 0 f f r 18 0 0 0 0 0 t f f f _null_ )); DATA(insert OID = 1255 ( pg_proc PGNSP 81 PGUID 0 1255 0 0 0 0 f f r 19 0 0 0 0 0 t f f f _null_ ));
DESCR(""); DESCR("");
DATA(insert OID = 1259 ( pg_class PGNSP 83 PGUID 0 1259 0 0 0 0 f f r 24 0 0 0 0 0 t f f f _null_ )); DATA(insert OID = 1259 ( pg_class PGNSP 83 PGUID 0 1259 0 0 0 0 f f r 24 0 0 0 0 0 t f f f _null_ ));
DESCR(""); DESCR("");
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: clauses.h,v 1.50 2001/12/10 22:54:12 tgl Exp $ * $Id: clauses.h,v 1.51 2002/04/05 00:31:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -48,7 +48,8 @@ extern bool contain_subplans(Node *clause); ...@@ -48,7 +48,8 @@ extern bool contain_subplans(Node *clause);
extern List *pull_subplans(Node *clause); extern List *pull_subplans(Node *clause);
extern void check_subplans_for_ungrouped_vars(Query *query); extern void check_subplans_for_ungrouped_vars(Query *query);
extern bool contain_noncachable_functions(Node *clause); extern bool contain_mutable_functions(Node *clause);
extern bool contain_volatile_functions(Node *clause);
extern bool is_pseudo_constant_clause(Node *clause); extern bool is_pseudo_constant_clause(Node *clause);
extern List *pull_constant_clauses(List *quals, List **constantQual); extern List *pull_constant_clauses(List *quals, List **constantQual);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: lsyscache.h,v 1.48 2002/04/02 01:03:07 tgl Exp $ * $Id: lsyscache.h,v 1.49 2002/04/05 00:31:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -32,13 +32,13 @@ extern bool op_mergejoinable(Oid opno, Oid ltype, Oid rtype, ...@@ -32,13 +32,13 @@ extern bool op_mergejoinable(Oid opno, Oid ltype, Oid rtype,
extern void op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop, extern void op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
RegProcedure *ltproc, RegProcedure *gtproc); RegProcedure *ltproc, RegProcedure *gtproc);
extern Oid op_hashjoinable(Oid opno, Oid ltype, Oid rtype); extern Oid op_hashjoinable(Oid opno, Oid ltype, Oid rtype);
extern bool op_iscachable(Oid opno); extern char op_volatile(Oid opno);
extern Oid get_commutator(Oid opno); extern Oid get_commutator(Oid opno);
extern Oid get_negator(Oid opno); extern Oid get_negator(Oid opno);
extern RegProcedure get_oprrest(Oid opno); extern RegProcedure get_oprrest(Oid opno);
extern RegProcedure get_oprjoin(Oid opno); extern RegProcedure get_oprjoin(Oid opno);
extern Oid get_func_rettype(Oid funcid); extern Oid get_func_rettype(Oid funcid);
extern bool func_iscachable(Oid funcid); extern char func_volatile(Oid funcid);
extern Oid get_relname_relid(const char *relname, Oid relnamespace); extern Oid get_relname_relid(const char *relname, Oid relnamespace);
extern char *get_rel_name(Oid relid); extern char *get_rel_name(Oid relid);
extern Oid get_rel_type_id(Oid relid); extern Oid get_rel_type_id(Oid relid);
......
...@@ -62,7 +62,7 @@ WHERE p1.oid != p2.oid AND ...@@ -62,7 +62,7 @@ WHERE p1.oid != p2.oid AND
(p1.prolang != p2.prolang OR (p1.prolang != p2.prolang OR
p1.proisinh != p2.proisinh OR p1.proisinh != p2.proisinh OR
p1.proistrusted != p2.proistrusted OR p1.proistrusted != p2.proistrusted OR
p1.proiscachable != p2.proiscachable OR p1.provolatile != p2.provolatile OR
p1.pronargs != p2.pronargs OR p1.pronargs != p2.pronargs OR
p1.proretset != p2.proretset); p1.proretset != p2.proretset);
oid | proname | oid | proname oid | proname | oid | proname
......
...@@ -61,7 +61,7 @@ WHERE p1.oid != p2.oid AND ...@@ -61,7 +61,7 @@ WHERE p1.oid != p2.oid AND
(p1.prolang != p2.prolang OR (p1.prolang != p2.prolang OR
p1.proisinh != p2.proisinh OR p1.proisinh != p2.proisinh OR
p1.proistrusted != p2.proistrusted OR p1.proistrusted != p2.proistrusted OR
p1.proiscachable != p2.proiscachable OR p1.provolatile != p2.provolatile OR
p1.pronargs != p2.pronargs OR p1.pronargs != p2.pronargs OR
p1.proretset != p2.proretset); p1.proretset != p2.proretset);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment