aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sisudoc/outputs
diff options
context:
space:
mode:
Diffstat (limited to 'src/sisudoc/outputs')
-rw-r--r--src/sisudoc/outputs/io_out/sqlite.d59
1 files changed, 55 insertions, 4 deletions
diff --git a/src/sisudoc/outputs/io_out/sqlite.d b/src/sisudoc/outputs/io_out/sqlite.d
index f96846d..1e1970e 100644
--- a/src/sisudoc/outputs/io_out/sqlite.d
+++ b/src/sisudoc/outputs/io_out/sqlite.d
@@ -64,6 +64,49 @@ static auto rgx = RgxO();
static auto rgx_xhtml = RgxXHTML();
static auto mkup = InlineMarkup();
long _metadata_tid_lastrowid;
+/+ ↓ sqlite db schema version, stamped into the db as PRAGMA user_version +/
+/+ bump whenever the table or index definitions in this module change, and +/
+/+ bump the matching expectation in sisudoc-spine-search-cgi +/
+enum sqlite_db_schema_version = 1;
+/+ ↓ tally of failed sqlite statements, shared: sqlite output may run in parallel +/
+private shared int _sqlite_failure_tally = 0;
+/+ ↓ schema version mismatch is reported once per run, not once per document +/
+private shared int _sqlite_schema_mismatch_reported = 0;
+/+ ↓ record a failed sqlite statement, reported on stderr, tallied for exit status +/
+void sqliteFailureRecord(string note, string msg) {
+ import core.atomic : atomicOp;
+ atomicOp!"+="(_sqlite_failure_tally, 1);
+ stderr.writeln("ERROR SQLite (", note, "): ", msg);
+}
+/+ ↓ count of failed sqlite statements this run, zero when all went well +/
+int sqliteFailureTally() {
+ import core.atomic : atomicLoad;
+ return atomicLoad(_sqlite_failure_tally);
+}
+/+ ↓ compare the schema version stamped in an existing db with this spine's +/
+void sqliteSchemaVersionCheck(Db)(Db db, string sqlite_file) {
+ import core.atomic : atomicOp;
+ int _found;
+ try {
+ _found = db.execute("PRAGMA user_version;").oneValue!int;
+ } catch (Exception) {
+ return;
+ }
+ if (_found == sqlite_db_schema_version
+ || _found == 0) { /+ ↓ zero: db predates the stamp, or has no tables yet +/
+ return;
+ }
+ if (atomicOp!"+="(_sqlite_schema_mismatch_reported, 1) == 1) {
+ stderr.writeln("ERROR SQLite : db schema version mismatch: ", sqlite_file);
+ stderr.writeln(" db holds schema version ", _found,
+ ", this spine writes schema version ", sqlite_db_schema_version);
+ stderr.writeln(" recreate the db, e.g.: spine --sqlite-db-recreate",
+ " --sqlite-db-path=... --sqlite-db-filename=...");
+ sqliteFailureRecord("schema version",
+ "db schema version " ~ _found.to!string
+ ~ " != spine schema version " ~ sqlite_db_schema_version.to!string);
+ }
+}
template SQLiteHubBuildTablesAndPopulate() {
void SQLiteHubBuildTablesAndPopulate(D)(D doc) {
auto pth_sqlite = spinePathsSQLite!()(doc.matters.sqlite.filename, doc.matters.sqlite.path);
@@ -129,6 +172,7 @@ template SQLiteHubBuildTablesAndPopulate() {
}
try {
auto db = Database(pth_sqlite.sqlite_file);
+ sqliteSchemaVersionCheck(db, pth_sqlite.sqlite_file);
SQLiteDbStatementComposite!()(db, doc);
}
catch (FileException e) {
@@ -172,6 +216,7 @@ template SQLiteHubDiscreteBuildTablesAndPopulate() {
}
}
auto db = Database(pth_sqlite.sqlite_file(doc.matters.src.filename));
+ sqliteSchemaVersionCheck(db, pth_sqlite.sqlite_file(doc.matters.src.filename));
template SQLiteDiscreteDbStatementComposite() {
void SQLiteDiscreteDbStatementComposite(Db,D)(
Db db,
@@ -235,9 +280,9 @@ template SQLiteDbRun() {
"\nCOMMIT TRANSACTION;\n"
);
} catch (ErrnoException ex) {
- writeln("ERROR SQLite : ", ex);
+ sqliteFailureRecord(note, ex.msg);
} catch (Exception ex) {
- writeln("ERROR SQLite : ", ex);
+ sqliteFailureRecord(note, ex.msg);
}
{ /+ debug +/
if (opt_action.debug_do_sqlite) {
@@ -1142,7 +1187,10 @@ template SQLiteTablesReCreate() {
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);
- ┃",);
+ PRAGMA user_version = %s;
+ ┃",
+ sqlite_db_schema_version,
+ );
return _sql_instruct;
}
}
@@ -1654,7 +1702,10 @@ template SQLiteTablesCreate() {
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);
- ┃",);
+ PRAGMA user_version = %s;
+ ┃",
+ sqlite_db_schema_version,
+ );
return _sql_instruct;
}
}