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
@@ -1119,14 +1119,23 @@
 }
 
 std::string SQLiteQueryExecutor::getDraft(std::string key) const {
-  std::unique_ptr<Draft> draft =
-      SQLiteQueryExecutor::getStorage().get_pointer<Draft>(key);
+  static std::string getDraftByPrimaryKeySQL =
+      "SELECT * "
+      "FROM drafts "
+      "WHERE key = ?;";
+  std::unique_ptr<Draft> draft = getEntityByPrimaryKey<Draft>(
+      SQLiteQueryExecutor::getConnection(), getDraftByPrimaryKeySQL, key);
   return (draft == nullptr) ? "" : draft->text;
 }
 
 std::unique_ptr<Thread>
 SQLiteQueryExecutor::getThread(std::string threadID) const {
-  return SQLiteQueryExecutor::getStorage().get_pointer<Thread>(threadID);
+  static std::string getThreadByPrimaryKeySQL =
+      "SELECT * "
+      "FROM threads "
+      "WHERE id = ?;";
+  return getEntityByPrimaryKey<Thread>(
+      SQLiteQueryExecutor::getConnection(), getThreadByPrimaryKeySQL, threadID);
 }
 
 void SQLiteQueryExecutor::updateDraft(std::string key, std::string text) const {
@@ -1340,8 +1349,14 @@
 }
 
 std::string SQLiteQueryExecutor::getPersistStorageItem(std::string key) const {
-  std::unique_ptr<PersistItem> entry =
-      SQLiteQueryExecutor::getStorage().get_pointer<PersistItem>(key);
+  static std::string getPersistStorageItemByPrimaryKeySQL =
+      "SELECT * "
+      "FROM persist_storage "
+      "WHERE key = ?;";
+  std::unique_ptr<PersistItem> entry = getEntityByPrimaryKey<PersistItem>(
+      SQLiteQueryExecutor::getConnection(),
+      getPersistStorageItemByPrimaryKeySQL,
+      key);
   return (entry == nullptr) ? "" : entry->item;
 }
 
@@ -1470,8 +1485,14 @@
 }
 
 std::string SQLiteQueryExecutor::getMetadata(std::string entry_name) const {
-  std::unique_ptr<Metadata> entry =
-      SQLiteQueryExecutor::getStorage().get_pointer<Metadata>(entry_name);
+  std::string getMetadataByPrimaryKeySQL =
+      "SELECT * "
+      "FROM metadata "
+      "WHERE name = ?;";
+  std::unique_ptr<Metadata> entry = getEntityByPrimaryKey<Metadata>(
+      SQLiteQueryExecutor::getConnection(),
+      getMetadataByPrimaryKeySQL,
+      entry_name);
   return (entry == nullptr) ? "" : entry->data;
 }
 
diff --git a/native/cpp/CommonCpp/DatabaseManagers/entities/EntityQueryHelpers.h b/native/cpp/CommonCpp/DatabaseManagers/entities/EntityQueryHelpers.h
--- a/native/cpp/CommonCpp/DatabaseManagers/entities/EntityQueryHelpers.h
+++ b/native/cpp/CommonCpp/DatabaseManagers/entities/EntityQueryHelpers.h
@@ -20,4 +20,36 @@
   return allEntities;
 }
 
+template <typename T>
+std::unique_ptr<T> getEntityByPrimaryKey(
+    sqlite3 *db,
+    std::string getEntityByPrimaryKeySQL,
+    std::string primaryKey) {
+  SQLiteStatementWrapper preparedSQL(
+      db, getEntityByPrimaryKeySQL, "Failed to fetch row by primary key.");
+  int bindResult =
+      sqlite3_bind_text(preparedSQL, 1, primaryKey.c_str(), -1, SQLITE_STATIC);
+  if (bindResult != SQLITE_OK) {
+    std::stringstream error_message;
+    error_message << "Failed to bind primary key to SQL statement. Details: "
+                  << sqlite3_errstr(bindResult) << std::endl;
+    throw std::runtime_error(error_message.str());
+  }
+
+  int stepResult = sqlite3_step(preparedSQL);
+  if (stepResult == SQLITE_DONE) {
+    return nullptr;
+  }
+
+  if (stepResult != SQLITE_ROW) {
+    std::stringstream error_message;
+    error_message << "Failed to fetch row by primary key. Details: "
+                  << sqlite3_errstr(stepResult) << std::endl;
+    throw std::runtime_error(error_message.str());
+  }
+
+  T entity = T::fromSQLResult(preparedSQL, 0);
+  return std::make_unique<T>(std::move(entity));
+}
+
 } // namespace comm
diff --git a/native/cpp/CommonCpp/DatabaseManagers/entities/Metadata.h b/native/cpp/CommonCpp/DatabaseManagers/entities/Metadata.h
--- a/native/cpp/CommonCpp/DatabaseManagers/entities/Metadata.h
+++ b/native/cpp/CommonCpp/DatabaseManagers/entities/Metadata.h
@@ -1,5 +1,7 @@
 #pragma once
 
+#include "SQLiteDataConverters.h"
+#include <sqlite3.h>
 #include <string>
 
 namespace comm {
@@ -7,6 +9,11 @@
 struct Metadata {
   std::string name;
   std::string data;
+
+  static Metadata fromSQLResult(sqlite3_stmt *sqlRow, int idx) {
+    return Metadata{
+        getStringFromSQLRow(sqlRow, idx), getStringFromSQLRow(sqlRow, idx + 1)};
+  }
 };
 
 } // namespace comm
diff --git a/native/cpp/CommonCpp/DatabaseManagers/entities/PersistItem.h b/native/cpp/CommonCpp/DatabaseManagers/entities/PersistItem.h
--- a/native/cpp/CommonCpp/DatabaseManagers/entities/PersistItem.h
+++ b/native/cpp/CommonCpp/DatabaseManagers/entities/PersistItem.h
@@ -1,5 +1,7 @@
 #pragma once
 
+#include "SQLiteDataConverters.h"
+#include <sqlite3.h>
 #include <string>
 
 namespace comm {
@@ -7,6 +9,11 @@
 struct PersistItem {
   std::string key;
   std::string item;
+
+  static PersistItem fromSQLResult(sqlite3_stmt *sqlRow, int idx) {
+    return PersistItem{
+        getStringFromSQLRow(sqlRow, idx), getStringFromSQLRow(sqlRow, idx + 1)};
+  }
 };
 
 } // namespace comm
diff --git a/web/database/_generated/comm_query_executor.wasm b/web/database/_generated/comm_query_executor.wasm
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001

literal 0
Hc$@<O00001