File: sql_db.h

package info (click to toggle)
muchsync 6-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, sid
  • size: 580 kB
  • sloc: cpp: 3,860; sh: 982; makefile: 17
file content (145 lines) | stat: -rw-r--r-- 4,075 bytes parent folder | download | duplicates (2)
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 */