PostgreSQL Source Code  git master
plpy_elog.c File Reference
#include "postgres.h"
#include "lib/stringinfo.h"
#include "plpython.h"
#include "plpy_elog.h"
#include "plpy_main.h"
#include "plpy_procedure.h"
Include dependency graph for plpy_elog.c:

Go to the source code of this file.

Functions

static void PLy_traceback (PyObject *e, PyObject *v, PyObject *tb, char **xmsg, char **tbmsg, int *tb_depth)
 
static void PLy_get_spi_error_data (PyObject *exc, int *sqlerrcode, char **detail, char **hint, char **query, int *position, char **schema_name, char **table_name, char **column_name, char **datatype_name, char **constraint_name)
 
static void PLy_get_error_data (PyObject *exc, int *sqlerrcode, char **detail, char **hint, char **schema_name, char **table_name, char **column_name, char **datatype_name, char **constraint_name)
 
static char * get_source_line (const char *src, int lineno)
 
static void get_string_attr (PyObject *obj, char *attrname, char **str)
 
static bool set_string_attr (PyObject *obj, char *attrname, char *str)
 
void PLy_elog_impl (int elevel, const char *fmt,...)
 
static void PLy_get_sqlerrcode (PyObject *exc, int *sqlerrcode)
 
void PLy_exception_set (PyObject *exc, const char *fmt,...)
 
