Toad World® Forums

Debugger problem: Am I doing something wrong?


#1

CREATE OR REPLACE PACKAGE BODY ABC2

AS

PROCEDURE proc1

AS

  x   VARCHAR2 (1);

  PROCEDURE innerproc

  AS

  BEGIN

     x := 'a';

     null;

  END;

BEGIN

  x:= 'g';

  null;

  innerproc;

END proc1;

END abc2;

When I enter procedure innerproc, I get

“undeclared identifier ‘X’”

How can I see the value of x when I am inside innerproc?

Thanks,

Mike


#2

Mike,

I think you may just be running across a limitation (henceforth to be known as a
feature) of Oracle. For all watches, we don’t keep track of any values in Toad,
we query Oracle for the value using dbms_debug.program_info. In this case,

Oracle returns 3 which is “error_no_such_object” (see

http://download.oracle.com/docs/cd/B10501_01/appdev.920/a96612/d_debug2.htm#1005620
). Out of curiosity, I checked in SQL Developer (which uses JDWP instead of
DBMS) and it seems to have the same issue.

Greg


#3

How can I see the value of
x when I am inside innerproc?

Greg is correct, it has to do with the concept of scope and when the appropriate variables are “in scope”. The basic explanation is: you’re using a variable cross-scope.

If you really want to do that - and good coding practices dictates you shouldn’t - then you want to move your declaration “up a level in scope”. Like so:

CREATE OR REPLACE PACKAGE BODY ABC2
AS
x VARCHAR2(1);
PROCEDURE proc1

Then you’ll be able to see the variable at all levels.

Good coding practices:

You really should build each function/procedure in a “black box” format. What I mean by that is that you can rip out the code and run it stand alone. Right now, the inner procedure is reliant on the variable defined by the outer procedure. You couldn’t extract the inner procedure and run it stand alone without modifications.

This raises such questions as: do you really need that inner procedure if it’s supposed to be part of the whole?

On the other hand, if you build it “black box”, then you gain a ton of benefits. For example, you can literally take the complete procedure out and use it elsewhere. Let’s say you find another process that could use that exact procedure. For example, maybe it was a procedure that strips out all non-alphanumeric values of a field. Very useful if you think you might have to deal with garbage data and want to clean it up a bit.

You can take the procedure, move it out to a more generic package and call that procedure from all locations where you need it. Another benefit example is that if you find a logical flaw in that code, instead of having to make the changes in all locations, you just have one location to maintain.

Example of the black box - and a more recommended solution so you can trace the variable through:

CREATE OR REPLACE PACKAGE BODY ABC2
AS
PROCEDURE proc1
AS
x VARCHAR2(1);
PROCEDURE innerproc (io_value IN OUT VARCHAR2)
AS
BEGIN
io_value := ‘a’;
null;
END innerproc;
BEGIN
x := ‘g’;
null;
innerproc( x );
END proc1;
END ABC2;

Roger S.

This communication, including any attached documentation, is intended only for the person or entity to which it is addressed, and may contain confidential, personal and/or privileged information. Any unauthorized disclosure, copying, or taking action on the contents is strictly prohibited. If you have received this message in error, please contact us immediately so we may correct our records. Please then delete or destroy the original transmission and any subsequent reply.


#4

Well dbms_debug.program_info is just dumb then. While I accept that this is
the way it works, I don’t accept that there is any reason it SHOULD work
this way. Obviously the program is capable of resolving the variable reference
by ‘looking up scope’, so why can’t the debugger!

I understand Roger’s design discussion. The concept to which he refers is
called ‘Common Coupling’. I would never write code this way myself, but
sometimes you don’t have the luxury of refactoring an entire program ( that
somebody else wrote ) just to make some small change.

The way I would have wrote it is …

CREATE OR REPLACE PACKAGE BODY ABC2

AS

PROCEDURE innerproc (io_value IN OUT VARCHAR2)

AS

BEGIN

  io_value := 'a';

END innerproc;

PROCEDURE proc1

AS

  x   VARCHAR2 (1);

BEGIN

  x := 'g';

  innerproc (x);

END proc1;

END ABC2;

but the question is really about the debugger, not how to write good code. :slight_smile:

Thanks, guys, for the confirmation that it’s not something I am doing wrong
with the debugger.

Regards,

Mike

On Tue, Mar 22, 2011 at 1:12 PM, Simoneau, Roger
wrote:

>> How can I see the value of
>> x when I am inside innerproc?

Greg is correct, it has to do with the concept of scope and when the
appropriate variables are "in scope". The basic explanation is:
you're using a variable cross-scope.

If you really want to do that - and good coding practices dictates you
shouldn't - then you want to move your declaration "up a level in
scope". Like so:

CREATE OR REPLACE PACKAGE BODY ABC2
AS

x VARCHAR2(1);
PROCEDURE proc1
...

Then you'll be able to see the variable at all levels.

Good coding practices:

You really should build each function/procedure in a "black box"
format. What I mean by that is that you can rip out the code and run it
stand alone. Right now, the inner procedure is reliant on the variable
defined by the outer procedure. You couldn't extract the inner procedure
and run it stand alone without modifications.

