aboutsummaryrefslogtreecommitdiff
path: root/src/data.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/data.cpp')
-rw-r--r--src/data.cpp182
1 files changed, 167 insertions, 15 deletions
diff --git a/src/data.cpp b/src/data.cpp
index d6c4c5f..4960afc 100644
--- a/src/data.cpp
+++ b/src/data.cpp
@@ -6,6 +6,7 @@
6#include <mw/database.hpp> 6#include <mw/database.hpp>
7#include <mw/error.hpp> 7#include <mw/error.hpp>
8#include <mw/utils.hpp> 8#include <mw/utils.hpp>
9#include <utility>
9 10
10#include "data.hpp" 11#include "data.hpp"
11 12
@@ -39,6 +40,18 @@ LinkItem linkFromTuple(const LinkTuple& t)
39 40
40} // namespace 41} // namespace
41 42
43std::string LinkItem::visibilityToStr(Visibility v)
44{
45 switch(v)
46 {
47 case PUBLIC:
48 return "public";
49 case PRIVATE:
50 return "private";
51 }
52 std::unreachable();
53}
54
42mw::E<std::unique_ptr<DataSourceSQLite>> 55mw::E<std::unique_ptr<DataSourceSQLite>>
43DataSourceSQLite::fromFile(const std::string& db_file) 56DataSourceSQLite::fromFile(const std::string& db_file)
44{ 57{
@@ -53,7 +66,7 @@ DataSourceSQLite::fromFile(const std::string& db_file)
53 DO_OR_RETURN(data_source->setSchemaVersion(1)); 66 DO_OR_RETURN(data_source->setSchemaVersion(1));
54 DO_OR_RETURN(data_source->db->execute( 67 DO_OR_RETURN(data_source->db->execute(
55 "CREATE TABLE IF NOT EXISTS Users " 68 "CREATE TABLE IF NOT EXISTS Users "
56 "(id INTEGER PRIMARY KEY, openid_uid TEXT, name TEXT);")); 69 "(id INTEGER PRIMARY KEY, openid_uid TEXT UNIQUE, name TEXT UNIQUE);"));
57 DO_OR_RETURN(data_source->db->execute( 70 DO_OR_RETURN(data_source->db->execute(
58 "CREATE TABLE IF NOT EXISTS LinkItems " 71 "CREATE TABLE IF NOT EXISTS LinkItems "
59 "(id INTEGER PRIMARY KEY, owner_id INTEGER NOT NULL," 72 "(id INTEGER PRIMARY KEY, owner_id INTEGER NOT NULL,"
@@ -80,25 +93,138 @@ mw::E<void> DataSourceSQLite::setSchemaVersion(int64_t v) const
80 return db->execute(std::format("PRAGMA user_version = {};", v)); 93 return db->execute(std::format("PRAGMA user_version = {};", v));
81} 94}
82 95
83mw::E<std::vector<LinkItem>> 96mw::E<std::optional<User>>
84DataSourceSQLite::items(std::optional<int64_t> parent) 97DataSourceSQLite::userByOpenIDUID(const std::string& uid) const
98{
99 if(db == nullptr)
100 {
101 return std::unexpected(mw::runtimeError("Database is not connected."));
102 }
103 ASSIGN_OR_RETURN(mw::SQLiteStatement sql, db->statementFromStr(
104 "SELECT id, openid_uid, name FROM Users WHERE openid_uid = ?;"));
105 DO_OR_RETURN(sql.bind(uid));
106 ASSIGN_OR_RETURN(auto users, (db->eval<int64_t, std::string, std::string>(
107 std::move(sql))));
108 if(users.empty())
109 {
110 return std::nullopt;
111 }
112 if(users.size() > 1)
113 {
114 return std::unexpected(mw::runtimeError("Found duplicated users"));
115 }
116 User u;
117 u.id = std::get<0>(users[0]);
118 u.openid_uid = std::get<1>(users[0]);
119 u.name = std::get<2>(users[0]);
120 return u;
121}
122
123mw::E<int64_t> DataSourceSQLite::addUser(User&& u) const
85{ 124{
125 if(db == nullptr)
126 {
127 return std::unexpected(mw::runtimeError("Database is not connected."));
128 }
129 ASSIGN_OR_RETURN(mw::SQLiteStatement sql, db->statementFromStr(
130 "INSERT INTO Users (id, openid_uid, name) VALUES (NULL, ?, ?)"));
131 DO_OR_RETURN(sql.bind(u.openid_uid, u.name));
132 DO_OR_RETURN(db->execute(std::move(sql)));
133 return db->lastInsertRowID();
134}
135
136mw::E<std::optional<User>> DataSourceSQLite::userByID(const int64_t id) const
137{
138 if(db == nullptr)
139 {
140 return std::unexpected(mw::runtimeError("Database is not connected."));
141 }
142 ASSIGN_OR_RETURN(mw::SQLiteStatement sql, db->statementFromStr(
143 "SELECT id, openid_uid, name FROM Users WHERE id = ?;"));
144 DO_OR_RETURN(sql.bind(id));
145 ASSIGN_OR_RETURN(auto users, (db->eval<int64_t, std::string, std::string>(
146 std::move(sql))));
147 if(users.empty())
148 {
149 return std::nullopt;
150 }
151 if(users.size() > 1)
152 {
153 return std::unexpected(mw::runtimeError("Found duplicated users"));
154 }
155 User u;
156 u.id = std::get<0>(users[0]);
157 u.openid_uid = std::get<1>(users[0]);
158 u.name = std::get<2>(users[0]);
159 return u;
160}
161
162mw::E<std::optional<User>> DataSourceSQLite::userByName(const std::string& name)
163 const
164{
165 if(db == nullptr)
166 {
167 return std::unexpected(mw::runtimeError("Database is not connected."));
168 }
169 ASSIGN_OR_RETURN(mw::SQLiteStatement sql, db->statementFromStr(
170 "SELECT id, openid_uid, name FROM Users WHERE name = ?;"));
171 DO_OR_RETURN(sql.bind(name));
172 ASSIGN_OR_RETURN(auto users, (db->eval<int64_t, std::string, std::string>(
173 std::move(sql))));
174 if(users.empty())
175 {
176 return std::nullopt;
177 }
178 if(users.size() > 1)
179 {
180 return std::unexpected(mw::runtimeError("Found duplicated users"));
181 }
182 User u;
183 u.id = std::get<0>(users[0]);
184 u.openid_uid = std::get<1>(users[0]);
185 u.name = std::get<2>(users[0]);
186 return u;
187}
188
189mw::E<std::optional<LinkItem>> DataSourceSQLite::itemByID(int64_t id) const
190{
191 if(db == nullptr)
192 {
193 return std::unexpected(mw::runtimeError("Database is not connected."));
194 }
86 std::vector<LinkTuple> links; 195 std::vector<LinkTuple> links;
87 if(!parent.has_value()) 196 // Querying root-level links.
197 ASSIGN_OR_RETURN(mw::SQLiteStatement stat, db->statementFromStr(
198 "SELECT id, owner_id, parent_id, name, url, description, visibility,"
199 " time from LinkItems WHERE id = ?;"));
200 DO_OR_RETURN(stat.bind(id));
201 ASSIGN_OR_RETURN(links, (db->eval<LINK_TUPLE_TYPES>(std::move(stat))));
202 if(links.empty())
88 { 203 {
89 // Querying root-level links. 204 return std::nullopt;
90 ASSIGN_OR_RETURN(links, (db->eval<LINK_TUPLE_TYPES>(
91 "SELECT id, owner_id, parent_id, name, url, description, visibility,"
92 " time from LinkItems WHERE parent_id IS NULL;")));
93 } 205 }
94 else 206 if(links.size() > 1)
207 {
208 return std::unexpected(mw::runtimeError("Duplicate item ID"));
209 }
210
211 return linkFromTuple(links[0]);
212}
213
214mw::E<std::vector<LinkItem>> DataSourceSQLite::itemsByParent(int64_t parent)
215 const
216{
217 if(db == nullptr)
95 { 218 {
96 ASSIGN_OR_RETURN(mw::SQLiteStatement stat, db->statementFromStr( 219 return std::unexpected(mw::runtimeError("Database is not connected."));
97 "SELECT id, owner_id, parent_id, name, url, description, visibility,"
98 " time from LinkItems WHERE parent_id = ?;"));
99 DO_OR_RETURN(stat.bind<int64_t>(*parent));
100 ASSIGN_OR_RETURN(links, (db->eval<LINK_TUPLE_TYPES>(std::move(stat))));
101 } 220 }
221 std::vector<LinkTuple> links;
222 // Querying root-level links.
223 ASSIGN_OR_RETURN(mw::SQLiteStatement stat, db->statementFromStr(
224 "SELECT id, owner_id, parent_id, name, url, description, visibility,"
225 " time from LinkItems WHERE parent_id = ?;"));
226 DO_OR_RETURN(stat.bind(parent));
227 ASSIGN_OR_RETURN(links, (db->eval<LINK_TUPLE_TYPES>(std::move(stat))));
102 std::vector<LinkItem> result; 228 std::vector<LinkItem> result;
103 for(const LinkTuple& t : links) 229 for(const LinkTuple& t : links)
104 { 230 {
@@ -107,8 +233,34 @@ DataSourceSQLite::items(std::optional<int64_t> parent)
107 return result; 233 return result;
108} 234}
109 235
110mw::E<int64_t> DataSourceSQLite::addLink(LinkItem&& link) 236mw::E<std::vector<LinkItem>>
237DataSourceSQLite::itemsTopLevelByUser(int64_t user_id) const
111{ 238{
239 if(db == nullptr)
240 {
241 return std::unexpected(mw::runtimeError("Database is not connected."));
242 }
243 std::vector<LinkTuple> links;
244 // Querying root-level links.
245 ASSIGN_OR_RETURN(mw::SQLiteStatement stat, db->statementFromStr(
246 "SELECT id, owner_id, parent_id, name, url, description, visibility,"
247 " time from LinkItems WHERE parent_id IS NULL AND owner_id = ?;"));
248 DO_OR_RETURN(stat.bind(user_id));
249 ASSIGN_OR_RETURN(links, (db->eval<LINK_TUPLE_TYPES>(std::move(stat))));
250 std::vector<LinkItem> result;
251 for(const LinkTuple& t : links)
252 {
253 result.push_back(linkFromTuple(t));
254 }
255 return result;
256}
257
258mw::E<int64_t> DataSourceSQLite::addLink(LinkItem&& link) const
259{
260 if(db == nullptr)
261 {
262 return std::unexpected(mw::runtimeError("Database is not connected."));
263 }
112 ASSIGN_OR_RETURN(mw::SQLiteStatement sql, db->statementFromStr( 264 ASSIGN_OR_RETURN(mw::SQLiteStatement sql, db->statementFromStr(
113 "INSERT INTO LinkItems (id, owner_id, parent_id, name, url," 265 "INSERT INTO LinkItems (id, owner_id, parent_id, name, url,"
114 " description, visibility, time) VALUES (?, ?, ?, ?, ?, ?, ?, ?)")); 266 " description, visibility, time) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"));