Programming Question, Find First, VS. For First...

tbaxter11

New Member
Hi All!....
I’m an old time Progress programmer who got out of the programming
world for a few years, but now I’m back… my question is code
performance-specific… I recall reading somewhere (Possibly in one of
John Campbell’s publications) that a

for first record. end.

is more efficient than a

find first record.

I’ve proven it with enhanced program speed, but… I don’t recall the
explanation of the mechanics which make the “for first” statement
faster than the “find first”… could some kind soul out there jog this
old man’s memory about the “inner workings” of this statement vs. the
find statement? (they both used the same "where" criteria AND the
same index, but with substantial and noticeable performance
differences.) Thank-you, Terry Baxter tbaxter999@gmail.com
 

Cringer

ProgressTalk.com Moderator
Staff member
I'm not sure of the ins and outs, but a FOR FIRST is able to use multiple indexes, whereas FIND FIRST just uses on index. Also, best practise is not to use FIND FIRST at all unless you are 100% certain you will only ever get back one record, rather use FIND on its own and check for ambiguity.
 

RealHeavyDude

Well-Known Member
The FIND is designed to retrieve a unique record so there is no sense in using FIRST. When using FIRST it will happily retrieve the record even when the find is not unique and chances are that you will encounter silent database corruption.

Probably the only reason why the FIRST, NEXT, PREV, LAST option on FIND exists is UI related. In V6 ChUI you would use these to scroll to a down frame. But, IMHO, that is the only legitimate use case and of course, since Progress introduced the browse widget probably not recommended anymore too.

Regarding performance: You might gain a better performance from a FOR FIRST or query because the compiler might pick multiple indexes to solve it. But that only happens in clearly defined scenarios where the WHERE clause and the indexes must be designed accordingly. Other than that I don't see a point why they should be faster when you retrieve exactly one record.

Heavy Regards, RealHeavyDude.
 

TomBascom

Curmudgeon
Several things spring to mind:

1) FOR FIRST misbehaves. The "firstness" is not necessarily what you might expect. Details elude me at this ungodly hour. But the sort ordering does not work the way you probably think that it does.

2) if you are seeing a performance benefit from either of these constructs your indexes are not properly supporting you.

3) If you get a unique record with FIRST you are misleading the maintenance programmer into thinking that there is a set of records.

4) If the record is non-unique and you are not initiating a loop then you are violating third normal form by making that FIRST record special. And you are setting yourself up for some extremely difficult to find and repair bugs.
 

GregTomkins

Active Member
I don't use this myself, but I see this idiom a lot, for the case where a record may just as likely exist as not:

Code:
FOR FIRST some_table:
    some_table.some_field = "X".
END.

Which is arguably a bit neater than:

Code:
FIND FIRST some_table NO-ERROR.

IF AVAIL some_table
THEN some_table.some_field = "X".

I don't share Tom's distaste for FIND FIRST. It's probably not best practice, but really, with all due respect, if ambiguous records cause 'extremely' difficult bugs ... well, I wish my 'extremely' difficult bugs were that simple!
 

TomBascom

Curmudgeon
The problem is that you don't know that you have the bug until you start believing end user's tall tales of strange behavior. And then you have no idea what you're looking for.
 

TomBascom

Curmudgeon
I don't use this myself, but I see this idiom a lot, for the case where a record may just as likely exist as not:

Code:
FOR FIRST some_table:
    some_table.some_field = "X".
END.

Get yourself a copy of sports2000. Then try this:
Code:
for each customer no-lock by discount:
  display custNum name discount.
end.

Take note of the "first" customer.

Now try this:
Code:
for first customer no-lock by discount:
  display custNum name discount.
end.

And lastly:

Code:
for first customer no-lock break by discount:
  display custNum name discount.
end.

Do you still think that FOR FIRST is a good way to get a meaningful "first" record?
 

TomBascom

Curmudgeon
BTW -- if you were working in a shop where a mix of FIND FIRST and the different FOR FIRST styles is used you might see why I say that unfettered plastering of "FIRST" across your code leads to bugs.
 

GregTomkins

Active Member
I'm not going to spend too much time defending something I don't actually do myself. But where I have seen it used, it is always where there is no doubt as to the uniqueness of the record. For example, 'FIND FIRST state WHERE state_code = 'NY''. I can see a minor benefit of decluttered code, but I suppose at the expense that maybe someday some lunatic will define two New Yorks.

Incidentally <irrelevant tangent alert> my sense of debug difficulty has been redefined by doing JavaScript for the past few months. There, you have functions creating functions that create still more functions that call functions in the first function to generate yet another function, ad infinitum (and don't get me started about CSS). When I get to go back to Progress, it's like, 'Wow!, this is so simple!', and I could likely diagnose a misbegotten FIND FIRST in about 2 seconds.

Thanks for the comments, cheers!
 

TomBascom

Curmudgeon
IMHO there was no doubt that NY was unique until I saw the word FIRST. Then I had to wonder... could there be another? If there are 2 could there be 200? Just how many NYs are there in this State table? What's going on here?

If it is unique you should NOT be saying FIRST.

I had some fun with JS this week too ;)
 
Top