Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4bdb4be

Browse files
committed
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).
1 parent 0e11aea commit 4bdb4be

File tree

26 files changed

+1666
-1540
lines changed

26 files changed

+1666
-1540
lines changed

doc/src/sgml/catalogs.sgml

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<!--
22
Documentation of the system catalogs, directed toward PostgreSQL developers
3-
$Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.39 2002/03/29 19:05:57 tgl Exp $
3+
$Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.40 2002/04/05 00:31:22 tgl Exp $
44
-->
55

66
<chapter id="catalogs">
@@ -1653,6 +1653,15 @@
16531653
<entry>Name of the function</entry>
16541654
</row>
16551655

1656+
<row>
1657+
<entry>pronamespace</entry>
1658+
<entry><type>oid</type></entry>
1659+
<entry>pg_namespace.oid</entry>
1660+
<entry>
1661+
The OID of the namespace that contains this function
1662+
</entry>
1663+
</row>
1664+
16561665
<row>
16571666
<entry>proowner</entry>
16581667
<entry><type>int4</type></entry>
@@ -1681,13 +1690,6 @@
16811690
<entry>not functional</entry>
16821691
</row>
16831692

1684-
<row>
1685-
<entry>proiscachable</entry>
1686-
<entry><type>bool</type></entry>
1687-
<entry></entry>
1688-
<entry>Function returns same result for same input values</entry>
1689-
</row>
1690-
16911693
<row>
16921694
<entry>proisstrict</entry>
16931695
<entry><type>bool</type></entry>
@@ -1700,6 +1702,25 @@
17001702
</entry>
17011703
</row>
17021704

1705+
<row>
1706+
<entry>provolatile</entry>
1707+
<entry><type>char</type></entry>
1708+
<entry></entry>
1709+
<entry>
1710+
<structfield>provolatile</structfield> tells whether the function's
1711+
result depends only on its input arguments, or is affected by outside
1712+
factors.
1713+
It is <literal>i</literal> for <quote>immutable</> functions,
1714+
which always deliver the same result for the same inputs.
1715+
It is <literal>s</literal> for <quote>stable</> functions,
1716+
whose results (for fixed inputs) do not change within a scan.
1717+
It is <literal>v</literal> for <quote>volatile</> functions,
1718+
whose results may change at any time. (Use <literal>v</literal> also
1719+
for functions with side-effects, so that calls to them cannot get
1720+
optimized away.)
1721+
</entry>
1722+
</row>
1723+
17031724
<row>
17041725
<entry>pronargs</entry>
17051726
<entry><type>int2</type></entry>

doc/src/sgml/ref/create_function.sgml

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.34 2002/03/22 19:20:37 petere Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.35 2002/04/05 00:31:24 tgl Exp $
33
-->
44

55
<refentry id="SQL-CREATEFUNCTION">
@@ -160,35 +160,63 @@ CREATE [ OR REPLACE ] FUNCTION <replaceable class="parameter">name</replaceable>
160160

161161
<variablelist>
162162
<varlistentry>
163-
<term>iscachable</term>
163+
<term>isStrict</term>
164164
<listitem>
165165
<para>
166-
<option>Iscachable</option> indicates that the function always
167-
returns the same result when given the same argument values (i.e.,
168-
it does not do database lookups or otherwise use information not
169-
directly present in its parameter list). The optimizer uses
170-
<option>iscachable</option> to know whether it is safe to
171-
pre-evaluate a call of the function.
166+
<option>isStrict</option> indicates that the function always
167+
returns NULL whenever any of its arguments are NULL. If this
168+
attribute is specified, the function is not executed when there
169+
are NULL arguments; instead a NULL result is assumed automatically.
170+
When <option>isStrict</option> is not specified, the function will
171+
be called for NULL inputs. It is then the function author's
172+
responsibility to check for NULLs if necessary and respond
173+
appropriately.
172174
</para>
173175
</listitem>
174176
</varlistentry>
175177

