feat(draft): add /history export|import for SQLite<->flatfile migration
DRAFT — not yet tested end-to-end with a live XMPP session. New commands: /history export [<jid>] — copy messages from SQLite to flat-file /history import [<jid>] — copy messages from flat-file to SQLite Both merge with existing data; duplicates are skipped using stanza-id or a SHA-256 fallback key (timestamp + sender + body prefix). Implementation (src/database_export.c): - Export: paginate SQLite via get_previous_chat, read existing flatfile for dedup, write merged result via ff_write_line + atomic rename - Import: parse flatfile lines via ff_parse_line, build dedup set from SQLite, insert new messages via add_incoming (preserves original timestamps for both directions) - List all contacts: db_sqlite_list_contacts() queries UNION of DISTINCT from_jid/to_jid; flatfile enumerates flatlog directories Wiring: - database.h: declare export/import functions + db_sqlite_list_contacts - database_sqlite.c: add db_sqlite_list_contacts() - cmd_defs.c: add export/import to /history synopsis and args - cmd_funcs.c: add export/import handlers in cmd_history() - cmd_ac.c: add 'export' and 'import' to history_ac - Makefile.am: add database_export.c to core_sources - stub_database.c: add stubs for test linking - profanity.1: document export/import in man page All code guarded with #ifdef HAVE_SQLITE — builds cleanly without it.
This commit is contained in:
@@ -817,3 +817,37 @@ db_backend_sqlite(void)
|
||||
{
|
||||
return &sqlite_backend;
|
||||
}
|
||||
|
||||
GSList*
|
||||
db_sqlite_list_contacts(void)
|
||||
{
|
||||
GSList* contacts = NULL;
|
||||
if (!g_chatlog_database)
|
||||
return NULL;
|
||||
|
||||
const Jid* myjid = connection_get_jid();
|
||||
if (!myjid || !myjid->barejid)
|
||||
return NULL;
|
||||
|
||||
const char* q = "SELECT DISTINCT `from_jid` FROM `ChatLogs` "
|
||||
"WHERE `from_jid` != ? "
|
||||
"UNION "
|
||||
"SELECT DISTINCT `to_jid` FROM `ChatLogs` "
|
||||
"WHERE `to_jid` != ?";
|
||||
sqlite3_stmt* stmt = NULL;
|
||||
if (!_db_prepare_ctx(q, &stmt, "db_sqlite_list_contacts"))
|
||||
return NULL;
|
||||
|
||||
sqlite3_bind_text(stmt, 1, myjid->barejid, -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 2, myjid->barejid, -1, SQLITE_STATIC);
|
||||
|
||||
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
const char* jid = (const char*)sqlite3_column_text(stmt, 0);
|
||||
if (jid && strlen(jid) > 0) {
|
||||
contacts = g_slist_append(contacts, g_strdup(jid));
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
return contacts;
|
||||
}
|
||||
Reference in New Issue
Block a user