Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3340059
D13140.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Referenced Files
None
Subscribers
None
D13140.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D13140: [web] Create a function that fetches messages in batches
Attached
Detach File
Event Timeline
Log In to Comment