176178
<varlistentry>
177-
<term>isstrict</term>
179+
<term>isImmutable</term>
180+
<term>isCachable</term>
181+
<term>isStable</term>
182+
<term>isVolatile</term>
178183
<listitem>
179184
<para>
180-
<option>isstrict</option> indicates that the function always
181-
returns NULL whenever any of its arguments are NULL. If this
182-
attribute is specified, the function is not executed when there
183-
are NULL arguments; instead a NULL result is assumed automatically.
184-
When <option>isstrict</option> is not specified, the function will
185-
be called for NULL inputs. It is then the function author's
186-
responsibility to check for NULLs if necessary and respond
187-
appropriately.
185+
These attributes inform the system whether it is safe to replace
186+
multiple evaluations of the function with a single evaluation.
187+
At most one choice should be specified. (If none of these appear,
188+
<option>isVolatile</option> is the default assumption.)
189+
<option>isImmutable</option> indicates that the function always
190+
returns the same result when given the same argument values; that
191+
is, it does not do database lookups or otherwise use information not
192+
directly present in its parameter list. If this option is given,
193+
any call of the function with all-constant arguments can be
194+
immediately replaced with the function value.
195+
<option>isCachable</option> is an
196+
obsolete equivalent of <option>isImmutable</option>; it's still
197+
accepted for backwards-compatibility reasons.
198+
<option>isStable</option> indicates that within a single table scan
199+
the function will consistently
200+
return the same result for the same argument values, but that its
201+
result could change across SQL statements. This is the appropriate
202+
selection for functions whose results depend on database lookups,
203+
parameter variables (such as the current timezone), etc. Also note
204+
that the <literal>CURRENT_TIMESTAMP</> family of functions qualify
205+
as stable, since their values do not change within a transaction.
206+
<option>isVolatile</option> indicates that the function value can
207+
change even within a single table scan, so no optimizations can be
208+
made. Relatively few database functions are volatile in this sense;
209+
some examples are <literal>random()</>, <literal>currval()</>,
210+
<literal>timeofday()</>. Note that any function that has side-effects
211+
must be classified volatile, even if its result is quite predictable,
212+
to prevent calls from being optimized away; an example is
213+
<literal>setval()</>.
188214
</para>
189215
</listitem>
190216
</varlistentry>
191217
</variablelist>
218+
219+
Attribute names are not case-sensitive.
192220
</para>
193221

194222
</refsect1>
@@ -342,7 +370,7 @@ CREATE TABLE product (
342370
<programlisting>
343371
CREATE FUNCTION point(complex) RETURNS point
344372
AS '/home/bernie/pgsql/lib/complex.so', 'complex_to_point'
345-
LANGUAGE C;
373+
LANGUAGE C WITH (isStrict);
346374
</programlisting>
347375

348376
The C declaration of the function could be:
@@ -359,6 +387,9 @@ Point * complex_to_point (Complex *z)
359387
return p;
360388
}
361389
</programlisting>
390+
391+
Note that the function is marked <quote>strict</>; this allows us
392+
to skip checking for NULL input in the function body.
362393
</para>
363394
</refsect1>
364395

doc/src/sgml/release.sgml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.130 2002/04/03 05:39:28 petere Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.131 2002/04/05 00:31:23 tgl Exp $
33
-->
44

