Quite new to datasets.
I have a dataset with 3 levels. Parent, detail and subdetail.
With the trackchanges on every buffer I did some changes
When I do a HdsChanges:get-changes(originaldataste, true), I receive all the changes for the complete dataset. I need a dataset per top-buffer, because depending on the contents of that buffer I want to invoke a method on an appsever with input-output dataset-handle only the dataset with de content of top-buffer P1. For top-buffer (P2) maybe we need to invoke on another appserver. Ect. The idea is to make manually separate datasets with an identically copy of the beforebuffer and the tables . For parent buffer 1 I need a dataset with follow contents :
How can I do this copy? Buffer per buffer via buffer-copy. But how can I copy a before-buffer in the before table of the new dataset. A beforetable we can not manage.
Thanks for advice.
You can have multiple datasets that contains the same buffers, so there is no need to do a buffer-copy to achieve this.
You can achieve this with static dataset definitions or by creating dynamic datasets.
The benefit with static definitions is that it is quick to define the datasets. The drawback is that you need to define buffers with different names in each dataset. This may cause problems if you have code that accesses buffers by name in other places. The buffer names disappears if you do a deep copy, so it will not be a problem on the appserver.
The benefit with dynamic datasets is that the dynamic buffers can be defined wiih the same name as the table. The drawback with dynamic definitions is that the code is quite verbose. You should write some kind of library or utility for this, so it can be easy to use the next time.
The chance is that once you realize the flexibility you can achieve by this you will use it a lot...
Tkx for your response. But I don't see it how to do.
I send the dataset to a method in the back-end as follows INPUT-OUTPUT DATASET-HANDLE DSChanges BY-REFERENCE.
In that class I have the definition of 2 datasets
def temp-table ttparent ..
def temp-table ttdetail
def temp-table ttSubdetail …
DEFINE DATASET ds1 FOR ttparent, ttdetail, ttsubdetail
DATA-RELATION rel1 for ttparnet, ttdetail RELATION-FIELDS (field1, field1)
DATA-RELATION rel2 FOR ttdetail, ttsubdetail
RELATION-FIELDS (field2, field2)
def temp-table ttparentCopy..
def temp-table ttdetailCopy
def temp-table ttSubdetailCopy…
DEFINE DATASET dsCopy FOR ttparentCopy, ttdetailCopy, ttsubdetaiCopyl
DATA-RELATION rel1 for ttparnetCopy, ttdetailCopy RELATION-FIELDS (field1, field1)
DATA-RELATIONrel 2 FOR ttdetailCopy, ttsubdetailCopy
def var lOriginal as handle.
lOriginal = dataset ds1:handle.
lOriginal :copy-dataset (ioDSChanges ). => I make the DSChanges static.
But how can I fill now the dscopy with only the records for parent P1 (and his childs) and de beforebuffer form the DSChanges.
If I do also a copy :
def var ITest as handle.
ITest = datset dscopy:handle.
lTest :copy-dataset (ioDSChanges ). => then I have all records
If I delete the records not for parent 1, I still have the beforerecords of all the deleted records?
If I do then a query on the before-table of ITest then I still have the before-record SD211 and P3?
I don'ts see it how I can made this. Tkx
I may have misunderstood the problem. Can you clarify? When you say you need a dataset per top-buffer and referred to P1, P2 and P3 as different buffers I assumed they were different tables as the term buffer typically is associated with a table. But the term buffer may also be used for a record I guess. If P1 , P2 and P3 are records of the same table then my suggestion is not going to help. In both cases you should probably trim down the data before they are passed to the appserver.
The top-buffer is TTParent and P1, P2 en P3 are records in ttParent.. D11, is a record in buffer ttDetail and the child of P1. Then SD111 and SD112 are record in ttsubdetail and Childs of D11.
In the dataset ds1 they are all related to my ttparent-record P1 (ttparent is the topbuffer in ds1). I just needs all these records (and the before-buffers ) in a separate dataset to send to appserver1.
Same for P2. Is a record in ttparent. D12 and D21 are child records in ttdetail, and SD211 and SD212 are records in ttsubdetail and childs of ttdetail-record D21
Also this set of records in the dataset ds1 I want to move to a separate dataset (with the before-buffers) an send then to appserver2
P1,P2,P3 are records in ttparent. ttparent is the TOP-buffer in my dataset ds1.
P1 is a record in ttparent, D11 is a record in ttdetail and a child of P1, SD111 and SD112 are records in ttsubddetail and childs of ttdetail-record .
I need only these set of records with there before-table records in an new dataset to send them to appserver1.
Same for P2. ttparent-record P2 with childs in ttdetail D12 and D21 and childs in ttsubdetail SD211 and SD212.
These set I need to send to appserver2
My problem is that they come all in 1 dataset ds1 and I need to split then up per ttparent (and all his childs) in a new dataset. Also I need the before-buffers.
When arrived in the concerning appserver I need to evaluate the changes (therefore I need the before-buffer.
Otherwise it was a simple copy, but in that case I have only the current values and I lost the changes made.
I think you are using "buffer" to reference a "record". In ABL a BUFFER is somehow an equivalent to an SQL Cursor.
It is not a record, but a "pointer to a record". It provides access to any record in a TABLE, so it is "equivalent" to TABLE, not to record.
In any case, what I understands is that you need a DATASET with just one top level record, instead of all the records.
I must say I don't see the point of that design, but...
You can't manually modify the before table, but you can copy to a DATASET the orignal data of the top level row, and childrens. Then apply the same changes you did to the "whole dataset" for that particular set of rows.
If you ask me (I know you didn't) it does not make any sense..
If you plan to use onely some of the changes in a particular method, it will be more razonable (to me obviously) to pass the whole dataset, and a list, or aditional TABLE, with the ids of the rows you want the method to process. This way you avoid to copy what you already have.
P1 is a record in ttparent, D11 is a record in ttdetail and a child of P1, SD111 and SD112 are records in ttsubddetail and childs od ttdetail-record .
When arrived in the concerning appserver I need to evaluate the changes (therefor I need the before-buffer.
Otherwise it was a simple copy, but in that case I have the current values and I lost the changes
You are right I meant a record not a buffer.
But it is a an idea to send the whole dataset + a list with records (or the id's) that need to be processed. Then only backside is the traffic.
I tried to answer (clarify) but it seems that my posts don't come online. I try it again..
It is possible to delete records from the change dataset after it has been extracted. I'm not at all sure if it is the best approach.
You use the dataset top-nav-query to traverse the top levels. For the records that are NOT to be saved you loop through the buffer:num--child-relation and use the buffer:get-child-relation(<number>):query to traverse and delete the children. The traverse through the children needs to be called recursively. You delete records on each level including the top level, making sure the delete happens after the child delete.
The hard part is to get rid of deletes. You may use a similar approach, but you have to traverse the before-buffers, since the after-buffer is gone. You cannot use the child-relations to find the deletes in child data. You also cannot delete the before-buffer records, but have to use buffer:reject-row-changes. I suspect you then ideally should delete the after-buffer that likely was resurrected by the reject. It might be hard to find as there are no rowids that links them. The records row-state should be 0 so it probably does no harm to keep it.