Release with if avail.

Kalan

Member
Hi all,

I knew the usage of release statement and its limitation. But my query is, do we need to really use if avail <table name> then release <table name> in order to use the release smt.

As of my practical experience release does not require 'if avail smt' and it wont cause any error or warning in compile or run time. But my friend is insisting to use this without any reason. can u pls justify this?
 

tamhas

ProgressTalk.com Sponsor
99 times out of 100, people who advocate using release at all, especially if they advocate it as something to use all the time, don't understand what it does and are deceived about it really does do. 99 times out of 100 or more, it is not needed at all.
 

medu

Member
99 times out of 100 or more, it is not needed at all.
let's make it 100% and forget about it... if you really need to force the write triggers or validate data in the buffer use VALIDATE, really... forget about RELEASE, don't even think about it, it's like a pretty blond lady you think you can never have but in fact it's not “what you see it's what you get” :)
 

oetalker

New Member
find first pt_mstr no-lock no-error.

for first pt_mstr exclusive-lock:
end.

/** at this point record is in buffer
and it is share-locked. So you may
want to release it right here.
**/

release pt_mstr.

pause.
 

tamhas

ProgressTalk.com Sponsor
What is your point? What do you think the release is doing there? Bet you are wrong! :)

The real point is that any such activity should be in a DO FOR pt_mstr or a FOR EACH pt_mstr block to scope the buffer. Properly scope the buffer and you know exactly what has happened to it at the end of the block. No release necessary or useful.
 

RealHeavyDude

Well-Known Member
IMHO they should have never named the statement RELEASE. Something like WRITE-IN-GREAT-HASTE would have been more appropriate ...

You should make yourself familiar with the concept of buffer scope and how you can control it. The release statement does not have any effect on buffer scope.

Heavy Regards, RealHeavyDude.
 

medu

Member
yeah, only if they will at least clear up the documentation... isn't that one simple example of 'best programming practice' (I simply love the 'transaction' comment)?

The following example uses a browse widget to scan Customer records. Records within the browse are read with NO-LOCK. If you choose the Update Customer button, the CHOOSE trigger starts a transaction and applies an EXCLUSIVE-LOCK to the Customer record. When you have completed any updates, the procedure displays the new values in the browse widget and then executes a RELEASE statement. This ensures that the lock is released when the transaction ends.

Code:
ON CHOOSE OF upd-cust DO: /* TRANSACTION */
   FIND Customer WHERE ROWID(Customer) = curr-cust EXCLUSIVE-LOCK.
   UPDATE Customer WITH FRAME cust-frame 
      VIEW-AS DIALOG-BOX  TITLE "Customer Update".  
   
   methRtn = brow-cust:REFRESH().  
   DISPLAY Customer EXCEPT Customer.Comments  
      WITH FRAME curr-frame SIDE-LABELS.  

   RELEASE Customer.
END.
 

RealHeavyDude

Well-Known Member
We all love the documentation Progress provides us with - especially the code snippets, don't we?

But in the end it all comes down to what's IMHO important for every software developer. Maybe one can write some software in simply re-produce what one finds in the documentation. I think that documentation is just a start. Nevertheless it should state that the code snippets are simplified, abstract or whatever when they are. IMHO it is much more important for a successful developer to understand the concepts in order to be able to solve "real" problems.


Heavy Regards, RealHeavyDude.
 

medu

Member
true, but it still should not pollute their minds like that... after all you can't even tell them to rtfm, they eventually will learn it the hard way :(
 

TomBascom

Curmudgeon
find first pt_mstr no-lock no-error.

for first pt_mstr exclusive-lock:
end.

/** at this point record is in buffer
and it is share-locked. So you may
want to release it right here.
**/

release pt_mstr.

pause.

This may be a new record for bad sample code ;)
 

oetalker

New Member
My point was to give an example where release can be used. Ofcourse, release is not required at all if the record scope can be fixed. That part was already said by two of the wizards (99% and 100%).

What’s happening here? Some demo of Power? I see that finally the last wizard comes along and throws his stone. Shame on you. Now go and answer the Interview questions...
 

tamhas

ProgressTalk.com Sponsor
The point is that it is not a good example of where release should be used. I'm not convinced there is any such example. One doesn't make a case for this being a good example of the need for release by not doing the things one should always do to limit scope. There are no examples where record scope can't be limited.
 

medu

Member
My point was to give an example where release can be used. Ofcourse, release is not required at all if the record scope can be fixed. That part was already said by two of the wizards (99% and 100%).

What’s happening here? Some demo of Power? I see that finally the last wizard comes along and throws his stone. Shame on you. Now go and answer the Interview questions...

As far that I know there is only one wizard in the Progress world, but even if there were more I don't trust wizards... in fact those were the last units that i've ever build in warcraft ;)

In a way Tom was correct and I'm sure he did not meant to offend anyone, as you can see we have already a great deal of good programming in documentation itself... mfg/pro is not exactly the best reference either, although I do not know if that piece of code is actually living in there or you just made it as an example.

Bottom line is, there are no wizards nor absolute true... if you think that there is a real legitimate use for RELEASE then we can discuss about it. As about the flame wars that starts from time to time you have to get used with it, when swimming with the sharks you might as well by bitten once in a while :)
 

