Author |
Message
|
goffinf |
Posted: Thu Jun 02, 2011 9:46 am Post subject: Output structure treatment of NULL |
|
|
Chevalier
Joined: 05 Nov 2005 Posts: 401
|
MB version 6.1.0.3
I perhaps should have known this but today I was surprised by .. :-
If I have code such as :-
Code: |
SET OutputRoot.XMLNSC.response.text = InputRoot.XMLNSC.nonExistantField;
|
I expected no output to be created because the input evaluates to NULL (or maybe I'm wrong about that ?). But in fact what I get is :-
<response/>
That is, the output structure up to the final part is created anyway.
If instead I do this :-
Code: |
DECLARE AmINULL CHAR InputRoot.XMLNSC.nonExistantField;
SET OutputRoot.XMLNSC.response.text = AmINULL;
|
no output structure is created at all.
Can someone explain the difference ?
This isn't just an acadmic question, I had (wrongly it seems) assumed that if I assign an output XMLNSC element in ESQL to an input element that doesn't exist, nothing would be produced (which is the effect I want).
Regards
Fraser. |
|
Back to top |
|
 |
smdavies99 |
Posted: Thu Jun 02, 2011 10:27 am Post subject: |
|
|
 Jedi Council
Joined: 10 Feb 2003 Posts: 6076 Location: Somewhere over the Rainbow this side of Never-never land.
|
Take a user trace and see what 'Wonderous Stories' are revealed. _________________ WMQ User since 1999
MQSI/WBI/WMB/'Thingy' User since 2002
Linux user since 1995
Every time you reinvent the wheel the more square it gets (anon). If in doubt think and investigate before you ask silly questions. |
|
Back to top |
|
 |
Vitor |
Posted: Thu Jun 02, 2011 10:32 am Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
Is there a message set associated with the output that defines the field as mandatory? I know you say you don't want it but just checking. _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
goffinf |
Posted: Thu Jun 02, 2011 10:56 am Post subject: |
|
|
Chevalier
Joined: 05 Nov 2005 Posts: 401
|
Actually it now appears that my initial testing was not correct. The case I sited where no output is produced (by assigning a variable first) *does* in fact produce the same (unwanted) output as the other example.
I have also tried this :-
Code: |
SET OutputRoot.XMLNSC.response.text = COALESCE(InputRoot.XMLNSC.nonExistantField, NULL)
|
but it too still outputs <response/>
Victor: No there's no msgset involved here.
smdavies99: Sure I'll do that and post back here.
Fraser. |
|
Back to top |
|
 |
mqjeff |
Posted: Thu Jun 02, 2011 11:10 am Post subject: |
|
|
Grand Master
Joined: 25 Jun 2008 Posts: 17447
|
Try applying FP 8.
Try using VALUE clause. |
|
Back to top |
|
 |
Vitor |
Posted: Thu Jun 02, 2011 11:28 am Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
mqjeff wrote: |
Try applying FP 8. |
Just tried it using WMB 6.1.0.9 and got the expected "Assigning NULL to <the target field name>, thus deleting it" in my user trace.
Interested to know what you see. _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
smdavies99 |
Posted: Thu Jun 02, 2011 11:35 am Post subject: |
|
|
 Jedi Council
Joined: 10 Feb 2003 Posts: 6076 Location: Somewhere over the Rainbow this side of Never-never land.
|
Vitor wrote: |
Just tried it using WMB 6.1.0.9 and got the expected "Assigning NULL to <the target field name>, thus deleting it" in my user trace.
|
This has been true for sometime. I've often 'grepped' for the 'Assigning NULL' to find issued in code. IMHO, it is a neat trick. _________________ WMQ User since 1999
MQSI/WBI/WMB/'Thingy' User since 2002
Linux user since 1995
Every time you reinvent the wheel the more square it gets (anon). If in doubt think and investigate before you ask silly questions. |
|
Back to top |
|
 |
Vitor |
Posted: Thu Jun 02, 2011 11:46 am Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
smdavies99 wrote: |
This has been true for sometime. I've often 'grepped' for the 'Assigning NULL' to find issued in code. IMHO, it is a neat trick. |
It is the behaviour everyone including the OP seems to be expecting.
I certainly was expecting it. _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
goffinf |
Posted: Thu Jun 02, 2011 1:44 pm Post subject: |
|
|
Chevalier
Joined: 05 Nov 2005 Posts: 401
|
Vitor wrote: |
smdavies99 wrote: |
This has been true for sometime. I've often 'grepped' for the 'Assigning NULL' to find issued in code. IMHO, it is a neat trick. |
It is the behaviour everyone including the OP seems to be expecting.
I certainly was expecting it. |
Hmmm, I'm not so sure.
So taking the advice earlier of creating a User Trace, I do indeed see the ' Assigning NULL ...' as in :-
Code: |
Assigning NULL to ''OutputRoot.XMLNSC.response.text'', thus deleting it.
|
But it seems to me that all that means is that it is deleting the 'text' part of the message tree but leaving the parts before it in tact, hence the output is <response/>.
What I was expecting was that NONE of the message tree would be constructed ! |
|
Back to top |
|
 |
rekarm01 |
Posted: Thu Jun 02, 2011 2:33 pm Post subject: Re: Output structure treatment of NULL |
|
|
Grand Master
Joined: 25 Jun 2008 Posts: 1415
|
goffinf wrote: |
But it seems to me that all that means is that it is deleting the 'text' part of the message tree but leaving the parts before it in tact, hence the output is <response/>.
What I was expecting was that NONE of the message tree would be constructed ! |
In order to navigate from the root to the target field, the SET statement will still try to create any missing fields along the way (or throw an exception if it can't), even when deleting the (possibly non-existent) target field.
So, in the given example, it will create a missing <response>, whether it creates <text> or not.
goffinf wrote: |
If instead I do this, no output structure is created at all:
Code: |
DECLARE AmINULL CHAR InputRoot.XMLNSC.nonExistentField;
SET OutputRoot.XMLNSC.response.text = AmINULL; |
|
Now that would have been unexpected.
Perhaps adding an IF statement would work better:
Code: |
IF InputRoot.XMLNSC.nonExistentField IS NOT NULL
THEN
SET OutputRoot.XMLNSC.response.text = InputRoot.XMLNSC.nonExistentField;
END IF; |
|
|
Back to top |
|
 |
goffinf |
Posted: Thu Jun 02, 2011 2:50 pm Post subject: |
|
|
Chevalier
Joined: 05 Nov 2005 Posts: 401
|
Quote: |
Perhaps adding an IF statement would work better: |
Yes that would work and indeed that is a strategy that I have considered. However, ... I am mapping about 500 input elements and I don't really want the overhead of doing an IF test for each one just so i can supress (or rather not create) any partial output tree.
That said, thinking about the behaviour I see here and that others have confirmed, it *does* seem to be perfectly reasonable. That is, there's no way that MB could or probably should assume that just because the assignment to a 'leaf' node of the message tree turns out to be a NULL and causes that leaf not to be created, that it should assume I want all of the tree constructed up to the leaf to also be removed. Indeed if it did that it would be pretty disasterous for most of the code that most of us write I suppose.
Looks like I'm going to have to suck up the 500 IF tests, or use a different transformation method.
Fraser. |
|
Back to top |
|
 |
fjb_saper |
Posted: Thu Jun 02, 2011 7:33 pm Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
goffinf wrote: |
Quote: |
Perhaps adding an IF statement would work better: |
Yes that would work and indeed that is a strategy that I have considered. However, ... I am mapping about 500 input elements and I don't really want the overhead of doing an IF test for each one just so i can supress (or rather not create) any partial output tree.
That said, thinking about the behaviour I see here and that others have confirmed, it *does* seem to be perfectly reasonable. That is, there's no way that MB could or probably should assume that just because the assignment to a 'leaf' node of the message tree turns out to be a NULL and causes that leaf not to be created, that it should assume I want all of the tree constructed up to the leaf to also be removed. Indeed if it did that it would be pretty disasterous for most of the code that most of us write I suppose.
Looks like I'm going to have to suck up the 500 IF tests, or use a different transformation method.
Fraser. |
Don't do 500 IF tests. This will give you a prohibitive cost.
Build the tree and let the response be created. Go through your 500 fields... Then assign your reference to response. Move the reference to the last/first child. If the move is not successful remove the reference from the tree... done.
Have fun  _________________ MQ & Broker admin |
|
Back to top |
|
 |
goffinf |
Posted: Fri Jun 03, 2011 2:33 am Post subject: |
|
|
Chevalier
Joined: 05 Nov 2005 Posts: 401
|
I had thought (I think) of something like this approach ... but figured it would probably still amount to the same thing (500 IF tests), that is, instead of 500 * IF fieldX IS NULL, I would still have 500 * IF LASTMOVE(Ref)
Did you mean build a temporary output tree in the Environment to recurse thru, ... then build up the actual OutputRoot as a result of testing the success (or not) of MOVE statements ?
or am I sadly misunderstanding something ?
Let me provide a more concrete example (simplified of course) :-
Lets say as a result of running the complete transformation ESQL I end up with this :-
Code: |
<Person>
<FirstName Val="Fred"/>
<MiddleInitial />
<Surname Val="Bloggs"/>
<Age/>
<Gender/>
<Address>
<Line1 Val="1 The Street"/>
<Line2/>
<Line3 Val="Sometown"/>
</Address>
</Person>
|
I identify the problem as ... any element that does NOT have a Val attribute should not be included in the output so that means, these elements should be removed :-
<MiddleInitial />
<Age/>
<Gender/>
<Line2/>
The actual structure contains 500+ elements.
Using the approach you have [kindly] suggested how can I apply it to this structure.
Regards
Fraser.[/code] |
|
Back to top |
|
 |
fjb_saper |
Posted: Fri Jun 03, 2011 8:53 pm Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
goffinf wrote: |
Let me provide a more concrete example (simplified of course) :-
Lets say as a result of running the complete transformation ESQL I end up with this :-
Code: |
<Person>
<FirstName Val="Fred"/>
<MiddleInitial />
<Surname Val="Bloggs"/>
<Age/>
<Gender/>
<Address>
<Line1 Val="1 The Street"/>
<Line2/>
<Line3 Val="Sometown"/>
</Address>
</Person>
|
I identify the problem as ... any element that does NOT have a Val attribute should not be included in the output so that means, these elements should be removed :-
<MiddleInitial />
<Age/>
<Gender/>
<Line2/>
The actual structure contains 500+ elements.
Using the approach you have [kindly] suggested how can I apply it to this structure.
Regards
Fraser. |
Again quite different from the previous proposal where the 500 tags where supposed to be children of the previous tag.
What you display here are final tags... so it looks like what you have in your code is
SET refperson.MiddleInitial VALUE = some null value ref;
Change that to
SET refperson.MiddleInitial = some null value ref;
This will create and delete the MiddleInitial tag in the same statement.
Now you only need to check the refperson at the end. If there are no children and the fieldValue(refperson) = null, you can then use
SET refperson = NULL;
and it will also delete the refperson tag. You then will need to move the reference as it no longer points to an existing location.
Have fun  _________________ MQ & Broker admin |
|
Back to top |
|
 |
goffinf |
Posted: Sat Jun 04, 2011 5:45 am Post subject: |
|
|
Chevalier
Joined: 05 Nov 2005 Posts: 401
|
Hmm, I'm still confusing you with my example, my fault sorry.
This is the structure that I want to end up with AFTER the transformation (but WITHOUT the empty elements) :-
Code: |
<Person>
<FirstName Val="Fred"/>
<MiddleInitial />
<Surname Val="Bloggs"/>
<Age/>
<Gender/>
<Address>
<Line1 Val="1 The Street"/>
<Line2/>
<Line3 Val="Sometown"/>
</Address>
</Person>
|
However, the source for this is NOT in the same structure, it looks more like this (note: not all of the elements expected in the output are present) :-
Code: |
<Person>
<FirstName>Fred</FirstName>
<Surname>Bloggs</Surname>
<Address>
<Line1>1 The Street</Line1>
<Line3>Sometown</Line3>
</Address>
</Person>
|
So ... when I use code like this (choosing an example where the element I'm expecting to map is not actually present) :-
Code: |
SET OutputRoot.XMLNSC.Person.MiddleInitial.(XMLNSC.Attribute)Val = InputRoot.XMLNSC.Person.MiddleInitial;
|
I end up with ...
Code: |
<Person>
...
<MiddleInitial />
|
Whilst what I want is for the MiddleInitial element to not appear at all in the output.
Thanks for you patience.
Fraser. |
|
Back to top |
|
 |
|