The AVM effectively goes through the following steps for the buffer on which you execute the FILL method, or for each top-level table in the ProDataSet if you are filling the whole ProDataSet:
1. Opens and performs a GET-FIRST on the top-level database query.
2. Creates a record in the top-level temp-table.
3. Performs a BUFFER-COPY from the database record buffers to the data table buffer, doing field mappings and excluding or including fields as specified in the table and Data-Source definitions and the ATTACH-DATA-SOURCE method.
4. If the data table is a parent in one or more active relations, prepares each child query in turn if this is the first use of it. The FILL then does steps 5-7 for each child.
5. Opens the child query; does a GET-FIRST on it; creates a record in its temp-table; and buffer-copies the database buffers into the temp-table buffer.
6. Repeats Steps 4 and 5 for any children of the child.
7. Does a GET-NEXT on the child for as long as there are more records in its query, and buffer-copies them into new records in its data table.
8. Goes back to the top level, does a GET-NEXT at that level, and continues the process in steps 2 through 7. For each child level, it just plugs key values from the parent into the child query, without having to actually re-prepare it, and reopens the child query for the current parent.
For more information about events and the custom code that developers can write for them, see ProDataSetsEvents.
This interleaving allows the AVM to maintain integrity throughout the entire FILL process, so that parent and child records are not read in separate loops, which would allow for the possibility that parent records would have changed or been deleted.