Discussion:
4GL compares NULL differently
(too old to reply)
Denis Melnikov
2005-10-26 12:28:06 UTC
Permalink
4GL 7.32.UC2
Solaris 2.6

4GL must compare NULL to any not-NULL value as FALSE.
And it acts this way... sometimes.

Please review the following sample:
DEFINE m_inv_amt DECIMAL(12,2)

FUNCTION AmtUsed()

IF m_inv_amt != 0 THEN
RETURN true
ELSE
RETURN false
END IF
END FUNCTION
<<<<<<<<<<<<<<<<<<

When m_inv_amt is NULL, AmtUsed() returns FALSE at one moment,
and TRUE at another. And the FALSE/TRUE sequence doesn't
change from run to run.

Is it a known bug or a new feature?
Denis Melnikov
2005-10-26 12:34:23 UTC
Permalink
P.S. 4GL C compiler.
Clive Eisen
2005-10-26 12:40:15 UTC
Permalink
Post by Denis Melnikov
P.S. 4GL C compiler.
Because any equality or inequality test against null is specifically
undefined

You have to test 'is null'ness before applying your !=0 or whatever tests

--
Clive
Denis Melnikov
2005-10-26 13:55:17 UTC
Permalink
Post by Clive Eisen
Because any equality or inequality test against null is specifically
undefined
No!

IBM Informix 4GL Reference Manual Version 7.32:
"If any operand of a 4GL Boolean comparison is NULL, the value of the
comparison is FALSE (rather than NULL), unless the IS NULL keywords are
also included in the expression."
Post by Clive Eisen
You have to test 'is null'ness before applying your !=0 or whatever tests
This is workaround which we have to use in our new code. Unfortunatelly
we have the great amount of legacy code without the workaround.
Post by Clive Eisen
--
Clive
June C. Hunt
2005-10-26 13:03:39 UTC
Permalink
Post by Denis Melnikov
4GL 7.32.UC2
Solaris 2.6
4GL must compare NULL to any not-NULL value as FALSE.
And it acts this way... sometimes.
DEFINE m_inv_amt DECIMAL(12,2)
FUNCTION AmtUsed()
IF m_inv_amt != 0 THEN
RETURN true
ELSE
RETURN false
END IF
END FUNCTION
<<<<<<<<<<<<<<<<<<
When m_inv_amt is NULL, AmtUsed() returns FALSE at one moment,
and TRUE at another. And the FALSE/TRUE sequence doesn't
change from run to run.
Is it a known bug or a new feature?
I'm not quite ready to call it either. Just out of curiosity, what happens
if you write:
IF m_inv_amt = 0 THEN

Do you get a more consistent result?

I ask because of the comments in the I4GL Concepts and Use Guide. Null
values are discussed and the manual does tell you (on page 8-27 of manual
Part No. 000-8875) that "If you compare a null value to anything else, the
result is NULL. Is 'A' equal to unknown? The only answer can be unknown.
Thus every comparison expression has not two but three possible results:
TRUE, FALSE, and unknown, or NULL." The manual goes on to tell you that
NULL (unknown) will be treated as FALSE when evaluated by statements such as
IF and WHILE. My question comes from the fact that you are not testing to
see if the value of m_inv_amt is equal to zero, but rather, is m_inv_amt not
equal to zero. It is the 'not' part of the comparison that has my interest.

It has been a while since I've had the pleasure of working with pure I4GL,
but we never took the result of a possible NULL for granted. If the
possibility for a NULL value exists, I would suggest you check specifically
for NULL. In any case, I'll be interested to see if you get other responses
to this.

