@@ -36,7 +36,10 @@ ERROR: spiexceptions.SyntaxError: syntax error at or near "syntax"
36
36
LINE 1: syntax error
37
37
^
38
38
QUERY: syntax error
39
- CONTEXT: PL/Python function "sql_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"
40
43
/* check the handling of uncaught python exceptions
41
44
*/
42
45
CREATE FUNCTION exception_index_invalid(text) RETURNS text
@@ -45,7 +48,10 @@ CREATE FUNCTION exception_index_invalid(text) RETURNS text
45
48
LANGUAGE plpythonu;
46
49
SELECT exception_index_invalid('test');
47
50
ERROR: IndexError: list index out of range
48
- CONTEXT: PL/Python function "exception_index_invalid"
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"
49
55
/* check handling of nested exceptions
50
56
*/
51
57
CREATE FUNCTION exception_index_invalid_nested() RETURNS text
@@ -59,7 +65,10 @@ LINE 1: SELECT test5('foo')
59
65
^
60
66
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
61
67
QUERY: SELECT test5('foo')
62
- CONTEXT: PL/Python function "exception_index_invalid_nested"
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"
63
72
/* a typo
64
73
*/
65
74
CREATE FUNCTION invalid_type_uncaught(a text) RETURNS text
@@ -75,7 +84,10 @@ return None
75
84
LANGUAGE plpythonu;
76
85
SELECT invalid_type_uncaught('rick');
77
86
ERROR: spiexceptions.UndefinedObject: type "test" does not exist
78
- CONTEXT: PL/Python function "invalid_type_uncaught"
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"
79
91
/* for what it's worth catch the exception generated by
80
92
* the typo, and return None
81
93
*/
@@ -121,7 +133,10 @@ return None
121
133
LANGUAGE plpythonu;
122
134
SELECT invalid_type_reraised('rick');
123
135
ERROR: plpy.Error: type "test" does not exist
124
- CONTEXT: PL/Python function "invalid_type_reraised"
136
+ CONTEXT: Traceback (most recent call last):
137
+ PL/Python function "invalid_type_reraised", line 6, in <module>
138
+ plpy.error(str(ex))
139
+ PL/Python function "invalid_type_reraised"
125
140
/* no typo no messing about
126
141
*/
127
142
CREATE FUNCTION valid_type(a text) RETURNS text
@@ -140,6 +155,164 @@ SELECT valid_type('rick');
140
155
141
156
(1 row)
142
157
158
+ /* error in nested functions to get a traceback
159
+ */
160
+ CREATE FUNCTION nested_error() RETURNS text
161
+ AS
162
+ 'def fun1():
163
+ plpy.error("boom")
164
+
165
+ def fun2():
166
+ fun1()
167
+
168
+ def fun3():
169
+ fun2()
170
+
171
+ fun3()
172
+ return "not reached"
173
+ '
174
+ LANGUAGE plpythonu;
175
+ SELECT nested_error();
176
+ ERROR: plpy.Error: boom
177
+ CONTEXT: Traceback (most recent call last):
178
+ PL/Python function "nested_error", line 10, in <module>
179
+ fun3()
180
+ PL/Python function "nested_error", line 8, in fun3
181
+ fun2()
182
+ PL/Python function "nested_error", line 5, in fun2
183
+ fun1()
184
+ PL/Python function "nested_error", line 2, in fun1
185
+ plpy.error("boom")
186
+ PL/Python function "nested_error"
187
+ /* raising plpy.Error is just like calling plpy.error
188
+ */
189
+ CREATE FUNCTION nested_error_raise() RETURNS text
190
+ AS
191
+ 'def fun1():
192
+ raise plpy.Error("boom")
193
+
194
+ def fun2():
195
+ fun1()
196
+
197
+ def fun3():
198
+ fun2()
199
+
200
+ fun3()
201
+ return "not reached"
202
+ '
203
+ LANGUAGE plpythonu;
204
+ SELECT nested_error_raise();
205
+ ERROR: plpy.Error: boom
206
+ CONTEXT: Traceback (most recent call last):
207
+ PL/Python function "nested_error_raise", line 10, in <module>
208
+ fun3()
209
+ PL/Python function "nested_error_raise", line 8, in fun3
210
+ fun2()
211
+ PL/Python function "nested_error_raise", line 5, in fun2
212
+ fun1()
213
+ PL/Python function "nested_error_raise", line 2, in fun1
214
+ raise plpy.Error("boom")
215
+ PL/Python function "nested_error_raise"
216
+ /* using plpy.warning should not produce a traceback
217
+ */
218
+ CREATE FUNCTION nested_warning() RETURNS text
219
+ AS
220
+ 'def fun1():
221
+ plpy.warning("boom")
222
+
223
+ def fun2():
224
+ fun1()
225
+
226
+ def fun3():
227
+ fun2()
228
+
229
+ fun3()
230
+ return "you''ve been warned"
231
+ '
232
+ LANGUAGE plpythonu;
233
+ SELECT nested_warning();
234
+ WARNING: boom
235
+ CONTEXT: PL/Python function "nested_warning"
236
+ nested_warning
237
+ --------------------
238
+ you've been warned
239
+ (1 row)
240
+
241
+ /* AttributeError at toplevel used to give segfaults with the traceback
242
+ */
243
+ CREATE FUNCTION toplevel_attribute_error() RETURNS void AS
244
+ $$
245
+ plpy.nonexistent
246
+ $$ LANGUAGE plpythonu;
247
+ SELECT toplevel_attribute_error();
248
+ ERROR: AttributeError: 'module' object has no attribute 'nonexistent'
249
+ CONTEXT: Traceback (most recent call last):
250
+ PL/Python function "toplevel_attribute_error", line 2, in <module>
251
+ plpy.nonexistent
252
+ PL/Python function "toplevel_attribute_error"
253
+ /* Calling PL/Python functions from SQL and vice versa should not lose context.
254
+ */
255
+ CREATE OR REPLACE FUNCTION python_traceback() RETURNS void AS $$
256
+ def first():
257
+ second()
258
+
259
+ def second():
260
+ third()
261
+
262
+ def third():
263
+ plpy.execute("select sql_error()")
264
+
265
+ first()
266
+ $$ LANGUAGE plpythonu;
267
+ CREATE OR REPLACE FUNCTION sql_error() RETURNS void AS $$
268
+ begin
269
+ select 1/0;
270
+ end
271
+ $$ LANGUAGE plpgsql;
272
+ CREATE OR REPLACE FUNCTION python_from_sql_error() RETURNS void AS $$
273
+ begin
274
+ select python_traceback();
275
+ end
276
+ $$ LANGUAGE plpgsql;
277
+ CREATE OR REPLACE FUNCTION sql_from_python_error() RETURNS void AS $$
278
+ plpy.execute("select sql_error()")
279
+ $$ LANGUAGE plpythonu;
280
+ SELECT python_traceback();
281
+ ERROR: spiexceptions.DivisionByZero: division by zero
282
+ CONTEXT: Traceback (most recent call last):
283
+ PL/Python function "python_traceback", line 11, in <module>
284
+ first()
285
+ PL/Python function "python_traceback", line 3, in first
286
+ second()
287
+ PL/Python function "python_traceback", line 6, in second
288
+ third()
289
+ PL/Python function "python_traceback", line 9, in third
290
+ plpy.execute("select sql_error()")
291
+ PL/Python function "python_traceback"
292
+ SELECT sql_error();
293
+ ERROR: division by zero
294
+ CONTEXT: SQL statement "select 1/0"
295
+ PL/pgSQL function "sql_error" line 3 at SQL statement
296
+ SELECT python_from_sql_error();
297
+ ERROR: spiexceptions.DivisionByZero: division by zero
298
+ CONTEXT: Traceback (most recent call last):
299
+ PL/Python function "python_traceback", line 11, in <module>
300
+ first()
301
+ PL/Python function "python_traceback", line 3, in first
302
+ second()
303
+ PL/Python function "python_traceback", line 6, in second
304
+ third()
305
+ PL/Python function "python_traceback", line 9, in third
306
+ plpy.execute("select sql_error()")
307
+ PL/Python function "python_traceback"
308
+ SQL statement "select python_traceback()"
309
+ PL/pgSQL function "python_from_sql_error" line 3 at SQL statement
310
+ SELECT sql_from_python_error();
311
+ ERROR: spiexceptions.DivisionByZero: division by zero
312
+ CONTEXT: Traceback (most recent call last):
313
+ PL/Python function "sql_from_python_error", line 2, in <module>
314
+ plpy.execute("select sql_error()")
315
+ PL/Python function "sql_from_python_error"
143
316
/* check catching specific types of exceptions
144
317
*/
145
318
CREATE TABLE specific (
@@ -187,7 +360,10 @@ plpy.execute("rollback to save")
187
360
$$ LANGUAGE plpythonu;
188
361
SELECT manual_subxact();
189
362
ERROR: plpy.SPIError: SPI_execute failed: SPI_ERROR_TRANSACTION
190
- CONTEXT: PL/Python function "manual_subxact"
363
+ CONTEXT: Traceback (most recent call last):
364
+ PL/Python function "manual_subxact", line 2, in <module>
365
+ plpy.execute("savepoint save")
366
+ PL/Python function "manual_subxact"
191
367
/* same for prepared plans
192
368
*/
193
369
CREATE FUNCTION manual_subxact_prepared() RETURNS void AS $$
@@ -199,4 +375,7 @@ plpy.execute(rollback)
199
375
$$ LANGUAGE plpythonu;
200
376
SELECT manual_subxact_prepared();
201
377
ERROR: plpy.SPIError: SPI_execute_plan failed: SPI_ERROR_TRANSACTION
202
- CONTEXT: PL/Python function "manual_subxact_prepared"
378
+ CONTEXT: Traceback (most recent call last):
379
+ PL/Python function "manual_subxact_prepared", line 4, in <module>
380
+ plpy.execute(save)
381
+ PL/Python function "manual_subxact_prepared"
0 commit comments