From 89e850e6fda9e4e441712012abe971fe938d595a Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Mon, 5 Dec 2011 19:52:15 +0200 Subject: plpython: Add SPI cursor support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a function plpy.cursor that is similar to plpy.execute but uses an SPI cursor to avoid fetching the entire result set into memory. Jan UrbaƄski, reviewed by Steve Singer --- doc/src/sgml/plpython.sgml | 81 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'doc/src') diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml index eda2bbf34c5..618f8d055e9 100644 --- a/doc/src/sgml/plpython.sgml +++ b/doc/src/sgml/plpython.sgml @@ -891,6 +891,15 @@ $$ LANGUAGE plpythonu; can be modified. + + Note that calling plpy.execute will cause the entire + result set to be read into memory. Only use that function when you are sure + that the result set will be relatively small. If you don't want to risk + excessive memory usage when fetching large results, + use plpy.cursor rather + than plpy.execute. + + For example: @@ -958,6 +967,78 @@ $$ LANGUAGE plpythonu; + + Accessing Data with Cursors + + + The plpy.cursor function accepts the same arguments + as plpy.execute (except for limit) + and returns a cursor object, which allows you to process large result sets + in smaller chunks. As with plpy.execute, either a query + string or a plan object along with a list of arguments can be used. The + cursor object provides a fetch method that accepts an + integer parameter and returns a result object. Each time you + call fetch, the returned object will contain the next + batch of rows, never larger than the parameter value. Once all rows are + exhausted, fetch starts returning an empty result + object. Cursor objects also provide an + iterator + interface, yielding one row at a time until all rows are exhausted. + Data fetched that way is not returned as result objects, but rather as + dictionaries, each dictionary corresponding to a single result row. + + + + Cursors are automatically disposed of. But if you want to explicitly + release all resources held by a cursor, use the close + method. Once closed, a cursor cannot be fetched from anymore. + + + + + Do not confuse objects created by plpy.cursor with + DB-API cursors as defined by + the Python Database + API specification. They don't have anything in common except for + the name. + + + + + An example of two ways of processing data from a large table is: + +CREATE FUNCTION count_odd_iterator() RETURNS integer AS $$ +odd = 0 +for row in plpy.cursor("select num from largetable"): + if row['num'] % 2: + odd += 1 +return odd +$$ LANGUAGE plpythonu; + +CREATE FUNCTION count_odd_fetch(batch_size integer) RETURNS integer AS $$ +odd = 0 +cursor = plpy.cursor("select num from largetable") +while True: + rows = cursor.fetch(batch_size) + if not rows: + break + for row in rows: + if row['num'] % 2: + odd += 1 +return odd +$$ LANGUAGE plpythonu; + +CREATE FUNCTION count_odd_prepared() RETURNS integer AS $$ +odd = 0 +plan = plpy.prepare("select num from largetable where num % $1 <> 0", ["integer"]) +rows = list(plpy.cursor(plan, [2])) + +return len(rows) +$$ LANGUAGE plpythonu; + + + + Trapping Errors -- cgit v1.2.3