|
RSS Feed - WebSphere MQ Support
|
RSS Feed - Message Broker Support
|
 |
|
WMB 6 \ unset REFERENCE in procedures |
« View previous topic :: View next topic » |
Author |
Message
|
hopsala |
Posted: Sun Oct 19, 2008 5:29 am Post subject: WMB 6 \ unset REFERENCE in procedures |
|
|
 Guardian
Joined: 24 Sep 2004 Posts: 960
|
The REFERENCE saga continues...
Let's say I created a procedure that returns a common reference NameRef from a given position treeRoot:
Code: |
CREATE PROCEDURE get_NameRef (
IN treeRoot REFERENCE,
OUT NamedRef REFERENCE)
BEGIN
MOVE NamedRef TO treeRoot.MRM.Data.Name;
IF NOT LASTMOVE(jobDataRef) THEN
THROW USER EXCEPTION VALUES('Unable to reference');
END IF;
END; |
And I call it like so:
Code: |
DECLARE NameRef REFERENCE InputRoot;
CALL get_NameRef(Environment.OriginalRequest, NameRef);
DECLARE whatever CHARACTER 'MiaWallace'; |
You will note that I check LASTMOVE within my function, because I don't want to do it every time I call get_NameRef. However, to put it simply - this just doesn't work. (p.s the initial reference to InputRoot is irrelevent, and is only used since the fr%^@ing syntax demands an initial value for references)
If the target MOVE field doesn't exist, LASTMOVE returns TRUE!
In this case, if "Environment.OriginalRequest.MRM.Data.Name" doesn't exist. Apparently, since NameRef is not a regular variable but a parameter, it remains in some sort of limbo state..
Moreover, an exception is thrown (since NameRef is never set) but not when the procedure ends or on LASTMOVE, rather in the next line of the code that called it! That is, you'll get the following exception:
Quote: |
RecoverableException
File = F:\\build\\S000_P\\src\\DataFlowEngine\\ImbRdl\\ImbRdlStatementGroup.cpp
Line = 589
Function = SqlStatementGroup::execute
Type = ComIbmComputeNode
Name = CENSURED#FCMComposite_1_7
Label = CENSURED
Catalog = BIPv600
Severity = 3
Number = 2488
Text = Error detected, rethrowing
Insert
Type = 5
Text = flow1.Main
Insert
Type = 5
Text = 19.3
Insert
Type = 5
Text = DECLARE whatever CHARACTER 'MiaWallace';
RecoverableException
File = F:/build/S000_P/export/x86_nt_4/usr/include\\ImbRdlReference.inl
Line = 60
Function = SqlReference::fieldPosition
Type =
Name =
Label =
Catalog = BIPv600
Severity = 3
Number = 2111
Text = Illegal use
Insert
Type = 2
Text = 0 |
From which it is impossible to understand what the problem was.
There is a workaround for this, namely to add the line "MOVE NamedRef TO TreeRoot" at the beginning of the procedure, so that LASTMOVE returns FALSE, but I must say it's quite ugly and easy to forget. Also, i'm getting tired of working around REFERENCEs rather than working with them...
Any suggestions? Is this a bug, or another wonderous working-as-designed edge case? Peeved as I am, I'd be glad to hear other opinions. |
|
Back to top |
|
 |
fjb_saper |
Posted: Sun Oct 19, 2008 1:21 pm Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
I would not be surprised if the folks from Hursley tell us working as designed. You declared the input parm as a reference but you are effectively passing a tree node to it. If that tree node does not exist or the reference you would be passing to it were invalid you can expect the same result.
Now imagine you would declare a proper reference to pass as input value:
declare myinref reference to Environment.OriginalRequest;
Wouldn't you verify in the next line that it got assigned properly?
IF LASTMOVE(myinref) THEN ....
Of course this puts the burden of safety to the caller. If you want to foolproof your procedure as you have discovered it is prudent to verify that the target is a valid reference before using it... for that matter you should also verify that the source is a valid reference...
I also noticed that you move the reference. I would have expected a SET command to move not the reference but the content.... but you might have had another purpose in mind there and this is valid as any...
Enjoy  _________________ MQ & Broker admin |
|
Back to top |
|
 |
mqjeff |
Posted: Sun Oct 19, 2008 1:56 pm Post subject: Re: WMB 6 \ unset REFERENCE in procedures |
|
|
Grand Master
Joined: 25 Jun 2008 Posts: 17447
|
hopsala wrote: |
IF NOT LASTMOVE(jobDataRef) THEN |
? |
|
Back to top |
|
 |
