Options

Strange behaviour of ISEMPTY

AleSlammerAleSlammer Member Posts: 25
Hi All.

Today I have experienced something "funny" about ISEMPTY. When using ISEMPTY it initializes an empty record set for a record variable which was not initialized before. So if you have no filters on the record variable, then it will be considered a not empty if you do an ISEMPTY on it right after. The following code with my comments will show what I experienced. l_RoundingJobBudgetJnlLine is a variable of job budget journal line record:
IF l_RoundingJobBudgetJnlLine.ISEMPTY THEN //Here it is empty, but it initializes an empty record set
l_OriginalLCYAmt := l_RoundingGLBudgetEntry.Amount
ELSE
l_OriginalLCYAmt := l_RoundingJobBudgetJnlLine."Total Cost (LCY)";

IF l_RoundingAmount <> 0 THEN BEGIN
l_RoundLine := TRUE;
IF l_RoundingAmount < 0 THEN BEGIN
  IF l_RoundingJobBudgetJnlLine.ISEMPTY THEN
	l_RoundingGLBudgetEntry.VALIDATE(Amount,l_RoundingGLBudgetEntry.Amount - l_RoundingAmount)
  ELSE
	l_RoundingJobBudgetJnlLine.VALIDATE("Total Cost",l_RoundingJobBudgetJnlLine."Total Cost" - l_RoundingAmount);
END ELSE BEGIN
  IF l_RoundingJobBudgetJnlLine.ISEMPTY THEN //here it is not empty, because it was initialized, and there is no filters set on the record
	l_RoundingGLBudgetEntry.VALIDATE(Amount,l_RoundingGLBudgetEntry.Amount + l_RoundingAmount)
  ELSE
	l_RoundingJobBudgetJnlLine.VALIDATE("Total Cost",l_RoundingJobBudgetJnlLine."Total Cost" + l_RoundingAmount);
END;


Is there any reason for this ?? In my opinion the behaviour is not optimal. I can work around it (I guess I have to anyway), but still can't let it go.

