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