mgk |
Posted: Mon Oct 20, 2008 1:27 am Post subject: |
|
|
 Padawan
Joined: 31 Jul 2003 Posts: 1642
|
Hi,
Firstly it would be interesting to know which level of the code you are on, as I do not get the exception you report when I try your code (after changing 'jobDataRef' to 'NamedRef'; I assume this was a typo).
Secondly, I can see why you are having difficulties as OUT REFERENCE parameters to procedures and functions are not documented as well as they could be, so I will try and explain them here and arrange for a doc update as well.
All parameters to functions and procedures are pass by value, so they are copied into local temp variables before the routine is executed, and copied back again afterwards if they are OUT or INOUT parameters.
However, when you have an OUT REFERENCE the question arises "where should it point to" as the SQL rules for all OUT parameters state that they are NULL on entry to the routine. The ESQL answer to this question is actually "nowhere", ie they to are NULL (and this is one area that needs a doc update) on entry to the routine. And when you MOVE a NULL OUT REFERENCE to a location that does exist all is fine and LASTMOVE returns TRUE. However, if you move a NULL OUT REFERENCE to a location that does not exist, the LASTMOVE function returns NULL (UNKNOWN) to follow the ESQL general rule that the result of an expression involving NULL is NULL.
Therefore, in this case to avoid this you could write your code as:
Code: |
IF LASTMOVE(NamedRef) THEN
//Do Work
ELSE
//Lastmove returned false or NULL
THROW USER EXCEPTION VALUES('Unable to reference');
END IF; |
or you could write it as:
Code: |
IF NOT LASTMOVE(NamedRef) OR NamedRef IS NULL THEN
THROW USER EXCEPTION VALUES('Unable to reference');
END IF; |
I was also interested to know why you choose to use an OUT reference in this case, as (from the code you posted) if would have been simpler to use an INOUT REFERENCE for NamedRef (which would also avoid NULL OUT REFERENCES).
I hope this helps.
Regards, _________________ MGK
The postings I make on this site are my own and don't necessarily represent IBM's positions, strategies or opinions. |
|
Back to top |
|
 |
hopsala |
Posted: Wed Oct 22, 2008 8:33 am Post subject: |
|
|
 Guardian
Joined: 24 Sep 2004 Posts: 960
|
mgk -
the null tip is just what I needed! Indeed, this isn't documented at all. Also, the fact that one cannot set reference vars to null (I don't really understand why this is, btw) threw me off, and I thought reference vars can never be null.
Anyway, your first code snippet won't work, because as I said LASTMOVE returns true in my scenario. Your second snippet should work, and i'll try it in a few days when I get back to the site.
The parameter is not an INOUT var because the idea is that I return it. I would have returned it as a function return value, but reference return types are (surprise surprise..) not allowed. I thought it would be wrong to use the inout type for mere technical reasons, and mislead everyone who'll use the procedure in future as to the real purpose of the parameter.
jeff -
'jobDataRef' was indeed a typo. It does not appear in the original code.
fjb, assuming I got your meaning -
I wanted the burden to be on the procedure, not the caller, hence my code is the way it is. And I did mean to set the reference, not the content.
All -
Here's what I'm trying to do: At one point I noticed that I keep writing the same reference strings again and again in different nodes & flows of the same project. I thought it would make sense to have a few common procedures, which will always return the right reference point in the tree, rather than copy-paste the same "X.Y.Z.." again and again. I thought OUT reference vars would be the way to do it, but of course I may be wrong..
Cheers for all the help! |
|
Back to top |
|
 |
mgk |
Posted: Wed Oct 22, 2008 8:43 am Post subject: |
|
|
 Padawan
Joined: 31 Jul 2003 Posts: 1642
|
Hi,
Quote: |
Anyway, your first code snippet won't work, because as I said LASTMOVE returns true in my scenario |
I tested the code I posted and it worked for me, and LASTMOVE returned NULL, not TRUE. If you try this agains and find it returns TRUE in the case you posted above, then I consider this a defect, in which case you need to move to a later fixpac or raise a PMR.
Quote: |
this isn't documented at all. |
I will get this changed as soon as I can.
Regards, _________________ MGK
The postings I make on this site are my own and don't necessarily represent IBM's positions, strategies or opinions. |
|
Back to top |
|
 |
|
|
 |
|
Page 1 of 1 |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|
|
|