--
June Hunt
Denis Melnikov
2005-10-26 14:20:22 UTC
Permalink
Post by June C. Hunt
Post by Denis Melnikov
4GL 7.32.UC2
Solaris 2.6
4GL must compare NULL to any not-NULL value as FALSE.
And it acts this way... sometimes.
DEFINE m_inv_amt DECIMAL(12,2)
FUNCTION AmtUsed()
IF m_inv_amt != 0 THEN
RETURN true
ELSE
RETURN false
END IF
END FUNCTION
<<<<<<<<<<<<<<<<<<
When m_inv_amt is NULL, AmtUsed() returns FALSE at one moment,
and TRUE at another. And the FALSE/TRUE sequence doesn't
change from run to run.
Is it a known bug or a new feature?
I'm not quite ready to call it either. Just out of curiosity, what happens
IF m_inv_amt = 0 THEN
Do you get a more consistent result?
No, we have the same inconsistency.
Post by June C. Hunt
I ask because of the comments in the I4GL Concepts and Use Guide. Null
values are discussed and the manual does tell you (on page 8-27 of manual
Part No. 000-8875) that "If you compare a null value to anything else, the
result is NULL. Is 'A' equal to unknown? The only answer can be unknown.
TRUE, FALSE, and unknown, or NULL." The manual goes on to tell you that
NULL (unknown) will be treated as FALSE when evaluated by statements such as
IF and WHILE. My question comes from the fact that you are not testing to
see if the value of m_inv_amt is equal to zero, but rather, is m_inv_amt not
equal to zero.
It's because we need to handle "not-zero" and all other possibilities
including NULL.
Post by June C. Hunt
It is the 'not' part of the comparison that has my interest.
It has been a while since I've had the pleasure of working with pure I4GL,
but we never took the result of a possible NULL for granted. If the
possibility for a NULL value exists, I would suggest you check specifically
for NULL. In any case, I'll be interested to see if you get other responses
to this.
Thank you for advice.
R.A. Reissaus
2005-10-26 14:07:15 UTC
Permalink
You must of course realize that the number 0 is NOT equal to NULL! NULL is
not a value but a state (more or less saying 'I am not yet defined'). So it
is entirely possible that when equating to the number zero yu get different
result especialy when comparing to TRUE or FALSE wich or equally NOT the
same as NULL. True and False are constant with the respective value of the
numbers 1 and zero.



------------------------------------------------------------------------
R.A. Reissaus
Risdi, Amsterdam, the Netherlands
Ibm/Informix Consultants
Telefoon: +31(0)20 6331140 : Phone
Mobiel : +31(0)6 51185352 : Mobile
E-mail : ***@risdi.com
Website : www.risdi.com
------------------------------------------------------------------------
Disclaimer:
`Externe E-Mail wordt door partijen niet gebruikt voor het aangaan van
verplichtingen`

`Any e-mail messages from sending parties named in this e-mail are given
in good faith but shall not be binding nor shall they be construed as
constituting any obligation on the part of any such party.`
------------------------------------------------------------------------
-----Oorspronkelijk bericht-----
Verzonden: woensdag 26 oktober 2005 14:28
Onderwerp: 4GL compares NULL differently
4GL 7.32.UC2
Solaris 2.6
4GL must compare NULL to any not-NULL value as FALSE.
And it acts this way... sometimes.
DEFINE m_inv_amt DECIMAL(12,2)
FUNCTION AmtUsed()
IF m_inv_amt != 0 THEN
RETURN true
ELSE
RETURN false
END IF
END FUNCTION
<<<<<<<<<<<<<<<<<<
When m_inv_amt is NULL, AmtUsed() returns FALSE at one
moment, and TRUE at another. And the FALSE/TRUE sequence
doesn't change from run to run.
Is it a known bug or a new feature?
sending to informix-list
Obnoxio The Clown
2005-10-26 15:58:13 UTC
Permalink
Post by Denis Melnikov
4GL 7.32.UC2
Solaris 2.6
4GL must compare NULL to any not-NULL value as FALSE.
Oh? I always thought you had to explicitly check for nulls.
Post by Denis Melnikov
And it acts this way... sometimes.
DEFINE m_inv_amt DECIMAL(12,2)
FUNCTION AmtUsed()
IF m_inv_amt != 0 THEN
RETURN true
ELSE
RETURN false
END IF
END FUNCTION
<<<<<<<<<<<<<<<<<<
When m_inv_amt is NULL, AmtUsed() returns FALSE at one moment,
and TRUE at another. And the FALSE/TRUE sequence doesn't
change from run to run.
Is it a known bug or a new feature?
--
Bye now,
Obnoxio

