db_sync: unified msg table — one DB, one table per channel
- db_sync: rename column author→node_id, open chats.db instead of sync file, db_sync_instance_add takes table_name directly - chat_core: remove CREATE TABLE msg_ch_*, remove on_db_sync_insert (74 lines), remove fallback INSERT in submit_message, add minimal on_msg_inserted for GUI notification only - db_manager: update getMessages for new schema (parse JSON from data column), fix ORDER BY to use author_signature instead of datahash, update syncCursorNext to parse JSON - si_register simplified: db_count from same table, no more msg vs sync gap
This commit is contained in:
1 parent
7c2798ec0e
commit
e71cae16c1
4 files changed
+93
-164
No files matched your search
@@ -46,7 +46,7 @@ QByteArray DbManager::computeChainHash(const QByteArray& prevChain,
|
||||
QByteArray DbManager::getLastChainHash(const QString& chId) const {
|
||||
QString tbl = msgTableName(chId);
|
||||
QByteArray sql = QStringLiteral(
|
||||
"SELECT chain_hash FROM \"%1\" ORDER BY timestamp, datahash DESC LIMIT 1")
|
||||
"SELECT chain_hash FROM \"%1\" ORDER BY timestamp, author_signature DESC LIMIT 1")
|
||||
.arg(tbl).toUtf8();
|
||||
sqlite3_stmt* stmt = prepareOrNull(sql.constData());
|
||||
if (!stmt) return QByteArray(32, '\0');
|
||||
@@ -125,24 +125,39 @@ QList<ChannelRow> DbManager::getChannels() const {
|
||||
QList<MessageRow> DbManager::getMessages(const QString& chId, int limit) const {
|
||||
QList<MessageRow> list;
|
||||
QString sql = QStringLiteral(
|
||||
"SELECT id, node_id, content_type, data, timestamp, datahash, chain_hash,"
|
||||
" signature, is_outgoing, is_read"
|
||||
" FROM \"%1\" ORDER BY timestamp, datahash ASC LIMIT ?").arg(msgTableName(chId));
|
||||
"SELECT id, node_id, data, timestamp, chain_hash, author_signature"
|
||||
" FROM \"%1\" ORDER BY timestamp, author_signature ASC LIMIT ?").arg(msgTableName(chId));
|
||||
sqlite3_stmt* stmt = prepareOrNull(sql.toUtf8().constData());
|
||||
if (!stmt) return list;
|
||||
sqlite3_bind_int(stmt, 1, limit);
|
||||
/* helper: parse JSON field from data column: {"n":<id>,"ch":"<id>","ct":"<>","d":"<>"} */
|
||||
auto parseJsonField = [](const QByteArray& json, const char* key) -> QByteArray {
|
||||
QByteArray pat = "\"" + QByteArray(key) + "\":\"";
|
||||
int idx = json.indexOf(pat);
|
||||
if (idx < 0) return {};
|
||||
idx += pat.size();
|
||||
int end = idx;
|
||||
while (end < json.size() && !(json[end] == '"' && (end == idx || json[end - 1] != '\\'))) end++;
|
||||
if (end > idx) return QByteArray(json.constData() + idx, end - idx);
|
||||
return {};
|
||||
};
|
||||
uint64_t myId = 0;
|
||||
{ sqlite3_stmt* ms = prepareOrNull("SELECT node_id FROM local_identity WHERE id=1");
|
||||
if (ms) { if (sqlite3_step(ms) == SQLITE_ROW) myId = (uint64_t)sqlite3_column_int64(ms, 0); sqlite3_finalize(ms); } }
|
||||
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
MessageRow m;
|
||||
m.id = sqlite3_column_int64(stmt, 0);
|
||||
m.authorNodeId = (quint64)sqlite3_column_int64(stmt, 1);
|
||||
m.contentType = colText(stmt, 2);
|
||||
m.data = colBlob(stmt, 3);
|
||||
m.timestamp = sqlite3_column_int64(stmt, 4);
|
||||
m.datahash = (uint64_t)sqlite3_column_int64(stmt, 5);
|
||||
m.chainHash = colBlob(stmt, 6);
|
||||
m.signature = colBlob(stmt, 7);
|
||||
m.isOutgoing = sqlite3_column_int(stmt, 8) != 0;
|
||||
m.isRead = sqlite3_column_int(stmt, 9) != 0;
|
||||
QByteArray jdata = colBlob(stmt, 2);
|
||||
m.contentType = QString::fromUtf8(parseJsonField(jdata, "ct"));
|
||||
if (m.contentType.isEmpty()) m.contentType = "text/plain";
|
||||
m.data = parseJsonField(jdata, "d");
|
||||
m.timestamp = sqlite3_column_int64(stmt, 3);
|
||||
m.datahash = 0;
|
||||
m.chainHash = colBlob(stmt, 4);
|
||||
m.signature = colBlob(stmt, 5);
|
||||
m.isOutgoing = (m.authorNodeId == myId);
|
||||
m.isRead = true;
|
||||
list.append(m);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
@@ -376,7 +391,7 @@ QByteArray DbManager::syncCount(const QString& chId) const {
|
||||
|
||||
QByteArray DbManager::syncChainHashAt(const QString& chId, uint32_t pos) const {
|
||||
QString sql = QStringLiteral(
|
||||
"SELECT chain_hash FROM \"%1\" ORDER BY timestamp, datahash ASC LIMIT 1 OFFSET ?")
|
||||
"SELECT chain_hash FROM \"%1\" ORDER BY timestamp, author_signature ASC LIMIT 1 OFFSET ?")
|
||||
.arg(msgTableName(chId));
|
||||
sqlite3_stmt* stmt = prepareOrNull(sql.toUtf8().constData());
|
||||
if (!stmt) return QByteArray(32, '\0');
|
||||
@@ -389,8 +404,8 @@ QByteArray DbManager::syncChainHashAt(const QString& chId, uint32_t pos) const {
|
||||
|
||||
QByteArray DbManager::syncCursorOpen(const QString& chId) {
|
||||
QString sql = QStringLiteral(
|
||||
"SELECT timestamp, datahash, node_id, content_type, data"
|
||||
" FROM \"%1\" ORDER BY timestamp, datahash ASC").arg(msgTableName(chId));
|
||||
"SELECT timestamp, node_id, data, author_signature"
|
||||
" FROM \"%1\" ORDER BY timestamp, author_signature ASC").arg(msgTableName(chId));
|
||||
sqlite3_stmt* stmt = prepareOrNull(sql.toUtf8().constData());
|
||||
if (!stmt) { QByteArray r(4, '\0'); return r; }
|
||||
uint32_t id = m_nextCursorId++;
|
||||
@@ -405,10 +420,23 @@ QByteArray DbManager::syncCursorNext(uint32_t cursorId) {
|
||||
|
||||
/* return: [ts:8][dh:8][nid:8][ct_len:1][ct:var][data_len:4][data:var] */
|
||||
qint64 ts = sqlite3_column_int64(it.value(), 0);
|
||||
uint64_t dh = (uint64_t)sqlite3_column_int64(it.value(), 1);
|
||||
uint64_t nid = (uint64_t)sqlite3_column_int64(it.value(), 2);
|
||||
QString ct = colText(it.value(), 3);
|
||||
QByteArray data = colBlob(it.value(), 4);
|
||||
uint64_t nid = (uint64_t)sqlite3_column_int64(it.value(), 1);
|
||||
QByteArray jdata = colBlob(it.value(), 2);
|
||||
/* parse JSON from data column */
|
||||
auto jField = [](const QByteArray& j, const char* k) -> QByteArray {
|
||||
QByteArray p = "\"" + QByteArray(k) + "\":\"";
|
||||
int i = j.indexOf(p); if (i < 0) return {};
|
||||
i += p.size(); int e = i;
|
||||
while (e < j.size() && !(j[e] == '"' && (e == i || j[e - 1] != '\\'))) e++;
|
||||
return (e > i) ? QByteArray(j.constData() + i, e - i) : QByteArray();
|
||||
};
|
||||
QByteArray ct_raw = jField(jdata, "ct");
|
||||
QString ct = QString::fromUtf8(ct_raw);
|
||||
if (ct.isEmpty()) ct = "text/plain";
|
||||
QByteArray ddata = jField(jdata, "d");
|
||||
/* compute datahash for wire format compat */
|
||||
uint8_t dh_buf[32]; SHA256((const uint8_t*)ddata.constData(), ddata.size(), dh_buf);
|
||||
uint64_t dh; memcpy(&dh, dh_buf, 8);
|
||||
|
||||
QByteArray out;
|
||||
out.append((const char*)&ts, 8);
|
||||
@@ -417,9 +445,9 @@ QByteArray DbManager::syncCursorNext(uint32_t cursorId) {
|
||||
QByteArray ctb = ct.toUtf8();
|
||||
out.append((char)(uint8_t)ctb.size());
|
||||
out.append(ctb);
|
||||
uint32_t dLen = (uint32_t)data.size();
|
||||
uint32_t dLen = (uint32_t)ddata.size();
|
||||
out.append((const char*)&dLen, 4);
|
||||
out.append(data);
|
||||
out.append(ddata);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user