55
<appendix id="release">
@@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without
2424
worries about funny characters.
2525
-->
2626
<literallayout><![CDATA[
27+
Define a third class of function volatility to allow indexscans in more cases
2728
Locale support is now built by default; choice of locale is set by initdb and/or at run-time
2829
ALTER TABLE ALTER COLUMN SET/DROP NOT NULL
2930
EXPLAIN output comes out as a query result, not a NOTICE message

src/backend/catalog/indexing.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.86 2002/03/29 19:06:00 tgl Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.87 2002/04/05 00:31:24 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -64,7 +64,7 @@ char *Name_pg_opclass_indices[Num_pg_opclass_indices] =
6464
char *Name_pg_operator_indices[Num_pg_operator_indices] =
6565
{OperatorOidIndex, OperatorNameIndex};
6666
char *Name_pg_proc_indices[Num_pg_proc_indices] =
67-
{ProcedureOidIndex, ProcedureNameIndex};
67+
{ProcedureOidIndex, ProcedureNameNspIndex};
6868
char *Name_pg_relcheck_indices[Num_pg_relcheck_indices] =
6969
{RelCheckIndex};
7070
char *Name_pg_rewrite_indices[Num_pg_rewrite_indices] =

src/backend/catalog/pg_proc.c

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.67 2002/03/29 19:06:02 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.68 2002/04/05 00:31:25 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -40,17 +40,17 @@ static void checkretval(Oid rettype, List *queryTreeList);
4040
* ----------------------------------------------------------------
4141
*/
4242
Oid
43-
ProcedureCreate(char *procedureName,
43+
ProcedureCreate(const char *procedureName,
4444
Oid procNamespace,
4545
bool replace,
4646
bool returnsSet,
4747
Oid returnType,
4848
Oid languageObjectId,
49-
char *prosrc,
50-
char *probin,
49+
const char *prosrc,
50+
const char *probin,
5151
bool trusted,
52-
bool canCache,
5352
bool isStrict,
53+
char volatility,
5454
int32 byte_pct,
5555
int32 perbyte_cpu,
5656
int32 percall_cpu,
@@ -167,7 +167,7 @@ ProcedureCreate(char *procedureName,
167167
*/
168168
if (parameterCount == 1 && OidIsValid(typev[0]) &&
169169
(relid = typeidTypeRelid(typev[0])) != 0 &&
170-
get_attnum(relid, procedureName) != InvalidAttrNumber)
170+
get_attnum(relid, (char *) procedureName) != InvalidAttrNumber)
171171
elog(ERROR, "method %s already an attribute of type %s",
172172
procedureName, typeidTypeName(typev[0]));
173173

@@ -180,7 +180,9 @@ ProcedureCreate(char *procedureName,
180180

181181
if (languageObjectId == SQLlanguageId)
182182
{
183-
querytree_list = pg_parse_and_rewrite(prosrc, typev, parameterCount);
183+
querytree_list = pg_parse_and_rewrite((char *) prosrc,
184+
typev,
185+
parameterCount);
184186
/* typecheck return value */
185187
checkretval(returnType, querytree_list);
186188
}
@@ -196,12 +198,11 @@ ProcedureCreate(char *procedureName,
196198
* of backwards compatibility, accept an empty 'prosrc' value as
197199
* meaning the supplied SQL function name.
198200
*/
199-
200201
if (languageObjectId == INTERNALlanguageId)
201202
{
202203
if (strlen(prosrc) == 0)
203204
prosrc = procedureName;
204-
if (fmgr_internal_function(prosrc) == InvalidOid)
205+
if (fmgr_internal_function((char *) prosrc) == InvalidOid)
205206
elog(ERROR,
206207
"there is no built-in function named \"%s\"",
207208
prosrc);
@@ -216,17 +217,18 @@ ProcedureCreate(char *procedureName,
216217
* called, but it seems friendlier to verify the library's validity at
217218
* CREATE FUNCTION time.
218219
*/
219-
220220
if (languageObjectId == ClanguageId)
221221
{
222222
void *libraryhandle;
223223

224224
/* If link symbol is specified as "-", substitute procedure name */
225225
if (strcmp(prosrc, "-") == 0)
226226
prosrc = procedureName;
227-
(void) load_external_function(probin, prosrc, true,
227+
(void) load_external_function((char *) probin,
228+
(char *) prosrc,
229+
true,
228230
&libraryhandle);
229-
(void) fetch_finfo_record(libraryhandle, prosrc);
231+
(void) fetch_finfo_record(libraryhandle, (char *) prosrc);
230232
}
231233

232234
/*
@@ -242,18 +244,18 @@ ProcedureCreate(char *procedureName,
242244

243245
i = 0;
244246
namestrcpy(&procname, procedureName);
245-
values[i++] = NameGetDatum(&procname);
246-
values[i++] = Int32GetDatum(GetUserId());
247-
values[i++] = ObjectIdGetDatum(languageObjectId);
248-
/* XXX isinherited is always false for now */
249-
values[i++] = BoolGetDatum(false);
250-
values[i++] = BoolGetDatum(trusted);
251-
values[i++] = BoolGetDatum(canCache);
252-
values[i++] = BoolGetDatum(isStrict);
253-
values[i++] = UInt16GetDatum(parameterCount);
254-
values[i++] = BoolGetDatum(returnsSet);
255-
values[i++] = ObjectIdGetDatum(returnType);
256-
values[i++] = PointerGetDatum(typev);
247+
values[i++] = NameGetDatum(&procname); /* proname */
248+
values[i++] = ObjectIdGetDatum(procNamespace); /* pronamespace */
249+
values[i++] = Int32GetDatum(GetUserId()); /* proowner */
250+
values[i++] = ObjectIdGetDatum(languageObjectId); /* prolang */
251+
values[i++] = BoolGetDatum(false); /* proisinh (unused) */
252+
values[i++] = BoolGetDatum(trusted); /* proistrusted */
253+
values[i++] = BoolGetDatum(isStrict); /* proisstrict */
254+
values[i++] = CharGetDatum(volatility); /* provolatile */
255+
values[i++] = UInt16GetDatum(parameterCount); /* pronargs */
256+
values[i++] = BoolGetDatum(returnsSet); /* proretset */
257+
values[i++] = ObjectIdGetDatum(returnType); /* prorettype */
258+
values[i++] = PointerGetDatum(typev); /* proargtypes */
257259
values[i++] = Int32GetDatum(byte_pct); /* probyte_pct */
258260
values[i++] = Int32GetDatum(perbyte_cpu); /* properbyte_cpu */
259261
values[i++] = Int32GetDatum(percall_cpu); /* propercall_cpu */
@@ -262,6 +264,8 @@ ProcedureCreate(char *procedureName,
262264
CStringGetDatum(prosrc));
263265
values[i++] = DirectFunctionCall1(textin, /* probin */
264266
CStringGetDatum(probin));
267+
/* proacl will be handled below */
268+
265269

266270
rel = heap_openr(ProcedureRelationName, RowExclusiveLock);
267271
tupDesc = rel->rd_att;
@@ -294,7 +298,7 @@ ProcedureCreate(char *procedureName,
294298
elog(ERROR, "ProcedureCreate: cannot change return type of existing function."
295299
"\n\tUse DROP FUNCTION first.");
296300

297-
/* do not change existing permissions */
301+
/* do not change existing permissions, either */
298302
replaces[Anum_pg_proc_proacl-1] = ' ';
299303

300304
/* Okay, do it... */

0 commit comments

Comments
 (0)