"C'est pas parce qu'on n'a rien ` dire qu'il faut fermer sa gueule"
- Coluche

"You are an index and a prologue to the history of lust and foul thoughts."
- William Shakespeare
sending to informix-list
m***@aol.com
2005-10-26 17:59:50 UTC
Permalink
This has been a know issue with decision statements in 4gl as far as I
can remember back in to the early 90's.
If the variable has any possibility of being null then it should be
checked as part of the condition first:

IF m_inv_amt is NULL or m_inv_amt != 0 then
RETURN true
ELSE
RETURN false
END IF

unless you want it the other way then
IF m_inv_amt is NOT NULL and m_inv_amt != 0 then
RETURN true
ELSE
RETURN false
END IF
Post by Denis Melnikov
DEFINE m_inv_amt DECIMAL(12,2)
FUNCTION AmtUsed()
IF m_inv_amt != 0 THEN
RETURN true
ELSE
RETURN false
END IF
END FUNCTION
sending to informix-list
Jonathan Leffler
2005-10-27 03:55:20 UTC
Permalink
Post by Denis Melnikov
4GL 7.32.UC2
Solaris 2.6
4GL must compare NULL to any not-NULL value as FALSE.
No. Except in the context of IS [NOT] NULL, NULL compared with anything,
including another null, is unknown. Since unknown is not TRUE, the IF
condition fails and the ELSE clause is taken.

And it acts this way... sometimes.
Post by Denis Melnikov
DEFINE m_inv_amt DECIMAL(12,2)
FUNCTION AmtUsed()
IF m_inv_amt != 0 THEN
RETURN true
ELSE
RETURN false
END IF
END FUNCTION
<<<<<<<<<<<<<<<<<<
When m_inv_amt is NULL, AmtUsed() returns FALSE at one moment,
and TRUE at another. And the FALSE/TRUE sequence doesn't
change from run to run.
The function should always return FALSE when given NULL as an argument. The
condition compares NULL with something, which is unknown, and unknown is not
true, so the ELSE clause should *always* be chosen when the argument is
NULL.

If you can demonstrate that iteratively calling the function with a NULL
does indeed sometimes return true and sometimes returns false, then you have
a bug. I have my doubts about that - but if you can demonstrate the problem,
you have found a bug.

Is it a known bug or a new feature?
Now, I notice that in fact you are not passing m_inv_amt as an argument; it
is a global variable. All of a sudden, there are other mechanisms available
for producing indeterminate behaviour. Basically, anything that could be
modifying the global variable could be triggering the problem. And
'anything' could include accidental buffer overflows in some shape or form.
How do you know that m_inv_amt is always NULL before calling the function?

This is a case where there is precious little obvious advantage to using a
global and some obvious advantages to using a parameter.

To instrument, add an simple IF statement to the function:

IF m_inv_amt IS NULL THEN DISPLAY "m_inv_amt IS NULL" ELSE DISPLAY
"m_inv_amt IS NOT NULL" END IF

Or, if you have an error log open, log the message to the log.

Also track the return values - probably by modifying the main IF clause.

Keep track of whether there are any cases where minv_amt is null and you get
a true return from the function. In all honesty, I don't expect you to find
any, but show the demo code and the log and we can see what it takes to
reproduce it.

--
Jonathan Leffler #include <disclaimer.h>
Email: ***@earthlink.net, ***@us.ibm.com
Guardian of DBD::Informix v2005.02 -- http://dbi.perl.org/
sending to informix-list
Denis Melnikov
2005-10-27 13:21:38 UTC
Permalink
Post by Jonathan Leffler
Post by Denis Melnikov
DEFINE m_inv_amt DECIMAL(12,2)
FUNCTION AmtUsed()
IF m_inv_amt != 0 THEN
RETURN true
ELSE
RETURN false
END IF
END FUNCTION
<<<<<<<<<<<<<<<<<<
When m_inv_amt is NULL, AmtUsed() returns FALSE at one moment,
and TRUE at another. And the FALSE/TRUE sequence doesn't
change from run to run.
If you can demonstrate that iteratively calling the function with a NULL
does indeed sometimes return true and sometimes returns false, then you have
a bug. I have my doubts about that - but if you can demonstrate the problem,
you have found a bug.
Yes, we inserted check for NULL before the first IF. It always
DISPLAYed "NULL!" when m_inv_amt was NULL but AmtUsed() returned
TRUE/FALSE discordantly.

