Fix PL/Python for recursion and interleaved set-returning functions.
[pgsql.git] / src / pl / plpython / expected / plpython_error_0.out
blob5323906122284044a2ccc213feb714c46fb9c7d1
1 -- test error handling, i forgot to restore Warn_restart in
2 -- the trigger handler once. the errors and subsequent core dump were
3 -- interesting.
4 /* Flat out Python syntax error
5  */
6 CREATE FUNCTION python_syntax_error() RETURNS text
7         AS
8 '.syntaxerror'
9         LANGUAGE plpythonu;
10 ERROR:  could not compile PL/Python function "python_syntax_error"
11 DETAIL:  SyntaxError: invalid syntax (line 2)
12 /* With check_function_bodies = false the function should get defined
13  * and the error reported when called
14  */
15 SET check_function_bodies = false;
16 CREATE FUNCTION python_syntax_error() RETURNS text
17         AS
18 '.syntaxerror'
19         LANGUAGE plpythonu;
20 SELECT python_syntax_error();
21 ERROR:  could not compile PL/Python function "python_syntax_error"
22 DETAIL:  SyntaxError: invalid syntax (line 2)
23 /* Run the function twice to check if the hashtable entry gets cleaned up */
24 SELECT python_syntax_error();
25 ERROR:  could not compile PL/Python function "python_syntax_error"
26 DETAIL:  SyntaxError: invalid syntax (line 2)
27 RESET check_function_bodies;
28 /* Flat out syntax error
29  */
30 CREATE FUNCTION sql_syntax_error() RETURNS text
31         AS
32 'plpy.execute("syntax error")'
33         LANGUAGE plpythonu;
34 SELECT sql_syntax_error();
35 ERROR:  spiexceptions.SyntaxError: syntax error at or near "syntax"
36 LINE 1: syntax error
37         ^
38 QUERY:  syntax error
39 CONTEXT:  Traceback (most recent call last):
40   PL/Python function "sql_syntax_error", line 1, in <module>
41     plpy.execute("syntax error")
42 PL/Python function "sql_syntax_error"
43 /* check the handling of uncaught python exceptions
44  */
45 CREATE FUNCTION exception_index_invalid(text) RETURNS text
46         AS
47 'return args[1]'
48         LANGUAGE plpythonu;
49 SELECT exception_index_invalid('test');
50 ERROR:  IndexError: list index out of range
51 CONTEXT:  Traceback (most recent call last):
52   PL/Python function "exception_index_invalid", line 1, in <module>
53     return args[1]
54 PL/Python function "exception_index_invalid"
55 /* check handling of nested exceptions
56  */
57 CREATE FUNCTION exception_index_invalid_nested() RETURNS text
58         AS
59 'rv = plpy.execute("SELECT test5(''foo'')")
60 return rv[0]'
61         LANGUAGE plpythonu;
62 SELECT exception_index_invalid_nested();
63 ERROR:  spiexceptions.UndefinedFunction: function test5(unknown) does not exist
64 LINE 1: SELECT test5('foo')
65                ^
66 HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
67 QUERY:  SELECT test5('foo')
68 CONTEXT:  Traceback (most recent call last):
69   PL/Python function "exception_index_invalid_nested", line 1, in <module>
70     rv = plpy.execute("SELECT test5('foo')")
71 PL/Python function "exception_index_invalid_nested"
72 /* a typo
73  */
74 CREATE FUNCTION invalid_type_uncaught(a text) RETURNS text
75         AS
76 'if "plan" not in SD:
77         q = "SELECT fname FROM users WHERE lname = $1"
78         SD["plan"] = plpy.prepare(q, [ "test" ])
79 rv = plpy.execute(SD["plan"], [ a ])
80 if len(rv):
81         return rv[0]["fname"]
82 return None
84         LANGUAGE plpythonu;
85 SELECT invalid_type_uncaught('rick');
86 ERROR:  spiexceptions.UndefinedObject: type "test" does not exist
87 CONTEXT:  Traceback (most recent call last):
88   PL/Python function "invalid_type_uncaught", line 3, in <module>
89     SD["plan"] = plpy.prepare(q, [ "test" ])
90 PL/Python function "invalid_type_uncaught"
91 /* for what it's worth catch the exception generated by
92  * the typo, and return None
93  */
94 CREATE FUNCTION invalid_type_caught(a text) RETURNS text
95         AS
96 'if "plan" not in SD:
97         q = "SELECT fname FROM users WHERE lname = $1"
98         try:
99                 SD["plan"] = plpy.prepare(q, [ "test" ])
100         except plpy.SPIError, ex:
101                 plpy.notice(str(ex))
102                 return None
103 rv = plpy.execute(SD["plan"], [ a ])
104 if len(rv):
105         return rv[0]["fname"]
106 return None
108         LANGUAGE plpythonu;
109 SELECT invalid_type_caught('rick');
110 NOTICE:  type "test" does not exist
111  invalid_type_caught 
112 ---------------------
114 (1 row)
116 /* for what it's worth catch the exception generated by
117  * the typo, and reraise it as a plain error
118  */
119 CREATE FUNCTION invalid_type_reraised(a text) RETURNS text
120         AS
121 'if "plan" not in SD:
122         q = "SELECT fname FROM users WHERE lname = $1"
123         try:
124                 SD["plan"] = plpy.prepare(q, [ "test" ])
125         except plpy.SPIError, ex:
126                 plpy.error(str(ex))
127 rv = plpy.execute(SD["plan"], [ a ])
128 if len(rv):
129         return rv[0]["fname"]
130 return None
132         LANGUAGE plpythonu;
133 SELECT invalid_type_reraised('rick');
134 ERROR:  plpy.Error: type "test" does not exist
135 CONTEXT:  Traceback (most recent call last):
136   PL/Python function "invalid_type_reraised", line 6, in <module>
137     plpy.error(str(ex))
138 PL/Python function "invalid_type_reraised"
139 /* no typo no messing about
140  */
141 CREATE FUNCTION valid_type(a text) RETURNS text
142         AS
143 'if "plan" not in SD:
144         SD["plan"] = plpy.prepare("SELECT fname FROM users WHERE lname = $1", [ "text" ])
145 rv = plpy.execute(SD["plan"], [ a ])
146 if len(rv):
147         return rv[0]["fname"]
148 return None
150         LANGUAGE plpythonu;
151 SELECT valid_type('rick');
152  valid_type 
153 ------------
155 (1 row)
157 /* error in nested functions to get a traceback
159 CREATE FUNCTION nested_error() RETURNS text
160         AS
161 'def fun1():
162         plpy.error("boom")
164 def fun2():
165         fun1()
167 def fun3():
168         fun2()
170 fun3()
171 return "not reached"
173         LANGUAGE plpythonu;
174 SELECT nested_error();
175 ERROR:  plpy.Error: boom
176 CONTEXT:  Traceback (most recent call last):
177   PL/Python function "nested_error", line 10, in <module>
178     fun3()
179   PL/Python function "nested_error", line 8, in fun3
180     fun2()
181   PL/Python function "nested_error", line 5, in fun2
182     fun1()
183   PL/Python function "nested_error", line 2, in fun1
184     plpy.error("boom")
185 PL/Python function "nested_error"
186 /* raising plpy.Error is just like calling plpy.error
188 CREATE FUNCTION nested_error_raise() RETURNS text
189         AS
190 'def fun1():
191         raise plpy.Error("boom")
193 def fun2():
194         fun1()
196 def fun3():
197         fun2()
199 fun3()
200 return "not reached"
202         LANGUAGE plpythonu;
203 SELECT nested_error_raise();
204 ERROR:  plpy.Error: boom
205 CONTEXT:  Traceback (most recent call last):
206   PL/Python function "nested_error_raise", line 10, in <module>
207     fun3()
208   PL/Python function "nested_error_raise", line 8, in fun3
209     fun2()
210   PL/Python function "nested_error_raise", line 5, in fun2
211     fun1()
212   PL/Python function "nested_error_raise", line 2, in fun1
213     raise plpy.Error("boom")
214 PL/Python function "nested_error_raise"
215 /* using plpy.warning should not produce a traceback
217 CREATE FUNCTION nested_warning() RETURNS text
218         AS
219 'def fun1():
220         plpy.warning("boom")
222 def fun2():
223         fun1()
225 def fun3():
226         fun2()
228 fun3()
229 return "you''ve been warned"
231         LANGUAGE plpythonu;
232 SELECT nested_warning();
233 WARNING:  boom
234    nested_warning   
235 --------------------
236  you've been warned
237 (1 row)
239 /* AttributeError at toplevel used to give segfaults with the traceback
241 CREATE FUNCTION toplevel_attribute_error() RETURNS void AS
243 plpy.nonexistent
244 $$ LANGUAGE plpythonu;
245 SELECT toplevel_attribute_error();
246 ERROR:  AttributeError: 'module' object has no attribute 'nonexistent'
247 CONTEXT:  Traceback (most recent call last):
248   PL/Python function "toplevel_attribute_error", line 2, in <module>
249     plpy.nonexistent
250 PL/Python function "toplevel_attribute_error"
251 /* Calling PL/Python functions from SQL and vice versa should not lose context.
252  */
253 CREATE OR REPLACE FUNCTION python_traceback() RETURNS void AS $$
254 def first():
255   second()
257 def second():
258   third()
260 def third():
261   plpy.execute("select sql_error()")
263 first()
264 $$ LANGUAGE plpythonu;
265 CREATE OR REPLACE FUNCTION sql_error() RETURNS void AS $$
266 begin
267   select 1/0;
269 $$ LANGUAGE plpgsql;
270 CREATE OR REPLACE FUNCTION python_from_sql_error() RETURNS void AS $$
271 begin
272   select python_traceback();
274 $$ LANGUAGE plpgsql;
275 CREATE OR REPLACE FUNCTION sql_from_python_error() RETURNS void AS $$
276 plpy.execute("select sql_error()")
277 $$ LANGUAGE plpythonu;
278 SELECT python_traceback();
279 ERROR:  spiexceptions.DivisionByZero: division by zero
280 CONTEXT:  Traceback (most recent call last):
281   PL/Python function "python_traceback", line 11, in <module>
282     first()
283   PL/Python function "python_traceback", line 3, in first
284     second()
285   PL/Python function "python_traceback", line 6, in second
286     third()
287   PL/Python function "python_traceback", line 9, in third
288     plpy.execute("select sql_error()")
289 PL/Python function "python_traceback"
290 SELECT sql_error();
291 ERROR:  division by zero
292 CONTEXT:  SQL statement "select 1/0"
293 PL/pgSQL function sql_error() line 3 at SQL statement
294 SELECT python_from_sql_error();
295 ERROR:  spiexceptions.DivisionByZero: division by zero
296 CONTEXT:  Traceback (most recent call last):
297   PL/Python function "python_traceback", line 11, in <module>
298     first()
299   PL/Python function "python_traceback", line 3, in first
300     second()
301   PL/Python function "python_traceback", line 6, in second
302     third()
303   PL/Python function "python_traceback", line 9, in third
304     plpy.execute("select sql_error()")
305 PL/Python function "python_traceback"
306 SQL statement "select python_traceback()"
307 PL/pgSQL function python_from_sql_error() line 3 at SQL statement
308 SELECT sql_from_python_error();
309 ERROR:  spiexceptions.DivisionByZero: division by zero
310 CONTEXT:  Traceback (most recent call last):
311   PL/Python function "sql_from_python_error", line 2, in <module>
312     plpy.execute("select sql_error()")
313 PL/Python function "sql_from_python_error"
314 /* check catching specific types of exceptions
315  */
316 CREATE TABLE specific (
317     i integer PRIMARY KEY
319 CREATE FUNCTION specific_exception(i integer) RETURNS void AS
321 from plpy import spiexceptions
322 try:
323     plpy.execute("insert into specific values (%s)" % (i or "NULL"));
324 except spiexceptions.NotNullViolation, e:
325     plpy.notice("Violated the NOT NULL constraint, sqlstate %s" % e.sqlstate)
326 except spiexceptions.UniqueViolation, e:
327     plpy.notice("Violated the UNIQUE constraint, sqlstate %s" % e.sqlstate)
328 $$ LANGUAGE plpythonu;
329 SELECT specific_exception(2);
330  specific_exception 
331 --------------------
333 (1 row)
335 SELECT specific_exception(NULL);
336 NOTICE:  Violated the NOT NULL constraint, sqlstate 23502
337  specific_exception 
338 --------------------
340 (1 row)
342 SELECT specific_exception(2);
343 NOTICE:  Violated the UNIQUE constraint, sqlstate 23505
344  specific_exception 
345 --------------------
347 (1 row)
349 /* SPI errors in PL/Python functions should preserve the SQLSTATE value
350  */
351 CREATE FUNCTION python_unique_violation() RETURNS void AS $$
352 plpy.execute("insert into specific values (1)")
353 plpy.execute("insert into specific values (1)")
354 $$ LANGUAGE plpythonu;
355 CREATE FUNCTION catch_python_unique_violation() RETURNS text AS $$
356 begin
357     begin
358         perform python_unique_violation();
359     exception when unique_violation then
360         return 'ok';
361     end;
362     return 'not reached';
363 end;
364 $$ language plpgsql;
365 SELECT catch_python_unique_violation();
366  catch_python_unique_violation 
367 -------------------------------
368  ok
369 (1 row)
371 /* manually starting subtransactions - a bad idea
372  */
373 CREATE FUNCTION manual_subxact() RETURNS void AS $$
374 plpy.execute("savepoint save")
375 plpy.execute("create table foo(x integer)")
376 plpy.execute("rollback to save")
377 $$ LANGUAGE plpythonu;
378 SELECT manual_subxact();
379 ERROR:  plpy.SPIError: SPI_execute failed: SPI_ERROR_TRANSACTION
380 CONTEXT:  Traceback (most recent call last):
381   PL/Python function "manual_subxact", line 2, in <module>
382     plpy.execute("savepoint save")
383 PL/Python function "manual_subxact"
384 /* same for prepared plans
385  */
386 CREATE FUNCTION manual_subxact_prepared() RETURNS void AS $$
387 save = plpy.prepare("savepoint save")
388 rollback = plpy.prepare("rollback to save")
389 plpy.execute(save)
390 plpy.execute("create table foo(x integer)")
391 plpy.execute(rollback)
392 $$ LANGUAGE plpythonu;
393 SELECT manual_subxact_prepared();
394 ERROR:  plpy.SPIError: SPI_execute_plan failed: SPI_ERROR_TRANSACTION
395 CONTEXT:  Traceback (most recent call last):
396   PL/Python function "manual_subxact_prepared", line 4, in <module>
397     plpy.execute(save)
398 PL/Python function "manual_subxact_prepared"
399 /* raising plpy.spiexception.* from python code should preserve sqlstate
400  */
401 CREATE FUNCTION plpy_raise_spiexception() RETURNS void AS $$
402 raise plpy.spiexceptions.DivisionByZero()
403 $$ LANGUAGE plpythonu;
404 DO $$
405 BEGIN
406         SELECT plpy_raise_spiexception();
407 EXCEPTION WHEN division_by_zero THEN
408         -- NOOP
410 $$ LANGUAGE plpgsql;
411 /* setting a custom sqlstate should be handled
412  */
413 CREATE FUNCTION plpy_raise_spiexception_override() RETURNS void AS $$
414 exc = plpy.spiexceptions.DivisionByZero()
415 exc.sqlstate = 'SILLY'
416 raise exc
417 $$ LANGUAGE plpythonu;
418 DO $$
419 BEGIN
420         SELECT plpy_raise_spiexception_override();
421 EXCEPTION WHEN SQLSTATE 'SILLY' THEN
422         -- NOOP
424 $$ LANGUAGE plpgsql;