4 CREATE FUNCTION nested_call_one(a text) RETURNS text
6 'q = "SELECT nested_call_two(''%s'')" % a
10 CREATE FUNCTION nested_call_two(a text) RETURNS text
12 'q = "SELECT nested_call_three(''%s'')" % a
16 CREATE FUNCTION nested_call_three(a text) RETURNS text
21 CREATE FUNCTION spi_prepared_plan_test_one(a text) RETURNS text
23 'if "myplan" not in SD:
24 q = "SELECT count(*) FROM users WHERE lname = $1"
25 SD["myplan"] = plpy.prepare(q, [ "text" ])
27 rv = plpy.execute(SD["myplan"], [a])
28 return "there are " + str(rv[0]["count"]) + " " + str(a) + "s"
29 except Exception as ex:
34 CREATE FUNCTION spi_prepared_plan_test_two(a text) RETURNS text
36 'if "myplan" not in SD:
37 q = "SELECT count(*) FROM users WHERE lname = $1"
38 SD["myplan"] = plpy.prepare(q, [ "text" ])
40 rv = SD["myplan"].execute([a])
41 return "there are " + str(rv[0]["count"]) + " " + str(a) + "s"
42 except Exception as ex:
47 CREATE FUNCTION spi_prepared_plan_test_nested(a text) RETURNS text
49 'if "myplan" not in SD:
50 q = "SELECT spi_prepared_plan_test_one(''%s'') as count" % a
51 SD["myplan"] = plpy.prepare(q)
53 rv = plpy.execute(SD["myplan"])
56 except Exception as ex:
61 CREATE FUNCTION join_sequences(s sequences) RETURNS text
63 'if not s["multipart"]:
65 q = "SELECT sequence FROM xsequences WHERE pid = ''%s''" % s["pid"]
69 seq = seq + r["sequence"]
73 CREATE FUNCTION spi_recursive_sum(a int) RETURNS int
77 r = plpy.execute("SELECT spi_recursive_sum(%d) as a" % (a-1))[0]["a"]
82 -- spi and nested calls
84 select nested_call_one('pass this along');
86 -----------------------------------------------------------------
87 {'nested_call_two': "{'nested_call_three': 'pass this along'}"}
90 select spi_prepared_plan_test_one('doe');
91 spi_prepared_plan_test_one
92 ----------------------------
96 select spi_prepared_plan_test_two('smith');
97 spi_prepared_plan_test_two
98 ----------------------------
102 select spi_prepared_plan_test_nested('smith');
103 spi_prepared_plan_test_nested
104 -------------------------------
108 SELECT join_sequences(sequences) FROM sequences;
119 SELECT join_sequences(sequences) FROM sequences
120 WHERE join_sequences(sequences) ~* '^A';
131 SELECT join_sequences(sequences) FROM sequences
132 WHERE join_sequences(sequences) ~* '^B';
137 SELECT spi_recursive_sum(10);
144 -- plan and result objects
146 CREATE FUNCTION result_metadata_test(cmd text) RETURNS int
148 plan = plpy.prepare(cmd)
149 plpy.info(plan.status()) # not really documented or useful
150 result = plpy.execute(plan)
151 if result.status() > 0:
152 plpy.info(result.colnames())
153 plpy.info(result.coltypes())
154 plpy.info(result.coltypmods())
155 return result.nrows()
158 $$ LANGUAGE plpythonu;
159 SELECT result_metadata_test($$SELECT 1 AS foo, '11'::text AS bar UNION SELECT 2, '22'$$);
165 ----------------------
169 SELECT result_metadata_test($$CREATE TEMPORARY TABLE foo1 (a int, b text)$$);
171 ERROR: plpy.Error: command did not produce a result set
172 CONTEXT: Traceback (most recent call last):
173 PL/Python function "result_metadata_test", line 6, in <module>
174 plpy.info(result.colnames())
175 PL/Python function "result_metadata_test"
176 CREATE FUNCTION result_nrows_test(cmd text) RETURNS int
178 result = plpy.execute(cmd)
179 return result.nrows()
180 $$ LANGUAGE plpythonu;
181 SELECT result_nrows_test($$SELECT 1$$);
187 SELECT result_nrows_test($$CREATE TEMPORARY TABLE foo2 (a int, b text)$$);
193 SELECT result_nrows_test($$INSERT INTO foo2 VALUES (1, 'one'), (2, 'two')$$);
199 SELECT result_nrows_test($$UPDATE foo2 SET b = '' WHERE a = 2$$);
205 CREATE FUNCTION result_len_test(cmd text) RETURNS int
207 result = plpy.execute(cmd)
209 $$ LANGUAGE plpythonu;
210 SELECT result_len_test($$SELECT 1$$);
216 SELECT result_len_test($$CREATE TEMPORARY TABLE foo3 (a int, b text)$$);
222 SELECT result_len_test($$INSERT INTO foo3 VALUES (1, 'one'), (2, 'two')$$);
228 SELECT result_len_test($$UPDATE foo3 SET b= '' WHERE a = 2$$);
234 CREATE FUNCTION result_subscript_test() RETURNS void
236 result = plpy.execute("SELECT 1 AS c UNION ALL SELECT 2 "
237 "UNION ALL SELECT 3 UNION ALL SELECT 4")
239 plpy.info(result[1]['c'])
240 plpy.info(result[-1]['c'])
242 plpy.info([item['c'] for item in result[1:3]])
243 plpy.info([item['c'] for item in result[::2]])
245 result[-1] = {'c': 1000}
246 result[:2] = [{'c': 10}, {'c': 100}]
247 plpy.info([item['c'] for item in result[:]])
249 # raises TypeError, but the message differs on Python 2.6, so silence it
251 plpy.info(result['foo'])
255 assert False, "TypeError not raised"
257 $$ LANGUAGE plpythonu;
258 SELECT result_subscript_test();
263 INFO: [10, 100, 3, 1000]
264 result_subscript_test
265 -----------------------
269 CREATE FUNCTION result_empty_test() RETURNS void
271 result = plpy.execute("select 1 where false")
275 $$ LANGUAGE plpythonu;
276 SELECT result_empty_test();
283 CREATE FUNCTION result_str_test(cmd text) RETURNS text
285 plan = plpy.prepare(cmd)
286 result = plpy.execute(plan)
288 $$ LANGUAGE plpythonu;
289 SELECT result_str_test($$SELECT 1 AS foo UNION SELECT 2$$);
291 ------------------------------------------------------------
292 <PLyResult status=5 nrows=2 rows=[{'foo': 1}, {'foo': 2}]>
295 SELECT result_str_test($$CREATE TEMPORARY TABLE foo1 (a int, b text)$$);
297 --------------------------------------
298 <PLyResult status=4 nrows=0 rows=[]>
302 CREATE FUNCTION simple_cursor_test() RETURNS int AS $$
303 res = plpy.cursor("select fname, lname from users")
306 if row['lname'] == 'doe':
309 $$ LANGUAGE plpythonu;
310 CREATE FUNCTION double_cursor_close() RETURNS int AS $$
311 res = plpy.cursor("select fname, lname from users")
314 $$ LANGUAGE plpythonu;
315 CREATE FUNCTION cursor_fetch() RETURNS int AS $$
316 res = plpy.cursor("select fname, lname from users")
317 assert len(res.fetch(3)) == 3
318 assert len(res.fetch(3)) == 1
319 assert len(res.fetch(3)) == 0
320 assert len(res.fetch(3)) == 0
322 # use next() or __next__(), the method name changed in
323 # http://www.python.org/dev/peps/pep-3114/
326 except AttributeError:
328 except StopIteration:
331 assert False, "StopIteration not raised"
332 $$ LANGUAGE plpythonu;
333 CREATE FUNCTION cursor_mix_next_and_fetch() RETURNS int AS $$
334 res = plpy.cursor("select fname, lname from users order by fname")
335 assert len(res.fetch(2)) == 2
340 except AttributeError:
341 item = res.__next__()
342 assert item['fname'] == 'rick'
344 assert len(res.fetch(2)) == 1
345 $$ LANGUAGE plpythonu;
346 CREATE FUNCTION fetch_after_close() RETURNS int AS $$
347 res = plpy.cursor("select fname, lname from users")
354 assert False, "ValueError not raised"
355 $$ LANGUAGE plpythonu;
356 CREATE FUNCTION next_after_close() RETURNS int AS $$
357 res = plpy.cursor("select fname, lname from users")
362 except AttributeError:
367 assert False, "ValueError not raised"
368 $$ LANGUAGE plpythonu;
369 CREATE FUNCTION cursor_fetch_next_empty() RETURNS int AS $$
370 res = plpy.cursor("select fname, lname from users where false")
371 assert len(res.fetch(1)) == 0
375 except AttributeError:
377 except StopIteration:
380 assert False, "StopIteration not raised"
381 $$ LANGUAGE plpythonu;
382 CREATE FUNCTION cursor_plan() RETURNS SETOF text AS $$
384 "select fname, lname from users where fname like $1 || '%' order by fname",
386 for row in plpy.cursor(plan, ["w"]):
388 for row in plan.cursor(["j"]):
390 $$ LANGUAGE plpythonu;
391 CREATE FUNCTION cursor_plan_wrong_args() RETURNS SETOF text AS $$
392 plan = plpy.prepare("select fname, lname from users where fname like $1 || '%'",
394 c = plpy.cursor(plan, ["a", "b"])
395 $$ LANGUAGE plpythonu;
396 CREATE TYPE test_composite_type AS (
400 CREATE OR REPLACE FUNCTION plan_composite_args() RETURNS test_composite_type AS $$
401 plan = plpy.prepare("select $1 as c1", ["test_composite_type"])
402 res = plpy.execute(plan, [{"a1": 3, "a2": "label"}])
404 $$ LANGUAGE plpythonu;
405 SELECT simple_cursor_test();
411 SELECT double_cursor_close();
413 ---------------------
417 SELECT cursor_fetch();
423 SELECT cursor_mix_next_and_fetch();
424 cursor_mix_next_and_fetch
425 ---------------------------
429 SELECT fetch_after_close();
435 SELECT next_after_close();
441 SELECT cursor_fetch_next_empty();
442 cursor_fetch_next_empty
443 -------------------------
447 SELECT cursor_plan();
455 SELECT cursor_plan_wrong_args();
456 ERROR: TypeError: Expected sequence of 1 argument, got 2: ['a', 'b']
457 CONTEXT: Traceback (most recent call last):
458 PL/Python function "cursor_plan_wrong_args", line 4, in <module>
459 c = plpy.cursor(plan, ["a", "b"])
460 PL/Python function "cursor_plan_wrong_args"
461 SELECT plan_composite_args();
463 ---------------------