Accessing temp-tables in a dataset?

Posted by Rom Elwell on 19-Aug-2014 15:41

SETUP:

/*** BEGIN DEFINITIONS ***/
&IF DEFINED (ttEntity_I) = 0 &THEN
DEFINE TEMP-TABLE ttEntity NO-UNDO
FIELD aField AS CHARACTER
FIELD bField AS INTEGER.
&GLOBAL-DEFINE ttEntity_I
&ENDIF

&IF DEFINED (dsEntity_I) = 0 &THEN
{ttEntity.i}
DEFINE DATASET dsEntity FOR ttEntity.
&GLOBAL-DEFINE dsEntity_I
&ENDIF
/*** END DEFINITIONS ***/

/*** Code snippet from an instance of the class aClass ***/
DEF VAR hdlEntity AS HANDLE.
DEF VAR hdlBuffer AS HANDLE.

hdlEntity = DATASET dsEntity:HANDLE.
DoWork(OUTPUT hdlEntity).  /* This method call loads data into the HANDLE OUTPUT parameter, hdlEntity */


hdlBuffer = hdlEntity:GET-BUFFER-HANDLE(TEMP-TABLE ttEntity:NAME).
/* OR IF YOU PREFER */
hdlBuffer = hdlEntity:GET-BUFFER-HANDLE(1).

/* What ways are there to reference the fields in the temp-table ttEntity at this point? */
/* I know the following allows me to access records in the temp-table using a QUERY object: */ 
IF VALID-HANDLE(hdlBuffer) THEN DO: 
CREATE QUERY hQry.
hQry:ADD-BUFFER(hdlBuffer).
hQry:QUERY-PREPARE ("FOR EACH " + hdlBuffer:NAME).
hQry:QUERY-OPEN().
hQry:GET-FIRST(). 
DO WHILE NOT hQry:QUERY-OFF-END:
MESSAGE hdlBuffer:GET-BUFFER-FIELD('aField'):BUFFER-VALUE() VIEW-AS ALERT-BOX.
hQry:GET-NEXT().
END.
DELETE OBJECT hQry.
END.

QUESTION: Is it possible to reference the temp-table directly, using the code snippets above, in a manner such as:

FIND FIRST ttEntity.
IF AVAIL ttEntity THEN 
MESSAGE ttEntity.aField VIEW-AS ALERT-BOX.



Posted by Mike Fechner on 20-Aug-2014 02:18

Had a second read on your source... The method DoWork returns the handle of the dataset. Couldn't it OUTPUT a DATASET-HANDLE or DATASET? In both cases you could call it with

DoWork (OUTPUT DATASET dsEntity).

DoWork is called as a method of a reference variable. So it's a method in the same class or a function in that .p? A function in a SUPER-PROCEDURE?

Depending on the whole situation, the DoWork method/function may already be working on the same instance of the Dataset as the caller and no parameter passing might be required.

If not, you might want to read about BY-REFERENCE passing of Dataset parameters. And while you're at it BIND as well.

All Replies

Posted by Mike Fechner on 19-Aug-2014 15:56

Check out the documentation about the „short hand syntax” (colon colon).
 
hDataset::eCustomer:FIND-FIRST ().
 
MESSAGE hDataset::eCustomer::CustNum .
 
etc.
 
hDatasetHandle::<buffer name> is the same as hDatasetHandle:GET-BUFFER-HANDLE (“<buffer name>”) .
 
and
 
hBufferHandle::<field name> is the same as hBufferHandle:GET-BUFFER-FIELD(“<field name>”):BUFFER-VALUE
 
and can be queued
 
hDatasetHandle::<buffer name>::<field name>
 
 
 
 

Posted by Thomas Mercer-Hursh on 19-Aug-2014 15:56

Why not?

Posted by Simon L. Prinsloo on 20-Aug-2014 02:08

Yes, given that you set the hdlEntity to the of the dataset, you can reference the defined temp-table directly. The code will be simpler and the compiler will alert you to typing errors in buffer and field names. The dynamic code sacrifice this for flexibility which you do not seem to need in this example.

Posted by Mike Fechner on 20-Aug-2014 02:18

Had a second read on your source... The method DoWork returns the handle of the dataset. Couldn't it OUTPUT a DATASET-HANDLE or DATASET? In both cases you could call it with

DoWork (OUTPUT DATASET dsEntity).

DoWork is called as a method of a reference variable. So it's a method in the same class or a function in that .p? A function in a SUPER-PROCEDURE?

Depending on the whole situation, the DoWork method/function may already be working on the same instance of the Dataset as the caller and no parameter passing might be required.

If not, you might want to read about BY-REFERENCE passing of Dataset parameters. And while you're at it BIND as well.

Posted by Simon L. Prinsloo on 20-Aug-2014 03:02

My previous postI was wrong.  

The assignment in the following part of your code is of no meaning, as the variable is immediately overwritten with the output of DoWork():

hdlEntity = DATASET dsEntity:HANDLE.
DoWork(OUTPUT hdlEntity).


This means that the handle may point to a another dataset from the one you defined and the dynamic code is the only safe option. On the other hand, if you use an "OUTPUT  DATASET dsEntity" parameter, as suggested by Mike, my previous post will apply.

Posted by Rom Elwell on 20-Aug-2014 04:10

Mike and Simon,  

Thank you for your assistance.  A week ago,  the datatype for the output parameter was indeed a DATASET-HANDLE using the BY-REFERENCE clause.  However,  during  a support call with Progress for an unrelated  issue,  the support engineer informed a coworker  that we should not be using  DATASET-HANDLE anyplace in our code except at the entry point into our processing from a NET client.  We questioned why we could not use DATASET-HANDLE and we're told that we were making deep copies of the associated  dataset (inspite of the presence of the BY-REFERENCE clause) and that we should be using HANDLE instead.   This is why you see the legacy line of hdlEntity = dsEntity:HANDLE.   Now I am concerned  that we could have used DATASET-HANDLE,  as originally designed....

Posted by Mike Fechner on 20-Aug-2014 04:16

The support engineer is correct, that a DATASET-HANDLE parameter may cause a deep copy and not just pass a reference if done wrong.
 
However – there are ways to deal with that. BY-REFERENCE is one, knowing when to delete stuff is another.
 
Forcing you to do dynamic coding (required by the fact that you return only a HANDLE) just because DATASET-HANDLE done wrong may occur memory leaks is, beg my pardon, ridiculous.
 
The Progress debugger has tools to help you with finding those memory leaks – and you certainly should test also for runtime errors and make sure, that all your DELETE OBJECT statements (if required) are in a location that’s guaranteed to be executed – like in a FINALLY block.  

Posted by Rom Elwell on 20-Aug-2014 06:04

Thank you Mike for your reply.  Our previous design utilized DATASET-HANDLE and calls to DELETE OBJECT both in the Deconstructor methods of the associated classes (for class variables of type Object or HANDLE) and in the class methods (when the Object or HANDLE was defined as a method variable).

Posted by Peter Judge on 21-Aug-2014 10:07

In addition to MIke's suggestion of the debugger, take a look at the LOG-MANAGER tool. As of v11 it has a LOG-ENTRY-TYPE of "TEMP-TABLE" which tracks temp-table creation and deletion (of the TT and PDS structures, not records in them). Very useful.

-- peter

Posted by Rom Elwell on 21-Aug-2014 10:11

Thank you Peter.  We are currently running 10.2b but migrating to 11.4 in the next two weeks.  My team is eager to have access to the new features and IDE with OE11.x.

This thread is closed