Comments

  • Options
    DenSterDenSter Member Posts: 8,304
    That's not because of strange behavior, you are using ISEMPTY in a completely wrong way. ISEMPTY returns a boolean whether the record set is empty or not. It does not actually retrieve a record. Why are you using it so many times? What's the purpose? What are you trying to do? explain what you mean to do with all those ISEMPTY statements in normal English.

    If you need to retrieve a record, you would use FINDFIRST or FINDLAST. If you need to loop through a recordset, you use FINDSET.
  • Options
    AleSlammerAleSlammer Member Posts: 25
    Hi Denster and thanks for answering. I am not using it to retrieve any records, I know what ISEMPTY is for. I am using it to find out out whether the job budget journal line variable is initialized. If it is, then I have to work with it, if not, then I will do something else. I know about FINDSET is used for looping through records etc.
    My concern is that After using ISEMPTY on an uninitialized variable, then right after (try this yourself with the debugger), then the variable is initialized, and if no filters are set on the record, then if you use ISEMPTY again, it will consider it as not empty. I don't see why it is a good idea that the system initializes an empty recordset when using ISEMPTY.

    I could code it in another way, and I have, but I was just wondering WHY it does it in that way. It does not make sense that ISEMPTY have a different outcome if you use it severel times in the same coding block, without modifying anything in the variable
  • Options
    krikikriki Member, Moderator Posts: 9,098
    Maybe "l_RoundingJobBudgetJnlLine.VALIDATE" removes the filters you put on it. That would explain the recordset is not empty anymore.

    PS: You should save the first ISEMPTY in a boolean field to avoid to do the ISEMPTY again. Why bother SQL server twice if you can do it only once. Performance will gain a little.
    Regards,Alain Krikilion
    No PM,please use the forum. || May the <SOLVED>-attribute be in your title!


  • Options
    AleSlammerAleSlammer Member Posts: 25
    Hi kriki, and thanks for answering.
    Maybe "l_RoundingJobBudgetJnlLine.VALIDATE" removes the filters you put on it. That would explain the recordset is not empty anymore.

    There wasn't any filters set, that was my point. The code above is when no filters are set. The variable has a value, IF i transfer values to it, under some given circumstances. The thing is that ISEMPTY valuates the record variable correct the first time as being empty. But since it initializes an empty record set, and since no filters are applied to the record variable, then if you do another ISEMPTY, then it will validate the record variable as not being empty, even though you haven't written any code o modify anything, or removing or adding filters to the record variable. It is quite strange
    PS: You should save the first ISEMPTY in a boolean field to avoid to do the ISEMPTY again. Why bother SQL server twice if you can do it only once. Performance will gain a little.

    yes, I have modified the code, to something similar to what you have suggested, but I am still scratching my head on WHY ISEMPTY initializes an empty record set of the variable. I really don't see any reason for this. And the documentation of ISEMPTY doesn't say anything about it.
  • Options
    DenSterDenSter Member Posts: 8,304
    You are clearly showing that you do NOT know what ISEMPTY is for, because you are using it to initialize a record. One more time: ISEMPTY is used to determine whether records exist or not, given the filters on the record variable, and that's it. Just don't use it to determine whether record variables are initialized, it doesn't work the way you are thinking because that is not what it is meant to be used for. Your repeated use of ISEMPTY in that code snippet makes absolutely no sense.

    If you want to initialize a record, you use the INIT command. In this case maybe something like:
    IF l_RoundingJobBudgetJnlLine.ISEMPTY THEN
      l_RoundingJobBudgetJnlLine.INIT;
    

    At this point, you have an initialized record, with all of the field values set to their initial value. If the l_RoundingJobBudgetJnlLine variable was used before, you will also need to clear (or set) the primary key values, because INIT does not reset those.

    But clearly, you want to do something with the record when it is not empty, so in your case, FINDFIRST is probably a better choice. Then again, we don't know the requirement behind your code, so it's just a guessing game for us.
  • Options
    AleSlammerAleSlammer Member Posts: 25
    Denster <--- I don't wan't to initialize the record, and I am not using ISEMPTY to initialize a record. I know that INIT should be used if that was what I would wan't. I am saying that ISEMPTY does initialize the record variable automatically with an empty recordset, which I think is not optimal, if you do an ISEMPTY later on the same variable (if there are no filters set). The outcome will be different the second time, which I think it shouldn't be. The outcome should be the same if you do the ISEMPTY command again.


    I will agreee on one thing though, and that is that it shouldn't be nescessary to use ISEMPTY twice in a row, without altering filters or anything else(thats is ineffective and stupid, I agree on that). I have stored the outcome of ISEMPTY in a boolean for later use. But this is not about what is smart or not, or some kind of code review. This is about ISEMPTY has an unexpected bi product, and returns different results when used twice in a row, when no filters are applied. THAT'S IT!! I don't see why the ISEMPTY should have that behaviour. Could we just focus on that ??
  • Options
    DenSterDenSter Member Posts: 8,304
    I'll give you one thing and that is that it is indeed confusing to see two different results for the same keyword. However, you are doing things with it that are not supposed to be done with it. If you would not do those things, you would not have the issue.

    Apparently you don't want to talk about the validity of your code though (and there are a number of other problems with your code) so I'll leave it at that. Suffice to say that if you would write proper code, you would not have any problem with the keyword.
  • Options
    reijermolenaarreijermolenaar Member Posts: 256
    Are you really saying that you get two different messages when you execute the following code? :shock:
    IF l_RoundingJobBudgetJnlLine.ISEMPTY THEN
      MESSAGE('Is empty')
    ELSE
      MESSAGE('Is not empty');
    
    IF l_RoundingJobBudgetJnlLine.ISEMPTY THEN
      MESSAGE('Is empty')
    ELSE
      MESSAGE('Is not empty');
    
    Reijer Molenaar
    Object Manager
  • Options
    AleSlammerAleSlammer Member Posts: 25
    I'll give you one thing and that is that it is indeed confusing to see two different results for the same keyword. However, you are doing things with it that are not supposed to be done with it. If you would not do those things, you would not have the issue.

    Apparently you don't want to talk about the validity of your code though (and there are a number of other problems with your code) so I'll leave it at that. Suffice to say that if you would write proper code, you would not have any problem with the keyword.

    I agree on the code I posted is not the best way to fo things, but still scratching head about why the command has that strange bi product and thought maybe somebody know about why it has this behaviour. The code in the first post is not the code that I have been using for the final solution but I accidently found out the strange behaviour and made the code example, which is tested in reality.
    Are you really saying that you get two different messages when you execute the following code?

    I haven't tried coding it exactly like your example, but yes i guess it should provide different outputs, IF you haven't filtered the record variable first. If you have applied filters, it would provide the same result (unless you have changed the filters between each use of ISEMPTY). I showed the execution of the code to 2 other programmers at work, using the debugger, where it clearly initialized the record variable, with an empty record set, when running the ISEMPTY command, and at the next ISEMPTY command, the variable wasn't empty.When I applied some lame filter like SETRANGE on Line No. with some odd linenumber, the second ISEMPTY command also evaluated the record variable as being empty because filters were applied. I know it is an odd example since ISEMPTY normally is used with filtering.
  • Options
    kinekine Member Posts: 12,562
    Still, I do not understand what do you mean with
    where it clearly initialized the record variable, with an empty record set, when running the ISEMPTY command, and at the next ISEMPTY command, the variable wasn't empty

    What do you mean with "it initialized the record variable with an empty record set"? ISEMPTY return only true or false, if there is some record found inside the filters or not. INTERNAL STATE of the record is "NONDETERMINATE". It means it could be A or B or anything else (it is same like when you try do NEXT where there is no next record. You cannot be sure that there is still the last record inside the variable, the state is theoretically NONDETERMINATED).

    What do you mean with "the variable wasn't empty"? It means that it found some record and returned true (and the first call returned false, because there was no record inside the filters)? Or do you mean "the fields of the record were set to some values"? Again, the internal state of the record after ISEMPTY is undefined.... Same like "What will be in fields of record, when you do FIND and there is no record?"...

    In C/AL (and Pascal and...) are situations, when the state of some variables will be undefined, e.g. when you have
    for i:=1 to 10 do begin 
    end;
    MESSAGE('%1',i);
    
    What do you think, what will the message display? Everybody will tell you that "10". Yes, but it is not full true, the value is NONDETERMINATED - and it is by definition. In real example, it will be 10, but you cannot count with it.

    May be that it is just misunderstanding because used language, but I just want to show you, that may be you are counting with something, which is not true... (everybody lie :-))
    Kamil Sacek
    MVP - Dynamics NAV
    My BLOG
    NAVERTICA a.s.
  • Options
    rdebathrdebath Member Posts: 383
    Sigh,

    There's nothing wrong or strange about ISEMPTY.

    He's just seeing the internal optimisation in C/AL that means a complex variable (eg a record) isn't given it's initial INIT until the first time it's used. It doesn't effect anything to do with the language and how it works, just what you can see in the debugger.

    As he's talking about 'Record Sets' I imagine he doesn't have any idea at all how NAV record variables actually work.
Sign In or Register to comment.