Page MenuHomePhabricator

D13140.diff
No OneTemporary

D13140.diff

diff --git a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h
--- a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h
+++ b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h
@@ -42,6 +42,8 @@
virtual void removeDrafts(const std::vector<std::string> &ids) const = 0;
virtual void removeAllMessages() const = 0;
virtual std::vector<MessageEntity> getInitialMessages() const = 0;
+ virtual std::vector<MessageEntity>
+ fetchMessages(std::string threadID, int limit, int offset) const = 0;
virtual void removeMessages(const std::vector<std::string> &ids) const = 0;
virtual void
removeMessagesForThreads(const std::vector<std::string> &threadIDs) const = 0;
@@ -190,6 +192,8 @@
virtual std::vector<WebThread> getAllThreadsWeb() const = 0;
virtual void replaceThreadWeb(const WebThread &thread) const = 0;
virtual std::vector<MessageWithMedias> getInitialMessagesWeb() const = 0;
+ virtual std::vector<MessageWithMedias>
+ fetchMessagesWeb(std::string threadID, int limit, int offset) const = 0;
virtual void replaceMessageWeb(const WebMessage &message) const = 0;
virtual NullableString getOlmPersistAccountDataWeb(int accountID) const = 0;
virtual std::vector<MessageWithMedias>
diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h
--- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h
+++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h
@@ -67,6 +67,8 @@
void removeDrafts(const std::vector<std::string> &ids) const override;
void removeAllMessages() const override;
std::vector<MessageEntity> getInitialMessages() const override;
+ std::vector<MessageEntity>
+ fetchMessages(std::string threadID, int limit, int offset) const override;
void removeMessages(const std::vector<std::string> &ids) const override;
void removeMessagesForThreads(
const std::vector<std::string> &threadIDs) const override;
@@ -207,6 +209,8 @@
std::vector<WebThread> getAllThreadsWeb() const override;
void replaceThreadWeb(const WebThread &thread) const override;
std::vector<MessageWithMedias> getInitialMessagesWeb() const override;
+ std::vector<MessageWithMedias>
+ fetchMessagesWeb(std::string threadID, int limit, int offset) const override;
void replaceMessageWeb(const WebMessage &message) const override;
NullableString getOlmPersistAccountDataWeb(int accountID) const override;
std::vector<MessageWithMedias>
diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
--- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
+++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp
@@ -1535,6 +1535,31 @@
return this->processMessagesResults(preparedSQL);
}
+std::vector<MessageEntity> SQLiteQueryExecutor::fetchMessages(
+ std::string threadID,
+ int limit,
+ int offset) const {
+ static std::string query =
+ "SELECT "
+ " m.id, m.local_id, m.thread, m.user, m.type, m.future_type, "
+ " m.content, m.time, media.id, media.container, media.thread, "
+ " media.uri, media.type, media.extras "
+ "FROM messages AS m "
+ "LEFT JOIN media "
+ " ON m.id = media.container "
+ "WHERE m.thread = ? "
+ "ORDER BY m.time DESC, m.id DESC "
+ "LIMIT ? OFFSET ?;";
+ SQLiteStatementWrapper preparedSQL(
+ SQLiteQueryExecutor::getConnection(), query, "Failed to fetch messages.");
+
+ bindStringToSQL(threadID.c_str(), preparedSQL, 1);
+ bindIntToSQL(limit, preparedSQL, 2);
+ bindIntToSQL(offset, preparedSQL, 3);
+
+ return this->processMessagesResults(preparedSQL);
+}
+
std::vector<MessageEntity> SQLiteQueryExecutor::processMessagesResults(
SQLiteStatementWrapper &preparedSQL) const {
std::string prevMsgIdx{};
@@ -2852,6 +2877,14 @@
return this->transformToWebMessages(messages);
}
+std::vector<MessageWithMedias> SQLiteQueryExecutor::fetchMessagesWeb(
+ std::string threadID,
+ int limit,
+ int offset) const {
+ auto messages = this->fetchMessages(threadID, limit, offset);
+ return this->transformToWebMessages(messages);
+}
+
void SQLiteQueryExecutor::replaceMessageWeb(const WebMessage &message) const {
this->replaceMessage(message.toMessage());
};
diff --git a/web/cpp/SQLiteQueryExecutorBindings.cpp b/web/cpp/SQLiteQueryExecutorBindings.cpp
--- a/web/cpp/SQLiteQueryExecutorBindings.cpp
+++ b/web/cpp/SQLiteQueryExecutorBindings.cpp
@@ -325,7 +325,8 @@
.function(
"updateMessageSearchIndex",
&SQLiteQueryExecutor::updateMessageSearchIndex)
- .function("searchMessages", &SQLiteQueryExecutor::searchMessagesWeb);
+ .function("searchMessages", &SQLiteQueryExecutor::searchMessagesWeb)
+ .function("fetchMessagesWeb", &SQLiteQueryExecutor::fetchMessagesWeb);
}
} // namespace comm
diff --git a/web/shared-worker/_generated/comm_query_executor.wasm b/web/shared-worker/_generated/comm_query_executor.wasm
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/web/shared-worker/queries/fetch-messages-queries.test.js b/web/shared-worker/queries/fetch-messages-queries.test.js
new file mode 100644
--- /dev/null
+++ b/web/shared-worker/queries/fetch-messages-queries.test.js
@@ -0,0 +1,109 @@
+// @flow
+
+import { messageTypes } from 'lib/types/message-types-enum.js';
+
+import { getDatabaseModule } from '../db-module.js';
+import { createNullableInt, createNullableString } from '../types/entities.js';
+import type {
+ MessageEntity,
+ WebMessage,
+} from '../types/sqlite-query-executor.js';
+import { clearSensitiveData } from '../utils/db-utils.js';
+
+const FILE_PATH = 'test.sqlite';
+
+describe('Fetch messages queries', () => {
+ let queryExecutor;
+ let dbModule;
+ const threadID = '123';
+ const userID = '124';
+
+ beforeAll(async () => {
+ dbModule = getDatabaseModule();
+
+ if (!dbModule) {
+ throw new Error('Database module is missing');
+ }
+ queryExecutor = new dbModule.SQLiteQueryExecutor(FILE_PATH);
+ if (!queryExecutor) {
+ throw new Error('SQLiteQueryExecutor is missing');
+ }
+
+ for (let i = 0; i < 50; i++) {
+ const message: WebMessage = {
+ id: i.toString(),
+ localID: createNullableString(),
+ thread: threadID,
+ user: userID,
+ type: messageTypes.TEXT,
+ futureType: createNullableInt(),
+ content: createNullableString(`text-${i}`),
+ time: i.toString(),
+ };
+ queryExecutor.replaceMessageWeb(message);
+ }
+ });
+
+ afterAll(() => {
+ clearSensitiveData(dbModule, FILE_PATH, queryExecutor);
+ });
+
+ function assertMessageEqual(message: MessageEntity, id: number) {
+ const expected: WebMessage = {
+ id: id.toString(),
+ localID: createNullableString(),
+ thread: threadID,
+ user: userID,
+ type: messageTypes.TEXT,
+ futureType: createNullableInt(),
+ content: createNullableString(`text-${id}`),
+ time: id.toString(),
+ };
+ expect(message.message).toEqual(expected);
+ }
+
+ it('should fetch the first messages', () => {
+ const result = queryExecutor.fetchMessagesWeb(threadID, 5, 0);
+ expect(result.length).toBe(5);
+ for (let i = 0; i < 5; i++) {
+ assertMessageEqual(result[i], 49 - i);
+ }
+ });
+
+ it('should fetch the following messages', () => {
+ const result = queryExecutor.fetchMessagesWeb(threadID, 5, 5);
+ expect(result.length).toBe(5);
+ for (let i = 0; i < 5; i++) {
+ assertMessageEqual(result[i], 44 - i);
+ }
+ });
+
+ it('should fetch the last messages', () => {
+ const result = queryExecutor.fetchMessagesWeb(threadID, 5, 45);
+ expect(result.length).toBe(5);
+ for (let i = 0; i < 5; i++) {
+ assertMessageEqual(result[i], 4 - i);
+ }
+ });
+
+ it('should check if thread ID matches', () => {
+ const result = queryExecutor.fetchMessagesWeb('000', 5, 45);
+ expect(result.length).toBe(0);
+ });
+
+ it('should fetch the remaining messages when limit exceeds the bounds', () => {
+ const result = queryExecutor.fetchMessagesWeb(threadID, 100, 40);
+ expect(result.length).toBe(10);
+ for (let i = 0; i < 10; i++) {
+ assertMessageEqual(result[i], 9 - i);
+ }
+ });
+
+ it('should return all the messages when limit is high enough', () => {
+ const result = queryExecutor.fetchMessagesWeb(threadID, 500, 0);
+ expect(result.length).toBe(50);
+ for (let i = 0; i < 50; i++) {
+ assertMessageEqual(result[i], 49 - i);
+ }
+ });
+});
diff --git a/web/shared-worker/types/entities.js b/web/shared-worker/types/entities.js
--- a/web/shared-worker/types/entities.js
+++ b/web/shared-worker/types/entities.js
@@ -180,4 +180,5 @@
clientDBMessageInfoToWebMessage,
webMessageToClientDBMessageInfo,
createNullableString,
+ createNullableInt,
};
diff --git a/web/shared-worker/types/sqlite-query-executor.js b/web/shared-worker/types/sqlite-query-executor.js
--- a/web/shared-worker/types/sqlite-query-executor.js
+++ b/web/shared-worker/types/sqlite-query-executor.js
@@ -48,7 +48,7 @@
+version: number,
};
-type MessageEntity = {
+export type MessageEntity = {
+message: WebMessage,
+medias: $ReadOnlyArray<Media>,
};
@@ -63,6 +63,11 @@
removeDrafts(ids: $ReadOnlyArray<string>): void;
getInitialMessagesWeb(): $ReadOnlyArray<MessageEntity>;
+ fetchMessagesWeb(
+ threadID: string,
+ limit: number,
+ offset: number,
+ ): $ReadOnlyArray<MessageEntity>;
removeAllMessages(): void;
removeMessages(ids: $ReadOnlyArray<string>): void;
removeMessagesForThreads(threadIDs: $ReadOnlyArray<string>): void;

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 22, 9:20 PM (18 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2565036
Default Alt Text
D13140.diff (9 KB)

Event Timeline