2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 // this rebuilds FTS5 tables in SQLite supplementary mail database.
18 module zsq_rebuild_fts5
is aliced
;
29 // ////////////////////////////////////////////////////////////////////////// //
30 extern(C
) int progressCB (void*) nothrow @nogc {
31 import core
.sys
.posix
.unistd
: write
, STDOUT_FILENO
;
32 static immutable string rotator
= "|/-\\";
33 static ubyte rpos
= 0;
36 buf
[1] = rotator
.ptr
[rpos
++];
38 write(STDOUT_FILENO
, buf
.ptr
, 3);
43 // ////////////////////////////////////////////////////////////////////////// //
44 void main (string
[] args
) {
45 ChiroTimerEnabled
= true;
46 chiroParseCommonCLIArgs(args
);
48 // here, i don't have any threads at all
49 if (sqlite3_config(SQLITE_CONFIG_SINGLETHREAD
) != SQLITE_OK
) throw new Exception("cannot switch SQLite to multi-threaded mode");
51 writeln("opening message support db...");
54 writeln("recreating FTS5 table...");
56 Timer ctm
= Timer(false);
59 if (args
.length
< 2 || args
[1] != "separate") {
63 foreach (auto row
; dbView
.statement(`SELECT COUNT(*) AS total FROM info;`).range
) total
= row
.total
!uint;
65 //sqlite3_progress_handler(dbView.getHandle, 2, &progressCB);
68 foreach (auto row
; dbView
.statement(`
69 SELECT COUNT(uid) AS processed
73 SELECT threads.tagid FROM threads
74 INNER JOIN tagnames USING(tagid)
76 threads.uid=info.uid AND
77 tagnames.hidden=0 AND SUBSTR(tagnames.tag, 1, 1)='/'
79 ;`).range
) processed
= row
.processed
!uint;
81 writeln("\r", total
, " messages processed (", total
-processed
, " skipped; ", processed
, " recorded).\x1b[K");
83 chiroRecreateFTS5(repopulate
:false);
85 auto stInsFTS5
= dbView
.persistentStatement(`
86 INSERT INTO fts5_messages
87 ( rowid, sender, subj, text, html)
88 VALUES( :uid,:sender,:subj,:text,:html)
91 auto stSelEmailNeedFTS
= dbView
.persistentStatement(`
92 SELECT threads.tagid AS tagid
94 INNER JOIN tagnames USING(tagid)
97 tagnames.hidden=0 AND SUBSTR(tagnames.tag, 1, 1)='/'
101 writeln("populating FTS5 table...");
103 foreach (auto row
; dbView
.statement(`SELECT count(*) AS total FROM info;`).range
) { total
= row
.total
!uint; break; }
107 dbView
.execute(`BEGIN TRANSACTION;`);
108 foreach (auto row
; dbView
.statement(`
109 SELECT uid AS uid, sender AS sender, subj AS subj, text AS text, html AS html
113 SELECT threads.tagid FROM threads
114 INNER JOIN tagnames USING(tagid)
116 threads.uid=fts5_msgview.uid AND
117 tagnames.hidden=0 AND SUBSTR(tagnames.tag, 1, 1)='/'
121 immutable uid
= row
.uid
!uint;
125 .bindConstText(":sender", row
.sender
!SQ3Text
)
126 .bindConstText(":subj", row
.subj
!SQ3Text
)
127 .bindConstText(":text", row
.text
!SQ3Text
)
128 .bindConstText(":html", row
.html
!SQ3Text
)
131 if (processed
%1024 == 1) {
132 write(" ", processed
, " ", processed
*100u/total
, "%\x1b[K\r");
135 dbView
.execute(`COMMIT TRANSACTION;`);
137 writeln("time: ", ctm
.toString
, "\x1b[K");
138 writeln(total
, " messages processed (", total
-processed
, " skipped, ", processed
, " recorded).\x1b[K");
143 writeln("closing time: ", ctm
.toString
, "\x1b[K");