void PLy_exception_set_plural (PyObject *exc, const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
 
void PLy_exception_set_with_details (PyObject *excclass, ErrorData *edata)
 

Variables

PyObject * PLy_exc_error = NULL
 
PyObject * PLy_exc_fatal = NULL
 
PyObject * PLy_exc_spi_error = NULL
 

Function Documentation

◆ get_source_line()

static char * get_source_line ( const char *  src,
int  lineno 
)
static

Definition at line 460 of file plpy_elog.c.

References next, pnstrdup(), and pstrdup().

Referenced by PLy_traceback().

461 {
462  const char *s = NULL;
463  const char *next = src;
464  int current = 0;
465 
466  /* sanity check */
467  if (lineno <= 0)
468  return NULL;
469 
470  while (current < lineno)
471  {
472  s = next;
473  next = strchr(s + 1, '\n');
474  current++;
475  if (next == NULL)
476  break;
477  }
478 
479  if (current != lineno)
480  return NULL;
481 
482  while (*s && isspace((unsigned char) *s))
483  s++;
484 
485  if (next == NULL)
486  return pstrdup(s);
487 
488  /*
489  * Sanity check, next < s if the line was all-whitespace, which should
490  * never happen if Python reported a frame created on that line, but check
491  * anyway.
492  */
493  if (next < s)
494  return NULL;
495 
496  return pnstrdup(s, next - s);
497 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1197
static int32 next
Definition: blutils.c:215
char * pstrdup(const char *in)
Definition: mcxt.c:1186

◆ get_string_attr()

static void get_string_attr ( PyObject *  obj,
char *  attrname,
char **  str 
)
static

Definition at line 592 of file plpy_elog.c.

References pstrdup(), and val.

Referenced by PLy_get_error_data().

593 {
594  PyObject *val;
595 
596  val = PyObject_GetAttrString(obj, attrname);
597  if (val != NULL && val != Py_None)
598  {
599  *str = pstrdup(PyString_AsString(val));
600  }
601  Py_XDECREF(val);
602 }
char * pstrdup(const char *in)
Definition: mcxt.c:1186
long val
Definition: informix.c:684

◆ PLy_elog_impl()

void PLy_elog_impl ( int  elevel,
const char *  fmt,
  ... 
)

Definition at line 47 of file plpy_elog.c.

References appendStringInfoVA(), Assert, StringInfoData::data, dgettext, enlargeStringInfo(), ereport, err_generic_string(), errcode(), errcontext, errdetail_internal(), errhint(), errmsg_internal(), FATAL, initStringInfo(), internalerrposition(), internalerrquery(), pfree(), PG_CATCH, PG_DIAG_COLUMN_NAME, PG_DIAG_CONSTRAINT_NAME, PG_DIAG_DATATYPE_NAME, PG_DIAG_SCHEMA_NAME, PG_DIAG_TABLE_NAME, PG_END_TRY, PG_RE_THROW, PG_TRY, PLy_exc_error, PLy_exc_fatal, PLy_exc_spi_error, PLy_get_error_data(), PLy_get_spi_error_data(), PLy_traceback(), TEXTDOMAIN, and val.

Referenced by _PG_init().

48 {
49  int save_errno = errno;
50  char *xmsg;
51  char *tbmsg;
52  int tb_depth;
53  StringInfoData emsg;
54  PyObject *exc,
55  *val,
56  *tb;
57  const char *primary = NULL;
58  int sqlerrcode = 0;
59  char *detail = NULL;
60  char *hint = NULL;
61  char *query = NULL;
62  int position = 0;
63  char *schema_name = NULL;
64  char *table_name = NULL;
65  char *column_name = NULL;
66  char *datatype_name = NULL;
67  char *constraint_name = NULL;
68 
69  PyErr_Fetch(&exc, &val, &tb);
70 
71  if (exc != NULL)
72  {
73  PyErr_NormalizeException(&exc, &val, &tb);
74 
75  if (PyErr_GivenExceptionMatches(val, PLy_exc_spi_error))
76  PLy_get_spi_error_data(val, &sqlerrcode,
77  &detail, &hint, &query, &position,
78  &schema_name, &table_name, &column_name,
79  &datatype_name, &constraint_name);
80  else if (PyErr_GivenExceptionMatches(val, PLy_exc_error))
81  PLy_get_error_data(val, &sqlerrcode, &detail, &hint,
82  &schema_name, &table_name, &column_name,
83  &datatype_name, &constraint_name);
84  else if (PyErr_GivenExceptionMatches(val, PLy_exc_fatal))
85  elevel = FATAL;
86  }
87 
88  /* this releases our refcount on tb! */
89  PLy_traceback(exc, val, tb,
90  &xmsg, &tbmsg, &tb_depth);
91 
92  if (fmt)
93  {
94  initStringInfo(&emsg);
95  for (;;)
96  {
97  va_list ap;
98  int needed;
99 
100  errno = save_errno;
101  va_start(ap, fmt);
102  needed = appendStringInfoVA(&emsg, dgettext(TEXTDOMAIN, fmt), ap);
103  va_end(ap);
104  if (needed == 0)
105  break;
106  enlargeStringInfo(&emsg, needed);
107  }
108  primary = emsg.data;
109 
110  /* Since we have a format string, we cannot have a SPI detail. */
111  Assert(detail == NULL);
112 
113  /* If there's an exception message, it goes in the detail. */
114  if (xmsg)
115  detail = xmsg;
116  }
117  else
118  {
119  if (xmsg)
120  primary = xmsg;
121  }
122 
123  PG_TRY();
124  {
125  ereport(elevel,
126  (errcode(sqlerrcode ? sqlerrcode : ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
127  errmsg_internal("%s", primary ? primary : "no exception data"),
128  (detail) ? errdetail_internal("%s", detail) : 0,
129  (tb_depth > 0 && tbmsg) ? errcontext("%s", tbmsg) : 0,
130  (hint) ? errhint("%s", hint) : 0,
131  (query) ? internalerrquery(query) : 0,
132  (position) ? internalerrposition(position) : 0,
133  (schema_name) ? err_generic_string(PG_DIAG_SCHEMA_NAME,
134  schema_name) : 0,
135  (table_name) ? err_generic_string(PG_DIAG_TABLE_NAME,
136  table_name) : 0,
137  (column_name) ? err_generic_string(PG_DIAG_COLUMN_NAME,
138  column_name) : 0,
139  (datatype_name) ? err_generic_string(PG_DIAG_DATATYPE_NAME,
140  datatype_name) : 0,
141  (constraint_name) ? err_generic_string(PG_DIAG_CONSTRAINT_NAME,
142  constraint_name) : 0));
143  }
144  PG_CATCH();
145  {
146  if (fmt)
147  pfree(emsg.data);
148  if (xmsg)
149  pfree(xmsg);
150  if (tbmsg)
151  pfree(tbmsg);
152  Py_XDECREF(exc);
153  Py_XDECREF(val);
154 
155  PG_RE_THROW();
156  }
157  PG_END_TRY();
158 
159  if (fmt)
160  pfree(emsg.data);
161  if (xmsg)
162  pfree(xmsg);
163  if (tbmsg)
164  pfree(tbmsg);
165  Py_XDECREF(exc);
166  Py_XDECREF(val);
167 }
int errhint(const char *fmt,...)
Definition: elog.c:974
#define PG_DIAG_SCHEMA_NAME
Definition: postgres_ext.h:65
#define TEXTDOMAIN
Definition: elog.h:144
#define PG_DIAG_COLUMN_NAME
Definition: postgres_ext.h:67
#define PG_DIAG_TABLE_NAME
Definition: postgres_ext.h:66
int errcode(int sqlerrcode)
Definition: elog.c:570
PyObject * PLy_exc_error
Definition: plpy_elog.c:19
static void PLy_traceback(PyObject *e, PyObject *v, PyObject *tb, char **xmsg, char **tbmsg, int *tb_depth)
Definition: plpy_elog.c:180
int errdetail_internal(const char *fmt,...)
Definition: elog.c:887
void pfree(void *pointer)
Definition: mcxt.c:1056
#define FATAL
Definition: elog.h:52
void enlargeStringInfo(StringInfo str, int needed)
Definition: stringinfo.c:270
#define ereport(elevel, rest)
Definition: elog.h:141
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
static int elevel
Definition: vacuumlazy.c:143
static void PLy_get_error_data(PyObject *exc, int *sqlerrcode, char **detail, char **hint, char **schema_name, char **table_name, char **column_name, char **datatype_name, char **constraint_name)
Definition: plpy_elog.c:442
#define dgettext(d, x)
Definition: c.h:1102
#define PG_DIAG_DATATYPE_NAME
Definition: postgres_ext.h:68
#define PG_DIAG_CONSTRAINT_NAME
Definition: postgres_ext.h:69
int internalerrquery(const char *query)
Definition: elog.c:1148
int errmsg_internal(const char *fmt,...)
Definition: elog.c:814
#define PG_CATCH()
Definition: elog.h:310
PyObject * PLy_exc_fatal
Definition: plpy_elog.c:20
#define Assert(condition)
Definition: c.h:732
#define PG_RE_THROW()
Definition: elog.h:331
#define errcontext
Definition: elog.h:183
int err_generic_string(int field, const char *str)
Definition: elog.c:1178
#define PG_TRY()
Definition: elog.h:301
int appendStringInfoVA(StringInfo str, const char *fmt, va_list args)
Definition: stringinfo.c:120
PyObject * PLy_exc_spi_error
Definition: plpy_elog.c:21
long val
Definition: informix.c:684
#define PG_END_TRY()
Definition: elog.h:317
static void PLy_get_spi_error_data(PyObject *exc, int *sqlerrcode, char **detail, char **hint, char **query, int *position, char **schema_name, char **table_name, char **column_name, char **datatype_name, char **constraint_name)
Definition: plpy_elog.c:406
int internalerrposition(int cursorpos)
Definition: elog.c:1128

◆ PLy_exception_set()

void PLy_exception_set ( PyObject *  exc,
const char *  fmt,
  ... 
)

Definition at line 502 of file plpy_elog.c.

References buf, dgettext, TEXTDOMAIN, and vsnprintf.

Referenced by PLy_cursor(), PLy_cursor_close(), PLy_cursor_fetch(), PLy_cursor_iternext(), PLy_cursor_plan(), PLy_output(), PLy_result_colnames(), PLy_result_coltypes(), PLy_result_coltypmods(), PLy_spi_execute(), PLy_spi_execute_plan(), PLy_spi_execute_query(), PLy_spi_prepare(), PLy_subtransaction_enter(), and PLy_subtransaction_exit().

503 {
504  char buf[1024];
505  va_list ap;
506 
507  va_start(ap, fmt);
508  vsnprintf(buf, sizeof(buf), dgettext(TEXTDOMAIN, fmt), ap);
509  va_end(ap);
510 
511  PyErr_SetString(exc, buf);
512 }
#define TEXTDOMAIN
Definition: elog.h:144
#define vsnprintf
Definition: port.h:191
static char * buf
Definition: pg_test_fsync.c:68
#define dgettext(d, x)
Definition: c.h:1102

◆ PLy_exception_set_plural()

void PLy_exception_set_plural ( PyObject *  exc,
const char *  fmt_singular,
const char *  fmt_plural,
unsigned long  n,
  ... 
)

Definition at line 516 of file plpy_elog.c.

References buf, dngettext, TEXTDOMAIN, and vsnprintf.

Referenced by PLy_cursor_plan(), and PLy_spi_execute_plan().

519 {
520  char buf[1024];
521  va_list ap;
522 
523  va_start(ap, n);
524  vsnprintf(buf, sizeof(buf),
525  dngettext(TEXTDOMAIN, fmt_singular, fmt_plural, n),
526  ap);
527  va_end(ap);
528 
529  PyErr_SetString(exc, buf);
530 }
#define TEXTDOMAIN
Definition: elog.h:144
#define vsnprintf
Definition: port.h:191
static char * buf
Definition: pg_test_fsync.c:68
#define dngettext(d, s, p, n)
Definition: c.h:1104

◆ PLy_exception_set_with_details()

void PLy_exception_set_with_details ( PyObject *  excclass,
ErrorData edata 
)

Definition at line 534 of file plpy_elog.c.

References generate_unaccent_rules::args, ErrorData::column_name, ErrorData::constraint_name, ErrorData::datatype_name, ErrorData::detail, elog, ERROR, error(), ErrorData::hint, ErrorData::internalquery, ErrorData::message, ErrorData::schema_name, set_string_attr(), ErrorData::sqlerrcode, ErrorData::table_name, and unpack_sql_state().

Referenced by PLy_output().

535 {
536  PyObject *args = NULL;
537  PyObject *error = NULL;
538 
539  args = Py_BuildValue("(s)", edata->message);
540  if (!args)
541  goto failure;
542 
543  /* create a new exception with the error message as the parameter */
544  error = PyObject_CallObject(excclass, args);
545  if (!error)
546  goto failure;
547 
548  if (!set_string_attr(error, "sqlstate",
549  unpack_sql_state(edata->sqlerrcode)))
550  goto failure;
551 
552  if (!set_string_attr(error, "detail", edata->detail))
553  goto failure;
554 
555  if (!set_string_attr(error, "hint", edata->hint))
556  goto failure;
557 
558  if (!set_string_attr(error, "query", edata->internalquery))
559  goto failure;
560 
561  if (!set_string_attr(error, "schema_name", edata->schema_name))
562  goto failure;
563 
564  if (!set_string_attr(error, "table_name", edata->table_name))
565  goto failure;
566 
567  if (!set_string_attr(error, "column_name", edata->column_name))
568  goto failure;
569 
570  if (!set_string_attr(error, "datatype_name", edata->datatype_name))
571  goto failure;
572 
573  if (!set_string_attr(error, "constraint_name", edata->constraint_name))
574  goto failure;
575 
576  PyErr_SetObject(excclass, error);
577 
578  Py_DECREF(args);
579  Py_DECREF(error);
580 
581  return;
582 
583 failure:
584  Py_XDECREF(args);
585  Py_XDECREF(error);
586 
587  elog(ERROR, "could not convert error to Python exception");
588 }
char * schema_name
Definition: elog.h:366
static void error(void)
Definition: sql-dyntest.c:147
int sqlerrcode
Definition: elog.h:359
static bool set_string_attr(PyObject *obj, char *attrname, char *str)
Definition: plpy_elog.c:608
char * unpack_sql_state(int sql_state)
Definition: elog.c:2831
char * internalquery
Definition: elog.h:373
#define ERROR
Definition: elog.h:43
char * table_name
Definition: elog.h:367
char * datatype_name
Definition: elog.h:369
char * detail
Definition: elog.h:361
char * column_name
Definition: elog.h:368
char * hint
Definition: elog.h:363
#define elog(elevel,...)
Definition: elog.h:226
char * constraint_name
Definition: elog.h:370
char * message
Definition: elog.h:360

◆ PLy_get_error_data()

static void PLy_get_error_data ( PyObject *  exc,
int *  sqlerrcode,
char **  detail,
char **  hint,
char **  schema_name,
char **  table_name,
char **  column_name,
char **  datatype_name,
char **  constraint_name 
)
static

Definition at line 442 of file plpy_elog.c.

References get_string_attr(), and PLy_get_sqlerrcode().

Referenced by PLy_elog_impl().

445 {
446  PLy_get_sqlerrcode(exc, sqlerrcode);
447  get_string_attr(exc, "detail", detail);
448  get_string_attr(exc, "hint", hint);
449  get_string_attr(exc, "schema_name", schema_name);
450  get_string_attr(exc, "table_name", table_name);
451  get_string_attr(exc, "column_name", column_name);
452  get_string_attr(exc, "datatype_name", datatype_name);
453  get_string_attr(exc, "constraint_name", constraint_name);
454 }
static void get_string_attr(PyObject *obj, char *attrname, char **str)
Definition: plpy_elog.c:592
static void PLy_get_sqlerrcode(PyObject *exc, int *sqlerrcode)
Definition: plpy_elog.c:382

◆ PLy_get_spi_error_data()

static void PLy_get_spi_error_data ( PyObject *  exc,
int *  sqlerrcode,
char **  detail,
char **  hint,
char **  query,
int *  position,
char **  schema_name,
char **  table_name,
char **  column_name,
char **  datatype_name,
char **  constraint_name 
)
static

Definition at line 406 of file plpy_elog.c.

References PLy_get_sqlerrcode().

Referenced by PLy_elog_impl().

411 {
412  PyObject *spidata;
413 
414  spidata = PyObject_GetAttrString(exc, "spidata");
415 
416  if (spidata != NULL)
417  {
418  PyArg_ParseTuple(spidata, "izzzizzzzz",
419  sqlerrcode, detail, hint, query, position,
420  schema_name, table_name, column_name,
421  datatype_name, constraint_name);
422  }
423  else
424  {
425  /*
426  * If there's no spidata, at least set the sqlerrcode. This can happen
427  * if someone explicitly raises a SPI exception from Python code.
428  */
429  PLy_get_sqlerrcode(exc, sqlerrcode);
430  }
431 
432  Py_XDECREF(spidata);
433 }
static void PLy_get_sqlerrcode(PyObject *exc, int *sqlerrcode)
Definition: plpy_elog.c:382

◆ PLy_get_sqlerrcode()

static void PLy_get_sqlerrcode ( PyObject *  exc,
int *  sqlerrcode 
)
static

Definition at line 382 of file plpy_elog.c.

References MAKE_SQLSTATE.

Referenced by PLy_get_error_data(), and PLy_get_spi_error_data().

383 {
384  PyObject *sqlstate;
385  char *buffer;
386 
387  sqlstate = PyObject_GetAttrString(exc, "sqlstate");
388  if (sqlstate == NULL)
389  return;
390 
391  buffer = PyString_AsString(sqlstate);
392  if (strlen(buffer) == 5 &&
393  strspn(buffer, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ") == 5)
394  {
395  *sqlerrcode = MAKE_SQLSTATE(buffer[0], buffer[1], buffer[2],
396  buffer[3], buffer[4]);
397  }
398 
399  Py_DECREF(sqlstate);
400 }
#define MAKE_SQLSTATE(ch1, ch2, ch3, ch4, ch5)
Definition: elog.h:62

◆ PLy_traceback()

static void PLy_traceback ( PyObject *  e,
PyObject *  v,
PyObject *  tb,
char **  xmsg,
char **  tbmsg,
int *  tb_depth 
)
static

Definition at line 180 of file plpy_elog.c.

References appendStringInfo(), appendStringInfoString(), Assert, PLyExecutionContext::curr_proc, StringInfoData::data, elog, ERROR, filename, get_source_line(), initStringInfo(), name, pfree(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLy_current_execution_context(), PLy_procedure_name(), proname, and PLyProcedure::src.

Referenced by PLy_elog_impl().

182 {
183  PyObject *e_type_o;
184  PyObject *e_module_o;
185  char *e_type_s = NULL;
186  char *e_module_s = NULL;
187  PyObject *vob = NULL;
188  char *vstr;
189  StringInfoData xstr;
190  StringInfoData tbstr;
191 
192  /*
193  * if no exception, return nulls
194  */
195  if (e == NULL)
196  {
197  *xmsg = NULL;
198  *tbmsg = NULL;
199  *tb_depth = 0;
200 
201  return;
202  }
203 
204  /*
205  * Format the exception and its value and put it in xmsg.
206  */
207 
208  e_type_o = PyObject_GetAttrString(e, "__name__");
209  e_module_o = PyObject_GetAttrString(e, "__module__");
210  if (e_type_o)
211  e_type_s = PyString_AsString(e_type_o);
212  if (e_type_s)
213  e_module_s = PyString_AsString(e_module_o);
214 
215  if (v && ((vob = PyObject_Str(v)) != NULL))
216  vstr = PyString_AsString(vob);
217  else
218  vstr = "unknown";
219 
220  initStringInfo(&xstr);
221  if (!e_type_s || !e_module_s)
222  {
223  if (PyString_Check(e))
224  /* deprecated string exceptions */
225  appendStringInfoString(&xstr, PyString_AsString(e));
226  else
227  /* shouldn't happen */
228  appendStringInfoString(&xstr, "unrecognized exception");
229  }
230  /* mimics behavior of traceback.format_exception_only */
231  else if (strcmp(e_module_s, "builtins") == 0
232  || strcmp(e_module_s, "__main__") == 0
233  || strcmp(e_module_s, "exceptions") == 0)
234  appendStringInfo(&xstr, "%s", e_type_s);
235  else
236  appendStringInfo(&xstr, "%s.%s", e_module_s, e_type_s);
237  appendStringInfo(&xstr, ": %s", vstr);
238 
239  *xmsg = xstr.data;
240 
241  /*
242  * Now format the traceback and put it in tbmsg.
243  */
244 
245  *tb_depth = 0;
246  initStringInfo(&tbstr);
247  /* Mimic Python traceback reporting as close as possible. */
248  appendStringInfoString(&tbstr, "Traceback (most recent call last):");
249  while (tb != NULL && tb != Py_None)
250  {
251  PyObject *volatile tb_prev = NULL;
252  PyObject *volatile frame = NULL;
253  PyObject *volatile code = NULL;
254  PyObject *volatile name = NULL;
255  PyObject *volatile lineno = NULL;
256  PyObject *volatile filename = NULL;
257 
258  PG_TRY();
259  {
260  /*
261  * Ancient versions of Python (circa 2.3) contain a bug whereby
262  * the fetches below can fail if the error indicator is set.
263  */
264  PyErr_Clear();
265 
266  lineno = PyObject_GetAttrString(tb, "tb_lineno");
267  if (lineno == NULL)
268  elog(ERROR, "could not get line number from Python traceback");
269 
270  frame = PyObject_GetAttrString(tb, "tb_frame");
271  if (frame == NULL)
272  elog(ERROR, "could not get frame from Python traceback");
273 
274  code = PyObject_GetAttrString(frame, "f_code");
275  if (code == NULL)
276  elog(ERROR, "could not get code object from Python frame");
277 
278  name = PyObject_GetAttrString(code, "co_name");
279  if (name == NULL)
280  elog(ERROR, "could not get function name from Python code object");
281 
282  filename = PyObject_GetAttrString(code, "co_filename");
283  if (filename == NULL)
284  elog(ERROR, "could not get file name from Python code object");
285  }
286  PG_CATCH();
287  {
288  Py_XDECREF(frame);
289  Py_XDECREF(code);
290  Py_XDECREF(name);
291  Py_XDECREF(lineno);
292  Py_XDECREF(filename);
293  PG_RE_THROW();
294  }
295  PG_END_TRY();
296 
297  /* The first frame always points at <module>, skip it. */
298  if (*tb_depth > 0)
299  {
301  char *proname;
302  char *fname;
303  char *line;
304  char *plain_filename;
305  long plain_lineno;
306 
307  /*
308  * The second frame points at the internal function, but to mimic
309  * Python error reporting we want to say <module>.
310  */
311  if (*tb_depth == 1)
312  fname = "<module>";
313  else
314  fname = PyString_AsString(name);
315 
316  proname = PLy_procedure_name(exec_ctx->curr_proc);
317  plain_filename = PyString_AsString(filename);
318  plain_lineno = PyInt_AsLong(lineno);
319 
320  if (proname == NULL)
322  &tbstr, "\n PL/Python anonymous code block, line %ld, in %s",
323  plain_lineno - 1, fname);
324  else
326  &tbstr, "\n PL/Python function \"%s\", line %ld, in %s",
327  proname, plain_lineno - 1, fname);
328 
329  /*
330  * function code object was compiled with "<string>" as the
331  * filename
332  */
333  if (exec_ctx->curr_proc && plain_filename != NULL &&
334  strcmp(plain_filename, "<string>") == 0)
335  {
336  /*
337  * If we know the current procedure, append the exact line
338  * from the source, again mimicking Python's traceback.py
339  * module behavior. We could store the already line-split
340  * source to avoid splitting it every time, but producing a
341  * traceback is not the most important scenario to optimize
342  * for. But we do not go as far as traceback.py in reading
343  * the source of imported modules.
344  */
345  line = get_source_line(exec_ctx->curr_proc->src, plain_lineno);
346  if (line)
347  {
348  appendStringInfo(&tbstr, "\n %s", line);
349  pfree(line);
350  }
351  }
352  }
353 
354  Py_DECREF(frame);
355  Py_DECREF(code);
356  Py_DECREF(name);
357  Py_DECREF(lineno);
358  Py_DECREF(filename);
359 
360  /* Release the current frame and go to the next one. */
361  tb_prev = tb;
362  tb = PyObject_GetAttrString(tb, "tb_next");
363  Assert(tb_prev != Py_None);
364  Py_DECREF(tb_prev);
365  if (tb == NULL)
366  elog(ERROR, "could not traverse Python traceback");
367  (*tb_depth)++;
368  }
369 
370  /* Return the traceback. */
371  *tbmsg = tbstr.data;
372 
373  Py_XDECREF(e_type_o);
374  Py_XDECREF(e_module_o);
375  Py_XDECREF(vob);
376 }
NameData proname
Definition: pg_proc.h:36
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:414
void pfree(void *pointer)
Definition: mcxt.c:1056
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
char * PLy_procedure_name(PLyProcedure *proc)
#define ERROR
Definition: elog.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
PLyProcedure * curr_proc
Definition: plpy_main.h:20
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
#define PG_CATCH()
Definition: elog.h:310
#define Assert(condition)
Definition: c.h:732
#define PG_RE_THROW()
Definition: elog.h:331
const char * name
Definition: encode.c:521
static char * filename
Definition: pg_dumpall.c:91
e
Definition: preproc-init.c:82
#define elog(elevel,...)
Definition: elog.h:226
#define PG_TRY()
Definition: elog.h:301
static char * get_source_line(const char *src, int lineno)
Definition: plpy_elog.c:460
#define PG_END_TRY()
Definition: elog.h:317

◆ set_string_attr()

static bool set_string_attr ( PyObject *  obj,
char *  attrname,
char *  str 
)
static

Definition at line 608 of file plpy_elog.c.

References val.

Referenced by PLy_exception_set_with_details().

609 {
610  int result;
611  PyObject *val;
612 
613  if (str != NULL)
614  {
615  val = PyString_FromString(str);
616  if (!val)
617  return false;
618  }
619  else
620  {
621  val = Py_None;
622  Py_INCREF(Py_None);
623  }
624 
625  result = PyObject_SetAttrString(obj, attrname, val);
626  Py_DECREF(val);
627 
628  return result != -1;
629 }
long val
Definition: informix.c:684

Variable Documentation

◆ PLy_exc_error

◆ PLy_exc_fatal

PyObject* PLy_exc_fatal = NULL

Definition at line 20 of file plpy_elog.c.

Referenced by PLy_add_exceptions(), and PLy_elog_impl().

◆ PLy_exc_spi_error

PyObject* PLy_exc_spi_error = NULL