Thank you.
Jonathan Leffler
2005-10-28 03:51:11 UTC
Permalink
Post by Denis Melnikov
Post by Jonathan Leffler
Post by Denis Melnikov
DEFINE m_inv_amt DECIMAL(12,2)
FUNCTION AmtUsed()
IF m_inv_amt != 0 THEN
RETURN true
ELSE
RETURN false
END IF
END FUNCTION
<<<<<<<<<<<<<<<<<<
When m_inv_amt is NULL, AmtUsed() returns FALSE at one moment,
and TRUE at another. And the FALSE/TRUE sequence doesn't
change from run to run.
If you can demonstrate that iteratively calling the function with a NULL
does indeed sometimes return true and sometimes returns false, then you have
a bug. I have my doubts about that - but if you can demonstrate the problem,
you have found a bug.
Yes, we inserted check for NULL before the first IF. It always
DISPLAYed "NULL!" when m_inv_amt was NULL but AmtUsed() returned
TRUE/FALSE discordantly.
Please show some demo code that demonstrates this behaviour on your
machine. In the absence of a reproduction, I find the claim implausible.

Can you do it in 30 lines (apart from debugging code)? Why not? What
does it take to get to a point where you can demonstrate the problem?
In what context do you use the result - or how do you know it returns
TRUE sometimes and FALSE others?
--
Jonathan Leffler #include <disclaimer.h>
Email: ***@earthlink.net, ***@us.ibm.com
Guardian of DBD::Informix v2005.02 -- http://dbi.perl.org/
Denis Melnikov
2005-10-28 13:51:08 UTC
Permalink
Post by Jonathan Leffler
Please show some demo code that demonstrates this behaviour on your
machine. In the absence of a reproduction, I find the claim implausible.
Unfortunately we couldn't reproduce the behavior with a short code.
In small sandbox it behaves as documented.
Post by Jonathan Leffler
Can you do it in 30 lines (apart from debugging code)? Why not? What
does it take to get to a point where you can demonstrate the problem?
In what context do you use the result - or how do you know it returns
TRUE sometimes and FALSE others?
--
Jonathan Leffler #include <disclaimer.h>
Guardian of DBD::Informix v2005.02 -- http://dbi.perl.org/
Walt Hultgren
2005-10-28 02:52:57 UTC
Permalink
Post by Jonathan Leffler
Post by Denis Melnikov
4GL 7.32.UC2
Solaris 2.6
4GL must compare NULL to any not-NULL value as FALSE.
No. Except in the context of IS [NOT] NULL, NULL compared with anything,
including another null, is unknown. Since unknown is not TRUE, the IF
condition fails and the ELSE clause is taken.
I've often found it expedient to use the construct:

if ( <logical expression(s)> )
then
else
<executable code>
end if

to help filter out NULL considerations. That is, there is no "then"
section of code. Does anyone know of a reason why this approach might be
deprecated?

Walt.
Fernando Nunes
2005-10-27 13:57:30 UTC
Permalink
Post by Denis Melnikov
4GL 7.32.UC2
Solaris 2.6
4GL must compare NULL to any not-NULL value as FALSE.
And it acts this way... sometimes.
DEFINE m_inv_amt DECIMAL(12,2)
FUNCTION AmtUsed()
IF m_inv_amt != 0 THEN
RETURN true
ELSE
RETURN false
END IF
END FUNCTION
<<<<<<<<<<<<<<<<<<
When m_inv_amt is NULL, AmtUsed() returns FALSE at one moment,
and TRUE at another. And the FALSE/TRUE sequence doesn't
change from run to run.
Is it a known bug or a new feature?
Look at Jonathan Leffler answer. Also bare in mind that in compiled 4GL
the variables AFAIK aren't guaranteed to be null before initialization...

I recall hitting a bug with some IF statements and null values but it
had to do with datetime values.

Regards.
scottishpoet
2005-10-27 19:11:40 UTC
Permalink
have you contacted your support provider?

