Skip to content

Propagation of Data-Dictionary Operations

DDOs perform these operations: save, delete, clear, clear all, and find. These operations are usually initiated by a DEO sending a message to its server DDO. The DEO operation is often initiated by users pressing a key. For example, a user may press the F2 key, which will cause the request_save message to be sent to the DEO. The DEO will send a message to its DDO, also called request_save. The DDO will then perform the save. If you understand how the five major data-dictionary operations behave, you can accurately predict how your program will behave.

Saves - Request_Save

When a DDO receives a request_save message, it will attempt to save a record for its main file. Saves propagate up. This means that a save can affect the main file of its DDO and all of the DDOs above it in the updating chain. For example:

  • If request_save is sent to ObjectA_DD, a record in File A will be saved.
  • If request_save is sent to ObjectD_DD, Files D, A, and B will be saved.
  • If request_save is sent to ObjectF_DD, Files F, D, E, A, B, and C will be saved.

What files would be saved if request_save is sent to H_DD? If you answered all files except G, you would be correct. This implies that you must have your parent-file DDOs properly connected if a data-dictionary save is to be properly processed.

It makes absolutely no difference what item the cursor is in when a user requests a save in a DEO. The record that gets saved is determined by the DDO. For example, if users press F2 when they are in a vendor field in an entry form that is connected to a checks DDO, a checks record will get saved. This may also save its parent vendor record (assuming the data-dictionary structure is correct). If the entry form was connected to a vendor DDO, the save would save the vendor record and not the checks record.

Deletes - Request_Delete

A request_delete attempts to delete the record from the DDO’s main file. If the cascade_delete_state property is true, there are child-file DDOs in the data-dictionary structure, and a relationship between the child and parent files is defined in the file definition, the DDO will also delete the child records. This process will recurse down the data-dictionary structure. Although a request_delete cannot delete a parent-file record, it can update a parent file. This means that a request_delete will propagate up and down the data-dictionary structure.

If the DDO’s cascade_delete_state property is false, the DDO will not delete a record to which a record(s) in a child file(s) relates. Therefore, if a delete occurs, the propagation direction will be up (just like a save).

For example:

  • If a request_delete were sent to ObjectH_DD, the record in File H would be deleted and Files A, B, C, D, E, and F would be updated.
  • A delete request sent to ObjectA_DD (if its cascade_delete_state is true) would delete a record in A, delete all of A’s child records in D, delete all of D’s child records in F, and delete all of F’s child records in G and H.

Deletes propagate up and down a data-dictionary structure. Deleted D records would update File B. Deleted F records would update E and C. In other words, every DDO in the file structure would be affected by a delete in A.

This suggests that you must have a complete data-server dictionary in place in order to delete records in a parent file. If you want automatic deletions of child-file records, this is true. Often you will want to prohibit deletes if there are child-file records relating to the main-file record. You can use the cascade_delete_state property to protect against this. If you disallow deletions of records that have children, deletes will act the same as saves and only propagate up the data-dictionary structure.

This will determine how complete your data-dictionary structure needs to be represented inside a view. If you need a view that can save and delete records from File A (it might be a vendor file) and you are disallowing deletes if child records exist, the only DDO that will be required in your view is A_DD. If you wish to be able to delete all child records, you will need the complete data-dictionary structure.

A few things about deletes should be emphasized:

  • The file that a record is deleted from is determined by the DDO and not the DEO that sent the message.
  • The record will be deleted from the receiving DDO's main file.
  • The propagation of deletes down to child records is determined by the data-server updating structure and the relationships in the files’ definitions. If either is missing, the child deletes will not occur.
  • Constraints have absolutely no effect on this process, but cascade_delete_state and the DD subclass's client-file list (add_client_file message) do.

Clear and Clear_all

The clear_all message is simple. It clears every file in the entire data-dictionary structure. clear_all propagates up and down.

The clear message clears the main file of the DDO and then propagates up the data-server structure. clear does not propagate down. For example, if clear were sent to D_DD, Files D, A, and B would be cleared. The other files would be unaffected.

Finding

