Re: proposal 9.4 plpgsql: allows access to call stack from GET DIAGNOSTICS statement - Mailing list pgsql-hackers

From Pavel Stehule
Subject Re: proposal 9.4 plpgsql: allows access to call stack from GET DIAGNOSTICS statement
Date
Msg-id CAFj8pRAVfEXGiq+f8=QVD=5Tb5xGMX=boYaMT18dsJKYX0FeAA@mail.gmail.com
Whole thread Raw
In response to Re: proposal 9.4 plpgsql: allows access to call stack from GET DIAGNOSTICS statement  (Rushabh Lathia <rushabh.lathia@gmail.com>)
Responses Re: proposal 9.4 plpgsql: allows access to call stack from GET DIAGNOSTICS statement
List pgsql-hackers
Hello

updated patch with some basic doc

Regards

Pavel


2013/6/26 Rushabh Lathia <rushabh.lathia@gmail.com>:
>
>
>
> On Wed, Jun 26, 2013 at 5:11 PM, Pavel Stehule <pavel.stehule@gmail.com>
> wrote:
>>
>> 2013/6/26 Rushabh Lathia <rushabh.lathia@gmail.com>:
>> >
>> >
>> >
>> > On Tue, Jun 25, 2013 at 11:09 AM, Pavel Stehule
>> > <pavel.stehule@gmail.com>
>> > wrote:
>> >>
>> >> 2013/6/25 Rushabh Lathia <rushabh.lathia@gmail.com>:
>> >> >
>> >> >
>> >> >
>> >> > On Tue, Jun 25, 2013 at 1:47 AM, Pavel Stehule
>> >> > <pavel.stehule@gmail.com>
>> >> > wrote:
>> >> >>
>> >> >> Hello
>> >> >>
>> >> >> This is fragment ofmy old code from orafce package - it is
>> >> >> functional,
>> >> >> but it is written little bit more generic due impossible access to
>> >> >> static variables (in elog.c)
>> >> >>
>> >> >> static char*
>> >> >> dbms_utility_format_call_stack(char mode)
>> >> >> {
>> >> >>    MemoryContext oldcontext = CurrentMemoryContext;
>> >> >>    ErrorData *edata;
>> >> >>    ErrorContextCallback *econtext;
>> >> >>    StringInfo sinfo;
>> >> >>
>> >> >>    #if PG_VERSION_NUM >= 80400
>> >> >>       errstart(ERROR, __FILE__, __LINE__, PG_FUNCNAME_MACRO,
>> >> >> TEXTDOMAIN);
>> >> >>    #else
>> >> >>       errstart(ERROR, __FILE__, __LINE__, PG_FUNCNAME_MACRO);
>> >> >>     #endif
>> >> >>
>> >> >>    MemoryContextSwitchTo(oldcontext);
>> >> >>
>> >> >>    for (econtext = error_context_stack;
>> >> >>          econtext != NULL;
>> >> >>          econtext = econtext->previous)
>> >> >>             (*econtext->callback) (econtext->arg);
>> >> >>
>> >> >>    edata = CopyErrorData();
>> >> >>    FlushErrorState();
>> >> >>
>> >> >> https://github.com/orafce/orafce/blob/master/utility.c
>> >> >>
>> >> >> 2013/6/24 Rushabh Lathia <rushabh.lathia@gmail.com>:
>> >> >> > Hi,
>> >> >> >
>> >> >> > Use of this feature is to get  call stack for debugging without
>> >> >> > raising
>> >> >> > exception. This definitely seems very useful.
>> >> >> >
>> >> >> > Here are my comments about the submitted patch:
>> >> >> >
>> >> >> > Patch gets applied cleanly (there are couple of white space
>> >> >> > warning
>> >> >> > but
>> >> >> > that's
>> >> >> > into test case file). make and make install too went smooth. make
>> >> >> > check
>> >> >> > was smooth too. Did some manual testing about feature and its went
>> >> >> > smooth.
>> >> >> >
>> >> >> > However would like to share couple of points:
>> >> >> >
>> >> >>
>> >> >> My main motive is concentration to stack info string only. So I
>> >> >> didn't
>> >> >> use err_start function, and I didn't use CopyErrorData too. These
>> >> >> routines does lot of other work.
>> >> >>
>> >> >>
>> >> >> > 1) I noticed that you did the initialization of edata manually,
>> >> >> > just
>> >> >> > wondering
>> >> >> > can't we directly use CopyErrorData() which will do that job ?
>> >> >> >
>> >> >>
>> >> >> yes, we can, but in this context on "context" field is interesting
>> >> >> for
>> >> >> us.
>> >> >>
>> >> >> > I found that inside CopyErrorData() there is Assert:
>> >> >> >
>> >> >> > Assert(CurrentMemoryContext != ErrorContext);
>> >> >> >
>> >> >> > And in the patch we are setting using ErrorContext as short living
>> >> >> > context,
>> >> >> > is
>> >> >> > it the reason of not using CopyErrorData() ?
>> >> >>
>> >> >> it was not a primary reason, but sure - this routine is not designed
>> >> >> for direct using from elog module. Next, we can save one palloc
>> >> >> call.
>> >> >
>> >> >
>> >> > Hmm ok.
>> >> >
>> >> >>
>> >> >>
>> >> >> >
>> >> >> >
>> >> >> > 2) To reset stack to empty, FlushErrorState() can be used.
>> >> >> >
>> >> >>
>> >> >> yes, it can be. I use explicit rows due different semantics,
>> >> >> although
>> >> >> it does same things. FlushErrorState some global ErrorState and it
>> >> >> is
>> >> >> used from other modules. I did a reset of ErrorContext. I fill a
>> >> >> small
>> >> >> difference there - so FlushErrorState is not best name for my
>> >> >> purpose.
>> >> >> What about modification:
>> >> >>
>> >> >> static void
>> >> >> resetErrorStack()
>> >> >> {
>> >> >>         errordata_stack_depth = -1;
>> >> >>         recursion_depth = 0;
>> >> >>         /* Delete all data in ErrorContext */
>> >> >>         MemoryContextResetAndDeleteChildren(ErrorContext);
>> >> >> }
>> >> >>
>> >> >> and then call in  InvokeErrorCallbacks -- resetErrorStack()
>> >> >>
>> >> >> and rewrote flushErrorState like
>> >> >>
>> >> >> void FlushErrorState(void)
>> >> >> {
>> >> >>   /* reset ErrorStack is enough */
>> >> >>   resetErrorStack();
>> >> >> }
>> >> >>
>> >> >> ???
>> >> >
>> >> >
>> >> > Nope. rather then that I would still prefer direct call of
>> >> > FlushErrorState().
>> >> >
>> >> >>
>> >> >>
>> >> >> but I can live well with direct call of FlushErrorState() - it is
>> >> >> only
>> >> >> minor change.
>> >> >>
>> >> >>
>> >> >> > 3) I was think about the usability of the feature and wondering
>> >> >> > how
>> >> >> > about if
>> >> >> > we add some header to the stack, so user can differentiate between
>> >> >> > STACK
>> >> >> > and
>> >> >> > normal NOTICE message ?
>> >> >> >
>> >> >> > Something like:
>> >> >> >
>> >> >> > postgres=# select outer_outer_func(10);
>> >> >> > NOTICE:  ----- Call Stack -----
>> >> >> > PL/pgSQL function inner_func(integer) line 4 at GET DIAGNOSTICS
>> >> >> > PL/pgSQL function outer_func(integer) line 3 at RETURN
>> >> >> > PL/pgSQL function outer_outer_func(integer) line 3 at RETURN
>> >> >> > CONTEXT:  PL/pgSQL function outer_func(integer) line 3 at RETURN
>> >> >> > PL/pgSQL function outer_outer_func(integer) line 3 at RETURN
>> >> >> >  outer_outer_func
>> >> >> > ------------------
>> >> >> >                20
>> >> >> > (1 row)
>> >> >>
>> >> >> I understand, but I don't think so it is good idea. Sometimes, you
>> >> >> would to use context for different purposes than debug log - for
>> >> >> example - you should to identify top most call or near call - and
>> >> >> any
>> >> >> additional lines means some little bit more difficult parsing. You
>> >> >> can
>> >> >> add this line simply (if you want)
>> >> >>
>> >> >> RAISE NOTICE e'--- Call Stack ---\n%', stack
>> >> >>
>> >> >> but there are more use cases, where you would not this information
>> >> >> (or
>> >> >> you can use own header (different language)), and better returns
>> >> >> only
>> >> >> clean data.
>> >> >
>> >> >
>> >> > I don't know but I still feel like given header from function it self
>> >> > would
>> >> > be
>> >> > nice to have things. Because it will help user to differentiate
>> >> > between
>> >> > STACK and normal NOTICE context message.
>> >> >
>> >> >
>> >> >>
>> >> >>
>> >> >> >
>> >> >> > I worked on point 2) and 3) and PFA patch for reference.
>> >> >>
>> >> >> so
>> >> >>
>> >> >> *1 CopyErrorData does one useless palloc more and it is too generic,
>> >> >
>> >> >
>> >> > Ok
>> >> >>
>> >> >>
>> >> >> *2 it is possible - I have not strong opinion
>> >> >
>> >> >
>> >> > Prefer  FlushErrorState() call.
>> >> >
>> >>
>> >> ok
>> >>
>> >> >>
>> >> >> *3 no, I would to return data in most simply and clean form without
>> >> >> any
>> >> >> sugar
>> >> >
>> >> >
>> >> > As a user perspective it would be nice to have sugar layer around.
>> >> >
>> >>
>> >> I understand, but disagree - strings are simply joined and is
>> >> difficult to separate it. I have strong opinion here.
>> >>
>> >> * a reason for this construct is not only using in debug notices
>> >> * sugar is not used in GET DIAGNOSTICS statement ever - so possible
>> >> introduction is not consistent with other
>> >
>> >
>> > Hmm because sugar is not used in GET DIAGNOSTICS statement ever,
>> > I think its should be fine.
>> >
>> >
>> > How about point 2) To reset stack to empty, FlushErrorState() can be
>> > used. ?
>>
>> I can use FlushErrorState() - final decision should do commiter.
>>
>> Thank you
>>
>> I'll send remastered patch today.
>
>
> Thanks Pavel.
>
>>
>>
>> Regards
>>
>> Pavel
>>
>> >
>> >>
>> >> Regards
>> >>
>> >> Pavel
>> >>
>> >>
>> >> >>
>> >> >>
>> >> >> What do you think?
>> >> >
>> >> >
>> >> > Others or committer having any opinion ?
>> >> >
>> >>
>> >> ???
>> >>
>> >> >>
>> >> >>
>> >> >> Regards
>> >> >>
>> >> >> Pavel
>> >> >>
>> >> >> >
>> >> >> > Thanks,
>> >> >> > Rushabh
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> > On Sat, Feb 2, 2013 at 2:53 PM, Pavel Stehule
>> >> >> > <pavel.stehule@gmail.com>
>> >> >> > wrote:
>> >> >> >>
>> >> >> >> Hello
>> >> >> >>
>> >> >> >> I propose enhancing GET DIAGNOSTICS statement about new field
>> >> >> >> PG_CONTEXT. It is similar to GET STACKED DIAGNOSTICS'
>> >> >> >> PG_EXCEPTION_CONTEXT.
>> >> >> >>
>> >> >> >> Motivation for this proposal is possibility to get  call stack
>> >> >> >> for
>> >> >> >> debugging without raising exception.
>> >> >> >>
>> >> >> >> This code is based on cleaned code from Orafce, where is used
>> >> >> >> four
>> >> >> >> years without any error reports.
>> >> >> >>
>> >> >> >> CREATE OR REPLACE FUNCTION public."inner"(integer)
>> >> >> >>  RETURNS integer
>> >> >> >>  LANGUAGE plpgsql
>> >> >> >> AS $function$
>> >> >> >> declare _context text;
>> >> >> >> begin
>> >> >> >>   get diagnostics _context = pg_context;
>> >> >> >>   raise notice '***%***', _context;
>> >> >> >>   return 2 * $1;
>> >> >> >> end;
>> >> >> >> $function$
>> >> >> >>
>> >> >> >> postgres=# select outer_outer(10);
>> >> >> >> NOTICE:  ***PL/pgSQL function "inner"(integer) line 4 at GET
>> >> >> >> DIAGNOSTICS
>> >> >> >> PL/pgSQL function "outer"(integer) line 3 at RETURN
>> >> >> >> PL/pgSQL function outer_outer(integer) line 3 at RETURN***
>> >> >> >> CONTEXT:  PL/pgSQL function "outer"(integer) line 3 at RETURN
>> >> >> >> PL/pgSQL function outer_outer(integer) line 3 at RETURN
>> >> >> >>  outer_outer
>> >> >> >> ─────────────
>> >> >> >>           20
>> >> >> >> (1 row)
>> >> >> >>
>> >> >> >> Ideas, comments?
>> >> >> >>
>> >> >> >> Regards
>> >> >> >>
>> >> >> >> Pavel Stehule
>> >> >> >>
>> >> >> >>
>> >> >> >> --
>> >> >> >> Sent via pgsql-hackers mailing list
>> >> >> >> (pgsql-hackers@postgresql.org)
>> >> >> >> To make changes to your subscription:
>> >> >> >> http://www.postgresql.org/mailpref/pgsql-hackers
>> >> >> >>
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> > --
>> >> >> > Rushabh Lathia
>> >> >
>> >> >
>> >> >
>> >> >
>> >> > --
>> >> > Rushabh Lathia
>> >
>> >
>> >
>> >
>> > --
>> > Rushabh Lathia
>
>
>
>
> --
> Rushabh Lathia

Attachment

pgsql-hackers by date:

Previous
From: Atri Sharma
Date:
Subject: Re: A better way than tweaking NTUP_PER_BUCKET
Next
From: Claudio Freire
Date:
Subject: Re: Kudos for Reviewers -- straw poll