This raises such questions as: do you really need that inner procedure if
it's supposed to be part of the whole?

On the other hand, if you build it "black box", then you gain a
ton of benefits. For example, you can literally take the complete procedure
out and use it elsewhere. Let's say you find another process that could
use that exact procedure. For example, maybe it was a procedure that strips
out all non-alphanumeric values of a field. Very useful if you think you
might have to deal with garbage data and want to clean it up a bit.

You can take the procedure, move it out to a more generic package and call
that procedure from all locations where you need it. Another benefit example
is that if you find a logical flaw in that code, instead of having to make
the changes in all locations, you just have one location to maintain.

Example of the black box - and a more recommended solution so you can trace
the variable through:

CREATE OR REPLACE PACKAGE BODY ABC2
AS
PROCEDURE proc1
AS
x VARCHAR2(1);

PROCEDURE innerproc (io_value IN OUT VARCHAR2)
AS
BEGIN
io_value := 'a';
null;
END innerproc;
BEGIN
x := 'g';
null;
innerproc( x );
END proc1;
END ABC2;

Roger S.

This communication, including any attached documentation, is intended only
for the person or entity to which it is addressed, and may contain
confidential, personal and/or privileged information. Any unauthorized
disclosure, copying, or taking action on the contents is strictly
prohibited. If you have received this message in error, please contact us
immediately so we may correct our records. Please then delete or destroy the
original transmission and any subsequent reply.

#5

Mike,

I feel your pain. Unfortunately, we have to play in the Oracle sandbox and play
by their rules. All we can do is ask for the value. Sometime we get it and
sometimes we get told we’re number one.

Greg

On Mar 22, 2011, at 6:09 PM, “Michael Moore” wrote:

Well dbms_debug.program_info is just dumb then. While I accept that this is
the way it works, I don't accept that there is any reason it SHOULD work
this way. Obviously the program is capable of resolving the variable
reference by 'looking up scope', so why can't the debugger!

I understand Roger’s design discussion. The concept to which he refers is
called ‘Common Coupling’. I would never write code this way myself, but
sometimes you don’t have the luxury of refactoring an entire program ( that
somebody else wrote ) just to make some small change.

The way I would have wrote it is …

CREATE OR REPLACE PACKAGE BODY ABC2

AS

PROCEDURE innerproc (io_value IN OUT VARCHAR2)

AS

BEGIN

io_value := 'a';

END innerproc;

PROCEDURE proc1

AS

x VARCHAR2 (1);

BEGIN

x := 'g';

innerproc (x);

END proc1;

END ABC2;

but the question is really about the debugger, not how to write good code.
:slight_smile:

Thanks, guys, for the confirmation that it’s not something I am doing wrong
with the debugger.

Regards,

Mike

On Tue, Mar 22, 2011 at 1:12 PM, Simoneau, Roger
> wrote:

How can I see the value of
x when I am inside innerproc?

Greg is correct, it has to do with the concept of scope and when the
appropriate variables are “in scope”. The basic explanation is: you’re
using a variable cross-scope.

    If you really want to do that - and good coding practices dictates you
    shouldn't - then you want to move your declaration "up a level in
    scope". Like so:

CREATE OR REPLACE PACKAGE BODY ABC2
AS

x VARCHAR2(1);
PROCEDURE proc1

    Then you'll be able to see the variable at all levels.

    Good coding practices:

    You really should build each function/procedure in a "black box" format.
    What I mean by that is that you can rip out the code and run it stand
    alone. Right now, the inner procedure is reliant on the variable defined
    by the outer procedure. You couldn't extract the inner procedure and run
    it stand alone without modifications.

    This raises such questions as: do you really need that inner procedure
    if it's supposed to be part of the whole?

    On the other hand, if you build it "black box", then you gain a ton of
    benefits. For example, you can literally take the complete procedure out
    and use it elsewhere. Let's say you find another process that could use
    that exact procedure. For example, maybe it was a procedure that strips
    out all non-alphanumeric values of a field. Very useful if you think you
    might have to deal with garbage data and want to clean it up a bit.

    You can take the procedure, move it out to a more generic package and
    call that procedure from all locations where you need it. Another
    benefit example is that if you find a logical flaw in that code, instead
    of having to make the changes in all locations, you just have one
    location to maintain.

    Example of the black box - and a more recommended solution so you can
    trace the variable through:

CREATE OR REPLACE PACKAGE BODY ABC2
AS
PROCEDURE proc1
AS
x VARCHAR2(1);

PROCEDURE innerproc (io_value IN OUT VARCHAR2)
AS
BEGIN
io_value := ‘a’;
null;
END innerproc;
BEGIN
x := ‘g’;
null;
innerproc( x );
END proc1;
END ABC2;

    Roger S.

    This communication, including any attached documentation, is intended
    only for the person or entity to which it is addressed, and may contain
    confidential, personal and/or privileged information. Any unauthorized
    disclosure, copying, or taking action on the contents is strictly
    prohibited. If you have received this message in error, please contact
    us immediately so we may correct our records. Please then delete or
    destroy the original transmission and any subsequent reply.