The primary find messages are request_find, find_by_recnum, and request_assign. These messages are different from the other messages in that you can request a find on a file that is not the main file of the DDO. For example, you could send request_find to D_DD asking it to find a record in File A. The DDO will perform the find and then notify the appropriate DDO (A_DD) about the results. This is important to understand. Operationally, requesting a parent-file find in a child-file DDO is the same as requesting the find directly of the parent-file DDO. After the find, the parent-file DDO will set its current_record property to the correct record.

The find is performed by the DDO that receives the message and not the DDO that owns the finding file. After a find, the DDO will notify other DDOs in its structure about the new record. This has some interesting implications for advanced usage. By augmenting the find procedures in DDOs, you can make two different DDOs respond differently to finding the same record. For example, we could augment the request_find message for DDO_D_DD as follows:

Procedure Request_Find Integer iMode Integer iFile Integer iIndex
    If (iFile <> A.File_Number) ;
        Forward Send Request_Find iMode iFile iIndex
End_Procedure

In this example, we have disabled any finding of File A records by DDO_D_DD. Request_find messages for File A that are sent to D_DD are ignored. All other finds are processed, and a find sent directly to A_DD would also be processed.

A find operation will often result in the finding of parent records (the relate process). When this happens, the parent-file DDO(s) is (are) properly notified of the new record. Usually, a DDO is requested to find a record in its main file or in one of its parent files.

A DDO’s current_record property determines what record the DDO will work with. There will be times when the current_record in the DDO and the record in the file buffer will be different. DDOs act on the current_record and not on the contents of the file buffer (actually, it will make sure that the buffer is loaded with the right record before a save or delete). Simply finding a record does not make the DDO aware of a record. You must send one of the finding messages to the DDO. This will set the current_record property.

Use the message request_assign if you want a DDO to latch onto the record in the file buffer. This will perform a relate on the record, notify all concerned DDOs, and send the message refresh to all DEOs that would be affected by this process.

Use the message find_by_recnum if you want a DDO to find a particular record. This will find the record, perform a relate, notify all concerned DDOs, and send the message refresh to all DEOs that would be affected by this process.

The request_find message will find a record for a selected file, in a selected direction, by a selected index. It also performs a relate, notifies other DDOs, and refreshes the DEOs.

When these messages are used, they are usually sent from a DEO. Below are examples of the usage:

// procedure inside a DEO
Procedure DoSomething
    Integer iServer iRec iFile
    Get Server to iServer // ID of DDO
    :
    // latch onto record in vendor file buffer
    Send Request_Assign of iServer Vendor.File_Number
    :
    // or, find a particular record for the main_file
    Get Main_File to iFile
    Get piMyRecNum to iRec // user defined property
    Send Find_By_Recnum of iServer iFile iRec
    :
    // or, find the next record for vendor by index 1
    Send Request_Find of iServer GT Vendor.File_Number 1
    :
End_Procedure

It is very helpful to understand how data-dictionary behaviors propagate. When you do, you will be able to predict how DDOs will behave for any given operation. It will also help you determine where DEOs should connect to a data-dictionary structure.

A Data-Dictionary-Propagation Quiz

Quiz 1

We have a data-dictionary structure (no constraints) as shown in the diagram. Our DEOs could connect to any of these objects. For example, if our DEO were using DDO D, all of the DEO’s data-file requests (save, clear, delete, find) will be handled by DDO D.

