-*- mode: org -*-
#+TITLE: sisudoc spine (doc_reform) output sqlite
#+DESCRIPTION: documents - structuring, publishing in multiple formats & search
#+FILETAGS: :spine:output:db:sql:sqlite:
#+AUTHOR: Ralph Amissah
#+EMAIL: [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]]
#+COPYRIGHT: Copyright (C) 2015 (continuously updated, current 2026) Ralph Amissah
#+LANGUAGE: en
#+STARTUP: content hideblocks hidestars noindent entitiespretty
#+PROPERTY: header-args+ :eval never-export :exports code
#+PROPERTY: header-args+ :noweb yes :padline no
#+PROPERTY: header-args+ :results silent :cache no
#+PROPERTY: header-args+ :mkdirp yes
#+OPTIONS: H:3 num:nil toc:t \n:t ::t |:t ^:nil -:t f:t *:t
- magic single double-quote → " ← FIX changes hilighting behavior (occuring
after it) in org document. INVESTIGATE (org-mode CONFIG?) FIND & FIX
- [[./doc-reform.org][doc-reform.org]] [[./][org/]]
- [[./output_hub.org][output_hub]]
sudo chown ralph:ralph /var/www
- create db
~dr/bin/spine-ldc -v \
--sqlite-db-create --sqlite-db-filename="spine.search.db" \
--output=/var/www/html \
~grotto/repo/git.repo/code/project-spine/doc-reform-markup/markup_samples/markup/pod-samples/pod/*
- update db
~dr/bin/spine-ldc -v \
--sqlite-update --sqlite-db-filename="spine.search.db" \
--output=/var/www/html \
~grotto/repo/git.repo/code/project-spine/doc-reform-markup/markup_samples/markup/pod-samples/pod/*
- produce html (and some other) output files
~dr/bin/spine-ldc -v --html --epub --latex --odt \
--output=/var/www \
~grotto/repo/git.repo/code/project-spine/doc-reform-markup/markup_samples/markup/pod-samples/pod/*
* sql
** _module, templates_ :module:
*** template
#+HEADER: :tangle "../src/sisudoc/outputs/io_out/sqlite_collection_db.d"
#+HEADER: :noweb yes
#+BEGIN_SRC d
<
")
.replaceAll(rgx.br_line, "
")
.replaceAll(rgx.br_line_spaced, "
")
.replaceAll(rgx_xhtml.line_break, "
");
return _txt;
}
string _html_font_face(string _txt){
_txt = _txt
.replaceAll(rgx.inline_emphasis, "$1")
.replaceAll(rgx.inline_bold, "$1")
.replaceAll(rgx.inline_underscore, "$1")
.replaceAll(rgx.inline_italics, "$1")
.replaceAll(rgx.inline_superscript, "$1")
.replaceAll(rgx.inline_subscript, "$1")
.replaceAll(rgx.inline_strike, "$1")
.replaceAll(rgx.inline_insert, "$1")
.replaceAll(rgx.inline_mono, "$1")
.replaceAll(rgx.inline_cite, "$1");
return _txt;
}
string _notes;
string _urls;
string _txt = _html_font_face(_html_special_characters(obj.text));
{ /+ debug +/
if (doc_matters.opt.action.debug_do_sqlite) {
writeln(_txt, "\n");
}
}
return _txt;
}
#+END_SRC
****** special characters
#+NAME: sanitize_and_munge_inline_html_special_characters
#+BEGIN_SRC d
string html_special_characters(string _txt){
_txt = _txt
.replaceAll(rgx_xhtml.ampersand, "&")
.replaceAll(rgx_xhtml.quotation, """)
.replaceAll(rgx_xhtml.less_than, "<")
.replaceAll(rgx_xhtml.greater_than, ">")
.replaceAll(rgx.nbsp_char, " ")
.replaceAll(rgx.br_line_inline, "
")
.replaceAll(rgx.br_line, "
")
.replaceAll(rgx.br_line_spaced, "
")
.replaceAll(rgx_xhtml.line_break, "
");
return _txt;
}
#+END_SRC
****** special characters for code
#+NAME: sanitize_and_munge_inline_html_special_characters_code
#+BEGIN_SRC d
string html_special_characters_code(string _txt){
_txt = _txt
.replaceAll(rgx_xhtml.ampersand, "&")
.replaceAll(rgx_xhtml.quotation, """)
.replaceAll(rgx_xhtml.less_than, "<")
.replaceAll(rgx_xhtml.greater_than, ">")
.replaceAll(rgx.nbsp_char, " ");
return _txt;
}
#+END_SRC
****** font_face
#+NAME: sanitize_and_munge_inline_html_font_face
#+BEGIN_SRC d
string html_font_face(string _txt){
_txt = _txt
.replaceAll(rgx.inline_emphasis, "$1")
.replaceAll(rgx.inline_bold, "$1")
.replaceAll(rgx.inline_underscore, "$1")
.replaceAll(rgx.inline_italics, "$1")
.replaceAll(rgx.inline_superscript, "$1")
.replaceAll(rgx.inline_subscript, "$1")
.replaceAll(rgx.inline_strike, "$1")
.replaceAll(rgx.inline_insert, "$1")
.replaceAll(rgx.inline_mono, "$1")
.replaceAll(rgx.inline_cite, "$1");
return _txt;
}
#+END_SRC
****** inline markup
******* grouped text
#+NAME: sanitize_and_munge_inline_html_grouped_text_bullets_indents
#+BEGIN_SRC d
string inline_grouped_text_bullets_indents(M,O)(
M doc_matters,
const O obj,
string _txt,
string _suffix = ".html",
string _xml_type = "seg",
) {
static auto rgx = RgxO();
static auto rgx_xhtml = RgxXHTML();
if (obj.metainfo.is_a == "group") {
_txt = (_txt)
.replaceAll(rgx.grouped_para_indent_1,
" ")
.replaceAll(rgx.grouped_para_indent_2,
" ")
.replaceAll(rgx.grouped_para_indent_3,
" ")
.replaceAll(rgx.grouped_para_indent_4,
" ")
.replaceAll(rgx.grouped_para_indent_5,
" ")
.replaceAll(rgx.grouped_para_indent_6,
" ")
.replaceAll(rgx.grouped_para_indent_7,
" ")
.replaceAll(rgx.grouped_para_indent_8,
" ")
.replaceAll(rgx.grouped_para_indent_9,
" ")
.replaceAll(rgx.grouped_para_indent_hang, " ")
.replaceAll(rgx.grouped_para_bullet, "● ")
.replaceAll(rgx.grouped_para_bullet_indent_1,
" ● ")
.replaceAll(rgx.grouped_para_bullet_indent_2,
" ● ")
.replaceAll(rgx.grouped_para_bullet_indent_3,
" ● ")
.replaceAll(rgx.grouped_para_bullet_indent_4,
" ● ")
.replaceAll(rgx.grouped_para_bullet_indent_5,
" ● ")
.replaceAll(rgx.grouped_para_bullet_indent_6,
" ● ")
.replaceAll(rgx.grouped_para_bullet_indent_7,
" ● ")
.replaceAll(rgx.grouped_para_bullet_indent_8,
" ● ")
.replaceAll(rgx.grouped_para_bullet_indent_9,
" ● ");
}
return _txt;
}
#+END_SRC
******* images
#+NAME: sanitize_and_munge_inline_html_images
#+BEGIN_SRC d
string inline_images(M,O)(
M doc_matters,
const O obj,
string _txt,
string _suffix = ".html",
string _xml_type = "seg",
) {
string _img_pth;
if (_xml_type == "epub") {
_img_pth = "image/";
} else if (_xml_type == "scroll") {
_img_pth = "../../image/";
} else if (_xml_type == "seg") {
_img_pth = "../../../image/";
}
if (_txt.match(rgx.inline_image)) {
_txt = replaceAll!(m =>
m["pre"].to!string
~ _img_element(_img_pth ~ m["img"].to!string, m["width"].to!string,
m["height"].to!string, _image_alt(m["post"].to!string))
~ " " ~ _image_rest(m["post"].to!string)
)(_txt, rgx.inline_image);
}
return _txt;
}
/+ ↓ the same treatment of an image as the html and epub writers give
it, because this is the html the cgi search renders: the markup's
description is the alt text, and dimensions that are not there are
not written as zeroes.
+/
string _image_alt(string _post) {
if (auto m = _post.matchFirst(rgx.inline_image_alt)) {
return m["alt"].to!string;
}
return "";
}
string _image_rest(string _post) {
if (auto m = _post.matchFirst(rgx.inline_image_alt)) {
return m.post.to!string;
}
return _post;
}
string _img_element(string _src, string _w, string _h, string _alt) {
string _dim = (_w == "0" && _h == "0")
? ""
: " width=\"" ~ _w ~ "\" height=\"" ~ _h ~ "\"";
return "";
}
#+END_SRC
******* links
******** scroll, seg, epub
#+NAME: sanitize_and_munge_inline_html_inline_links
#+BEGIN_SRC d
string inline_links(M,O)(
M doc_matters,
const O obj,
string _txt,
string _xml_type = "seg",
) {
if (obj.has.inline_links) {
if (obj.metainfo.is_a != "code") {
_txt = replaceAll!(m =>
m["linked_text"] ~ "┤" ~ to!string((obj.stow.link[m["num"].to!ulong])).encode ~ "├"
)(_txt, rgx.inline_link_number_only);
}
if ((_txt.match(rgx.mark_internal_site_lnk))
&& (_xml_type == "scroll")) { // conditions reversed to avoid: gdc compiled program run segfault
_txt = _txt.replaceAll(
rgx.inline_seg_link,
"$1");
}
auto pth_html = spinePathsHTML!()(doc_matters.output_path, doc_matters.src.language);
if (_xml_type == "seg") {
foreach (m; _txt.matchAll(rgx.inline_link_seg_and_hash)) {
if (m.captures["hash"] in doc_matters.has.tag_associations) {
if (m.captures["hash"] == doc_matters.has.tag_associations[(m.captures["hash"])]["seg_lv4"]) {
_txt = _txt.replaceFirst(
rgx.inline_link_seg_and_hash,
"┥$1┝┤"
~ doc_matters.conf_make_meta.conf.w_srv_data_root_url_html
~ "/"
~ pth_html.tail_fn_seg(doc_matters.src.filename, "$2.html")
~ "├"
);
} else {
_txt = _txt.replaceFirst(
rgx.inline_link_seg_and_hash,
"┥$1┝┤"
~ doc_matters.conf_make_meta.conf.w_srv_data_root_url_html
~ "/"
~ doc_matters.src.filename_base
~ "/"
~ doc_matters.has.tag_associations[(m.captures["hash"])]["seg_lv4"]
~ ".html"
~ "#" ~ m.captures["hash"]
~ "├"
);
}
} else {
if (doc_matters.opt.action.vox_gt_1) {
writeln(
"WARNING on internal document links, anchor to link <<"
~ m.captures["hash"]
~ ">> not found in document, "
~ "anchor: " ~ m.captures["hash"]
~ " document: " ~ doc_matters.src.filename
);
}
}
}
} else {
if (auto m = _txt.match(rgx.inline_link_seg_and_hash)) {
_txt = _txt.replaceFirst(
rgx.inline_link_seg_and_hash,
"┥$1┝┤"
~ doc_matters.conf_make_meta.conf.w_srv_data_root_url_html
~ "/"
~ pth_html.tail_fn_scroll(doc_matters.src.filename)
~ "#" ~ m.captures["hash"]
~ "├"
);
}
}
_txt = _txt
.replaceAll(
rgx.inline_link_fn_suffix,
("$1.html"))
.replaceAll(
rgx.inline_link,
("$1"))
.replaceAll(
rgx.mark_internal_site_lnk,
"");
}
debug(markup_links) {
if (_txt.match(rgx.inline_link)) {
writeln(__LINE__,
" (missed) markup link identified (",
obj.has.inline_links,
"): ", obj.metainfo.is_a, ": ",
obj.text
);
}
// if (obj.metainfo.is_a == "bookindex") { // DEBUG LINE
// if (_txt.match(regex(r""
~ "" ~ m.captures["num"] ~ "."
~ m.captures["note"]
~ "
%s
┃", obj.metainfo.is_a, _txt, ); return o; } #+END_SRC ******* +fancy+ ##+NAME: prepare_objects_html #+BEGIN_SRC d string html_heading(M,O)( M doc_matters, const O obj, ) { string o; string _txt = munge_html(doc_matters, obj); o = format(q"┃%s
┃", obj.metainfo.is_a, obj.attrib.indent_hang, obj.attrib.indent_base, _txt ); return o; } #+END_SRC ****** quote #+NAME: html_objects_quote #+BEGIN_SRC d string html_quote(M,O)( M doc_matters, const O obj, ) { assert(obj.metainfo.is_of_part == "body"); assert(obj.metainfo.is_of_section == "body" || "glossary" || "bibliography" || "bookindex" || "blurb"); assert(obj.metainfo.is_of_type == "block"); assert(obj.metainfo.is_a == "quote"); string _txt = munge_html(doc_matters, obj); string o = format(q"┃%s
┃", obj.metainfo.is_a, _txt ); return o; } #+END_SRC ****** group #+NAME: html_objects_group #+BEGIN_SRC d string html_group(M,O)( M doc_matters, const O obj, ) { assert(obj.metainfo.is_of_part == "body"); assert(obj.metainfo.is_of_section == "body" || "glossary" || "bibliography" || "bookindex" || "blurb"); assert(obj.metainfo.is_of_type == "block"); assert(obj.metainfo.is_a == "group"); string _txt = munge_html(doc_matters, obj); _txt = inline_markup(doc_matters, obj, _txt); string o = format(q"┃%s
┃", obj.metainfo.is_a, _txt ); return o; } #+END_SRC ****** block #+NAME: html_objects_block #+BEGIN_SRC d string html_block(M,O)( M doc_matters, const O obj, ) { assert(obj.metainfo.is_of_part == "body"); assert(obj.metainfo.is_of_section == "body" || "glossary" || "bibliography" || "bookindex" || "blurb"); assert(obj.metainfo.is_of_type == "block"); assert(obj.metainfo.is_a == "block"); string _txt = munge_html(doc_matters, obj); _txt = inline_markup(doc_matters, obj, _txt); string o = format(q"┃%s
┃", obj.metainfo.is_a, _txt.stripRight ); return o; } #+END_SRC ****** verse #+NAME: html_objects_verse #+BEGIN_SRC d string html_verse(M,O)( M doc_matters, const O obj, ) { assert(obj.metainfo.is_of_part == "body"); assert(obj.metainfo.is_of_section == "body" || "glossary" || "bibliography" || "bookindex" || "blurb"); assert(obj.metainfo.is_of_type == "block"); assert(obj.metainfo.is_a == "verse"); string _txt = munge_html(doc_matters, obj); string o = format(q"┃%s
┃", obj.metainfo.is_a, _txt ); return o; } #+END_SRC ****** code #+NAME: html_objects_code #+BEGIN_SRC d string html_code(O)( const O obj, ) { assert(obj.metainfo.is_of_part == "body"); assert(obj.metainfo.is_of_section == "body"); assert(obj.metainfo.is_of_type == "block"); assert(obj.metainfo.is_a == "code"); string _txt = html_special_characters_code(obj.text); string o = format(q"┃%s
┃", obj.metainfo.is_a, _txt ); return o; } #+END_SRC ****** table #+NAME: html_objects_table #+BEGIN_SRC d string html_table(M,O)( M doc_matters, const O obj, ) { assert(obj.metainfo.is_of_part == "body"); assert(obj.metainfo.is_of_section == "body"); assert(obj.metainfo.is_of_type == "block"); assert(obj.metainfo.is_a == "table"); Tuple!(string, string) _tablarize(O)( const O obj, string _txt, ) { string[] _table_rows = _txt.split(rgx.table_delimiter_row); string[] _table_cols; string _table; string _tablenote; bool _in_head = false; bool _in_body = false; foreach(row_idx, row; _table_rows) { _table_cols = row.split(rgx.table_delimiter_col); if ((_table_cols.length == 1) && (_table_rows.length <= row_idx+2)) { // check row_idx+2 (rather than == ++row_idx) _tablenote ~= _table_cols[0]; continue; } /+ ↓ a heading row goes in , the rest in +/ if (row_idx == 0 && obj.table.heading) { _table ~= ""; _in_head = true; } else if (!_in_body) { if (_in_head) { _table ~= ""; _in_head = false; } _table ~= ""; _in_body = true; } _table ~= "" ~ _note.strip ~ "
") ); return o; } #+END_SRC *** 2. hub (sqlite_format_and_load_objects) **** sql related #+NAME: sqlite_load_object_string #+BEGIN_SRC d string sqlite_load_string(M,O)( M doc_matters, const O obj, ) { string o; return o; } #+END_SRC #+NAME: sqlite_load_object_statement #+BEGIN_SRC d string sqlite_statement(O)( const O obj, string _txt, string _html, ) { void _sql_exe(O)( string _sql, ) { writeln(_html); writeln(_sql); } string _sql; return _sql; } #+END_SRC **** heading #+NAME: hub_format_and_sqlite_load_objects_heading #+BEGIN_SRC d string[string] heading(M,O)( M doc_matters, const O obj, ) { string[string] obj_txt = [ "text": generic_munge_sanitize_text_for_search(obj.text), "html": html_heading(doc_matters, obj) ]; { /+ debug +/ if (doc_matters.opt.action.debug_do_sqlite) { debug(sql_txt) { writeln(obj_txt["text"]); } debug(sql_html) { writeln(obj_txt["html"]); } } else { // load sql } } return obj_txt; } #+END_SRC **** para #+NAME: hub_format_and_sqlite_load_objects_para #+BEGIN_SRC d string[string] para(M,O)( M doc_matters, const O obj, ) { string[string] obj_txt = [ "text": generic_munge_sanitize_text_for_search(obj.text), "html": html_para(doc_matters, obj) ]; { /+ debug +/ if (doc_matters.opt.action.debug_do_sqlite) { debug(sql_txt) { writeln(obj_txt["text"]); } debug(sql_html) { writeln(obj_txt["html"]); } } else { // load sql } } return obj_txt; } #+END_SRC **** quote #+NAME: hub_format_and_sqlite_load_objects_quote #+BEGIN_SRC d string[string] quote(M,O)( M doc_matters, const O obj, ) { string[string] obj_txt = [ "text": generic_munge_sanitize_text_for_search(obj.text), "html": html_quote(doc_matters, obj) ]; { /+ debug +/ if (doc_matters.opt.action.debug_do_sqlite) { debug(sql_txt) { writeln(obj_txt["text"]); } debug(sql_html) { writeln(obj_txt["html"]); } } else { // load sql } } return obj_txt; } #+END_SRC **** group #+NAME: hub_format_and_sqlite_load_objects_group #+BEGIN_SRC d string[string] group(M,O)( M doc_matters, const O obj, ) { string[string] obj_txt = [ "text": generic_munge_sanitize_text_for_search(obj.text), "html": html_group(doc_matters, obj) ]; { /+ debug +/ if (doc_matters.opt.action.debug_do_sqlite) { debug(sql_txt) { writeln(obj_txt["text"]); } debug(sql_html) { writeln(obj_txt["html"]); } } else { // load sql } } return obj_txt; } #+END_SRC **** block #+NAME: hub_format_and_sqlite_load_objects_block #+BEGIN_SRC d string[string] block(M,O)( M doc_matters, const O obj, ) { string[string] obj_txt = [ "text": generic_munge_sanitize_text_for_search(obj.text), "html": html_block(doc_matters, obj) ]; { /+ debug +/ if (doc_matters.opt.action.debug_do_sqlite) { debug(sql_txt) { writeln(obj_txt["text"]); } debug(sql_html) { writeln(obj_txt["html"]); } } else { // load sql } } return obj_txt; } #+END_SRC **** verse #+NAME: hub_format_and_sqlite_load_objects_verse #+BEGIN_SRC d string[string] verse(M,O)( M doc_matters, const O obj, ) { string[string] obj_txt = [ "text": generic_munge_sanitize_text_for_search(obj.text), "html": html_verse(doc_matters, obj) ]; { /+ debug +/ if (doc_matters.opt.action.debug_do_sqlite) { debug(sql_txt) { writeln(obj_txt["text"]); } debug(sql_html) { writeln(obj_txt["html"]); } } else { // load sql } } return obj_txt; } #+END_SRC **** code #+NAME: hub_format_and_sqlite_load_objects_code #+BEGIN_SRC d string[string] code(M,O)( M doc_matters, const O obj, ) { string[string] obj_txt = [ "text": generic_munge_sanitize_text_for_search(obj.text), "html": html_code(obj) ]; { /+ debug +/ if (doc_matters.opt.action.debug_do_sqlite) { debug(sql_txt) { writeln(obj_txt["text"]); } debug(sql_html) { writeln(obj_txt["html"]); } } else { // load sql } } return obj_txt; } #+END_SRC **** table #+NAME: hub_format_and_sqlite_load_objects_table #+BEGIN_SRC d string[string] table(M,O)( M doc_matters, const O obj, ) { string[string] obj_txt = [ "text": generic_munge_sanitize_text_for_search(obj.text), "html": html_table(doc_matters, obj) ]; { /+ debug +/ if (doc_matters.opt.action.debug_do_sqlite) { debug(sql_txt) { writeln(obj_txt["text"]); } debug(sql_html) { writeln(obj_txt["html"]); } } else { // load sql } } return obj_txt; } #+END_SRC ** 4. ↻ loop, identify, load - loop template #+NAME: sqlite_objects_loop #+BEGIN_SRC d auto format_and_sqlite_load = SQLiteFormatAndLoadObject!()(doc.matters); string[string] obj_txt; string doc_text; string[] _insert_doc_objects; foreach (part; doc.matters.has.keys_seq.sql) { foreach (obj; doc.abstraction[part]) { switch (obj.metainfo.is_of_part) { case "frontmatter": assert(part == "head", part); switch (obj.metainfo.is_of_type) { case "para": switch (obj.metainfo.is_a) { case "heading": obj_txt = format_and_sqlite_load.heading(doc.matters, obj); break; default: { /+ debug +/ if (doc.matters.opt.action.debug_do_sqlite) { writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); } } break; } break; default: { /+ debug +/ if (doc.matters.opt.action.debug_do_sqlite) { writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_type); } } break; } break; case "body": // assert(part == "body", part); switch (obj.metainfo.is_of_type) { case "para": switch (obj.metainfo.is_a) { case "heading": debug (asserts) { if (part != "body") { writeln(__LINE__, ": ", obj.text); } } obj_txt = format_and_sqlite_load.heading(doc.matters, obj); break; case "para": obj_txt = format_and_sqlite_load.para(doc.matters, obj); break; default: { /+ debug +/ if (doc.matters.opt.action.debug_do_sqlite) { writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); } } break; } break; case "block": switch (obj.metainfo.is_a) { case "quote": obj_txt = format_and_sqlite_load.quote(doc.matters, obj); break; case "group": obj_txt = format_and_sqlite_load.group(doc.matters, obj); break; case "block": obj_txt = format_and_sqlite_load.block(doc.matters, obj); break; case "poem": // double check on keeping both poem & verse break; case "verse": obj_txt = format_and_sqlite_load.verse(doc.matters, obj); break; case "code": obj_txt = format_and_sqlite_load.code(doc.matters, obj); break; case "table": obj_txt = format_and_sqlite_load.table(doc.matters, obj); break; default: { /+ debug +/ if (doc.matters.opt.action.debug_do_sqlite) { writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); } } break; } break; default: { /+ debug +/ if (doc.matters.opt.action.debug_do_sqlite) { writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_type); } } break; } break; case "backmatter": assert(part == "glossary" || "bibliography" || "bookindex" || "blurb" || "tail", part); switch (obj.metainfo.is_of_type) { case "para": switch (obj.metainfo.is_a) { case "heading": obj_txt = format_and_sqlite_load.heading(doc.matters, obj); break; case "glossary": assert(part == "glossary", part); obj_txt = format_and_sqlite_load.para(doc.matters, obj); break; case "bibliography": assert(part == "bibliography", part); obj_txt = format_and_sqlite_load.para(doc.matters, obj); break; case "bookindex": assert(part == "bookindex", part); obj_txt = format_and_sqlite_load.para(doc.matters, obj); break; case "blurb": assert(part == "blurb", part); obj_txt = format_and_sqlite_load.para(doc.matters, obj); break; default: { /+ debug +/ if (doc.matters.opt.action.debug_do_sqlite) { writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); } } break; } break; default: { /+ debug +/ if (doc.matters.opt.action.debug_do_sqlite) { writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_type); } } break; } break; case "comment": break; default: { /+ debug +/ if (doc.matters.opt.action.debug_do_sqlite) { writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_of_part); // check where empty value could come from writeln(__FILE__, ":", __LINE__, ": ", obj.metainfo.is_a); writeln(__FILE__, ":", __LINE__, ": ", obj.text); // check where empty value could come from } } break; } if (obj.metainfo.is_a == "heading") { if (doc.matters.opt.action.show_sqlite) { if (obj.metainfo.heading_lev_markup == 0) { writeln(doc.matters.src.filename); } writeln( "markup: ", obj.metainfo.heading_lev_markup, "> ", obj.metainfo.dom_structure_markedup_tags_status, "; collapsed: ", obj.metainfo.heading_lev_collapsed, "> ", obj.metainfo.dom_structure_collapsed_tags_status, "; ocn: ", obj.metainfo.ocn, "; parent: ", obj.metainfo.parent_lev_markup, "; ocn: ", obj.metainfo.parent_ocn, "; ", ); } } if (!(obj.metainfo.is_a == "comment")) { _insert_doc_objects ~= insertDocObjectsRow(obj); } } // loop closes } return _insert_doc_objects.join.to!(char[]).toUTF8; #+END_SRC ** 5. SQL statements :statement: *** drop index and tables **** DROP INDEX IF EXISTS #+NAME: sqlite_statement_drop_existing_index #+BEGIN_SRC sql DROP INDEX IF EXISTS idx_ocn; DROP INDEX IF EXISTS idx_uid; DROP INDEX IF EXISTS idx_digest_clean; DROP INDEX IF EXISTS idx_digest_all; DROP INDEX IF EXISTS idx_clean; DROP INDEX IF EXISTS idx_title; DROP INDEX IF EXISTS idx_author; DROP INDEX IF EXISTS src_filename_base; DROP INDEX IF EXISTS idx_language_document_char; DROP INDEX IF EXISTS idx_classify_topic_register; DROP INDEX IF EXISTS idx_topic_list; #+END_SRC **** DROP TABLE IF EXISTS #+NAME: sqlite_statement_drop_existing_tables #+BEGIN_SRC sql DROP TABLE IF EXISTS metadata_and_text; DROP TABLE IF EXISTS topic_register; DROP TABLE IF EXISTS doc_objects; DROP TABLE IF EXISTS urls; #+END_SRC *** create tables and index **** CREATE TABLE IF NOT EXISTS metadata_and_text #+NAME: sqlite_statement_create_table_metadata_and_src_txt #+BEGIN_SRC sql CREATE TABLE IF NOT EXISTS metadata_and_text ( uid VARCHAR(256) UNIQUE, -- filename, language char, pod/txt (decide on delimiter [,;:/]) src_composite_id_per_txt VARCHAR(256) NOT NULL, -- UNIQUE, z pod name if any + src filename + language code src_composite_id_per_pod VARCHAR(256) NOT NULL, -- z pod name if any + src filename title VARCHAR(800) NOT NULL, title_main VARCHAR(400) NOT NULL, title_sub VARCHAR(400) NULL, title_short VARCHAR(400) NULL, title_edition VARCHAR(10) NULL, title_language VARCHAR(100) NULL, title_language_char VARCHAR(6) NULL, creator_author VARCHAR(600) NOT NULL, creator_author_last_first VARCHAR(600) NOT NULL, creator_author_email VARCHAR(100) NULL, creator_author_hon VARCHAR(100) NULL, creator_author_nationality VARCHAR(100) NULL, creator_editor VARCHAR(600) NULL, creator_contributor VARCHAR(600) NULL, creator_illustrator VARCHAR(600) NULL, creator_photographer VARCHAR(600) NULL, creator_translator VARCHAR(600) NULL, creator_prepared_by VARCHAR(600) NULL, creator_digitized_by VARCHAR(600) NULL, creator_audio VARCHAR(600) NULL, creator_video VARCHAR(600) NULL, language_document VARCHAR(100) NULL, language_document_char VARCHAR(6) NOT NULL, language_original VARCHAR(100) NULL, language_original_char VARCHAR(6) NULL, date_added_to_site VARCHAR(10) NULL, date_available VARCHAR(10) NULL, date_created VARCHAR(10) NULL, date_issued VARCHAR(10) NULL, date_modified VARCHAR(10) NULL, date_published VARCHAR(10) NULL, date_valid VARCHAR(10) NULL, date_translated VARCHAR(10) NULL, date_original_publication VARCHAR(10) NULL, date_generated VARCHAR(10) NULL, original_title VARCHAR(800) NULL, original_publisher VARCHAR(600) NULL, original_language VARCHAR(100) NULL, original_language_char VARCHAR(6) NULL, original_source VARCHAR(600) NULL, original_institution VARCHAR(600) NULL, original_nationality VARCHAR(100) NULL, rights_copyright VARCHAR(2500) NULL, rights_copyright_audio VARCHAR(2500) NULL, rights_copyright_cover VARCHAR(2500) NULL, rights_copyright_illustrations VARCHAR(2500) NULL, rights_copyright_photographs VARCHAR(2500) NULL, rights_copyright_text VARCHAR(2500) NULL, rights_copyright_translation VARCHAR(2500) NULL, rights_copyright_video VARCHAR(2500) NULL, rights_license VARCHAR(2500) NULL, identifier_oclc VARCHAR(30) NULL, identifier_isbn VARCHAR(16) NULL, classify_topic_register VARCHAR(2500) NULL, classify_subject VARCHAR(600) NULL, classify_loc VARCHAR(30) NULL, classify_dewey VARCHAR(30) NULL, classify_keywords VARCHAR(600) NULL, notes_abstract TEXT NULL, notes_description TEXT NULL, notes_comment TEXT NULL, notes_coverage VARCHAR(200) NULL, notes_relation VARCHAR(200) NULL, notes_history VARCHAR(600) NULL, notes_type VARCHAR(600) NULL, notes_format VARCHAR(600) NULL, notes_prefix TEXT NULL, notes_prefix_a TEXT NULL, notes_prefix_b TEXT NULL, notes_suffix TEXT NULL, publisher VARCHAR(600) NULL, src_filename_base VARCHAR(256) NOT NULL, src_filename_suffix VARCHAR(6) NOT NULL, src_fingerprint VARCHAR(256) NULL, src_filesize VARCHAR(10) NULL, src_wordcount VARCHAR(10) NULL, pod_name VARCHAR(256) NULL, -- zipped pod, work to be done here pod_fingerprint VARCHAR(256) NULL, -- zipped pod, work to be done here pod_size VARCHAR(10) NULL, -- zipped pod, work to be done here site_url_doc_root VARCHAR(256) NULL, -- url path to doc root site_url_html_toc VARCHAR(256) NULL, site_url_html_scroll VARCHAR(256) NULL, site_url_epub VARCHAR(256) NULL, links TEXT NULL ); #+END_SRC **** CREATE TABLE IF NOT EXISTS topic_register #+NAME: sqlite_statement_create_table_topic_register #+BEGIN_SRC sql CREATE TABLE IF NOT EXISTS topic_register ( -- tid BIGINT PRIMARY KEY, uid_metadata_and_text VARCHAR(256) REFERENCES metadata_and_text(uid) ON DELETE CASCADE, -- src_composite_id_per_txt VARCHAR(256) NOT NULL, - UNIQUE, - z pod name if any + src filename + language code -- src_composite_id_per_pod VARCHAR(256) NOT NULL, - z pod name if any + src filename topic_register VARCHAR(250) NOT NULL, site_url_doc_root VARCHAR(256) NULL, -- url path to doc root site_url_html_toc VARCHAR(256) NULL, site_url_html_scroll VARCHAR(256) NULL ); #+END_SRC **** CREATE TABLE site_urls ? #+NAME: sqlite_statement_create_table_site_urls #+BEGIN_SRC sql CREATE TABLE IF NOT EXISTS site_urls ( -- tid BIGINT PRIMARY KEY, uid_metadata_and_text VARCHAR(256) REFERENCES metadata_and_text(uid) ON DELETE CASCADE, src_composite_id_per_txt VARCHAR(256) NOT NULL, -- UNIQUE, - z pod name if any + src filename + language code src_composite_id_per_pod VARCHAR(256) NOT NULL, -- z pod name if any + src filename site_url_doc_root VARCHAR(256) NULL, -- url path to doc root site_url_html_toc VARCHAR(256) NULL, site_url_html_scroll VARCHAR(256) NULL ); #+END_SRC **** CREATE TABLE doc_objects #+NAME: sqlite_statement_create_table_objects #+BEGIN_SRC sql CREATE TABLE IF NOT EXISTS doc_objects ( lid BIGINT PRIMARY KEY, uid_metadata_and_text VARCHAR(256) REFERENCES metadata_and_text(uid) ON DELETE CASCADE, ocn SMALLINT, obj_id VARCHAR(6) NULL, clean TEXT NULL, body TEXT NULL, seg VARCHAR(256) NULL, lev_an VARCHAR(1), is_of_type VARCHAR(16), is_a VARCHAR(16), lev SMALLINT NULL, node VARCHAR(16) NULL, -- not written to parent VARCHAR(16) NULL, last_descendant VARCHAR(16) NULL, -- headings only digest_clean CHAR(256), digest_all CHAR(256), seg_name CHAR(256), types CHAR(1) NULL ); #+END_SRC **** CREATE INDEX #+NAME: sqlite_statement_create_index #+BEGIN_SRC sql CREATE INDEX IF NOT EXISTS idx_ocn ON doc_objects(ocn); CREATE INDEX IF NOT EXISTS idx_digest_clean ON doc_objects(digest_clean); CREATE INDEX IF NOT EXISTS idx_digest_all ON doc_objects(digest_all); CREATE INDEX IF NOT EXISTS idx_clean ON doc_objects(clean); CREATE INDEX IF NOT EXISTS idx_title ON metadata_and_text(title); CREATE INDEX IF NOT EXISTS idx_author ON metadata_and_text(creator_author_last_first); CREATE INDEX IF NOT EXISTS idx_uid ON metadata_and_text(uid); CREATE INDEX IF NOT EXISTS idx_filename ON metadata_and_text(src_filename_base); CREATE INDEX IF NOT EXISTS idx_language ON metadata_and_text(language_document_char); CREATE INDEX IF NOT EXISTS idx_topics ON metadata_and_text(classify_topic_register); CREATE INDEX IF NOT EXISTS idx_topic_list ON topic_register(topic_register); #+END_SRC *** TODO local site link & info *** delete rows (delete document) **** DELETE uid rows doc matters & metadata ***** sql statement: dlang format #+NAME: sqlite_formatted_delete_format #+BEGIN_SRC d string _uid = doc_matters.src.doc_uid; string _delete_uid = format(q"┃ #+END_SRC ***** DELETE FROM ... WHERE #+NAME: sqlite_formatted_delete_sql #+BEGIN_SRC sql DELETE FROM metadata_and_text WHERE uid = '%s'; DELETE FROM doc_objects WHERE uid_metadata_and_text = '%s'; #+END_SRC ***** VALUES #+NAME: sqlite_formatted_delete_values #+BEGIN_SRC d ┃", _uid, _uid, ); #+END_SRC *** inserts **** INSERT doc matters & metadata ***** sql statement: dlang format #+NAME: sqlite_formatted_insertions_doc_matters_metadata_format #+BEGIN_SRC d string _uid = SQLinsertDelimiter!()(doc_matters.src.doc_uid); string _insert_metadata = format(q"┃ #+END_SRC ***** INSERT INTO #+NAME: sqlite_formatted_insertions_doc_matters_metadata_sql #+BEGIN_SRC sql INSERT INTO metadata_and_text ( uid, src_filename_base, src_filename_suffix, src_composite_id_per_txt, src_composite_id_per_pod, title, title_main, title_sub, title_short, title_edition, title_language, creator_author, creator_author_last_first, creator_author_email, creator_illustrator, creator_translator, language_document, language_document_char, date_added_to_site, date_available, date_created, date_issued, date_modified, date_published, date_valid, rights_copyright, rights_copyright_audio, rights_copyright_cover, rights_copyright_illustrations, rights_copyright_photographs, rights_copyright_text, rights_copyright_translation, rights_copyright_video, rights_license, identifier_oclc, identifier_isbn, classify_dewey, classify_keywords, classify_loc, classify_subject, classify_topic_register, original_title, original_publisher, original_language, original_language_char, original_source, notes_abstract, notes_description, publisher, site_url_doc_root ) #+END_SRC ***** VALUES #+NAME: sqlite_formatted_insertions_doc_matters_metadata_sql_values #+BEGIN_SRC sql VALUES ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' ); #+END_SRC ***** dlang values for formatting #+NAME: sqlite_formatted_insertions_doc_matters_metadata_values #+BEGIN_SRC d ┃", _uid, SQLinsertDelimiter!()(doc_matters.src.filename_base), SQLinsertDelimiter!()(doc_matters.src.filename_extension), SQLinsertDelimiter!()(doc_matters.src.docname_composite_unique_per_src_doc), SQLinsertDelimiter!()(doc_matters.src.docname_composite_unique_per_src_pod), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.title_full), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.title_main), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.title_subtitle), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.title_short), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.title_edition), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.title_language), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.creator_author), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.creator_author_surname_fn), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.creator_author_email), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.creator_illustrator), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.creator_translator), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.language_document), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.language_document_char), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.date_added_to_site), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.date_available), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.date_created), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.date_issued), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.date_modified), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.date_published), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.date_valid), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_copyright), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_copyright_audio), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_copyright_cover), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_copyright_illustrations), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_copyright_photographs), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_copyright_text), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_copyright_translation), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_copyright_video), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.rights_license), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.identifier_oclc), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.identifier_isbn), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.classify_dewey), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.classify_keywords), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.classify_loc), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.classify_subject), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.classify_topic_register), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.notes_abstract), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.notes_description), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.original_title), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.original_publisher), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.original_language), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.original_language_char), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.original_source), SQLinsertDelimiter!()(doc_matters.conf_make_meta.meta.publisher), SQLinsertDelimiter!()(doc_matters.conf_make_meta.conf.w_srv_data_root_url_html) ); #+END_SRC **** INSERT topic register writeln(doc_matters.conf_make_meta.meta.classify_topic_register_arr); ***** loop sql statement: dlang format #+NAME: sqlite_formatted_insertions_topic_register_loop #+BEGIN_SRC d string _uid = SQLinsertDelimiter!()(doc_matters.src.doc_uid); string[] _insert_topics; foreach (topic_line; doc_matters.conf_make_meta.meta.classify_topic_register_expanded_arr) { // writeln(topic_line); #+END_SRC ***** sql statement: dlang format #+NAME: sqlite_formatted_insertions_topic_register_format #+BEGIN_SRC d _insert_topics ~= format(q"┃ #+END_SRC ***** INSERT INTO #+NAME: sqlite_formatted_insertions_topic_register_sql #+BEGIN_SRC sql INSERT INTO topic_register ( uid_metadata_and_text, topic_register ) #+END_SRC ***** VALUES #+NAME: sqlite_formatted_insertions_topic_register_sql_values #+BEGIN_SRC sql VALUES ( '%s', '%s' ); #+END_SRC ***** dlang values for formatting #+NAME: sqlite_formatted_insertions_topic_register_values #+BEGIN_SRC d ┃", _uid, SQLinsertDelimiter!()(topic_line) ); #+END_SRC **** INSERT doc objects lid unique, increment by 1 per object, not ocn metadata tid document number unique either: - increment by adding 1 for each document, - make hash of document filename or url and use? ***** sql statement: dlang format #+NAME: sqlite_formatted_insertions_doc_objects_format #+BEGIN_SRC d string _insert_doc_objects_row = format(q"┃ #+END_SRC ***** INSERT INTO #+NAME: sqlite_formatted_insertions_doc_objects_sql #+BEGIN_SRC sql INSERT INTO doc_objects ( uid_metadata_and_text, ocn, obj_id, clean, body, lev, is_of_type, is_a, seg_name ) #+END_SRC ***** VALUES #+NAME: sqlite_formatted_insertions_doc_objects_sql_values #+BEGIN_SRC sql VALUES ( '%s', %s, '%s', '%s', '%s', %s, '%s', '%s', '%s' ); #+END_SRC ***** dlang values for formatting #+NAME: sqlite_formatted_insertions_doc_objects_values #+BEGIN_SRC d ┃", _uid, obj.metainfo.ocn, obj.metainfo.identifier, SQLinsertDelimiter!()(obj_txt["text"]), SQLinsertDelimiter!()(obj_txt["html"]), obj.metainfo.heading_lev_markup, obj.metainfo.is_of_type, obj.metainfo.is_a, obj.tags.html_segment_anchor_tag_is ); #+END_SRC * org includes * sqlite collection search db schema version #+NAME: sqlite_collection_search_db_schema_version #+BEGIN_SRC org <<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:sqlite_collection_search_db_schema_version()>> #+END_SRC ** project version #+NAME: spine_version #+HEADER: :noweb yes #+BEGIN_SRC emacs-lisp <<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:spine_project_version()>> #+END_SRC ** year #+NAME: year #+HEADER: :noweb yes #+BEGIN_SRC emacs-lisp <<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:year()>> #+END_SRC ** document header including copyright & license #+NAME: doc_header_including_copyright_and_license #+HEADER: :noweb yes #+BEGIN_SRC emacs-lisp <<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:spine_doc_header_including_copyright_and_license()>> #+END_SRC * __END__