The export writes the stored form, so a round trip is not byte-identical

Table of Contents

1. Summary

Export runs the import backwards and rebuilds a whole ORE input from rows. Each document is fetched from the component that owns it and each projection reverses it. The one thing a document does not get back is the rendering it arrived with: a file that said F is stored as Following, so the export writes Following. That is the design, not a defect, and a test compares the export to the rows or to a second read of its own text, never to the text a person supplied.

2. The path

projects/ores.ore/service/src/messaging/run_configuration_operations.cpp:418 is export_run. It returns a map of file name to text: the run document plus one file for each configuration the report binds. The market data and the portfolio are not in it. The function runs in four steps.

  1. Read the run document from reporting (rp::get_run_document_request), and reverse it to a typed record.
  2. Write ore.xml from that record.
  3. For each binding that names a configuration document, ask the owning component for its rows and reverse them.
  4. Key each file by the name the run document's Setup gives it, so the output directory is one ORE can run.

Step 3 is the reason the run document is stored as bindings rather than as a document: the export needs the identity of each configuration to ask its owner, and a document in the run document's rows would be a second copy of what the owners already hold.

the_export_writes_the_stored_form.png

3. What survives, and what does not

The rows keep everything a document states except the rendering of a value that has more than one. Two consequences, and they are not the same consequence:

  • The export is stable. The set names one form of each value and names itself for it, so importing an exported document changes no row, and exporting it again gives the same text. The stored form is a fixed point of the path.
  • The export is not the import. The first export differs from the file the person supplied, in exactly those values a boundary converted: the guard rewrites a curve document's MF, and a convention document's codec rewrote it before the row existed. A test that compares an export to an arbitrary input is therefore wrong about what the system promises.

The two tests state the promise precisely, and each one covers a different half:

  • projects/ores.ore/core/tests/xml_curve_configuration_projection_roundtrip_tests.cpp:72 reads, maps, reverses and writes every curve configuration in the corpus, then reads the result and compares the two records. Both sides pass through the same read, so the case asserts that the projection's shape survives the round trip, and it cannot see a conversion: the curve codec states none.
  • projects/ores.refdata/core/tests/curve_configuration_database_roundtrip_tests.cpp:259 writes a document through the store and states the round trip on what the store returns: the document the rows hold exports and reads back unchanged. This is the only case that can be right about a value the guard rewrote.

4. Why the run document is rebuilt, not read

projects/ores.reporting/core/include/ores.reporting.core/service/run_document_service.hpp stores a risk report configuration, the bindings, and the run's own setting rows; get projects them back into a run_document. So the export never reads a blob and never parses a document it stored: it reads rows, the same way a screen does. A run document is therefore as reproducible as the rows it is built from, and a change to the projection changes every exported run document at once, which is the property that makes the format one thing rather than a copy per configuration.

5. See also

Emacs 29.3 (Org mode 9.6.15)