Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plv8 swallows error stack #211

Closed
bendiy opened this issue Feb 24, 2017 · 5 comments
Closed

plv8 swallows error stack #211

bendiy opened this issue Feb 24, 2017 · 5 comments

Comments

@bendiy
Copy link
Contributor

bendiy commented Feb 24, 2017

If PostgreSQL throws an error up the stack from a plv8.execute(...), the actual error stack is swallowed and hidden. When using plpgsql, the actual error line is reported.

Here's an example to demonstrate this:

CREATE OR REPLACE FUNCTION public._anerror()
  RETURNS boolean AS
$BODY$
BEGIN

  RAISE EXCEPTION 'my error';

  RETURN true;

END;
$BODY$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION public._callsanerror()
  RETURNS boolean AS
$BODY$
DECLARE
  something boolean;
BEGIN
  something := _anerror();

  RETURN something;
END;
$BODY$
  LANGUAGE plpgsql;

Then call _callsanerror() function either directly or through plpgsql:

SELECT _callsanerror();

Outputs the message:

ERROR:  my error
CONTEXT:  PL/pgSQL function _callsanerror() line 5 at assignment
********** Error **********

ERROR: my error
SQL state: P0001
Context: PL/pgSQL function _callsanerror() line 5 at assignment
DO $$
BEGIN
  SELECT _callsanerror();
END;
$$ LANGUAGE plpgsql;

Outputs the message:

ERROR:  my error
CONTEXT:  PL/pgSQL function _callsanerror() line 5 at assignment
SQL statement "SELECT _callsanerror()"
PL/pgSQL function inline_code_block line 3 at SQL statement
********** Error **********

ERROR: my error
SQL state: P0001
Context: PL/pgSQL function _callsanerror() line 5 at assignment
SQL statement "SELECT _callsanerror()"
PL/pgSQL function inline_code_block line 3 at SQL statement

When called from plv8, the relevate stack line that actually threw the error is swallowed:

DO $$
  plv8.execute("SELECT _callsanerror();");
$$ LANGUAGE plv8;

Outputs the message:

ERROR:  my error
DETAIL:  undefined() LINE 2:   plv8.execute("SELECT _callsanerror();");
********** Error **********

ERROR: my error
SQL state: XX000
Detail: undefined() LINE 2:   plv8.execute("SELECT _callsanerror();");

No reference to Context: PL/pgSQL function _callsanerror() line 5 at assignment.

Is there any way to make use of PG_EXCEPTION_CONTEXT and return the full stack?
https://www.postgresql.org/docs/current/static/plpgsql-control-structures.html#PLPGSQL-EXCEPTION-DIAGNOSTICS

@JerrySievert
Copy link
Member

it hasn't been super high priority - I will try to spend some time on it, but if anyone else wants to send a PR, I'd be happy to look at it.

@bendiy
Copy link
Contributor Author

bendiy commented Jun 26, 2017

Calling:

    RAISE EXCEPTION USING
      MESSAGE = 'A First Name is required.',
      DETAIL = 'A detailed message??',
      HINT = 'Do this to avoid that.',
      COLUMN = 'firstName'
      ;

Right now, the error object looks like:

{
  "column_name":"firstName",
  "constraint_name":null,
  "datatype_name":null,
  "message": "A First Name is required.",
  "schema_name":null,
  "sqlerrcode":"P0001",
  "stack": "some stack trace here...",
  "table_name":null
}

It would be nice to also include the following:
DETAIL
HINT

@bendiy
Copy link
Contributor Author

bendiy commented Jun 28, 2017

Error messages are reported here:

plv8/plv8.cc

Lines 1769 to 1773 in 57db50d

if (strstr(m_msg, "Error: ") == m_msg)
m_msg += 7;
appendStringInfo(&str, "%s() LINE %d: %s",
script.str("?"), lineno - 1, source.str("?"));
m_detail = str.data;

@bendiy
Copy link
Contributor Author

bendiy commented Jun 28, 2017

Looking at how psycopg2 does it, they use libpg and call PQerrorMessage():
https://www.postgresql.org/docs/current/static/libpq-status.html#LIBPQ-PQERRORMESSAGE

@bendiy
Copy link
Contributor Author

bendiy commented Jun 28, 2017

PostgreSQL's CopyErrorData() has:
detail
detail_log
hint
context
internalquery
assoc_context
https://doxygen.postgresql.org/elog_8c_source.html#l01497
And a few more that might exist:
https://doxygen.postgresql.org/elog_8h_source.html#l00329

I think edata->context is the stack:
https://doxygen.postgresql.org/elog_8h.html#ad811b6bbae02e9f946cef448df4f6701

That can be added here:

ErrorData *edata = CopyErrorData();

bendiy added a commit to bendiy/plv8 that referenced this issue Jun 30, 2017
bendiy added a commit to bendiy/plv8 that referenced this issue Jun 30, 2017
bendiy added a commit to bendiy/plv8 that referenced this issue Jun 30, 2017
bendiy added a commit to bendiy/plv8 that referenced this issue Jun 30, 2017
Send full error messages: ERRCODE, DETAIL, HINT, CONTEXT.
Use CONTEXT instead of DETAIL.
Return the correct ERRCODE.
Expose detail, hint, context, internalquery and sqlerrcode to JavaScript error catching.
bendiy added a commit to bendiy/plv8 that referenced this issue Jun 30, 2017
Send full error messages: ERRCODE, DETAIL, HINT, CONTEXT.
Use CONTEXT instead of DETAIL.
Return the correct ERRCODE.
Expose detail, hint, context, internalquery and sqlerrcode to JavaScript error catching.
JerrySievert added a commit that referenced this issue Jul 3, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants