Joedb 10.0.1
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
Writable_Database_h.cpp
Go to the documentation of this file.
3#include "joedb/ui/type_io.h"
4
5namespace joedb::generator
6{
7 ////////////////////////////////////////////////////////////////////////////
9 ////////////////////////////////////////////////////////////////////////////
10 (
11 const Compiler_Options &options
12 ):
13 Generator(".", "Writable_Database.h", options)
14 {
15 }
16
17 ////////////////////////////////////////////////////////////////////////////
19 ////////////////////////////////////////////////////////////////////////////
20 {
21 const Database &db = options.get_db();
22 auto tables = db.get_tables();
23
24 namespace_include_guard(out, "Writable_Database", options.get_name_space());
25
26 out << R"RRR(
27#include "Database_Writable.h"
28#include "joedb/Span.h"
29
30)RRR";
31
33
34 //
35 // Writable_Database
36 //
37 out << R"RRR(
38 namespace detail
39 {
40 class Client_Data;
41 }
42
43 class Client;
44 class Multiplexer;
45
46 /// A @ref Database that contains a @ref joedb::Writable_Journal and keeps them in sync
47 class Writable_Database: public Database_Writable
48 {
49 friend class detail::Client_Data;
50 friend class Client;
51 friend class Multiplexer;
52
53 private:
54 joedb::Writable_Journal journal;
55 bool ready_to_write;
56
57 void play_journal();
58 void auto_upgrade();
59 void check_single_row();
60 void initialize();
61)RRR";
62
63
64 if (!options.get_custom_names().empty())
65 {
66 out << R"RRR(
67 void custom(const std::string &name) override
68 {
69 Database_Writable::custom(name);
70
71 if (upgrading_schema)
72 {
73)RRR";
74 for (const auto &name: options.get_custom_names())
75 {
76 out << " if (name == \"" << name << "\")\n";
77 out << " " << name << "(*this);\n";
78 }
79 out << " }\n";
80 out << " }\n";
81
82 out << '\n';
83 out << " public:\n";
84 for (const auto &name: options.get_custom_names())
85 out << " static void " << name << "(Writable_Database &db);\n";
86 out << "\n private:";
87 }
88
89 if (db_has_values())
90 {
91 out << R"RRR(
92 void add_field
93 (
94 Table_Id table_id,
95 const std::string &name,
96 joedb::Type type
97 ) override;
98)RRR";
99 }
100
102 {
103 out <<"\n void create_table(const std::string &name) override;\n";
104 }
105
106 out << R"RRR(
107 Writable_Database
108 (
109 joedb::Buffered_File &file,
110 joedb::Recovery recovery,
111 bool perform_initialization
112 );
113
114 public:
115 Writable_Database(joedb::Buffered_File &file);
116
117 Writable_Database
118 (
119 joedb::Buffered_File &file,
120 joedb::Recovery recovery
121 );
122
123 const joedb::Readonly_Journal &get_journal() const {return journal;}
124
125 std::string read_blob(joedb::Blob blob) const
126 {
127 return journal.get_file().read_blob(blob);
128 }
129
130 joedb::Blob write_blob(const std::string &data) override
131 {
132 return journal.write_blob(data);
133 }
134
135 int64_t ahead_of_checkpoint() const
136 {
137 return journal.ahead_of_checkpoint();
138 }
139
140 void soft_checkpoint() override
141 {
142 journal.soft_checkpoint();
143 }
144
145 void hard_checkpoint() override
146 {
147 journal.hard_checkpoint();
148 }
149
150 void write_comment(const std::string &comment);
151 void write_timestamp();
152 void write_timestamp(int64_t timestamp);
153 void write_valid_data();
154 void flush() override {journal.flush();}
155)RRR";
156
157 for (const auto &[tid, tname]: tables)
158 {
159 out << '\n';
160 const bool single_row = options.get_table_options(tid).single_row;
161
162 //
163 // Erase all elements of the table
164 //
165 if (!single_row)
166 {
167 out << " void clear_" << tname << "_table();\n";
168 out << '\n';
169 }
170
171 if (single_row)
172 out << " private:\n";
173
174 //
175 // Uninitialized new
176 //
177 out << " id_of_" << tname << " new_" << tname << "()\n";
178 out << " {\n";
179
180 out << " id_of_" << tname << " result(Record_Id(storage_of_" << tname << ".freedom_keeper.get_free_record()));\n";
181 out << " storage_of_" << tname << ".resize(storage_of_" << tname << ".freedom_keeper.size());\n";
182 out << " internal_insert_" << tname << "(result.get_record_id());\n\n";
183 out << " journal.insert_into(Table_Id(" << tid << "), result.get_record_id());\n";
184 out << " return result;\n";
185 out << " }\n";
186 out << '\n';
187
188 //
189 // new uninitialized vector
190 //
191 if (!single_row)
192 {
193 out << " id_of_" << tname << " new_vector_of_" << tname << "(size_t size)\n";
194 out << " {\n";
195 out << " id_of_" << tname << " result(Record_Id(storage_of_" << tname;
196 out << ".size()));\n";
197 out << " storage_of_" << tname << ".resize(storage_of_";
198 out << tname << ".size() + size);\n";
199 out << " internal_vector_insert_" << tname << "(result.get_record_id(), size);\n";
200 out << " journal.insert_vector(Table_Id(" << tid;
201 out << "), result.get_record_id(), size);\n";
202 out << " return result;\n";
203 out << " }\n";
204 out << '\n';
205 }
206
207 //
208 // new with all fields
209 //
210 if (!db.get_fields(tid).empty())
211 {
212 out << " id_of_" << tname << " new_" << tname << '\n';
213 out << " (\n ";
214 {
215 bool first = true;
216
217 for (const auto &[fid, fname]: db.get_fields(tid))
218 {
219 if (first)
220 first = false;
221 else
222 out << ",\n ";
223
224 const Type &type = db.get_field_type(tid, fid);
225 write_type(type, false, true);
226 out << " field_value_of_" << fname;
227 }
228
229 out << '\n';
230 }
231 out << " )\n";
232 out << " {\n";
233 out << " auto result = new_" << tname << "();\n";
234
235 for (const auto &[fid, fname]: db.get_fields(tid))
236 out << " set_" << fname << "(result, field_value_of_" << fname << ");\n";
237
238 out << " return result;\n";
239 out << " }\n\n";
240 }
241
242 if (single_row)
243 out << " public:\n";
244
245 //
246 // Delete
247 //
248 if (!single_row)
249 {
250 out << " void delete_" << tname << "(id_of_" << tname << " record)\n";
251 out << " {\n";
252 out << " internal_delete_" << tname << "(record.get_record_id());\n";
253 out << " journal.delete_from(Table_Id(" << tid << "), record.get_record_id());\n";
254 out << " }\n\n";
255
256 out << " void delete_vector_of_" << tname << "(id_of_" << tname << " v, size_t size)\n";
257 out << " {\n";
258 out << " for (size_t i = size; i > 0;)\n";
259 out << " internal_delete_" << tname << "(v[--i].get_record_id());\n";
260 out << " journal.delete_vector(Table_Id(" << tid << "), v.get_record_id(), size);\n";
261 out << " }\n\n";
262 }
263
264 //
265 // Loop over fields
266 //
267 for (const auto &[fid, fname]: db.get_fields(tid))
268 {
269 const Type &type = db.get_field_type(tid, fid);
270
271 //
272 // Setter
273 //
274 out << " void set_" << fname;
275 out << "(id_of_" << tname << " record, ";
276 write_type(type, false, true);
277 out << " field_value_of_" << fname << ")\n";
278 out << " {\n";
279 out << " internal_update_" << tname << "__" << fname;
280
281 out << "(record.get_record_id(), ";
282 out << "field_value_of_" << fname << ");\n";
283 out << " journal.update_";
284 out << get_type_string(type);
285 out << "(Table_Id(" << tid << "), record.get_record_id(), Field_Id(" << fid << "), ";
286 out << "field_value_of_" << fname;
287 if (type.get_type_id() == Type::Type_Id::reference)
288 out << ".get_record_id()";
289 out << ");\n";
290
291 out << " }\n\n";
292
293 //
294 // Vector update
295 // Note: write even if exception, to keep memory and file in sync
296 //
297 out << " template<typename F> void update_vector_of_" << fname;
298 out << "(id_of_" << tname << " record, size_t size, F f)\n";
299 out << " {\n";
300 out << " std::exception_ptr exception;\n";
301 out << " joedb::Span<";
302 write_type(type, false, false);
303 out << "> span(&storage_of_" << tname;
304 out << ".field_value_of_" << fname << ".data()[record.get_id()], size);\n";
305 out << " try {f(span);}\n";
306 out << " catch (...) {exception = std::current_exception();}\n";
307 out << " internal_update_vector_" << tname << "__" << fname << "(record.get_record_id(), size, span.begin());\n";
308 out << " journal.update_vector_" << get_type_string(type) << "(Table_Id(" << tid << "), record.get_record_id(), Field_Id(" << fid << "), size, ";
309
310 if (type.get_type_id() == Type::Type_Id::reference)
311 out << "reinterpret_cast<Record_Id *>";
312
313 out << "(span.begin()));\n";
314 out << " if (exception)\n";
315 out << " std::rethrow_exception(exception);\n";
316 out << " }\n\n";
317 }
318 }
319
320 out << "\n };";
321
323 out << "\n#endif\n";
324 }
325}
const std::vector< std::string > & get_custom_names() const
const std::vector< std::string > & get_name_space() const
const Table_Options & get_table_options(Table_Id table_id) const
const Database & get_db() const
const std::map< Table_Id, std::string > & get_tables() const override
const Type & get_field_type(Table_Id table_id, Field_Id field_id) const override
const std::map< Field_Id, std::string > & get_fields(Table_Id table_id) const override
Type_Id get_type_id() const
Definition Type.h:41
static const char * get_type_string(Type type)
void write_type(Type type, bool return_type, bool setter_type)
Definition Generator.cpp:42
const Compiler_Options & options
Definition Generator.h:14
Writable_Database_h(const Compiler_Options &options)
void namespace_open(std::ostream &out, const std::vector< std::string > &n)
void namespace_close(std::ostream &out, const std::vector< std::string > &n)
void namespace_include_guard(std::ostream &out, const char *name, const std::vector< std::string > &n)
One code generator for each of the file generated by joedbc.
Definition Client_h.cpp:5