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).
This commit is contained in:
parent
0e11aea246
commit
4bdb4be62e
@ -1,6 +1,6 @@
|
||||
<!--
|
||||
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">
|
||||
@ -1653,6 +1653,15 @@
|
||||
<entry>Name of the function</entry>
|
||||
</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>
|
||||
<entry>proowner</entry>
|
||||
<entry><type>int4</type></entry>
|
||||
@ -1681,13 +1690,6 @@
|
||||
<entry>not functional</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>proiscachable</entry>
|
||||
<entry><type>bool</type></entry>
|
||||
<entry></entry>
|
||||
<entry>Function returns same result for same input values</entry>
|
||||
</row>
|
||||
|
||||
<row>
|
||||
<entry>proisstrict</entry>
|
||||
<entry><type>bool</type></entry>
|
||||
@ -1700,6 +1702,25 @@
|
||||
</entry>
|
||||
</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>
|
||||
<entry>pronargs</entry>
|
||||
<entry><type>int2</type></entry>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$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">
|
||||
@ -160,35 +160,63 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>iscachable</term>
|
||||
<term>isStrict</term>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>Iscachable</option> indicates that the function always
|
||||
returns the same result when given the same argument values (i.e.,
|
||||
it does not do database lookups or otherwise use information not
|
||||
directly present in its parameter list). The optimizer uses
|
||||
<option>iscachable</option> to know whether it is safe to
|
||||
pre-evaluate a call of the function.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>isstrict</term>
|
||||
<listitem>
|
||||
<para>
|
||||
<option>isstrict</option> indicates that the function always
|
||||
<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
|
||||
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>
|
||||
</variablelist>
|
||||
|
||||
Attribute names are not case-sensitive.
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
@ -342,7 +370,7 @@ CREATE TABLE product (
|
||||
<programlisting>
|
||||
CREATE FUNCTION point(complex) RETURNS point
|
||||
AS '/home/bernie/pgsql/lib/complex.so', 'complex_to_point'
|
||||
LANGUAGE C;
|
||||
LANGUAGE C WITH (isStrict);
|
||||
</programlisting>
|
||||
|
||||
The C declaration of the function could be:
|
||||
@ -359,6 +387,9 @@ Point * complex_to_point (Complex *z)
|
||||
return p;
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
Note that the function is marked <quote>strict</>; this allows us
|
||||
to skip checking for NULL input in the function body.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
$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">
|
||||
@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without
|
||||
worries about funny characters.
|
||||
-->
|
||||
<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
|
||||
ALTER TABLE ALTER COLUMN SET/DROP NOT NULL
|
||||
EXPLAIN output comes out as a query result, not a NOTICE message
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* 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] =
|
||||
char *Name_pg_operator_indices[Num_pg_operator_indices] =
|
||||
{OperatorOidIndex, OperatorNameIndex};
|
||||
char *Name_pg_proc_indices[Num_pg_proc_indices] =
|
||||
{ProcedureOidIndex, ProcedureNameIndex};
|
||||
{ProcedureOidIndex, ProcedureNameNspIndex};
|
||||
char *Name_pg_relcheck_indices[Num_pg_relcheck_indices] =
|
||||
{RelCheckIndex};
|
||||
char *Name_pg_rewrite_indices[Num_pg_rewrite_indices] =
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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);
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
Oid
|
||||
ProcedureCreate(char *procedureName,
|
||||
ProcedureCreate(const char *procedureName,
|
||||
Oid procNamespace,
|
||||
bool replace,
|
||||
bool returnsSet,
|
||||
Oid returnType,
|
||||
Oid languageObjectId,
|
||||
char *prosrc,
|
||||
char *probin,
|
||||
const char *prosrc,
|
||||
const char *probin,
|
||||
bool trusted,
|
||||
bool canCache,
|
||||
bool isStrict,
|
||||
char volatility,
|
||||
int32 byte_pct,
|
||||
int32 perbyte_cpu,
|
||||
int32 percall_cpu,
|
||||
@ -167,7 +167,7 @@ ProcedureCreate(char *procedureName,
|
||||
*/
|
||||
if (parameterCount == 1 && OidIsValid(typev[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",
|
||||
procedureName, typeidTypeName(typev[0]));
|
||||
|
||||
@ -180,7 +180,9 @@ ProcedureCreate(char *procedureName,
|
||||
|
||||
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 */
|
||||
checkretval(returnType, querytree_list);
|
||||
}
|
||||
@ -196,12 +198,11 @@ ProcedureCreate(char *procedureName,
|
||||
* of backwards compatibility, accept an empty 'prosrc' value as
|
||||
* meaning the supplied SQL function name.
|
||||
*/
|
||||
|
||||
if (languageObjectId == INTERNALlanguageId)
|
||||
{
|
||||
if (strlen(prosrc) == 0)
|
||||
prosrc = procedureName;
|
||||
if (fmgr_internal_function(prosrc) == InvalidOid)
|
||||
if (fmgr_internal_function((char *) prosrc) == InvalidOid)
|
||||
elog(ERROR,
|
||||
"there is no built-in function named \"%s\"",
|
||||
prosrc);
|
||||
@ -216,7 +217,6 @@ ProcedureCreate(char *procedureName,
|
||||
* called, but it seems friendlier to verify the library's validity at
|
||||
* CREATE FUNCTION time.
|
||||
*/
|
||||
|
||||
if (languageObjectId == ClanguageId)
|
||||
{
|
||||
void *libraryhandle;
|
||||
@ -224,9 +224,11 @@ ProcedureCreate(char *procedureName,
|
||||
/* If link symbol is specified as "-", substitute procedure name */
|
||||
if (strcmp(prosrc, "-") == 0)
|
||||
prosrc = procedureName;
|
||||
(void) load_external_function(probin, prosrc, true,
|
||||
(void) load_external_function((char *) probin,
|
||||
(char *) prosrc,
|
||||
true,
|
||||
&libraryhandle);
|
||||
(void) fetch_finfo_record(libraryhandle, prosrc);
|
||||
(void) fetch_finfo_record(libraryhandle, (char *) prosrc);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -242,18 +244,18 @@ ProcedureCreate(char *procedureName,
|
||||
|
||||
i = 0;
|
||||
namestrcpy(&procname, procedureName);
|
||||
values[i++] = NameGetDatum(&procname);
|
||||
values[i++] = Int32GetDatum(GetUserId());
|
||||
values[i++] = ObjectIdGetDatum(languageObjectId);
|
||||
/* XXX isinherited is always false for now */
|
||||
values[i++] = BoolGetDatum(false);
|
||||
values[i++] = BoolGetDatum(trusted);
|
||||
values[i++] = BoolGetDatum(canCache);
|
||||
values[i++] = BoolGetDatum(isStrict);
|
||||
values[i++] = UInt16GetDatum(parameterCount);
|
||||
values[i++] = BoolGetDatum(returnsSet);
|
||||
values[i++] = ObjectIdGetDatum(returnType);
|
||||
values[i++] = PointerGetDatum(typev);
|
||||
values[i++] = NameGetDatum(&procname); /* proname */
|
||||
values[i++] = ObjectIdGetDatum(procNamespace); /* pronamespace */
|
||||
values[i++] = Int32GetDatum(GetUserId()); /* proowner */
|
||||
values[i++] = ObjectIdGetDatum(languageObjectId); /* prolang */
|
||||
values[i++] = BoolGetDatum(false); /* proisinh (unused) */
|
||||
values[i++] = BoolGetDatum(trusted); /* proistrusted */
|
||||
values[i++] = BoolGetDatum(isStrict); /* proisstrict */
|
||||
values[i++] = CharGetDatum(volatility); /* provolatile */
|
||||
values[i++] = UInt16GetDatum(parameterCount); /* pronargs */
|
||||
values[i++] = BoolGetDatum(returnsSet); /* proretset */
|
||||
values[i++] = ObjectIdGetDatum(returnType); /* prorettype */
|
||||
values[i++] = PointerGetDatum(typev); /* proargtypes */
|
||||
values[i++] = Int32GetDatum(byte_pct); /* probyte_pct */
|
||||
values[i++] = Int32GetDatum(perbyte_cpu); /* properbyte_cpu */
|
||||
values[i++] = Int32GetDatum(percall_cpu); /* propercall_cpu */
|
||||
@ -262,6 +264,8 @@ ProcedureCreate(char *procedureName,
|
||||
CStringGetDatum(prosrc));
|
||||
values[i++] = DirectFunctionCall1(textin, /* probin */
|
||||
CStringGetDatum(probin));
|
||||
/* proacl will be handled below */
|
||||
|
||||
|
||||
rel = heap_openr(ProcedureRelationName, RowExclusiveLock);
|
||||
tupDesc = rel->rd_att;
|
||||
@ -294,7 +298,7 @@ ProcedureCreate(char *procedureName,
|
||||
elog(ERROR, "ProcedureCreate: cannot change return type of existing function."
|
||||
"\n\tUse DROP FUNCTION first.");
|
||||
|
||||
/* do not change existing permissions */
|
||||
/* do not change existing permissions, either */
|
||||
replaces[Anum_pg_proc_proacl-1] = ' ';
|
||||
|
||||
/* Okay, do it... */
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@ -145,7 +145,7 @@ static void
|
||||
compute_full_attributes(List *parameters,
|
||||
int32 *byte_pct_p, int32 *perbyte_cpu_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
|
||||
@ -156,18 +156,15 @@ compute_full_attributes(List *parameters,
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* used in the "expensive functions" optimizer, but that's been dead code
|
||||
* 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;
|
||||
@ -177,17 +174,26 @@ compute_full_attributes(List *parameters,
|
||||
*perbyte_cpu_p = PERBYTE_CPU;
|
||||
*percall_cpu_p = PERCALL_CPU;
|
||||
*outin_ratio_p = OUTIN_RATIO;
|
||||
*canCache_p = false;
|
||||
*isStrict_p = false;
|
||||
*volatility_p = PROVOLATILE_VOLATILE;
|
||||
|
||||
foreach(pl, parameters)
|
||||
{
|
||||
DefElem *param = (DefElem *) lfirst(pl);
|
||||
|
||||
if (strcasecmp(param->defname, "iscachable") == 0)
|
||||
*canCache_p = true;
|
||||
else if (strcasecmp(param->defname, "isstrict") == 0)
|
||||
if (strcasecmp(param->defname, "isstrict") == 0)
|
||||
*isStrict_p = true;
|
||||
else if (strcasecmp(param->defname, "isimmutable") == 0)
|
||||
*volatility_p = PROVOLATILE_IMMUTABLE;
|
||||
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)
|
||||
{
|
||||
/*
|
||||
@ -273,8 +279,8 @@ CreateFunction(ProcedureStmt *stmt)
|
||||
perbyte_cpu,
|
||||
percall_cpu,
|
||||
outin_ratio;
|
||||
bool canCache,
|
||||
isStrict;
|
||||
bool isStrict;
|
||||
char volatility;
|
||||
HeapTuple languageTuple;
|
||||
Form_pg_language languageStruct;
|
||||
|
||||
@ -311,7 +317,7 @@ CreateFunction(ProcedureStmt *stmt)
|
||||
|
||||
compute_full_attributes(stmt->withClause,
|
||||
&byte_pct, &perbyte_cpu, &percall_cpu,
|
||||
&outin_ratio, &canCache, &isStrict);
|
||||
&outin_ratio, &isStrict, &volatility);
|
||||
|
||||
interpret_AS_clause(languageOid, languageName, stmt->as,
|
||||
&prosrc_str, &probin_str);
|
||||
@ -329,8 +335,8 @@ CreateFunction(ProcedureStmt *stmt)
|
||||
prosrc_str, /* converted to text later */
|
||||
probin_str, /* converted to text later */
|
||||
true, /* (obsolete "trusted") */
|
||||
canCache,
|
||||
isStrict,
|
||||
volatility,
|
||||
byte_pct,
|
||||
perbyte_cpu,
|
||||
percall_cpu,
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 @@
|
||||
#include "catalog/index.h"
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/pg_opclass.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "commands/defrem.h"
|
||||
#include "miscadmin.h"
|
||||
#include "optimizer/clauses.h"
|
||||
@ -233,11 +234,11 @@ CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid)
|
||||
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.
|
||||
*/
|
||||
if (contain_noncachable_functions((Node *) predList))
|
||||
elog(ERROR, "Cannot use non-cachable function in index predicate");
|
||||
if (contain_mutable_functions((Node *) predList))
|
||||
elog(ERROR, "Functions in index predicate must be marked isImmutable");
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
* 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.
|
||||
*/
|
||||
if (!func_iscachable(funcid))
|
||||
elog(ERROR, "DefineIndex: index function must be marked iscachable");
|
||||
if (func_volatile(funcid) != PROVOLATILE_IMMUTABLE)
|
||||
elog(ERROR, "DefineIndex: index function must be marked isImmutable");
|
||||
|
||||
/* Process opclass, using func return type as default type */
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* 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,
|
||||
* Check for an indexqual that could be handled by a nestloop
|
||||
* join. We need the index key to be compared against an
|
||||
* 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))
|
||||
{
|
||||
@ -792,7 +792,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
|
||||
|
||||
isIndexable =
|
||||
!intMember(lfirsti(rel->relids), othervarnos) &&
|
||||
!contain_noncachable_functions((Node *) rightop) &&
|
||||
!contain_volatile_functions((Node *) rightop) &&
|
||||
is_indexable_operator(clause, opclass, true);
|
||||
freeList(othervarnos);
|
||||
return isIndexable;
|
||||
@ -804,7 +804,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
|
||||
|
||||
isIndexable =
|
||||
!intMember(lfirsti(rel->relids), othervarnos) &&
|
||||
!contain_noncachable_functions((Node *) leftop) &&
|
||||
!contain_volatile_functions((Node *) leftop) &&
|
||||
is_indexable_operator(clause, opclass, false);
|
||||
freeList(othervarnos);
|
||||
return isIndexable;
|
||||
@ -1142,7 +1142,7 @@ static const StrategyNumber
|
||||
* implies another. A simple and general way is to see if they are
|
||||
* equal(); this works for any kind of expression. (Actually, there
|
||||
* 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().)
|
||||
*
|
||||
* Our other way works only for (binary boolean) operators that are
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -52,7 +52,8 @@ static bool contain_subplans_walker(Node *node, void *context);
|
||||
static bool pull_subplans_walker(Node *node, List **listptr);
|
||||
static bool check_subplans_for_ungrouped_vars_walker(Node *node,
|
||||
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 Expr *simplify_op_or_func(Expr *expr, List *args);
|
||||
|
||||
@ -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
|
||||
* Recursively search for noncachable functions within a clause.
|
||||
* contain_mutable_functions
|
||||
* Recursively search for mutable functions within a clause.
|
||||
*
|
||||
* Returns true if any noncachable function (or operator implemented by a
|
||||
* noncachable function) is found. This test is needed so that we don't
|
||||
* Returns true if any mutable function (or operator implemented by a
|
||||
* 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
|
||||
* as a constant qualification.
|
||||
*
|
||||
* 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
|
||||
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
|
||||
contain_noncachable_functions_walker(Node *node, void *context)
|
||||
contain_mutable_functions_walker(Node *node, void *context)
|
||||
{
|
||||
if (node == NULL)
|
||||
return false;
|
||||
@ -731,18 +732,67 @@ contain_noncachable_functions_walker(Node *node, void *context)
|
||||
switch (expr->opType)
|
||||
{
|
||||
case OP_EXPR:
|
||||
if (!op_iscachable(((Oper *) expr->oper)->opno))
|
||||
if (op_volatile(((Oper *) expr->oper)->opno) != PROVOLATILE_IMMUTABLE)
|
||||
return true;
|
||||
break;
|
||||
case FUNC_EXPR:
|
||||
if (!func_iscachable(((Func *) expr->oper)->funcid))
|
||||
if (func_volatile(((Func *) expr->oper)->funcid) != PROVOLATILE_IMMUTABLE)
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
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);
|
||||
}
|
||||
|
||||
@ -754,23 +804,25 @@ contain_noncachable_functions_walker(Node *node, void *context)
|
||||
/*
|
||||
* is_pseudo_constant_clause
|
||||
* 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
|
||||
* Params and outer-level Vars. However, its value 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.
|
||||
* Params and outer-level Vars, not to mention functions whose results
|
||||
* may vary from one statement to the next. However, the clause's value
|
||||
* 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
|
||||
is_pseudo_constant_clause(Node *clause)
|
||||
{
|
||||
/*
|
||||
* 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
|
||||
* check for noncachable functions if we find no Vars.
|
||||
* check for volatile functions if we find no Vars.
|
||||
*/
|
||||
if (!contain_var_clause(clause) &&
|
||||
!contain_noncachable_functions(clause))
|
||||
!contain_volatile_functions(clause))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@ -1019,7 +1071,7 @@ CommuteClause(Expr *clause)
|
||||
*
|
||||
* We do understand that certain functions may deliver non-constant
|
||||
* 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
|
||||
* arguments as far as possible. Functions that are the arguments
|
||||
* of Iter nodes are also not evaluated.
|
||||
@ -1412,7 +1464,7 @@ simplify_op_or_func(Expr *expr, List *args)
|
||||
Oid result_typeid;
|
||||
HeapTuple func_tuple;
|
||||
Form_pg_proc funcform;
|
||||
bool proiscachable;
|
||||
char provolatile;
|
||||
bool proisstrict;
|
||||
bool proretset;
|
||||
int16 resultTypLen;
|
||||
@ -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
|
||||
* marked proiscachable.
|
||||
* marked immutable.
|
||||
*
|
||||
* XXX would it be better to take the result type from the pg_proc tuple,
|
||||
* rather than the Oper or Func node?
|
||||
@ -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.
|
||||
*/
|
||||
func_tuple = SearchSysCache(PROCOID,
|
||||
@ -1478,12 +1530,12 @@ simplify_op_or_func(Expr *expr, List *args)
|
||||
if (!HeapTupleIsValid(func_tuple))
|
||||
elog(ERROR, "Function OID %u does not exist", funcid);
|
||||
funcform = (Form_pg_proc) GETSTRUCT(func_tuple);
|
||||
proiscachable = funcform->proiscachable;
|
||||
provolatile = funcform->provolatile;
|
||||
proisstrict = funcform->proisstrict;
|
||||
proretset = funcform->proretset;
|
||||
ReleaseSysCache(func_tuple);
|
||||
|
||||
if (!proiscachable)
|
||||
if (provolatile != PROVOLATILE_IMMUTABLE)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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)
|
||||
(RegProcedure) F_INT2EQ,
|
||||
Int16GetDatum(nargs));
|
||||
|
||||
funcscan = systable_beginscan(heapRelation, ProcedureNameIndex, true,
|
||||
funcscan = systable_beginscan(heapRelation, ProcedureNameNspIndex, true,
|
||||
SnapshotNow, 2, skey);
|
||||
|
||||
while (HeapTupleIsValid(tuple = systable_getnext(funcscan)))
|
||||
|
@ -9,7 +9,7 @@
|
||||
#
|
||||
#
|
||||
# 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]*//' \
|
||||
-e 's/[ ]*).*$//' | \
|
||||
$AWK '
|
||||
/^#/ { print; next; }
|
||||
$4 == "12" { print; next; }' > $CPPTMPFILE
|
||||
$5 == "12" { print; next; }' > $CPPTMPFILE
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
cleanup
|
||||
@ -232,7 +232,7 @@ $AWK 'BEGIN {
|
||||
Bool["f"] = "false"
|
||||
}
|
||||
{ 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"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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)
|
||||
char *pro_name_or_oid = PG_GETARG_CSTRING(0);
|
||||
RegProcedure result = InvalidOid;
|
||||
int matches = 0;
|
||||
ScanKeyData skey[1];
|
||||
|
||||
if (pro_name_or_oid[0] == '-' && pro_name_or_oid[1] == '\0')
|
||||
PG_RETURN_OID(InvalidOid);
|
||||
|
||||
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;
|
||||
|
||||
@ -61,67 +61,33 @@ regprocin(PG_FUNCTION_ARGS)
|
||||
elog(ERROR, "No procedure with oid %s", pro_name_or_oid);
|
||||
matches = 1;
|
||||
}
|
||||
else if (!IsIgnoringSystemIndexes())
|
||||
{
|
||||
Relation hdesc;
|
||||
Relation idesc;
|
||||
IndexScanDesc sd;
|
||||
RetrieveIndexResult indexRes;
|
||||
HeapTupleData tuple;
|
||||
Buffer buffer;
|
||||
|
||||
ScanKeyEntryInitialize(&skey[0], 0x0,
|
||||
(AttrNumber) 1,
|
||||
(RegProcedure) F_NAMEEQ,
|
||||
CStringGetDatum(pro_name_or_oid));
|
||||
|
||||
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);
|
||||
index_close(idesc);
|
||||
heap_close(hdesc, AccessShareLock);
|
||||
}
|
||||
else
|
||||
{
|
||||
Relation proc;
|
||||
HeapScanDesc procscan;
|
||||
HeapTuple proctup;
|
||||
Relation hdesc;
|
||||
ScanKeyData skey[1];
|
||||
SysScanDesc funcscan;
|
||||
HeapTuple tuple;
|
||||
|
||||
ScanKeyEntryInitialize(&skey[0], 0x0,
|
||||
(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);
|
||||
hdesc = heap_openr(ProcedureRelationName, AccessShareLock);
|
||||
|
||||
while (HeapTupleIsValid(proctup = heap_getnext(procscan, 0)))
|
||||
funcscan = systable_beginscan(hdesc, ProcedureNameNspIndex, true,
|
||||
SnapshotNow, 1, skey);
|
||||
|
||||
while (HeapTupleIsValid(tuple = systable_getnext(funcscan)))
|
||||
{
|
||||
result = proctup->t_data->t_oid;
|
||||
result = (RegProcedure) tuple->t_data->t_oid;
|
||||
if (++matches > 1)
|
||||
break;
|
||||
}
|
||||
|
||||
heap_endscan(procscan);
|
||||
heap_close(proc, AccessShareLock);
|
||||
systable_endscan(funcscan);
|
||||
|
||||
heap_close(hdesc, AccessShareLock);
|
||||
}
|
||||
|
||||
if (matches > 1)
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* 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)
|
||||
querystr, /* sourceCode */
|
||||
fileName, /* fileName */
|
||||
true, /* trusted */
|
||||
false, /* canCache (assume unsafe) */
|
||||
false, /* isStrict (irrelevant, no args) */
|
||||
PROVOLATILE_VOLATILE, /* assume unsafe */
|
||||
100, /* byte_pct */
|
||||
0, /* perbyte_cpu */
|
||||
0, /* percall_cpu */
|
||||
|
24
src/backend/utils/cache/lsyscache.c
vendored
24
src/backend/utils/cache/lsyscache.c
vendored
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* 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
|
||||
* Eventually, the index information should go through here, too.
|
||||
@ -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
|
||||
op_iscachable(Oid opno)
|
||||
char
|
||||
op_volatile(Oid opno)
|
||||
{
|
||||
RegProcedure funcid = get_opcode(opno);
|
||||
|
||||
if (funcid == (RegProcedure) InvalidOid)
|
||||
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)
|
||||
}
|
||||
|
||||
/*
|
||||
* func_iscachable
|
||||
* Given procedure id, return the function's proiscachable flag.
|
||||
* func_volatile
|
||||
* Given procedure id, return the function's provolatile flag.
|
||||
*/
|
||||
bool
|
||||
func_iscachable(Oid funcid)
|
||||
char
|
||||
func_volatile(Oid funcid)
|
||||
{
|
||||
HeapTuple tp;
|
||||
bool result;
|
||||
char result;
|
||||
|
||||
tp = SearchSysCache(PROCOID,
|
||||
ObjectIdGetDatum(funcid),
|
||||
@ -628,7 +628,7 @@ func_iscachable(Oid funcid)
|
||||
if (!HeapTupleIsValid(tp))
|
||||
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);
|
||||
return result;
|
||||
}
|
||||
|
4
src/backend/utils/cache/syscache.c
vendored
4
src/backend/utils/cache/syscache.c
vendored
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* These routines allow the parser/planner/executor to perform
|
||||
@ -304,7 +304,7 @@ static const struct cachedesc cacheinfo[] = {
|
||||
0
|
||||
}},
|
||||
{ProcedureRelationName, /* PROCNAME */
|
||||
ProcedureNameIndex,
|
||||
ProcedureNameNspIndex, /* XXX very temporary */
|
||||
0,
|
||||
3,
|
||||
{
|
||||
|
@ -22,7 +22,7 @@
|
||||
*
|
||||
*
|
||||
* 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 @@
|
||||
#include "access/attnum.h"
|
||||
#include "access/htup.h"
|
||||
#include "catalog/pg_class.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "catalog/pg_trigger.h"
|
||||
#include "catalog/pg_type.h"
|
||||
|
||||
@ -1953,7 +1954,7 @@ getFuncs(int *numFuncs)
|
||||
int i_proretset;
|
||||
int i_prosrc;
|
||||
int i_probin;
|
||||
int i_iscachable;
|
||||
int i_provolatile;
|
||||
int i_isstrict;
|
||||
int i_usename;
|
||||
|
||||
@ -1965,7 +1966,20 @@ getFuncs(int *numFuncs)
|
||||
"SELECT pg_proc.oid, proname, prolang, pronargs, prorettype, "
|
||||
"proretset, proargtypes, prosrc, probin, "
|
||||
"(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 "
|
||||
"where pg_proc.oid > '%u'::oid",
|
||||
g_last_builtin_oid);
|
||||
@ -1976,7 +1990,7 @@ getFuncs(int *numFuncs)
|
||||
"SELECT pg_proc.oid, proname, prolang, pronargs, prorettype, "
|
||||
"proretset, proargtypes, prosrc, probin, "
|
||||
"(select usename from pg_user where proowner = usesysid) as usename, "
|
||||
"proiscachable, proisstrict "
|
||||
"provolatile, proisstrict "
|
||||
"from pg_proc "
|
||||
"where pg_proc.oid > '%u'::oid",
|
||||
g_last_builtin_oid);
|
||||
@ -2008,7 +2022,7 @@ getFuncs(int *numFuncs)
|
||||
i_proretset = PQfnumber(res, "proretset");
|
||||
i_prosrc = PQfnumber(res, "prosrc");
|
||||
i_probin = PQfnumber(res, "probin");
|
||||
i_iscachable = PQfnumber(res, "proiscachable");
|
||||
i_provolatile = PQfnumber(res, "provolatile");
|
||||
i_isstrict = PQfnumber(res, "proisstrict");
|
||||
i_usename = PQfnumber(res, "usename");
|
||||
|
||||
@ -2025,7 +2039,7 @@ getFuncs(int *numFuncs)
|
||||
finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
|
||||
finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
|
||||
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);
|
||||
|
||||
if (strlen(finfo[i].usename) == 0)
|
||||
@ -3559,20 +3573,32 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo, int i,
|
||||
asPart->data);
|
||||
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 (");
|
||||
listSep = listSepNone;
|
||||
|
||||
if (finfo[i].iscachable)
|
||||
if (finfo[i].provolatile == PROVOLATILE_IMMUTABLE)
|
||||
{
|
||||
appendPQExpBuffer(q, "%s iscachable", listSep);
|
||||
appendPQExpBuffer(q, "%s isImmutable", listSep);
|
||||
listSep = listSepComma;
|
||||
}
|
||||
else if (finfo[i].provolatile == PROVOLATILE_STABLE)
|
||||
{
|
||||
appendPQExpBuffer(q, "%s isStable", listSep);
|
||||
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)
|
||||
{
|
||||
appendPQExpBuffer(q, "%s isstrict", listSep);
|
||||
appendPQExpBuffer(q, "%s isStrict", listSep);
|
||||
listSep = listSepComma;
|
||||
}
|
||||
appendPQExpBuffer(q, " )");
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* 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
|
||||
*
|
||||
@ -71,8 +71,8 @@ typedef struct _funcInfo
|
||||
char *prosrc;
|
||||
char *probin;
|
||||
char *usename;
|
||||
int iscachable; /* Attr */
|
||||
int isstrict; /* Attr */
|
||||
char provolatile; /* Attr */
|
||||
bool isstrict; /* Attr */
|
||||
int dumped; /* 1 if already dumped */
|
||||
} FuncInfo;
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* 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 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 200203261
|
||||
#define CATALOG_VERSION_NO 200204031
|
||||
|
||||
#endif
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* 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 @@
|
||||
#define OpclassOidIndex "pg_opclass_oid_index"
|
||||
#define OperatorNameIndex "pg_operator_oprname_l_r_k_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 RelCheckIndex "pg_relcheck_rcrelid_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)
|
||||
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_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 */
|
||||
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));
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* 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
|
||||
* 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));
|
||||
*/
|
||||
#define Schema_pg_proc \
|
||||
{ 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, {"prolang"}, 26, 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, {"proistrusted"}, 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, {"pronamespace"}, 26, 0, 4, 2, 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, {"prolang"}, 26, 0, 4, 4, 0, -1, -1, true, 'p', false, 'i', false, false }, \
|
||||
{ 1255, {"proisinh"}, 16, 0, 1, 5, 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, {"pronargs"}, 21, 0, 2, 8, 0, -1, -1, true, 'p', false, 's', false, false }, \
|
||||
{ 1255, {"proretset"}, 16, 0, 1, 9, 0, -1, -1, true, 'p', false, 'c', false, false }, \
|
||||
{ 1255, {"prorettype"}, 26, 0, 4, 10, 0, -1, -1, true, 'p', false, 'i', false, false }, \
|
||||
{ 1255, {"proargtypes"}, 30, 0, INDEX_MAX_KEYS*4, 11, 0, -1, -1, false, 'p', false, 'i', false, false }, \
|
||||
{ 1255, {"probyte_pct"}, 23, 0, 4, 12, 0, -1, -1, true, 'p', false, 'i', false, false }, \
|
||||
{ 1255, {"properbyte_cpu"}, 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, {"prooutin_ratio"}, 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, {"probin"}, 17, 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, {"provolatile"}, 18, 0, 1, 8, 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, {"proretset"}, 16, 0, 1, 10, 0, -1, -1, true, 'p', false, 'c', false, false }, \
|
||||
{ 1255, {"prorettype"}, 26, 0, 4, 11, 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, {"probyte_pct"}, 23, 0, 4, 13, 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, {"propercall_cpu"}, 23, 0, 4, 15, 0, -1, -1, true, 'p', false, 'i', false, false }, \
|
||||
{ 1255, {"prooutin_ratio"}, 23, 0, 4, 16, 0, -1, -1, true, 'p', false, 'i', false, false }, \
|
||||
{ 1255, {"prosrc"}, 25, 0, -1, 17, 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 proowner 23 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 proisinh 16 0 1 4 0 -1 -1 t p f c f f));
|
||||
DATA(insert ( 1255 proistrusted 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 pronamespace 26 0 4 2 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 prolang 26 0 4 4 0 -1 -1 t p f i f f));
|
||||
DATA(insert ( 1255 proisinh 16 0 1 5 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 pronargs 21 0 2 8 0 -1 -1 t p f s f f));
|
||||
DATA(insert ( 1255 proretset 16 0 1 9 0 -1 -1 t p f c f f));
|
||||
DATA(insert ( 1255 prorettype 26 0 4 10 0 -1 -1 t p f i 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 probyte_pct 23 0 4 12 0 -1 -1 t 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 propercall_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 prosrc 25 0 -1 16 0 -1 -1 f x f i f f));
|
||||
DATA(insert ( 1255 probin 17 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 provolatile 18 0 1 8 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 proretset 16 0 1 10 0 -1 -1 t p f c f f));
|
||||
DATA(insert ( 1255 prorettype 26 0 4 11 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 probyte_pct 23 0 4 13 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 propercall_cpu 23 0 4 15 0 -1 -1 t p 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 prosrc 25 0 -1 17 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 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));
|
||||
|
@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* 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
|
||||
* 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
|
||||
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_ ));
|
||||
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("");
|
||||
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("");
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* 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);
|
||||
extern List *pull_subplans(Node *clause);
|
||||
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 List *pull_constant_clauses(List *quals, List **constantQual);
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
* 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,
|
||||
extern void op_mergejoin_crossops(Oid opno, Oid *ltop, Oid *gtop,
|
||||
RegProcedure *ltproc, RegProcedure *gtproc);
|
||||
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_negator(Oid opno);
|
||||
extern RegProcedure get_oprrest(Oid opno);
|
||||
extern RegProcedure get_oprjoin(Oid opno);
|
||||
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 char *get_rel_name(Oid relid);
|
||||
extern Oid get_rel_type_id(Oid relid);
|
||||
|
@ -62,7 +62,7 @@ WHERE p1.oid != p2.oid AND
|
||||
(p1.prolang != p2.prolang OR
|
||||
p1.proisinh != p2.proisinh OR
|
||||
p1.proistrusted != p2.proistrusted OR
|
||||
p1.proiscachable != p2.proiscachable OR
|
||||
p1.provolatile != p2.provolatile OR
|
||||
p1.pronargs != p2.pronargs OR
|
||||
p1.proretset != p2.proretset);
|
||||
oid | proname | oid | proname
|
||||
|
@ -61,7 +61,7 @@ WHERE p1.oid != p2.oid AND
|
||||
(p1.prolang != p2.prolang OR
|
||||
p1.proisinh != p2.proisinh OR
|
||||
p1.proistrusted != p2.proistrusted OR
|
||||
p1.proiscachable != p2.proiscachable OR
|
||||
p1.provolatile != p2.provolatile OR
|
||||
p1.pronargs != p2.pronargs OR
|
||||
p1.proretset != p2.proretset);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user