aboutsummaryrefslogtreecommitdiffhomepage
path: root/org
diff options
context:
space:
mode:
authorRalph Amissah <ralph.amissah@gmail.com>2026-09-08 08:28:24 -0400
committerRalph Amissah <ralph.amissah@gmail.com>2026-09-09 17:56:14 -0400
commit9af1dda9b03f745aa2b7700419574e2e3e59fde2 (patch)
tree62ebe97f85a6bac96aeede065c9137c087296c84 /org
parenta reader for the ocda db, and its round trip (diff)
ocda db: built from the .ssp, (tethered)
The ocda database is now built from the .ssp itself: the writer's lines are emitted, read straight back by ssp_in, and the objects that come out populate the database. Anything the .ssp does not carry, the database will not have either, by construction (rather than by test). [instead of as previously through a second walk over the in-memory abstraction] - spineAbstractionTxt is split: sspDocumentLines(doc) returns the whole .ssp as lines, and the file writer emits them. Output neutral, the reference test confirms. - spineAbstractionDb takes the abstraction as an argument rather than taking doc.abstraction. - sspRoundTripAbstraction(doc) in ssp_in is the join: lines out, lines in, abstraction returned. Both call sites in spine.d use it. - the header blocks and the image blobs still come from doc_matters (as: the .ssp does not carry image bytes). All (35) markup sample sourced databases built through the .ssp have byte identical SQL dumps to the one built directly before the change. That comparison also found one reader inaccuracy, which the .ssp round trip could not see because the writer omits the field either way: an absent identifier was restored as the ocn in every case, but for an object with no ocn it was empty ("a"~N identifiers are always written). Fixed; the two artefacts checking each other is what caught it. (assisted by Claude-Code)
Diffstat (limited to 'org')
-rw-r--r--org/in_source_files.org19
-rw-r--r--org/out_src_abstraction_ocda_peg_ssp.org11
-rw-r--r--org/out_src_abstraction_sqlite_db.org9
-rw-r--r--org/spine.org10
4 files changed, 41 insertions, 8 deletions
diff --git a/org/in_source_files.org b/org/in_source_files.org
index 0f50150..0a87ec4 100644
--- a/org/in_source_files.org
+++ b/org/in_source_files.org
@@ -930,11 +930,16 @@ template spineAbstractionRead() {
obj.metainfo.identifier = _tail[_sp + 1 .. $];
} else {
obj.metainfo.heading_lev_markup = _levOfMarkedUp(_tail);
- obj.metainfo.identifier = obj.metainfo.ocn.to!string;
+ /+ ↓ omitted means it equals the ocn, and for an object with no ocn
+ it was empty: "a"~N identifiers are always written
+ +/
+ obj.metainfo.identifier = (obj.metainfo.ocn != 0)
+ ? obj.metainfo.ocn.to!string : "";
}
} else {
obj.metainfo.is_a = _rest;
- obj.metainfo.identifier = obj.metainfo.ocn.to!string;
+ obj.metainfo.identifier = (obj.metainfo.ocn != 0)
+ ? obj.metainfo.ocn.to!string : "";
}
obj.metainfo.is_of_section = section;
continue;
@@ -1059,6 +1064,16 @@ template spineAbstractionRead() {
}
return doc;
}
+ /+ ↓ the abstraction as it survives a trip through the .ssp text: emitted
+ as lines by the writer, read straight back. what a consumer built
+ from this cannot see, the .ssp does not carry, which is what makes a
+ second artefact built from it unable to drift
+ +/
+ auto sspRoundTripAbstraction(D)(D doc) {
+ import sisudoc.ocda.abstraction.ssp;
+ mixin spineAbstractionTxt;
+ return sspRead(sspDocumentLines(doc)).abstraction;
+ }
SSPdocument sspReadFile(string file_path) {
string[] _lines;
try {
diff --git a/org/out_src_abstraction_ocda_peg_ssp.org b/org/out_src_abstraction_ocda_peg_ssp.org
index 3be6ce2..a541513 100644
--- a/org/out_src_abstraction_ocda_peg_ssp.org
+++ b/org/out_src_abstraction_ocda_peg_ssp.org
@@ -396,7 +396,11 @@ template spineAbstractionTxt() {
import std.string;
import std.array;
mixin sspObjectRecord;
- void spineAbstractionTxt(D)(D doc) {
+ /+ ↓ the whole .ssp for a document, as lines. the file writer below emits
+ these, and the abstraction db is built by reading them back, so the
+ database cannot carry anything the .ssp does not
+ +/
+ string[] sspDocumentLines(D)(D doc) {
auto doc_abstraction = doc.abstraction;
auto doc_matters = doc.matters;
string[] output;
@@ -538,6 +542,11 @@ template spineAbstractionTxt() {
output ~= "}";
output ~= "";
}
+ return output;
+ }
+ void spineAbstractionTxt(D)(D doc) {
+ auto doc_matters = doc.matters;
+ string[] output = sspDocumentLines(doc);
/+ ↓ write to file +/
/+ path: <output_path>/<language>/abstraction/<doc_uid_out>.ssp +/
string out_root = (doc_matters.output_path.length > 0)
diff --git a/org/out_src_abstraction_sqlite_db.org b/org/out_src_abstraction_sqlite_db.org
index 3daf045..6159fdd 100644
--- a/org/out_src_abstraction_sqlite_db.org
+++ b/org/out_src_abstraction_sqlite_db.org
@@ -42,9 +42,12 @@ template spineAbstractionDb() {
import std.array;
import d2sqlite3;
import sisudoc.outputs.io_out.paths_output;
-
- void spineAbstractionDb(D)(D doc) {
- auto doc_abstraction = doc.abstraction;
+ /+ ↓ the abstraction is passed in rather than taken from doc, because the
+ caller hands over one that has been through the .ssp: written as text
+ and read back. so the database is a function of the .ssp and cannot
+ carry anything the .ssp does not
+ +/
+ void spineAbstractionDb(D,A)(D doc, A doc_abstraction) {
auto doc_matters = doc.matters;
/+ ↓ determine output path +/
diff --git a/org/spine.org b/org/spine.org
index 722f235..84e4d04 100644
--- a/org/spine.org
+++ b/org/spine.org
@@ -1719,10 +1719,16 @@ if (doc.matters.opt.action.show_abstraction) {
#+NAME: spine_each_file_show_abstraction_db
#+BEGIN_SRC d
-/+ ↓ document abstraction sqlite database +/
+/+ ↓ document abstraction sqlite database, built from the .ssp: the
+ lines are emitted and read straight back, and the objects that
+ come out are what is written, so the database cannot carry
+ anything the .ssp does not
++/
if (doc.matters.opt.action.show_abstraction_db) {
+ import sisudoc.ocda.abstraction.ssp_in;
import sisudoc.outputs.io_out.create_abstraction_db;
- spineAbstractionDb!()(doc);
+ mixin spineAbstractionRead;
+ spineAbstractionDb!()(doc, sspRoundTripAbstraction(doc));
}
#+END_SRC