I think there may have been a fix made for this fairly recently.
Fernando Nunes
2005-10-28 10:24:47 UTC
Permalink
Post by scottishpoet
have you contacted your support provider?
I think there may have been a fix made for this fairly recently.
Yes... :)
I'm my "support provider", and yes the fine people from R&D fixed it and
I received it :)

Regards.
scottishpoet
2005-10-28 14:53:26 UTC
Permalink
sorry fernando, my response was to the original poster

there have been some bugs reported in this area over the last few
months in both 7.32.xC2 and 7.32.xC3 and these have recently been
resolved .
scottishpoet
2005-10-28 14:56:00 UTC
Permalink
in fact there is a recent article on the IBM knowledge base

http://www-1.ibm.com/support/docview.wss?rs=681&context=SSVT2J&context=SSCVRDE&context=SSCVRDD&context=SSCVRDJ&context=SSCVRDM&dc=DB520&dc=D600&dc=DB530&dc=D700&dc=DB500&dc=DB540&dc=DB510&dc=DB550&q1=4GL+NULL&uid=swg21218388&loc=en_US&cs=utf-8&lang=en
Dirk Moolman
2005-10-27 07:27:41 UTC
Permalink
We had a similar discussion in the office very recently. I told the
guys not to asume anything about variables, but to be very precise /
specific - to always initialise variables before working with them, and
I think this is a general programming rule in other languages as well.

In our case they were working with variables they did not always
initialise, and got inconsistent results back.
I also remember from my programming days that NULL values were not
consistent. I agree with testing for NULLS specifically and treating
them as just that.

Dirk


-----Original Message-----
From: owner-informix-***@iiug.org [mailto:owner-informix-***@iiug.org]
On Behalf Of Clive Eisen
Sent: 26 October 2005 02:40 PM
To: informix-***@iiug.org
Subject: Re: 4GL compares NULL differently
Post by Denis Melnikov
P.S. 4GL C compiler.
Because any equality or inequality test against null is specifically
undefined

You have to test 'is null'ness before applying your !=0 or whatever
tests

--
Clive
sending to informix-list
Dirk Moolman
2005-10-27 07:27:23 UTC
Permalink
-----Original Message-----
From: owner-informix-***@iiug.org [mailto:owner-informix-***@iiug.org]
On Behalf Of Obnoxio The Clown
Sent: 26 October 2005 05:58 PM
To: Denis Melnikov
Cc: informix-***@iiug.org
Subject: Re: 4GL compares NULL differently
Post by Denis Melnikov
4GL 7.32.UC2
Solaris 2.6
4GL must compare NULL to any not-NULL value as FALSE.
Oh? I always thought you had to explicitly check for nulls.
This is the way I understand it as well ...
sending to informix-list
Jonathan Leffler
2005-10-30 05:30:17 UTC
Permalink
Post by Denis Melnikov
Post by Jonathan Leffler
Please show some demo code that demonstrates this behaviour on your
machine. In the absence of a reproduction, I find the claim implausible.
Unfortunately we couldn't reproduce the behavior with a short code.
In small sandbox it behaves as documented.
Dear Denis,

Given the URL quoted by our Scottish Poet:

http://www-1.ibm.com/support/docview.wss?rs=681&context=SSVT2J&context=SSCVRDE&context=SSCVRDD&context=SSCVRDJ&context=SSCVRDM&dc=DB520&dc=D600&dc=DB530&dc=D700&dc=DB500&dc=DB540&dc=DB510&dc=DB550&q1=4GL+NULL&uid=swg21218388&loc=en_US&cs=utf-8&lang=en

aka: *http://tinyurl.com/dsq86

*which acknowledges a bug in this area, I withdraw my scepticism. (I have
bones to pick with the wording of the referenced document, but that's one
other story; I am also moderately amazed that people managed to break this
behaviour in I4GL, that that's a second other story.)

--
Jonathan Leffler #include <disclaimer.h>
Email: ***@earthlink.net, ***@us.ibm.com
Guardian of DBD::Informix v2005.02 -- http://dbi.perl.org/
sending to informix-list

Loading...