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

Commit fab177e

Browse files
committed
Improve documention on loading large data sets into plperl.
David Fetter
1 parent ed63689 commit fab177e

File tree

2 files changed

+74
-12
lines changed

2 files changed

+74
-12
lines changed

doc/src/sgml/plperl.sgml

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/plperl.sgml,v 2.42 2005/07/13 02:10:42 neilc Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/plperl.sgml,v 2.43 2005/08/12 21:42:53 momjian Exp $
33
-->
44

55
<chapter id="plperl">
@@ -46,7 +46,12 @@ $PostgreSQL: pgsql/doc/src/sgml/plperl.sgml,v 2.42 2005/07/13 02:10:42 neilc Exp
4646
<para>
4747
To create a function in the PL/Perl language, use the standard
4848
<xref linkend="sql-createfunction" endterm="sql-createfunction-title">
49-
syntax:
49+
syntax. A PL/Perl function must always return a scalar value. You
50+
can return more complex structures (arrays, records, and sets)
51+
in the appropriate context by returning a reference.
52+
Never return a list. Here follows an example of a PL/Perl
53+
function.
54+
5055
<programlisting>
5156
CREATE FUNCTION <replaceable>funcname</replaceable> (<replaceable>argument-types</replaceable>) RETURNS <replaceable>return-type</replaceable> AS $$
5257
# PL/Perl function body
@@ -282,7 +287,7 @@ SELECT * FROM perl_set();
282287
</para>
283288

284289
<para>
285-
PL/Perl provides two additional Perl commands:
290+
PL/Perl provides three additional Perl commands:
286291

287292
<variablelist>
288293
<varlistentry>
@@ -293,11 +298,18 @@ SELECT * FROM perl_set();
293298

294299
<term><literal><function>spi_exec_query</>(<replaceable>query</replaceable> [, <replaceable>max-rows</replaceable>])</literal></term>
295300
<term><literal><function>spi_exec_query</>(<replaceable>command</replaceable>)</literal></term>
301+
<term><literal><function>spi_query</>(<replaceable>command</replaceable>)</literal></term>
302+
<term><literal><function>spi_fetchrow</>(<replaceable>command</replaceable>)</literal></term>
303+
296304
<listitem>
297305
<para>
298-
Executes an SQL command. Here is an example of a query
299-
(<command>SELECT</command> command) with the optional maximum
300-
number of rows:
306+
<literal>spi_exec_query</literal> executes an SQL command and
307+
returns the entire rowset as a reference to an array of hash
308+
references. <emphasis>You should only use this command when you know
309+
that the result set will be relatively small.</emphasis> Here is an
310+
example of a query (<command>SELECT</command> command) with the
311+
optional maximum number of rows:
312+
301313
<programlisting>
302314
$rv = spi_exec_query('SELECT * FROM my_table', 5);
303315
</programlisting>
@@ -345,7 +357,7 @@ INSERT INTO test (i, v) VALUES (2, 'second line');
345357
INSERT INTO test (i, v) VALUES (3, 'third line');
346358
INSERT INTO test (i, v) VALUES (4, 'immortal');
347359

348-
CREATE FUNCTION test_munge() RETURNS SETOF test AS $$
360+
CREATE OR REPLACE FUNCTION test_munge() RETURNS SETOF test AS $$
349361
my $rv = spi_exec_query('select i, v from test;');
350362
my $status = $rv-&gt;{status};
351363
my $nrows = $rv-&gt;{processed};
@@ -360,7 +372,45 @@ $$ LANGUAGE plperl;
360372

361373
SELECT * FROM test_munge();
362374
</programlisting>
363-
</para>
375+
</para>
376+
<para>
377+
<literal>spi_query</literal> and <literal>spi_fetchrow</literal>
378+
work together as a pair for rowsets which may be large, or for cases
379+
where you wish to return rows as they arrive.
380+
<literal>spi_fetchrow</literal> works <emphasis>only</emphasis> with
381+
<literal>spi_query</literal>. The following example illustrates how
382+
you use them together:
383+
384+
<programlisting>
385+
CREATE TYPE foo_type AS (the_num INTEGER, the_text TEXT);
386+
387+
CREATE OR REPLACE FUNCTION lotsa_md5 (INTEGER) RETURNS SETOF foo_type AS $$
388+
use Digest::MD5 qw(md5_hex);
389+
my $file = '/usr/share/dict/words';
390+
my $t = localtime;
391+
elog(NOTICE, "opening file $file at $t" );
392+
open my $fh, '&lt;', $file # ooh, it's a file access!
393+
or elog(ERROR, "Can't open $file for reading: $!");
394+
my @words = &lt;$fh&gt;;
395+
close $fh;
396+
$t = localtime;
397+
elog(NOTICE, "closed file $file at $t");
398+
chomp(@words);
399+
my $row;
400+
my $sth = spi_query("SELECT * FROM generate_series(1,$_[0]) AS b(a)");
401+
while (defined ($row = spi_fetchrow($sth))) {
402+
return_next({
403+
the_num =&gt; $row-&gt;{a},
404+
the_text =&gt; md5_hex($words[rand @words])
405+
});
406+
}
407+
return;
408+
$$ LANGUAGE plperlu;
409+
410+
SELECT * from lotsa_md5(500);
411+
</programlisting>
412+
</para>
413+
364414
</listitem>
365415
</varlistentry>
366416

@@ -716,10 +766,20 @@ CREATE TRIGGER test_valid_id_trig
716766

717767
<listitem>
718768
<para>
719-
In the current implementation, if you are fetching or returning
720-
very large data sets, you should be aware that these will all go
721-
into memory.
769+
If you are fetching very large data sets using
770+
<literal>spi_exec_query</literal>, you should be aware that
771+
these will all go into memory. You can avoid this by using
772+
<literal>spi_query</literal>/<literal>spi_fetchrow</literal> as
773+
illustrated earlier.
774+
</para>
775+
<para>
776+
A similar problem occurs if a set-returning function passes a
777+
large set of rows back to postgres via <literal>return</literal>. You
778+
can avoid this problem too by instead using
779+
<literal>return_next</literal> for each row returned, as shown
780+
previously.
722781
</para>
782+
723783
</listitem>
724784
</itemizedlist>
725785
</para>

src/backend/storage/buffer/bufmgr.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.193 2005/08/12 05:05:50 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.194 2005/08/12 21:42:53 momjian Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -153,6 +153,8 @@ ReadBuffer(Relation reln, BlockNumber blockNum)
153153
* block is not currently in memory.
154154
*/
155155
bufHdr = BufferAlloc(reln, blockNum, &found);
156+
/* we are guaranted that nobody else has touched this will-be-new block */
157+
Assert(!(found && isExtend));
156158
if (found)
157159
BufferHitCount++;
158160
}

0 commit comments

Comments
 (0)