Re: 4gl and NULL integers with 7.30.UC1
Posted in 2000
Discussion spun off from a report that c4gl on Alpha generated bad code when assigning NULL to an INTEGER (emitting -2147483648 into a 64-bit int, so the insert failed). Andrew Hamm argued the 4GL language itself is unchanged and the fault is a c4gl code-generation bug, suggesting C compiler flags forcing 32-bit ints, and defended using "" as a NULL shorthand. Ronald Cole countered that "" is a zero-length string, not NULL, and that one should use INITIALIZE ... TO NULL and IS NULL tests; side debate followed on CLIPPED, LENGTH() and trailing blanks. No confirmed fix for the original compiler bug is recorded.
Auto-generated by DrWatson from the posts below — may be imperfect; read the full thread.
Topics: Connectivity: ESQL/C, 4GL & Embedded SQL, Data Types & Schema Design
John Carlson wrote in message <91t39d$5mm$1@news.xmission.com>... > >What about returning a variable set to null . . . i.e. > >Also, conversely on the function call . . . . > That's a trivially obvious suggestion, but what you've got to ask yourself is... "Do you feel lucky?" No, hang on, that's from a movie; what I mean is, why invent an artifact variable to get around a blatant weakness in the 4GL language? One day some genius is going to assign a value to that variable... More to the point, although it may sound surprising to use "" instead of NULL _when you first hear of it_ but it's one of those really simple things that I'm sure everyone could absorb in 5 seconds and recognize in the blink of an eye without taxing the ol' grey matter further. It's just another little technique. Books about C++ are absolutely LOADED with small and big ideas like that which you are told "mean" something. This one is trivial in comparison - a 1 symbol algorithm. What's more likely in many circumstances is that "another programmer" will ponder for a while what a variable is used for and it will take a while to dawn that it's merely getting around a weakness in 4GL. Until they go through those motions they may not even be aware of that weakness. So what is more appropriate? RETURN "" or the more indirect ritual? I knew a programmer who always declared the following global variables: zero, o, and one and hopefully remembered to initialize them properly at program startup. Why? Why? WHY??? The replies to this thread are quite interesting - I think it highlights the different ways people understand a language - high-level or literally? The fact is, 4GL is _documented_ to support conversion of character to numeric, and vice-versa. NULL is NULL is NULL no matter what data type it is. Consequently using "" in place of NULL is valid code, even though in the occasional place (such as a LET statement) it may be called dubious (and I'm NOT disagreeing with that). What's worse is, I've shown that 4GL has specific weaknesses when it comes to the NULL keyword, thereby sometimes FORCING you to use "". If the NULL keyword was universally accepted by the compilers in all possible places, I would have nothing to say on the subject. I've also shown that assigning "" to a numeric is specifically (and _documented to be_) acceptable in the semantics of the language; you just need to follow a chain of two language fact to understand that, which is far less understanding than it takes to understand prepared cursors for example. This has nothing to do with whether you are using UNIX or Windows compilers. If you read Walter Guertin's message carefully, you can see that it's a specific problem with the C code generated from c4gl. I've just tested 7.30.UC1 RDS and there is no change in the language. Walter is complaining about a bug in c4gl. What PROVES that the c4gl compiler is correctly understanding and automatically performing the conversion to numeric null _at compile time_ is the fact that the underlying C code is generated to perform the equivalent of r_test.code2 = -2147483648; My guess here is that it's generating the declaration of the C variable r_test.code2 to be a 64 bit integer (he's using Alpha) but not applying the same rule to the generation of the NULL representation. Then further down the code for the insert statement is legitimately validating the legality of the insert. After all, in a 64 bit integer, that number up there is just a little number compared to the biggest possible 64 bitters. The null representation for 64 bit must be much larger, but c4gl isn't generating it properly. Walter: I suggest you go looking to insert a C compiler flag somewhere (direct into c4gl or using some of the shell variables no doubt supported by the C compiler) to cause it to assume that C int are 32 bit instead of 64 bit. I spent 1/2 an hour messing with the Alpha compiler once, and vaguely remember the existence of a large set of flags to control all these options. Unfortunately I can't get back to that box, so I can't tell you the specific flags we used that you could try. I've been involved in the periphery of a development team using c4gl, and we've had to deal with several odd bugs in C/4GL over the years. It just seems to be a beast. NewEra was even worse. Sometimes Informix let a few bugs slip thru the tools. Damn.
"Andrew Hamm" <ahamm@sanderson.net.au> writes: > NULL is NULL is NULL no matter what data type it is. > Consequently using "" in place of NULL is valid code, even though in the > occasional place (such as a LET statement) it may be called dubious (and I'm > NOT disagreeing with that). Dubious? 4gl is broken here. "" is a zero length string. A zero length string is not null. SQL knows the difference. Use "initialize foo to null" and test "if foo is null" before accessing the value and you will *never* screw the pooch. > What's worse is, I've shown that 4GL has specific weaknesses when it comes > to the NULL keyword, thereby sometimes FORCING you to use "". 4gl lets you get away with a lot of sloppy programming, but it never FORCES you to be a sloppy programmer. -- Forte International, P.O. Box 1412, Ridgecrest, CA 93556-1412 Ronald Cole <ronald@forte-intl.com> Phone: (760) 499-9142 President, CEO Fax: (760) 499-9152 My GPG fingerprint: C3AF 4BE9 BEA6 F1C2 B084 4A88 8851 E6C8 69E3 B00B
Ronald Cole wrote in message ... >"Andrew Hamm" <ahamm@sanderson.net.au> writes: >> NULL is NULL is NULL no matter what data type it is. >> Consequently using "" in place of NULL is valid code, even though in the >> occasional place (such as a LET statement) it may be called dubious (and I'm >> NOT disagreeing with that). > >Dubious? 4gl is broken here. "" is a zero length string. A zero >length string is not null. SQL knows the difference. Use "initialize >foo to null" and test "if foo is null" before accessing the value and >you will *never* screw the pooch. > I'll agree that "" SHOULD be a zero length string as distinct from NULL, but that is not the semantics of 4GL so in reality you are wrong because "" is NULL in the world of 4GL. I will agree with you that this design of the language is sloppy. By the way, where was I suggesting that null tests were an issue? Let me stir the pot a bit more with this suggestion for you to ponder: if length(str) > 0 then ....... >4gl lets you get away with a lot of sloppy programming, but it never >FORCES you to be a sloppy programmer. > Thanks for the programming lesson. I'll take that on board. But do you think that the only difference between a good program and a bad program is whether or not you use workarounds for some shitty design corners of 4GL? I think not. Where is the room for agressive criticism of my imagined programming styles based on some observations I've made about the weaknesses of 4GL, the true semantics of 4GL AS IT IS IMPLEMENTED instead of HOW WE WISH IT TO BE, and a few suggestions about workarounds for those slightly flawed features of 4GL? Further, Walter Guertin needs to know that he's not going crazy, the definition of 4GL has not changed, and it is definitely a bug in the c4gl he is attempting to use. That is the reason for my contribution. Cheers, and Merry Christmas.
"Andrew Hamm" <ahamm@sanderson.net.au> writes: > I'll agree that "" SHOULD be a zero length string as distinct from NULL, but > that is not the semantics of 4GL so in reality you are wrong because "" is > NULL in the world of 4GL. Show me a page number in an Informix manual where it says so. > I will agree with you that this design of the > language is sloppy. By the way, where was I suggesting that null tests were > an issue? Let me stir the pot a bit more with this suggestion for you to > ponder: > > if length(str) > 0 then > ....... > > Thanks for the programming lesson. I'll take that on board. But do you think > that the only difference between a good program and a bad program is whether > or not you use workarounds for some shitty design corners of 4GL? I think > not. Where is the room for agressive criticism of my imagined programming > styles based on some observations I've made about the weaknesses of 4GL, the > true semantics of 4GL AS IT IS IMPLEMENTED instead of HOW WE WISH IT TO BE, > and a few suggestions about workarounds for those slightly flawed features > of 4GL? Further, Walter Guertin needs to know that he's not going crazy, the > definition of 4GL has not changed, and it is definitely a bug in the c4gl he > is attempting to use. That is the reason for my contribution. And if "let str = -32768" set str to null, then I wouldn't use it in my code, either!! I already said that I consider 4gl to be broken here, and I'll explain why in more detail here. Consider this: main define s char(10) initialize s to null call fubar(s) # I expect null string let s = "" call fubar(s) # I expect non-null, 0-length string let s = " " call fubar(s) # I expect non-null, 0-length string let s = "X" call fubar(s) # I expect non-null, 1-length string let s = "X " call fubar(s) # I expect non-null, 1-length string end main function fubar(s) define s char(10), l smallint if s is null then display "s is null" else let l = length(s) display "s is not null, length(s) =", l end if end function Knowing full well that Informix always removes trailing blanks from a string, as a programmer, I expect "" and " " to be the same entity: a zero-length string (just as I would expect "X" and "X " to be the same entity). I consider it sloppy programming to rely on 4gl's brokenness to write let s = "" when one intents to initialize s to null for the simple reason that 4gl lets you get away with it. As my "workround", I've always used " " when I intend a zero-length string for comparison or assignment and the initialize statement for null setting. I've *never* been bit for doing so. I'll posit that if Walter had been using my "workarounds" in the first place, he never would have had cause to post in the first place. Informix will probably never fix this for legacy reasons, but that's no reason to perpetuate "" being interpreted as null in one's own code (and as an added bonus, if Informix *does* fix it, you won't have to change your code: yet another reason not to perpetuate the ""-is-null myth)! And that is the reason for me tossing in *my* two-cents. Have a happy New Year! -- Forte International, P.O. Box 1412, Ridgecrest, CA 93556-1412 Ronald Cole <ronald@forte-intl.com> Phone: (760) 499-9142 President, CEO Fax: (760) 499-9152 My GPG fingerprint: C3AF 4BE9 BEA6 F1C2 B084 4A88 8851 E6C8 69E3 B00B
In article <m3d7ee3ekg.fsf@yakisoba.forte-intl.com>, Ronald Cole <ronald@forte-intl.com> writes >Knowing full well that Informix always removes trailing blanks from a >string, as a programmer, I expect "" and " " to be the same entity: a Then what is clipped for? To check for an 'empty string use' if (x is null) or (( length(x CLIPPED)) = 0) then true else false end if >Informix will probably never fix this for legacy reasons, but that's >no reason to perpetuate "" being interpreted as null in one's own code >(and as an added bonus, if Informix *does* fix it, you won't have to >change your code: yet another reason not to perpetuate the ""-is-null >myth)! > True! >And that is the reason for me tossing in *my* two-cents. > >Have a happy New Year! > -- David Williams
David Williams <djw@smooth1.demon.co.uk> writes: > Then what is clipped for? > > To check for an 'empty string use' > > if (x is null) or (( length(x CLIPPED)) = 0) then > true > else > false > end if " " != "" is good enough reason for me to avoid using "" for empty string in 4gl and SQL. "CLIPPED" is an operator that is really only needed for string catenation and display/print (because they behave unexpectedly, but consistently, too, probably to make output alignment "easier"). Remove the keyword "CLIPPED" from your code above and you'll see that it's superfluous. Look at my example again in my last post. -- Forte International, P.O. Box 1412, Ridgecrest, CA 93556-1412 Ronald Cole <ronald@forte-intl.com> Phone: (760) 499-9142 President, CEO Fax: (760) 499-9152 My GPG fingerprint: C3AF 4BE9 BEA6 F1C2 B084 4A88 8851 E6C8 69E3 B00B
If I remember correctly there is an implied "CLIPPED" with the LENGTH() function. That is, the length is totaled with trailing spaces ignored. Joe Ronald Cole wrote: > David Williams <djw@smooth1.demon.co.uk> writes: > > Then what is clipped for? > > > > To check for an 'empty string use' > > > > if (x is null) or (( length(x CLIPPED)) = 0) then > > true > > else > > false > > end if > > " " != "" is good enough reason for me to avoid using "" for empty > string in 4gl and SQL. "CLIPPED" is an operator that is really only > needed for string catenation and display/print (because they behave > unexpectedly, but consistently, too, probably to make output alignment > "easier"). Remove the keyword "CLIPPED" from your code above and > you'll see that it's superfluous. Look at my example again in my last > post. > > -- > Forte International, P.O. Box 1412, Ridgecrest, CA 93556-1412 > Ronald Cole <ronald@forte-intl.com> Phone: (760) 499-9142 > President, CEO Fax: (760) 499-9152 > My GPG fingerprint: C3AF 4BE9 BEA6 F1C2 B084 4A88 8851 E6C8 69E3 B00B
jmobley@sprintmail.com writes: > If I remember correctly there is an implied "CLIPPED" with the > LENGTH() function. That is, the length is totaled with trailing spaces > ignored. Yes, but I would state it this way: trailing spaces are only significant in string catenation and display/print (where CLIPPED is required to remove them): main if "X" = "X " then display "trailing spaces are not significant" else display "trailing spaces are significant" end if end main And to whomever is bi-directional gatewaying this newsgroup to Frank Louvado: May the fleas of a thousand camels infest your armpits!! -- Forte International, P.O. Box 1412, Ridgecrest, CA 93556-1412 Ronald Cole <ronald@forte-intl.com> Phone: (760) 499-9142 President, CEO Fax: (760) 499-9152 My GPG fingerprint: C3AF 4BE9 BEA6 F1C2 B084 4A88 8851 E6C8 69E3 B00B