A   B   C  
 \ / /  
  D   E  
   \ /  
    F
  • Clear All: What will happen if clear_all is sent to any of the DDOs? [All DDOs will be cleared].

  • Clear: What will happen if clear is sent to A? [A is cleared.] What happens if clear is sent to D? [D, A, and B are cleared.] What happens if clear is sent to F? [F, D, A, B, E, and C are cleared.] Clears propagate up.

  • Save: What will happen if request_save is sent to A? [A is saved.] What happens if request_save is sent to D? [D, A, and B are saved.] What happens if request_save is sent to F? [F, D, A, B, E, and C are saved]. Saves propagate up.

  • Delete: (Cascade_delete_state is true in all DDOs.) What will happen if request_delete is sent to A? [A will be deleted, A's children in D will be deleted, D's children in F will be deleted. B, E, and C will be updated]. What will happen if request_delete is sent to D? [D will be deleted, D's children in F will be deleted. A, B, E, and C will be updated]. What will happen if request_delete is sent to F? [F is deleted, A, B, C, D, and E are updated].

  • Find: When a find request is made to a DDO, the file to find in is passed as a parameter. You can request that a DDO find a record for its file or any of its parents’ files. Unless you have augmented your find procedures, asking either DDO A or D to find a record for File A will yield the same results.

  • What happens if a request_find for File A is sent to A? [A is found.] What happens if a request_find for File A is sent to D or F? [A is found]. What happens if a request_find for File D is sent to D? [D is found and related, A and B are notified of the new related records]. What happens if a request_find for File F is sent to F? [F is found and related; A, B, C, D, and E are notified of the new related records].

Quiz 2

We will give our data-dictionary structure the following values:

A   B   C = Customer  
 \ / /  
  D   E = Vendor  
   \ /  
    D = Order Header  
    F = Inventory  
    F = Order Detail  

F has a relates-to constraint to D.
DEO_Header_Entry is using D.
DEO_Table_Entry is using F.

We now have a standard order-file structure. We will hook two DEOs to this structure: an order-header-entry form using D and an order-detail grid using F. This means that users will only be sending data-dictionary requests to DDOs D and F. Without a relates-to constraint between F and D, the data-entry behaviors will not be appropriate for our entry-form/grid setup. The save and delete behaviors are fine; the clear and find behaviors are not.

We must add a relates-to constraint in DDO F which will constrain F records at any given moment to only those relating to the current record of its Parent File D. Constraints have no impact on saving or deleting (which is good). They do change the clear and find behaviors (which is also good).

  • Clear: What happens if clear is sent to D? [D, A, and B are cleared, D will notify its constrained child, F, that it has a new blank record. F will attempt to find a record that is related to the blank child. Hopefully, it will fail, clearing F, E, and C. The net result is that all files are cleared.] What happens if clear is sent to F? [F, E, and C are cleared. When F attempts to clear DDO D, it will "bump" into the relates-to constraint and halt the clear up that tree branch.]

  • Find: What happens if a request_find for File A is sent to D or F? [A is found, nothing else is changed]. What happens if a request_find for File D is sent to D? [D is found and related. A and B are notified of the new related records. In addition, D will notify its constrained child file F about the new parent record. F will find the first valid record and tell the grid object about the record. The grid object will fill in the grid with valid records. Files E and C are related and their DDOs are notified of the change. Therefore, when D is changed, the child grid record will change as well. This is good.] What happens if a request_find for File F is sent to F? [F is found only if F is a valid child for D. Therefore D, A, and B cannot change. Files E and C are related and their DDOs are notified of the change.]

The header object will contain the fields allowing us to find the customer records (A). We did not choose to constrain the order header file to the customer file. For finding purposes, we do not want our search of orders to be limited to a single customer. We did not create a separate DEO for the customer fields. If we had done this (and that DEO was using the customer DDO), we would have gotten undesired save and delete behaviors. Save would have only saved the customer file. Deletes would have deleted the customer record and all of its children.

Quiz 3

We will now create a view for customer entry. We will base the view on a single DDO.

A

A = Customer

  • What are the implications of removing the child-file DDOs? If you review our data-dictionary-propagation rules, you will note that the only behavior that would propagate down is a delete. Saves propagate up. Since we have no parent files, this operation will be fine. If the child-file DDOs are not provided, a delete will not delete any child records. This means that we would end up with "orphan" records (orders). Normally we do not want this. We will control this in the DDO’s cascade_delete_state property, making it impossible to delete customers that have child records.

How complete does your data-dictionary structure have to be? Locate the childmost-file DDO, which will have a DEO using it. Make sure that all parent-file DDOs are in your structure and properly connected. If not, your saves and deletes may not work properly. If you are disallowing deletes of records that have children, you will not need to create any DDOs below the lowest "used" DDO. If you are allowing child-record deletes, you must make sure that the child DDOs and all of those DDOs’ updated DDOs are provided and connected.