oetalker

New Member
Keep dreaming Mr. Shark. I hope one day you will realize that you are just a fish... and that is for your own good.
There is more in the world to feel good about than knowing “record scope” and feeling like a shark.. ?;^P
 

medu

Member
Now you're really misinterpreting my words, what I've meant to say is that you really should not take it so personally and that in what Tom said it was nothing that could make you be so defensive but it looks like I'm not doing any good in helping you to relax a bit :)

And regardless of what you think i'm not a shark or any other type of fish, we are all just star dust but you are right about something, there is definitively a lot more in that world than all this ego damage therapy ;)
 

tamhas

ProgressTalk.com Sponsor
To be sure, there is more in the world ... but not understanding and controlling record scope is a sign of very poor ABL programming.
 

TomBascom

Curmudgeon
I wasn't intending to hurt anyone's feelings. I was just bemused to see so many bad practices in such a short bit of code being used to illustrate a way to use something that should probably never be used. Then again, maybe that was the point? Anyhow, I did add a smiley ;) And I'll happily apologize and buy the beer should we ever meet.

Well my mother always does say that if you don't have anything nice to say you shouldn't say anything at all. Once again she is proved right. I really should pay more attention to her.
 

oetalker

New Member
Here is a code that uses optimistic locking strategy. Can you make it work without release statement keeping the same strategy? (This is from ABL Essentials Document. I added a repeat to it)

Code:
/* h-findCurrent.p */
define variable l_cust like customer.custnum.
 
repeat:
  update l_cust.
 
  define frame CustFrame
  Customer.CustNum Customer.Name format "x(12)"
  Customer.CreditLimit Customer.Balance.
 
  /* When the user closes the frame by pressing F2, start a transaction: */
  on "GO" of frame CustFrame 
  do:
    do transaction:
      find current Customer exclusive-lock.
      if current-changed Customer then 
      do:
        message "This record has been changed by another user." skip
        "Please re-enter your changes." view-as alert-box.
        display Customer.CreditLimit Customer.Balance with frame CustFrame.
        return no-apply. /* Cancel the attempted update/GO */
      end.
 
      /* Otherwise assign the changes to the database record. */
      assign Customer.CreditLimit Customer.Balance.
    end.
 
    release Customer.
  end.
 
  /* To start out with, find, display, and enable the record with no lock. */
  find first Customer where custnum = l_cust no-lock.
  display Customer.CustNum Customer.Name Customer.CreditLimit Customer.Balance
  with frame CustFrame.
  enable Customer.CreditLimit Customer.Balance with frame CustFrame.
 
  /* Wait for the trigger condition to do the update and close the frame. */
  wait-for "GO" of frame CustFrame.
end.
 

tamhas

ProgressTalk.com Sponsor
The right answer is not to "make it work", but Don't Do That™ Many examples in the documentation are poor examples to use in real code. They are minimal examples which someone thought would illustrate a point, but since they seem to be written by people that seemingly never wrote a line of production code in their life, they often succeed more in showing off bad programming practice than they do in illustrating the principle. For starters, why would one compile the event-driven constructs of wait-for and enable with an update statement? There is something confused from the start. Then we have one field in a default frame and another set of fields in a named frame rather than cleanly defining both frames and doing so external to the repeat block. Then, once we fetch a customer record, we enable all the fields of the customer buffer ... so, actually we are updating the database and locking the record. No? What one wants, instead, is to populate local variables from the database and then let the database record go out of scope so that it is no longer locked. THEN, update the local records and do the check to see about whether it is safe to do the updates. This means that one can do the reads and writes in do for Customer blocks which will tightly scope the buffers and obviate the need for release.
 

TomBascom

Curmudgeon
Code:
/* h-findCurrent.p */ 

define variable l_cust like customer.custnum.

define frame CustFrame
  Customer.CustNum
  Customer.Name format "x(12)"
  Customer.CreditLimit
  Customer.Balance
.

/* When the user closes the frame by pressing F2, start a transaction: */

on "GO" of frame CustFrame do:

  define buffer xcustomer for customer.

  do for xCustomer transaction:

    find current Customer no-lock.
    find xCustomer exclusive-lock where xCustomer.custnum = l_cust.

    if current-changed Customer then
      do:

        message
          "This record has been changed by another user." skip
          "Please re-enter your changes."
          view-as alert-box
        .

        display Customer.CreditLimit Customer.Balance with frame CustFrame.

        return no-apply. /* Cancel the attempted update/GO */

      end.
     else  /* Otherwise assign the changes to the database record. */
      do:
        assign
          xCustomer.CreditLimit = input Customer.CreditLimit
          xCustomer.Balance     = input Customer.Balance
        .
      end.

  end.

  return.

end.
          
/* To start out with, find, display, and enable the record with no lock. */
          
repeat:  
  
  update l_cust.
 
  find Customer no-lock where custnum = l_cust.

  display 
    Customer.CustNum Customer.Name Customer.CreditLimit Customer.Balance
   with  
    frame CustFrame
  .
          
  enable Customer.CreditLimit Customer.Balance with frame CustFrame.
      
  /* Wait for the trigger condition to do the update and close the frame. */
  
  wait-for "GO" of frame CustFrame.
  
end.
 
Top