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:
Tom Lane 2002-04-05 00:31:36 +00:00
parent 0e11aea246
commit 4bdb4be62e
26 changed files with 1668 additions and 1542 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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] =

View File

@ -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... */

View File

@ -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,

View File

@ -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 */

View File

@ -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

View File

@ -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;
/*

View File

@ -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)))

View File

@ -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

View File

@ -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)

View File

@ -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 */

View File

@ -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;
}

View File

@ -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,
{

View File

@ -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, " )");

View File

@ -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;

View File

@ -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

View File

@ -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));

View File

@ -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));

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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);