1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
// -*- C++ -*-
#ifndef _SQL_DB_H
#define _SQL_DB_H 1
/** \file sql_db.h
* \brief Data structures representing information in SQL database.
*/
#include <exception>
#include <iosfwd>
#include <fstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "sqlstmt.h"
using std::string;
extern const char dbvers[];
/** Writestamp is the pair (replica-id, version-number). */
using writestamp = std::pair<i64,i64>;
std::istream &read_writestamp (std::istream &in, writestamp &ws);
/** A version vector is a set of ::writestamps with distinct
* replica-ids.
*/
using versvector = std::unordered_map<i64,i64>;
string show_sync_vector (const versvector &vv);
std::istream &read_sync_vector (std::istream &sb, versvector &vv);
versvector get_sync_vector (sqlite3 *db);
/** Open the SQL database containing muchsync state.
*
* If the file does not exist, it is created and initialized with a
* fresh database.
*/
sqlite3 *dbopen (const char *path, bool exclusive = false);
/** Retrieve a configuration value from the database.
*
* Example: `getconfig<i64>(db, "key")`
*/
template<typename T> T
getconfig (sqlite3 *db, const string &key)
{
static const char query[] = "SELECT value FROM configuration WHERE key = ?;";
return sqlstmt_t(db, query).param(key).step().template column<T>(0);
}
/** Set a configuration value in database. */
template<typename T> void
setconfig (sqlite3 *db, const string &key, const T &value)
{
static const char query[] =
"INSERT OR REPLACE INTO configuration VALUES (?, ?);";
sqlstmt_t(db, query).param(key, value).step();
}
/** Structure representing all occurences of a file with a particular
* content hash in the maildir. */
struct hash_info {
string hash;
i64 size = -1;
string message_id;
writestamp hash_stamp = {0, 0};
std::unordered_map<string,i64> dirs;
};
/** Pre-formatted queries for looking up ::hash_info structures in
* database. */
class hash_lookup {
sqlstmt_t gethash_;
sqlstmt_t getlinks_;
sqlstmt_t makehash_;
bool ok_ = false;
hash_info hi_;
i64 hash_id_;
std::vector<std::pair<string,string>> links_;
std::ifstream content_;
i64 docid_;
public:
const string maildir;
hash_lookup(const string &maildir, sqlite3 *db);
bool lookup(const string &hash);
void create(const hash_info &info);
bool ok() const { return ok_; }
i64 hash_id() const { assert (ok()); return hash_id_; }
const hash_info &info() const { assert (ok()); return hi_; }
const std::vector<std::pair<string,string>> &links() const {
assert (ok());
return links_;
}
i64 docid() const { assert (nlinks()); return docid_; }
int nlinks() const { return links().size(); }
string link_path(int i) const {
auto &lnk = links().at(i);
return maildir + "/" + lnk.first + "/" + lnk.second;
}
bool get_pathname(string *path, bool *from_trash = nullptr) const;
std::streambuf *content();
};
/** Structure representing all the tags associated with a particular
* message ID in the database.
*
* Note that multiple content hashes may contain the same message ID.
*/
struct tag_info {
string message_id;
writestamp tag_stamp = {0, 0};
std::unordered_set<string> tags;
};
/** Pre-formatted queries for looking up ::tag_info structures in
* database. */
class tag_lookup {
sqlstmt_t getmsg_;
sqlstmt_t gettags_;
bool ok_ = false;
tag_info ti_;
i64 docid_;
public:
tag_lookup (sqlite3 *db);
bool lookup(const string &msgid);
bool ok() const { return ok_; }
i64 docid() const { assert (ok()); return docid_; }
const tag_info &info() const { assert (ok()); return ti_; }
};
std::ostream &operator<< (std::ostream &os, const hash_info &hi);
std::istream &operator>> (std::istream &is, hash_info &hi);
std::ostream &operator<< (std::ostream &os, const tag_info &ti);
std::istream &operator>> (std::istream &is, tag_info &ti);
string trashname (const string &maildir, const string &hash);
string permissive_percent_encode (const string &raw);
i64 create_random_id ();
#endif /* !_SQL_DB_H */
|